summaryrefslogtreecommitdiffstats
path: root/src/sss_client/idmap/sss_nss_idmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sss_client/idmap/sss_nss_idmap.c')
-rw-r--r--src/sss_client/idmap/sss_nss_idmap.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/sss_client/idmap/sss_nss_idmap.c b/src/sss_client/idmap/sss_nss_idmap.c
new file mode 100644
index 000000000..e0faf6e78
--- /dev/null
+++ b/src/sss_client/idmap/sss_nss_idmap.c
@@ -0,0 +1,255 @@
+/*
+ SSSD
+
+ NSS Responder Interface for ID-SID mappings
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2013 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <nss.h>
+
+#include "sss_client/sss_cli.h"
+#include "sss_client/idmap/sss_nss_idmap.h"
+#include "util/strtonum.h"
+
+#define DATA_START (3 * sizeof(uint32_t))
+union input {
+ const char *str;
+ uint32_t id;
+};
+
+struct output {
+ enum sss_id_type type;
+ union {
+ char *str;
+ uint32_t id;
+ } d;
+};
+
+int nss_status_to_errno(enum nss_status nret) {
+ switch (nret) {
+ case NSS_STATUS_TRYAGAIN:
+ return EAGAIN;
+ case NSS_STATUS_SUCCESS:
+ return EOK;
+ case NSS_STATUS_UNAVAIL:
+ default:
+ return ENOENT;
+ }
+
+ return EINVAL;
+}
+
+static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
+ struct output *out)
+{
+ int ret;
+ size_t inp_len;
+ struct sss_cli_req_data rd;
+ uint8_t *repbuf = NULL;
+ size_t replen;
+ int errnop;
+ enum nss_status nret;
+ uint32_t num_results;
+ char *str = NULL;
+ size_t data_len;
+ uint32_t c;
+
+ switch (cmd) {
+ case SSS_NSS_GETSIDBYNAME:
+ case SSS_NSS_GETNAMEBYSID:
+ case SSS_NSS_GETIDBYSID:
+ ret = sss_strnlen(inp.str, SSS_NAME_MAX, &inp_len);
+ if (ret != EOK) {
+ return EINVAL;
+ }
+
+ rd.len = inp_len + 1;
+ rd.data = inp.str;
+
+ break;
+ case SSS_NSS_GETSIDBYID:
+ rd.len = sizeof(uint32_t);
+ rd.data = &inp.id;
+
+ break;
+ default:
+ return EINVAL;
+ }
+
+ sss_nss_lock();
+
+ nret = sss_nss_make_request(cmd, &rd, &repbuf, &replen, &errnop);
+ if (nret != NSS_STATUS_SUCCESS) {
+ ret = nss_status_to_errno(nret);
+ goto done;
+ }
+
+ if (replen < 8) {
+ ret = EBADMSG;
+ goto done;
+ }
+
+ num_results = ((uint32_t *)repbuf)[0];
+ if (num_results == 0) {
+ ret = ENOENT;
+ goto done;
+ } else if (num_results > 1) {
+ ret = EBADMSG;
+ goto done;
+ }
+
+ out->type = ((uint32_t *)repbuf)[2];
+
+ data_len = replen - DATA_START;
+
+ switch(cmd) {
+ case SSS_NSS_GETSIDBYID:
+ case SSS_NSS_GETSIDBYNAME:
+ case SSS_NSS_GETNAMEBYSID:
+ if (data_len <= 1 || repbuf[replen - 1] != '\0') {
+ ret = EBADMSG;
+ goto done;
+ }
+
+ str = malloc(sizeof(char) * data_len);
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ strncpy(str, (char *) repbuf + DATA_START, data_len);
+
+ out->d.str = str;
+
+ break;
+ case SSS_NSS_GETIDBYSID:
+ if (data_len != sizeof(uint32_t)) {
+ ret = EBADMSG;
+ goto done;
+ }
+
+ SAFEALIGN_COPY_UINT32(&c, repbuf + DATA_START, NULL);
+ out->d.id = c;
+
+ break;
+ default:
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ sss_nss_unlock();
+ free(repbuf);
+ if (ret != EOK) {
+ free(str);
+ }
+
+ return ret;
+}
+
+int sss_nss_getsidbyname(const char *fq_name, char **sid,
+ enum sss_id_type *type)
+{
+ int ret;
+ union input inp;
+ struct output out;
+
+ if (sid == NULL || fq_name == NULL || *fq_name == '\0') {
+ return EINVAL;
+ }
+
+ inp.str = fq_name;
+
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYNAME, &out);
+ if (ret == EOK) {
+ *sid = out.d.str;
+ *type = out.type;
+ }
+
+ return ret;
+}
+
+int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
+{
+ int ret;
+ union input inp;
+ struct output out;
+
+ if (sid == NULL) {
+ return EINVAL;
+ }
+
+ inp.id = id;
+
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYID, &out);
+ if (ret == EOK) {
+ *sid = out.d.str;
+ *type = out.type;
+ }
+
+ return ret;
+}
+
+int sss_nss_getnamebysid(const char *sid, char **fq_name,
+ enum sss_id_type *type)
+{
+ int ret;
+ union input inp;
+ struct output out;
+
+ if (fq_name == NULL || sid == NULL || *sid == '\0') {
+ return EINVAL;
+ }
+
+ inp.str = sid;
+
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYSID, &out);
+ if (ret == EOK) {
+ *fq_name = out.d.str;
+ *type = out.type;
+ }
+
+ return ret;
+}
+
+int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
+{
+ int ret;
+ union input inp;
+ struct output out;
+
+ if (id == NULL || id_type == NULL || sid == NULL || *sid == '\0') {
+ return EINVAL;
+ }
+
+ inp.str = sid;
+
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETIDBYSID, &out);
+ if (ret == EOK) {
+ *id = out.d.id;
+ *id_type = out.type;
+ }
+
+ return ret;
+}