/* SSSD NSS Responder Interface for ID-SID mappings Authors: Sumit Bose 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 . */ #include #include #include #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; }