[SSSD] [PATCHES] nss: add SSS_NSS_GETORIGBYNAME request

Sumit Bose sbose at redhat.com
Tue Oct 14 09:09:25 UTC 2014


Hi,

this patch adds a new interface to the nss responder which is similar to
SSS_NSS_GETSIDBYNAME but can return more information about the given
object than just the SID and which is not available with the POSIX
interface as well. As mentioned in the commit messages the main use case
is the extdom plugin on the FreeIPA server.

bye,
Sumit
-------------- next part --------------
From b986ab58a7f38771fbb860ca57c6ffd0a25917b9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 9 Oct 2014 15:13:55 +0200
Subject: [PATCH 1/2] nss: add SSS_NSS_GETORIGBYNAME request

This patch adds a new request to the nss responder which follows the
same flow as a SSS_NSSGETSIDBYNAME request but returns more data than
just the SID. The data is returned as pairs of \0-terminated strings
where the first string is the sysdb attribute name and the second the
corresponding value.

The main use case is on the FreeIPA server to make additional user and
group data available to the extdom plugin which then send this data to
SSSD running on FreeIPA clients.
---
 src/db/sysdb.h                  |  7 ++++
 src/providers/ldap/sdap.h       |  2 -
 src/responder/nss/nsssrv_cmd.c  | 91 ++++++++++++++++++++++++++++++++++++++++-
 src/sss_client/sss_cli.h        |  7 ++++
 src/tests/cmocka/test_nss_srv.c | 88 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 191 insertions(+), 4 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 03aac15..c93119c 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -138,6 +138,13 @@
 #define SYSDB_DOMAIN_ID "domainID"
 #define SYSDB_ID_RANGE_TYPE "idRangeType"
 
+#define ORIGINALAD_PREFIX "originalAD"
+#define OVERRIDE_PREFIX "override"
+#define SYSDB_DEFAULT_OVERRIDE_NAME "defaultOverrideName"
+
+#define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires"
+#define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl"
+
 #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)"
 
 #define SYSDB_UC "objectclass="SYSDB_USER_CLASS
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 7eb7cff..e9e2356 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -122,8 +122,6 @@ struct sdap_ppolicy_data {
 
 #define SYSDB_PWD_ATTRIBUTE "pwdAttribute"
 
-#define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires"
-#define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl"
 #define SYSDB_NDS_LOGIN_DISABLED "ndsLoginDisabled"
 #define SYSDB_NDS_LOGIN_EXPIRATION_TIME "ndsLoginExpirationTime"
 #define SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP "ndsLoginAllowedTimeMap"
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 256c26b..78ef1c5 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -982,6 +982,7 @@ static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min,
             case SSS_NSS_GETNAMEBYSID:
             case SSS_NSS_GETIDBYSID:
             case SSS_NSS_GETSIDBYNAME:
+            case SSS_NSS_GETORIGBYNAME:
             case SSS_NSS_GETSIDBYID:
                 ret = nss_cmd_getbysid_send_reply(dctx);
                 break;
@@ -1064,6 +1065,7 @@ static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min,
         }
         break;
     case SSS_NSS_GETSIDBYNAME:
+    case SSS_NSS_GETORIGBYNAME:
         ret = nss_cmd_getsidby_search(dctx);
         if (ret == EOK) {
             ret = nss_cmd_getbysid_send_reply(dctx);
@@ -1172,6 +1174,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx)
     case SSS_NSS_GETGRNAM:
     case SSS_NSS_INITGR:
     case SSS_NSS_GETSIDBYNAME:
+    case SSS_NSS_GETORIGBYNAME:
         break;
     default:
         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid command type [%d].\n", cmd);
@@ -1322,6 +1325,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx)
         }
         break;
     case SSS_NSS_GETSIDBYNAME:
+    case SSS_NSS_GETORIGBYNAME:
         ret = nss_cmd_getsidby_search(dctx);
         if (ret == EOK) {
             ret = nss_cmd_getbysid_send_reply(dctx);
@@ -1417,6 +1421,7 @@ static void nss_cmd_getbynam_done(struct tevent_req *req)
         }
         break;
     case SSS_NSS_GETSIDBYNAME:
+    case SSS_NSS_GETORIGBYNAME:
         ret = nss_cmd_getsidby_search(dctx);
         if (ret == EOK) {
             ret = nss_cmd_getbysid_send_reply(dctx);
@@ -3996,7 +4001,18 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
     struct nss_ctx *nctx;
     int ret;
     int err;
-    const char *attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR, NULL};
+    const char *attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR,
+                           ORIGINALAD_PREFIX SYSDB_NAME,
+                           ORIGINALAD_PREFIX SYSDB_UIDNUM,
+                           ORIGINALAD_PREFIX SYSDB_GIDNUM,
+                           ORIGINALAD_PREFIX SYSDB_GECOS,
+                           ORIGINALAD_PREFIX SYSDB_HOMEDIR,
+                           ORIGINALAD_PREFIX SYSDB_SHELL,
+                           SYSDB_UPN,
+                           SYSDB_DEFAULT_OVERRIDE_NAME,
+                           SYSDB_AD_ACCOUNT_EXPIRES,
+                           SYSDB_AD_USER_ACCOUNT_CONTROL,
+                           SYSDB_DEFAULT_ATTRS, NULL};
     bool user_found = false;
     bool group_found = false;
     struct ldb_message *msg = NULL;
