summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2014-10-09 21:05:34 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-10-14 18:29:11 +0200
commit0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47e (patch)
treefb81c6e36a8565cf5d9d311036e6395c6a0f84d1 /src
parent229c292143dcd4120acb022682b5b7d0aca622dd (diff)
downloadsssd-0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47e.tar.gz
sssd-0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47e.tar.xz
sssd-0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47e.zip
sss_nss_idmap: add sss_nss_getorigbyname()
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 <pbrezina@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/sss_client/idmap/sss_nss_idmap.c113
-rw-r--r--src/sss_client/idmap/sss_nss_idmap.exports7
-rw-r--r--src/sss_client/idmap/sss_nss_idmap.h32
-rw-r--r--src/tests/cmocka/sss_nss_idmap-tests.c26
4 files changed, 177 insertions, 1 deletions
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;
@@ -153,6 +235,15 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
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;
goto done;
@@ -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_ */
diff --git a/src/tests/cmocka/sss_nss_idmap-tests.c b/src/tests/cmocka/sss_nss_idmap-tests.c
index 034f3a1ec..4141a3279 100644
--- a/src/tests/cmocka/sss_nss_idmap-tests.c
+++ b/src/tests/cmocka/sss_nss_idmap-tests.c
@@ -46,6 +46,9 @@ uint8_t buf1[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x
uint8_t buf2[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 0x00};
uint8_t buf3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 0x00};
uint8_t buf4[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 'x'};
+
+uint8_t buf_orig1[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 'k', 'e', 'y', 0x00, 'v', 'a', 'l', 'u', 'e', 0x00};
+
enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
struct sss_cli_req_data *rd,
uint8_t **repbuf, size_t *replen,
@@ -68,7 +71,8 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
return d->nss_status;
}
-void test_getsidbyname(void **state) {
+void test_getsidbyname(void **state)
+{
int ret;
char *sid = NULL;
size_t c;
@@ -111,11 +115,31 @@ void test_getsidbyname(void **state) {
}
}
+void test_getorigbyname(void **state)
+{
+ int ret;
+ struct sss_nss_kv *kv_list;
+ enum sss_id_type type;
+ struct sss_nss_make_request_test_data d = {buf_orig1, sizeof(buf_orig1), 0, NSS_STATUS_SUCCESS};
+
+ will_return(sss_nss_make_request, &d);
+ ret = sss_nss_getorigbyname("test", &kv_list, &type);
+ assert_int_equal(ret, EOK);
+ assert_int_equal(type, SSS_ID_TYPE_UID);
+ assert_string_equal(kv_list[0].key, "key");
+ assert_string_equal(kv_list[0].value, "value");
+ assert_null(kv_list[1].key);
+ assert_null(kv_list[1].value);
+
+ sss_nss_free_kv(kv_list);
+}
+
int main(int argc, const char *argv[])
{
const UnitTest tests[] = {
unit_test(test_getsidbyname),
+ unit_test(test_getorigbyname),
};
return run_tests(tests);