diff options
author | Sumit Bose <sbose@redhat.com> | 2014-10-09 15:13:55 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-10-14 18:29:01 +0200 |
commit | 229c292143dcd4120acb022682b5b7d0aca622dd (patch) | |
tree | 98b85b3f54003042c8c7fb603a8faf164eb65f06 | |
parent | abee3216261e3378430e472f0c992470b33976f0 (diff) | |
download | sssd-229c292143dcd4120acb022682b5b7d0aca622dd.tar.gz sssd-229c292143dcd4120acb022682b5b7d0aca622dd.tar.xz sssd-229c292143dcd4120acb022682b5b7d0aca622dd.zip |
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.
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-rw-r--r-- | src/db/sysdb.h | 7 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 2 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 91 | ||||
-rw-r--r-- | src/sss_client/sss_cli.h | 7 | ||||
-rw-r--r-- | 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 03aac1524..c93119cf1 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 7eb7cffd8..e9e23561c 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 256c26b17..78ef1c5ad 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 edb520c8e..2d909311c 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 644468dbb..65298cdf0 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. */ |