@@ -4195,7 +4211,8 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
         }
 
         if (dctx->res->count == 0 && !dctx->check_provider) {
-            if (cmdctx->cmd == SSS_NSS_GETSIDBYNAME) {
+            if (cmdctx->cmd == SSS_NSS_GETSIDBYNAME
+                    || cmdctx->cmd == SSS_NSS_GETORIGBYNAME) {
                 ret = sss_ncache_set_user(nctx->ncache, false, dom, name);
                 if (ret != EOK) {
                     DEBUG(SSSDBG_MINOR_FAILURE,
@@ -4428,6 +4445,67 @@ static errno_t fill_sid(struct sss_packet *packet,
     return EOK;
 }
 
+static errno_t fill_orig(struct sss_packet *packet,
+                         enum sss_id_type id_type,
+                         struct ldb_message *msg)
+{
+    int ret;
+    const char *tmp_str;
+    uint8_t *body;
+    size_t blen;
+    size_t pctr = 0;
+    size_t c;
+    size_t sum;
+    const char *orig_attr_list[] = {SYSDB_SID_STR,
+                                    ORIGINALAD_PREFIX SYSDB_NAME,
+                                    ORIGINALAD_PREFIX SYSDB_UIDNUM,
+                                    ORIGINALAD_PREFIX SYSDB_GIDNUM,
+                                    ORIGINALAD_PREFIX SYSDB_HOMEDIR,
+                                    ORIGINALAD_PREFIX SYSDB_GECOS,
+                                    ORIGINALAD_PREFIX SYSDB_SHELL,
+                                    SYSDB_UPN,
+                                    SYSDB_DEFAULT_OVERRIDE_NAME,
+                                    SYSDB_AD_ACCOUNT_EXPIRES,
+                                    SYSDB_AD_USER_ACCOUNT_CONTROL,
+                                    NULL};
+    struct sized_string keys[sizeof(orig_attr_list)];
+    struct sized_string vals[sizeof(orig_attr_list)];
+
+    sum = 0;
+    for (c = 0; orig_attr_list[c] != NULL; c++) {
+        tmp_str = ldb_msg_find_attr_as_string(msg, orig_attr_list[c], NULL);
+        if (tmp_str != NULL) {
+            to_sized_string(&keys[c], orig_attr_list[c]);
+            sum += keys[c].len;
+            to_sized_string(&vals[c], tmp_str);
+            sum += vals[c].len;
+        } else {
+            vals[c].len = 0;
+        }
+    }
+
+    ret = sss_packet_grow(packet, sum +  3 * sizeof(uint32_t));
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+        return ret;
+    }
+
+    sss_packet_get_body(packet, &body, &blen);
+    SAFEALIGN_SETMEM_UINT32(body, 1, &pctr); /* Num results */
+    SAFEALIGN_SETMEM_UINT32(body + pctr, 0, &pctr); /* reserved */
+    SAFEALIGN_COPY_UINT32(body + pctr, &id_type, &pctr);
+    for (c = 0; orig_attr_list[c] != NULL; c++) {
+        if (vals[c].len != 0) {
+            memcpy(&body[pctr], keys[c].str, keys[c].len);
+            pctr+= keys[c].len;
+            memcpy(&body[pctr], vals[c].str, vals[c].len);
+            pctr+= vals[c].len;
+        }
+    }
+
+    return EOK;
+}
+
 static errno_t fill_name(struct sss_packet *packet,
                          struct sss_domain_info *dom,
                          enum sss_id_type id_type,
@@ -4572,6 +4650,9 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx)
     case SSS_NSS_GETSIDBYID:
         ret = fill_sid(cctx->creq->out, id_type, dctx->res->msgs[0]);
         break;
+    case SSS_NSS_GETORIGBYNAME:
+        ret = fill_orig(cctx->creq->out, id_type, dctx->res->msgs[0]);
+        break;
     default:
         DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type.\n");
         return EINVAL;
@@ -4774,6 +4855,11 @@ static int nss_cmd_getidbysid(struct cli_ctx *cctx)
     return nss_cmd_getbysid(SSS_NSS_GETIDBYSID, cctx);
 }
 
+static int nss_cmd_getorigbyname(struct cli_ctx *cctx)
+{
+    return nss_cmd_getbynam(SSS_NSS_GETORIGBYNAME, cctx);
+}
+
 struct cli_protocol_version *register_cli_protocol_version(void)
 {
     static struct cli_protocol_version nss_cli_protocol_version[] = {
@@ -4809,6 +4895,7 @@ static struct sss_cmd_table nss_cmds[] = {
     {SSS_NSS_GETSIDBYID, nss_cmd_getsidbyid},
     {SSS_NSS_GETNAMEBYSID, nss_cmd_getnamebysid},
     {SSS_NSS_GETIDBYSID, nss_cmd_getidbysid},
+    {SSS_NSS_GETORIGBYNAME, nss_cmd_getorigbyname},
     {SSS_CLI_NULL, NULL}
 };
 
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index edb520c..2d90931 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -244,6 +244,13 @@ SSS_NSS_GETIDBYSID   = 0x0114, /**< Takes the zero terminated string
                                     another unsigned 32bit integer value
                                     indicating the type (unknown, user, group,
                                     both) of the object. */
+SSS_NSS_GETORIGBYNAME = 0x0115, /**< Takes a zero terminated fully qualified
+                                     name and returns a list of zero
+                                     terminated strings with key-value pairs
+                                     where the first string is the key and
+                                     second the value. Hence the list should
+                                     have an even number of strings, if not
+                                     the whole list is invalid. */
 };
 
 /**
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 644468d..65298cd 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -1741,6 +1741,92 @@ void test_nss_well_known_getsidbyname_special(void **state)
     assert_int_equal(ret, EOK);
 }
 
+static int test_nss_getorigbyname_check(uint32_t status, uint8_t *body,
+                                        size_t blen)
+{
+    const char *s;
+    enum sss_id_type id_type;
+    size_t rp = 2 * sizeof(uint32_t);
+
+    assert_int_equal(status, EOK);
+
+    SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
+    assert_int_equal(id_type, SSS_ID_TYPE_UID);
+
+    /* Sequence of null terminated strings */
+    s = (char *) body+rp;
+    assert_string_equal(s, SYSDB_SID_STR);
+    rp += strlen(s) + 1;
+    assert_true(rp < blen);
+
+    s = (char *) body+rp;
+    assert_string_equal(s, "S-1-2-3-4");
+    rp += strlen(s) + 1;
+    assert_true(rp < blen);
+
+    s = (char *) body+rp;
+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
+    rp += strlen(s) + 1;
+    assert_true(rp < blen);
+
+    s = (char *) body+rp;
+    assert_string_equal(s, "orig_name");
+    rp += strlen(s) + 1;
+    assert_true(rp < blen);
+
+    s = (char *) body+rp;
+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
+    rp += strlen(s) + 1;
+    assert_true(rp < blen);
+
+    s = (char *) body+rp;
+    assert_string_equal(s, "1234");
+    rp += strlen(s) + 1;
+    assert_int_equal(rp, blen);
+
+    return EOK;
+}
+
+void test_nss_getorigbyname(void **state)
+{
+    errno_t ret;
+    struct sysdb_attrs *attrs;
+
+    attrs = sysdb_new_attrs(nss_test_ctx);
+    assert_non_null(attrs);
+
+    ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
+                                 "orig_name");
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
+    assert_int_equal(ret, EOK);
+
+    /* Prime the cache with a valid user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "testuserorig", 1234, 5689, "test user orig",
+                         "/home/testuserorig", "/bin/sh", NULL,
+                         attrs, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    mock_input_user_or_group("testuserorig");
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getorigbyname_check);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+}
+
 void nss_test_setup(void **state)
 {
     struct sss_test_conf_param params[] = {
@@ -1875,6 +1961,8 @@ int main(int argc, const char *argv[])
                                  nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_well_known_getsidbyname_special,
                                  nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getorigbyname,
+                                 nss_test_setup, nss_test_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.3.1

-------------- next part --------------
From f8500f00224e781b03ebab0ab396565e4c034489 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 9 Oct 2014 21:05:34 +0200
Subject: [PATCH 2/2] 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.
---
 src/sss_client/idmap/sss_nss_idmap.c       | 113 +++++++++++++++++++++++++++++
 src/sss_client/idmap/sss_nss_idmap.exports |   2 +
 src/sss_client/idmap/sss_nss_idmap.h       |  32 ++++++++
 src/tests/cmocka/sss_nss_idmap-tests.c     |  26 ++++++-
 4 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/src/sss_client/idmap/sss_nss_idmap.c b/src/sss_client/idmap/sss_nss_idmap.c
index adb5889..55d8043 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 7b8488b..ba340ca 100644
--- a/src/sss_client/idmap/sss_nss_idmap.exports
+++ b/src/sss_client/idmap/sss_nss_idmap.exports
@@ -7,6 +7,8 @@ SSS_NSS_IDMAP_0.0.1 {
         sss_nss_getsidbyid;
         sss_nss_getnamebysid;
         sss_nss_getidbysid;
+        sss_nss_getorigbyname;
+        sss_nss_free_kv;
 
     # everything else is local
     local:
diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h
index 79dacfb..78a8a11 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 034f3a1..4141a32 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);
-- 
1.8.3.1



More information about the sssd-devel mailing list