From 3c60433641ce2e86b9b04778c8f8652ef0d097e4 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 11 Apr 2012 15:02:10 +0200 Subject: Make re_expression and full_name_format per domain options * Allows different user/domain qualified names for different domains. For example Domain\User or user@domain. * The global re_expression and full_name_format options remain as defaults for the domains. * Subdomains get the re_expression and full_name_format of their parent domain. https://bugzilla.redhat.com/show_bug.cgi?id=811663 --- src/confdb/confdb.h | 7 +- src/man/sssd.conf.5.xml | 67 +++++++++++---- src/responder/autofs/autofssrv_cmd.c | 4 +- src/responder/common/negcache.c | 15 ++-- src/responder/common/negcache.h | 1 - src/responder/common/responder.h | 6 +- src/responder/common/responder_common.c | 14 +-- src/responder/nss/nsssrv.c | 3 +- src/responder/nss/nsssrv_cmd.c | 22 +++-- src/responder/nss/nsssrv_netgroup.c | 4 +- src/responder/nss/nsssrv_services.c | 12 ++- src/responder/pam/pamsrv.c | 3 +- src/responder/pam/pamsrv_cmd.c | 20 ++--- src/responder/ssh/sshsrv_cmd.c | 4 +- src/responder/sudo/sudosrv_cmd.c | 4 +- src/tools/tools_util.c | 2 +- src/util/domain_info_utils.c | 1 + src/util/usertools.c | 145 ++++++++++++++++++++++++++++++-- src/util/util.h | 1 + 19 files changed, 252 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 5893897f9..db247b184 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -63,11 +63,13 @@ #define CONFDB_MONITOR_SBUS_TIMEOUT "sbus_timeout" #define CONFDB_MONITOR_ACTIVE_SERVICES "services" #define CONFDB_MONITOR_ACTIVE_DOMAINS "domains" -#define CONFDB_MONITOR_NAME_REGEX "re_expression" -#define CONFDB_MONITOR_FULL_NAME_FORMAT "full_name_format" #define CONFDB_MONITOR_TRY_INOTIFY "try_inotify" #define CONFDB_MONITOR_KRB5_RCACHEDIR "krb5_rcache_dir" +/* Both monitor and domains */ +#define CONFDB_NAME_REGEX "re_expression" +#define CONFDB_FULL_NAME_FORMAT "full_name_format" + /* Responders */ #define CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT "get_domains_timeout" @@ -207,6 +209,7 @@ struct sss_domain_info { int pwd_expiration_warning; struct sysdb_ctx *sysdb; + struct sss_names_ctx *names; struct sss_domain_info **subdomains; uint32_t subdomain_count; diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index c946c6e1f..4e38ffe6d 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -122,25 +122,12 @@ re_expression (string) - Regular expression that describes how to parse the string + Default regular expression that describes how to parse the string containing user name and domain into these components. - Default: (?P<name>[^@]+)@?(?P<domain>[^@]*$) - which translates to "the name is everything up to the - @ sign, the domain everything after that" - - - PLEASE NOTE: the support for non-unique named - subpatterns is not available on all platforms - (e.g. RHEL5 and SLES10). Only platforms with - libpcre version 7 or higher can support non-unique - named subpatterns. - - - PLEASE NOTE ALSO: older version of libpcre only - support the Python syntax (?P<name>) to label - subpatterns. + Each domain can have an individual regular expression configured. + see DOMAIN SECTIONS for more info on these regular expressions. @@ -148,7 +135,7 @@ full_name_format (string) - A + The default printf 3 -compatible format that describes how to @@ -156,7 +143,8 @@ name. - Default: %1$s@%2$s. + Each domain can have an individual format string configured. + see DOMAIN SECTIONS for more info on this option. @@ -1286,6 +1274,49 @@ + + re_expression (string) + + + Regular expression for this domain that describes how to parse + the string containing user name and domain into these components. + + + Default: (?P<name>[^@]+)@?(?P<domain>[^@]*$) + which translates to "the name is everything up to the + @ sign, the domain everything after that" + + + PLEASE NOTE: the support for non-unique named + subpatterns is not available on all platforms + (e.g. RHEL5 and SLES10). Only platforms with + libpcre version 7 or higher can support non-unique + named subpatterns. + + + PLEASE NOTE ALSO: older version of libpcre only + support the Python syntax (?P<name>) to label + subpatterns. + + + + + full_name_format (string) + + + A + printf + 3 + -compatible format that describes how to + translate a (name, domain) tuple for this domain into a fully + qualified name. + + + Default: %1$s@%2$s. + + + + lookup_family_order (string) diff --git a/src/responder/autofs/autofssrv_cmd.c b/src/responder/autofs/autofssrv_cmd.c index 7064591ab..4dfa94e40 100644 --- a/src/responder/autofs/autofssrv_cmd.c +++ b/src/responder/autofs/autofssrv_cmd.c @@ -374,8 +374,8 @@ setautomntent_send(TALLOC_CTX *mem_ctx, dctx->cmd_ctx = state->cmdctx; state->dctx = dctx; - ret = sss_parse_name(state, client->rctx->names, rawname, - &domname, &state->mapname); + ret = sss_parse_name_for_domains(state, client->rctx->domains, rawname, + &domname, &state->mapname); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, ("Invalid name received [%s]\n", rawname)); diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c index dd4c0008a..b59b1f341 100644 --- a/src/responder/common/negcache.c +++ b/src/responder/common/negcache.c @@ -565,7 +565,6 @@ int sss_ncache_reset_permament(struct sss_nc_ctx *ctx) errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, struct confdb_ctx *cdb, - struct sss_names_ctx *names_ctx, struct resp_ctx *rctx) { errno_t ret; @@ -597,8 +596,8 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, filter_set = true; for (i = 0; (filter_list && filter_list[i]); i++) { - ret = sss_parse_name(tmpctx, names_ctx, filter_list[i], - &domainname, &name); + ret = sss_parse_name_for_domains(tmpctx, domain_list, filter_list[i], + &domainname, &name); if (ret != EOK) { DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n", filter_list[i], ret)); @@ -642,8 +641,8 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, else if (ret != EOK) goto done; for (i = 0; (filter_list && filter_list[i]); i++) { - ret = sss_parse_name(tmpctx, names_ctx, filter_list[i], - &domainname, &name); + ret = sss_parse_name_for_domains(tmpctx, domain_list, filter_list[i], + &domainname, &name); if (ret != EOK) { DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n", filter_list[i], ret)); @@ -694,7 +693,7 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, filter_set = true; for (i = 0; (filter_list && filter_list[i]); i++) { - ret = sss_parse_name(tmpctx, names_ctx, filter_list[i], + ret = sss_parse_name(tmpctx, dom->names, filter_list[i], &domainname, &name); if (ret != EOK) { DEBUG(1, ("Invalid name in filterGroups list: [%s] (%d)\n", @@ -739,8 +738,8 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, else if (ret != EOK) goto done; for (i = 0; (filter_list && filter_list[i]); i++) { - ret = sss_parse_name(tmpctx, names_ctx, filter_list[i], - &domainname, &name); + ret = sss_parse_name_for_domains(tmpctx, domain_list, filter_list[i], + &domainname, &name); if (ret != EOK) { DEBUG(1, ("Invalid name in filterGroups list: [%s] (%d)\n", filter_list[i], ret)); diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h index 9d070c697..b2e6a7a91 100644 --- a/src/responder/common/negcache.h +++ b/src/responder/common/negcache.h @@ -72,7 +72,6 @@ int sss_ncache_reset_permament(struct sss_nc_ctx *ctx); */ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, struct confdb_ctx *cdb, - struct sss_names_ctx *names_ctx, struct resp_ctx *rctx); #endif /* _NSS_NEG_CACHE_H_ */ diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 27a58eae5..2cc85445c 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -93,8 +93,6 @@ struct resp_ctx { const char *sss_pipe_name; const char *confdb_service_path; - struct sss_names_ctx *names; - hash_table_t *dp_request_table; struct timeval get_domains_last_call; @@ -154,6 +152,10 @@ int sss_parse_name(TALLOC_CTX *memctx, struct sss_names_ctx *snctx, const char *orig, char **domain, char **name); +int sss_parse_name_for_domains(TALLOC_CTX *memctx, + struct sss_domain_info *domains, + const char *orig, char **domain, char **name); + int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain, struct be_conn **_conn); struct sss_domain_info * diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index faff0febd..2e3e98a9c 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -581,6 +581,14 @@ int sss_process_init(TALLOC_CTX *mem_ctx, continue; } + ret = sss_names_init(rctx->cdb, rctx->cdb, dom->name, &dom->names); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("fatal error initializing regex data for domain: %s\n", + dom->name)); + return ret; + } + ret = sss_dp_init(rctx, dp_intf, cli_name, dom); if (ret != EOK) { DEBUG(0, ("fatal error setting up backend connector\n")); @@ -594,12 +602,6 @@ int sss_process_init(TALLOC_CTX *mem_ctx, return ret; } - ret = sss_names_init(rctx, rctx->cdb, &rctx->names); - if (ret != EOK) { - DEBUG(0, ("fatal error initializing regex data\n")); - return ret; - } - /* after all initializations we are ready to listen on our socket */ ret = set_unix_socket(rctx); if (ret != EOK) { diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c index 85bf6dc82..622538046 100644 --- a/src/responder/nss/nsssrv.c +++ b/src/responder/nss/nsssrv.c @@ -162,8 +162,7 @@ static int nss_get_config(struct nss_ctx *nctx, nctx->cache_refresh_percent = 0; } - ret = sss_ncache_prepopulate(nctx->ncache, cdb, nctx->rctx->names, - nctx->rctx); + ret = sss_ncache_prepopulate(nctx->ncache, cdb, nctx->rctx); if (ret != EOK) { goto done; } diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 9f2864445..fc504700c 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -235,11 +235,13 @@ static int fill_pwent(struct sss_packet *packet, int i, ret, num, t; bool add_domain = dom->fqnames; const char *domain = dom->name; - const char *namefmt = nctx->rctx->names->fq_fmt; + const char *namefmt; bool packet_initialized = false; int ncret; TALLOC_CTX *tmp_ctx = NULL; + namefmt = dom->names->fq_fmt; + if (add_domain) dom_len = strlen(domain); to_sized_string(&pwfield, nctx->pwfield); @@ -794,8 +796,8 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) rawname = (const char *)body; domname = NULL; - ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname, - &domname, &cmdctx->name); + ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname, + &domname, &cmdctx->name); if (ret != EOK) { DEBUG(2, ("Invalid name received [%s]\n", rawname)); ret = ENOENT; @@ -1681,7 +1683,7 @@ static int fill_members(struct sss_packet *packet, size_t rsize = *_rsize; char *tmpstr; struct sized_string name; - const char *namefmt = nctx->rctx->names->fq_fmt; + const char *namefmt = dom->names->fq_fmt; TALLOC_CTX *tmp_ctx = NULL; size_t delim; @@ -1820,9 +1822,11 @@ static int fill_grent(struct sss_packet *packet, size_t rzero, rsize; bool add_domain = dom->fqnames; const char *domain = dom->name; - const char *namefmt = nctx->rctx->names->fq_fmt; + const char *namefmt; TALLOC_CTX *tmp_ctx = NULL; + namefmt = dom->names->fq_fmt; + if (add_domain) { delim = 1; dom_len = strlen(domain); @@ -2258,8 +2262,8 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) rawname = (const char *)body; domname = NULL; - ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname, - &domname, &cmdctx->name); + ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname, + &domname, &cmdctx->name); if (ret != EOK) { DEBUG(2, ("Invalid name received [%s]\n", rawname)); ret = ENOENT; @@ -3368,8 +3372,8 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) rawname = (const char *)body; domname = NULL; - ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname, - &domname, &cmdctx->name); + ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname, + &domname, &cmdctx->name); if (ret != EOK) { DEBUG(2, ("Invalid name received [%s]\n", rawname)); ret = ENOENT; diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c index 593b7e435..774d182bd 100644 --- a/src/responder/nss/nsssrv_netgroup.c +++ b/src/responder/nss/nsssrv_netgroup.c @@ -197,8 +197,8 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, dctx = state->dctx; dctx->cmdctx = state->cmdctx; - ret = sss_parse_name(state, client->rctx->names, rawname, - &domname, &state->netgr_shortname); + ret = sss_parse_name_for_domains(state, client->rctx->domains, rawname, + &domname, &state->netgr_shortname); if (ret != EOK) { DEBUG(2, ("Invalid name received [%s]\n", rawname)); goto error; diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c index 2e539f135..e0ee21c30 100644 --- a/src/responder/nss/nsssrv_services.c +++ b/src/responder/nss/nsssrv_services.c @@ -779,7 +779,7 @@ done: errno_t parse_getservbyname(TALLOC_CTX *mem_ctx, uint8_t *body, size_t blen, - struct sss_names_ctx *names, + struct sss_domain_info *domains, char **domain_name, char **service_name, char **service_protocol); @@ -820,7 +820,7 @@ int nss_cmd_getservbyname(struct cli_ctx *cctx) } ret = parse_getservbyname(cmdctx, body, blen, - cctx->rctx->names, + cctx->rctx->domains, &domname, &service_name, &service_protocol); @@ -870,7 +870,7 @@ done: errno_t parse_getservbyname(TALLOC_CTX *mem_ctx, uint8_t *body, size_t blen, - struct sss_names_ctx *names, + struct sss_domain_info *domains, char **domain_name, char **service_name, char **service_protocol) @@ -959,8 +959,8 @@ errno_t parse_getservbyname(TALLOC_CTX *mem_ctx, } } - ret = sss_parse_name(tmp_ctx, names, rawname, - &domname, &svc_name); + ret = sss_parse_name_for_domains(tmp_ctx, domains, rawname, + &domname, &svc_name); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("Could not split name and domain of [%s]\n", @@ -1034,7 +1034,6 @@ nss_cmd_getserv_done(struct tevent_req *req) errno_t parse_getservbyport(TALLOC_CTX *mem_ctx, uint8_t *body, size_t blen, - struct sss_names_ctx *names, uint16_t *service_port, char **service_protocol) { @@ -1138,7 +1137,6 @@ int nss_cmd_getservbyport(struct cli_ctx *cctx) } ret = parse_getservbyport(cmdctx, body, blen, - cctx->rctx->names, &port, &service_protocol); if (ret != EOK) { diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c index ecbf7d9a5..c94596c4c 100644 --- a/src/responder/pam/pamsrv.c +++ b/src/responder/pam/pamsrv.c @@ -171,8 +171,7 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, goto done; } - ret = sss_ncache_prepopulate(pctx->ncache, cdb, pctx->rctx->names, - pctx->rctx); + ret = sss_ncache_prepopulate(pctx->ncache, cdb, pctx->rctx); if (ret != EOK) { goto done; } diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index f1fdc3f0d..f6c1e8350 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -115,7 +115,7 @@ static int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd return EOK; } -static int pam_parse_in_data_v2(struct sss_names_ctx *snctx, +static int pam_parse_in_data_v2(struct sss_domain_info *domains, struct pam_data *pd, uint8_t *body, size_t blen) { @@ -153,8 +153,8 @@ static int pam_parse_in_data_v2(struct sss_names_ctx *snctx, ret = extract_string(&pam_user, size, body, blen, &c); if (ret != EOK) return ret; - ret = sss_parse_name(pd, snctx, pam_user, - &pd->domain, &pd->user); + ret = sss_parse_name_for_domains(pd, domains, pam_user, + &pd->domain, &pd->user); if (ret != EOK) return ret; break; case SSS_PAM_ITEM_SERVICE: @@ -205,13 +205,13 @@ static int pam_parse_in_data_v2(struct sss_names_ctx *snctx, } -static int pam_parse_in_data_v3(struct sss_names_ctx *snctx, +static int pam_parse_in_data_v3(struct sss_domain_info *domains, struct pam_data *pd, uint8_t *body, size_t blen) { int ret; - ret = pam_parse_in_data_v2(snctx, pd, body, blen); + ret = pam_parse_in_data_v2(domains, pd, body, blen); if (ret != EOK) { DEBUG(1, ("pam_parse_in_data_v2 failed.\n")); return ret; @@ -225,7 +225,7 @@ static int pam_parse_in_data_v3(struct sss_names_ctx *snctx, return EOK; } -static int pam_parse_in_data(struct sss_names_ctx *snctx, +static int pam_parse_in_data(struct sss_domain_info *domains, struct pam_data *pd, uint8_t *body, size_t blen) { @@ -241,7 +241,7 @@ static int pam_parse_in_data(struct sss_names_ctx *snctx, for (start = end; end < last; end++) if (body[end] == '\0') break; if (body[end++] != '\0') return EINVAL; - ret = sss_parse_name(pd, snctx, (char *)&body[start], &pd->domain, &pd->user); + ret = sss_parse_name_for_domains(pd, domains, (char *)&body[start], &pd->domain, &pd->user); if (ret != EOK) return ret; for (start = end; end < last; end++) if (body[end] == '\0') break; @@ -891,13 +891,13 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) switch (cctx->cli_protocol_version->version) { case 1: - ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen); + ret = pam_parse_in_data(cctx->rctx->domains, pd, body, blen); break; case 2: - ret = pam_parse_in_data_v2(cctx->rctx->names, pd, body, blen); + ret = pam_parse_in_data_v2(cctx->rctx->domains, pd, body, blen); break; case 3: - ret = pam_parse_in_data_v3(cctx->rctx->names, pd, body, blen); + ret = pam_parse_in_data_v3(cctx->rctx->domains, pd, body, blen); break; default: DEBUG(1, ("Illegal protocol version [%d].\n", diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c index fa02025e8..3c67fd4e9 100644 --- a/src/responder/ssh/sshsrv_cmd.c +++ b/src/responder/ssh/sshsrv_cmd.c @@ -704,8 +704,8 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx) } c += name_len; - ret = sss_parse_name(cmd_ctx, cctx->rctx->names, name, - &cmd_ctx->domname, &cmd_ctx->name); + ret = sss_parse_name_for_domains(cmd_ctx, cctx->rctx->domains, name, + &cmd_ctx->domname, &cmd_ctx->name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", name)); return ENOENT; diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c index 0f31df15a..f72e2be7b 100644 --- a/src/responder/sudo/sudosrv_cmd.c +++ b/src/responder/sudo/sudosrv_cmd.c @@ -214,8 +214,8 @@ static int sudosrv_cmd_get_sudorules(struct cli_ctx *cli_ctx) } domname = NULL; - ret = sss_parse_name(cmd_ctx, cli_ctx->rctx->names, rawname, - &domname, &cmd_ctx->username); + ret = sss_parse_name_for_domains(cmd_ctx, cli_ctx->rctx->domains, rawname, + &domname, &cmd_ctx->username); if (ret != EOK) { DEBUG(2, ("Invalid name received [%s]\n", rawname)); ret = ENOENT; diff --git a/src/tools/tools_util.c b/src/tools/tools_util.c index 871ba2b11..fbb1d81bd 100644 --- a/src/tools/tools_util.c +++ b/src/tools/tools_util.c @@ -268,7 +268,7 @@ int init_sss_tools(struct tools_ctx **_tctx) goto fini; } - ret = sss_names_init(tctx, tctx->confdb, &tctx->snctx); + ret = sss_names_init(tctx, tctx->confdb, tctx->local->name, &tctx->snctx); if (ret != EOK) { DEBUG(1, ("Could not set up parsing\n")); goto fini; diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c index 45f98d858..6eed835a9 100644 --- a/src/util/domain_info_utils.c +++ b/src/util/domain_info_utils.c @@ -85,6 +85,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, dom->netgroup_timeout = parent->netgroup_timeout; dom->service_timeout = parent->service_timeout; dom->override_homedir = parent->override_homedir; + dom->names = parent->names; dom->subdomain_homedir = parent->subdomain_homedir; diff --git a/src/util/usertools.c b/src/util/usertools.c index ff189e32f..7675585ea 100644 --- a/src/util/usertools.c +++ b/src/util/usertools.c @@ -54,10 +54,13 @@ static int sss_names_ctx_destructor(struct sss_names_ctx *snctx) return 0; } -int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, struct sss_names_ctx **out) +int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, + const char *domain, struct sss_names_ctx **out) { struct sss_names_ctx *ctx; + TALLOC_CTX *tmpctx = NULL; const char *errstr; + char *conf_path; int errval; int errpos; int ret; @@ -66,10 +69,26 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, struct sss_names if (!ctx) return ENOMEM; talloc_set_destructor(ctx, sss_names_ctx_destructor); - ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, - CONFDB_MONITOR_NAME_REGEX, NULL, &ctx->re_pattern); + tmpctx = talloc_new(NULL); + if (tmpctx == NULL) goto done; + + conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, domain); + if (conf_path == NULL) { + ret = ENOMEM; + goto done; + } + + ret = confdb_get_string(cdb, ctx, conf_path, + CONFDB_NAME_REGEX, NULL, &ctx->re_pattern); if (ret != EOK) goto done; + /* If not found in the domain, look in globals */ + if (ctx->re_pattern == NULL) { + ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, + CONFDB_NAME_REGEX, NULL, &ctx->re_pattern); + if (ret != EOK) goto done; + } + if (!ctx->re_pattern) { ctx->re_pattern = talloc_strdup(ctx, "(?P[^@]+)@?(?P[^@]*$)"); @@ -87,10 +106,17 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, struct sss_names #endif } - ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, - CONFDB_MONITOR_FULL_NAME_FORMAT, NULL, &ctx->fq_fmt); + ret = confdb_get_string(cdb, ctx, conf_path, + CONFDB_FULL_NAME_FORMAT, NULL, &ctx->fq_fmt); if (ret != EOK) goto done; + /* If not found in the domain, look in globals */ + if (ctx->fq_fmt == NULL) { + ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, + CONFDB_FULL_NAME_FORMAT, NULL, &ctx->fq_fmt); + if (ret != EOK) goto done; + } + if (!ctx->fq_fmt) { ctx->fq_fmt = talloc_strdup(ctx, "%1$s@%2$s"); if (!ctx->fq_fmt) { @@ -113,6 +139,7 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, struct sss_names ret = EOK; done: + talloc_free(tmpctx); if (ret != EOK) { talloc_free(ctx); } @@ -132,8 +159,10 @@ int sss_parse_name(TALLOC_CTX *memctx, origlen = strlen(orig); ret = pcre_exec(re, NULL, orig, origlen, 0, PCRE_NOTEMPTY, ovec, 30); - if (ret < 0) { - DEBUG(2, ("PCRE Matching error, %d\n", ret)); + if (ret == PCRE_ERROR_NOMATCH) { + return EINVAL; + } else if (ret < 0) { + DEBUG(SSSDBG_MINOR_FAILURE, ("PCRE Matching error, %d\n", ret)); return EINVAL; } @@ -174,6 +203,108 @@ int sss_parse_name(TALLOC_CTX *memctx, return EOK; } +static struct sss_domain_info * match_any_domain_or_subdomain_name ( + struct sss_domain_info *dom, const char *dmatch) +{ + uint32_t i; + + if (strcasecmp (dom->name, dmatch) == 0) + return dom; + + for (i = 0; i < dom->subdomain_count; i++) { + if (strcasecmp(dom->subdomains[i]->name, dmatch) == 0) { + return dom->subdomains[i]; + } + } + + return NULL; +} + +int sss_parse_name_for_domains(TALLOC_CTX *memctx, + struct sss_domain_info *domains, + const char *orig, char **domain, char **name) +{ + struct sss_domain_info *dom, *match; + char *rdomain, *rname; + char *dmatch, *nmatch; + char *only_name = NULL; + bool only_name_seen = false; + bool only_name_mismatch = false; + TALLOC_CTX *tmp_ctx; + int code; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) + return ENOMEM; + + rname = NULL; + rdomain = NULL; + + for (dom = domains; dom != NULL; dom = dom->next) { + code = sss_parse_name(tmp_ctx, dom->names, orig, &dmatch, &nmatch); + if (code == EOK) { + /* + * If the name matched without the domain part, make note of it. + * All the other domain expressions must agree on the domain-less + * name. + */ + if (dmatch == NULL) { + if (!only_name_seen) { + only_name = nmatch; + } else if (nmatch == NULL || only_name == NULL || + strcasecmp(only_name, nmatch) != 0) { + only_name_mismatch = true; + } + only_name_seen = true; + + /* + * If a domain was returned, then it must match the name of the + * domain that this expression was found on, or one of the + * subdomains. + */ + } else { + match = match_any_domain_or_subdomain_name (dom, dmatch); + if (match != NULL) { + DEBUG(SSSDBG_FUNC_DATA, ("name '%s' matched expression for " + "domain '%s', user is %s\n", + orig, dom->name, nmatch)); + rdomain = dmatch; + rname = nmatch; + break; + } + } + + /* EINVAL is returned when name doesn't match */ + } else if (code != EINVAL) { + talloc_free(tmp_ctx); + return code; + } + } + + if (rdomain == NULL && rname == NULL && + only_name_seen && !only_name_mismatch && only_name != NULL) { + DEBUG(SSSDBG_FUNC_DATA, + ("name '%s' matched without domain, user is %s\n", orig, nmatch)); + rdomain = NULL; + rname = only_name; + } + + if (rdomain != NULL) + *domain = talloc_steal(memctx, rdomain); + if (rname != NULL) + *name = talloc_steal(memctx, rname); + + talloc_free(tmp_ctx); + + if (rdomain == NULL && rname == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, + ("name '%s' did not match any domain's expression\n", orig)); + return EINVAL; + } + + return EOK; +} + char * sss_get_cased_name(TALLOC_CTX *mem_ctx, const char *orig_name, diff --git a/src/util/util.h b/src/util/util.h index 2912f899a..b51aebbd8 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -397,6 +397,7 @@ struct sss_names_ctx { int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, + const char *domain, struct sss_names_ctx **out); int sss_parse_name(TALLOC_CTX *memctx, -- cgit