From 0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47e Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 9 Oct 2014 21:05:34 +0200 Subject: sss_nss_idmap: add sss_nss_getorigbyname() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds an interface to the new SSS_NSS_GETORIGBYNAME request of the nss responder to libsss_nss_idmap. The main use case for this new call is to replace sss_nss_getsidbyname() in the extdom plugin on the FreeIPA server to get more information about the given object than just the SID which is not available with the default POSIX interfaces. Reviewed-by: Pavel Březina Reviewed-by: Lukáš Slebodník --- src/sss_client/idmap/sss_nss_idmap.c | 113 +++++++++++++++++++++++++++++ src/sss_client/idmap/sss_nss_idmap.exports | 7 ++ src/sss_client/idmap/sss_nss_idmap.h | 32 ++++++++ 3 files changed, 152 insertions(+) (limited to 'src/sss_client') diff --git a/src/sss_client/idmap/sss_nss_idmap.c b/src/sss_client/idmap/sss_nss_idmap.c index adb588975..55d8043bd 100644 --- a/src/sss_client/idmap/sss_nss_idmap.c +++ b/src/sss_client/idmap/sss_nss_idmap.c @@ -41,6 +41,7 @@ struct output { union { char *str; uint32_t id; + struct sss_nss_kv *kv_list; } d; }; @@ -58,6 +59,85 @@ int nss_status_to_errno(enum nss_status nret) { return EINVAL; } +void sss_nss_free_kv(struct sss_nss_kv *kv_list) +{ + size_t c; + + if (kv_list != NULL) { + for (c = 0; kv_list[c].key != NULL; c++) { + free(kv_list[c].key); + free(kv_list[c].value); + } + free(kv_list); + } +} + +static int buf_to_kv_list(uint8_t *buf, size_t buf_len, + struct sss_nss_kv **kv_list) +{ + size_t c; + size_t count = 0; + struct sss_nss_kv *list; + uint8_t *p; + int ret; + + for (c = 0; c < buf_len; c++) { + if (buf[c] == '\0') { + count++; + } + } + + if ((count % 2) != 0) { + return EINVAL; + } + count /= 2; + + list = calloc((count + 1), sizeof(struct sss_nss_kv)); + if (list == NULL) { + return ENOMEM; + } + + p = buf; + for (c = 0; c < count; c++) { + list[c].key = strdup((char *) p); + if (list[c].key == NULL) { + ret = ENOMEM; + goto done; + } + + p = memchr(p, '\0', buf_len - (p - buf)); + if (p == NULL) { + ret = EINVAL; + goto done; + } + p++; + + list[c].value = strdup((char *) p); + if (list[c].value == NULL) { + ret = ENOMEM; + goto done; + } + + p = memchr(p, '\0', buf_len - (p - buf)); + if (p == NULL) { + ret = EINVAL; + goto done; + } + p++; + } + + *kv_list = list; + + ret = EOK; + +done: + if (ret != EOK) { + sss_nss_free_kv(list); + } + + return ret; +} + static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , struct output *out) { @@ -72,11 +152,13 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , char *str = NULL; size_t data_len; uint32_t c; + struct sss_nss_kv *kv_list; switch (cmd) { case SSS_NSS_GETSIDBYNAME: case SSS_NSS_GETNAMEBYSID: case SSS_NSS_GETIDBYSID: + case SSS_NSS_GETORIGBYNAME: ret = sss_strnlen(inp.str, SSS_NAME_MAX, &inp_len); if (ret != EOK) { return EINVAL; @@ -152,6 +234,15 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , SAFEALIGN_COPY_UINT32(&c, repbuf + DATA_START, NULL); out->d.id = c; + break; + case SSS_NSS_GETORIGBYNAME: + ret = buf_to_kv_list(repbuf + DATA_START, data_len, &kv_list); + if (ret != EOK) { + goto done; + } + + out->d.kv_list = kv_list; + break; default: ret = EINVAL; @@ -255,3 +346,25 @@ int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type) return ret; } + +int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list, + enum sss_id_type *type) +{ + int ret; + union input inp; + struct output out; + + if (kv_list == NULL || fq_name == NULL || *fq_name == '\0') { + return EINVAL; + } + + inp.str = fq_name; + + ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETORIGBYNAME, &out); + if (ret == EOK) { + *kv_list = out.d.kv_list; + *type = out.type; + } + + return ret; +} diff --git a/src/sss_client/idmap/sss_nss_idmap.exports b/src/sss_client/idmap/sss_nss_idmap.exports index 7b8488b2a..8aa470241 100644 --- a/src/sss_client/idmap/sss_nss_idmap.exports +++ b/src/sss_client/idmap/sss_nss_idmap.exports @@ -12,3 +12,10 @@ SSS_NSS_IDMAP_0.0.1 { local: *; }; + +SSS_NSS_IDMAP_0.1.0 { + # public functions + global: + sss_nss_getorigbyname; + sss_nss_free_kv; +} SSS_NSS_IDMAP_0.0.1; diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h index 79dacfbdb..78a8a11c1 100644 --- a/src/sss_client/idmap/sss_nss_idmap.h +++ b/src/sss_client/idmap/sss_nss_idmap.h @@ -37,6 +37,11 @@ enum sss_id_type { SSS_ID_TYPE_BOTH /* used for user or magic private groups */ }; +struct sss_nss_kv { + char *key; + char *value; +}; + /** * @brief Find SID by fully qualified name * @@ -97,4 +102,31 @@ int sss_nss_getnamebysid(const char *sid, char **fq_name, int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type); +/** + * @brief Find original data by fully qualified name + * + * @param[in] fq_name Fully qualified name of a user or a group + * @param[out] kv_list A NULL terminate list of key-value pairs where the key + * is the attribute name in the cache of SSSD, + * must be freed by the caller with sss_nss_free_kv() + * @param[out] type Type of the object related to the given name + * + * @return + * - 0 (EOK): success, sid contains the requested SID + * - ENOENT: requested object was not found in the domain extracted from the given name + * - ENETUNREACH: SSSD does not know how to handle the domain extracted from the given name + * - ENOSYS: this call is not supported by the configured provider + * - EINVAL: input cannot be parsed + * - EIO: remote servers cannot be reached + * - EFAULT: any other error + */ +int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list, + enum sss_id_type *type); + +/** + * @brief Free key-value list returned by sss_nss_getorigbyname() + * + * @param[in] kv_list Key-value list returned by sss_nss_getorigbyname(). + */ +void sss_nss_free_kv(struct sss_nss_kv *kv_list); #endif /* SSS_NSS_IDMAP_H_ */ -- cgit