usertools.c revision 09a36be00ddcf1d7bd5b8a368143d5b2e2f4fb68
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/*
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch SSSD
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch User tools
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch This program is free software; you can redistribute it and/or modify
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch it under the terms of the GNU General Public License as published by
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch the Free Software Foundation; either version 3 of the License, or
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (at your option) any later version.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch This program is distributed in the hope that it will be useful,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch but WITHOUT ANY WARRANTY; without even the implied warranty of
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch GNU General Public License for more details.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch You should have received a copy of the GNU General Public License
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch along with this program. If not, see <http://www.gnu.org/licenses/>.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch*/
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <pwd.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <pcre.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <errno.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <talloc.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "confdb/confdb.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "util/util.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "util/safe-format-string.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "responder/common/responder.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#ifdef HAVE_LIBPCRE_LESSER_THAN_7
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_EXTENDED)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#else
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_DUPNAMES | PCRE_EXTENDED)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#endif
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch/* Function returns given realm name as new uppercase string */
7384b4e78eaab44693c985192276e31322155e32Stephan Boschchar *get_uppercase_realm(TALLOC_CTX *memctx, const char *name)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *realm;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *c;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch realm = talloc_strdup(memctx, name);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (!realm) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return NULL;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch c = realm;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch while(*c != '\0') {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch *c = toupper(*c);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch c++;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return realm;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int sss_names_ctx_destructor(struct sss_names_ctx *snctx)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (snctx->re) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch pcre_free(snctx->re);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch snctx->re = NULL;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#define IPA_AD_DEFAULT_RE "(((?P<domain>[^\\\\]+)\\\\(?P<name>.+$))|" \
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "((?P<name>[^@]+)@(?P<domain>.+$))|" \
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "(^(?P<name>[^@\\\\]+)$))"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic errno_t get_id_provider_default_re(TALLOC_CTX *mem_ctx,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct confdb_ctx *cdb,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *conf_path,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char **re_pattern)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#ifdef HAVE_LIBPCRE_LESSER_THAN_7
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen DEBUG(SSSDBG_MINOR_FAILURE,
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen "The libpcre version on this system is too old. Only "
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen "the user@DOMAIN name fully qualified name format will "
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen "be supported\n");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch *re_pattern = NULL;
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen return EOK;
30d917bcd48d70af0371baf27571cc198d621a62Timo Sirainen#else
9d0aee99a8c80d71137aa9b8c216cc203bec7a9aTimo Sirainen int ret;
9d0aee99a8c80d71137aa9b8c216cc203bec7a9aTimo Sirainen size_t c;
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen char *id_provider = NULL;
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen struct provider_default_re {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *name;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *re;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch } provider_default_re[] = {{"ipa", IPA_AD_DEFAULT_RE},
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch {"ad", IPA_AD_DEFAULT_RE},
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch {NULL, NULL}};
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ret = confdb_get_string(cdb, mem_ctx, conf_path, CONFDB_DOMAIN_ID_PROVIDER,
feba5e502b2131c9a1c766b7ef9ff041dbf71d1dStephan Bosch NULL, &id_provider);
a8c4e79ff50fac21b05a7368b052583d410ca15cTimo Sirainen if (ret != EOK) {
a8c4e79ff50fac21b05a7368b052583d410ca15cTimo Sirainen DEBUG(SSSDBG_OP_FAILURE, "Failed to read ID provider " \
70505f4839520ac67895992621c97d2480c22e7fTimo Sirainen "from conf db.\n");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch goto done;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (id_provider == NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch *re_pattern = NULL;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch } else {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch for (c = 0; provider_default_re[c].name != NULL; c++) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (strcmp(id_provider, provider_default_re[c].name) == 0) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch *re_pattern = talloc_strdup(mem_ctx, provider_default_re[c].re);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (*re_pattern == NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ret = ENOMEM;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch goto done;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
9dc01e0d10a61cab14867b26bf0d2d1dcf8ad978Timo Sirainen
9dc01e0d10a61cab14867b26bf0d2d1dcf8ad978Timo Sirainen ret = EOK;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschdone:
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch talloc_free(id_provider);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return ret;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#endif
aacf2a69acc59e9382578d6f4e030788abc79706Timo Sirainen}
aacf2a69acc59e9382578d6f4e030788abc79706Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic errno_t sss_fqnames_init(struct sss_names_ctx *nctx, const char *fq_fmt)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *fq;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch nctx->fq_fmt = talloc_strdup(nctx, fq_fmt);
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen if (nctx->fq_fmt == NULL) {
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen return ENOMEM;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch DEBUG(SSSDBG_CONF_SETTINGS, "Using fq format [%s].\n", nctx->fq_fmt);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* Fail if the name specifier is missing, or if the format is
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch * invalid */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch fq = sss_tc_fqname2 (nctx, nctx, "unused.example.com", "unused", "the-test-user");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (fq == NULL) {
636d0f43138468f8efe685a681326b123f660e49Timo Sirainen DEBUG(SSSDBG_OP_FAILURE,
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch "The fq format is invalid [%s]", nctx->fq_fmt);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return EINVAL;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch } else if (strstr (fq, "the-test-user") == NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch DEBUG(SSSDBG_OP_FAILURE,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Username pattern not found in [%s]\n", nctx->fq_fmt);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return ENOENT;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch talloc_free (fq);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return EOK;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschint sss_names_init_from_args(TALLOC_CTX *mem_ctx, const char *re_pattern,
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch const char *fq_fmt, struct sss_names_ctx **out)
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch{
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch struct sss_names_ctx *ctx;
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch const char *errstr;
636d0f43138468f8efe685a681326b123f660e49Timo Sirainen int errval;
636d0f43138468f8efe685a681326b123f660e49Timo Sirainen int errpos;
636d0f43138468f8efe685a681326b123f660e49Timo Sirainen int ret;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ctx = talloc_zero(mem_ctx, struct sss_names_ctx);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (!ctx) return ENOMEM;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch talloc_set_destructor(ctx, sss_names_ctx_destructor);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ctx->re_pattern = talloc_strdup(ctx, re_pattern);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (ctx->re_pattern == NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ret = ENOMEM;
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen goto done;
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen }
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch DEBUG(SSSDBG_CONF_SETTINGS, "Using re [%s].\n", ctx->re_pattern);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen ret = sss_fqnames_init(ctx, fq_fmt);
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen if (ret != EOK) {
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "Could not check the FQ names format"
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen "[%d]: %s\n", ret, sss_strerror(ret));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch goto done;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ctx->re = pcre_compile2(ctx->re_pattern,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch NAME_DOMAIN_PATTERN_OPTIONS,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch &errval, &errstr, &errpos, NULL);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (!ctx->re) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch DEBUG(SSSDBG_CRIT_FAILURE,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Invalid Regular Expression pattern at position %d."
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch " (Error: %d [%s])\n", errpos, errval, errstr);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ret = EFAULT;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch goto done;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch *out = ctx;
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainen ret = EOK;
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainen
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainendone:
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainen if (ret != EOK) {
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainen talloc_free(ctx);
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen }
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen return ret;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen}
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainenint sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen const char *domain, struct sss_names_ctx **out)
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen{
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen TALLOC_CTX *tmpctx = NULL;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen char *conf_path = NULL;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen char *re_pattern = NULL;;
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen char *fq_fmt = NULL;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen int ret;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen tmpctx = talloc_new(NULL);
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen if (tmpctx == NULL) {
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen ret = ENOMEM;
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen goto done;
d47b9f1bd7274c7b2d9049c2e1718d1cf89cc572Timo Sirainen }
d47b9f1bd7274c7b2d9049c2e1718d1cf89cc572Timo Sirainen
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen if (domain != NULL) {
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, domain);
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen if (conf_path == NULL) {
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen ret = ENOMEM;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen goto done;
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen }
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen ret = confdb_get_string(cdb, tmpctx, conf_path,
CONFDB_NAME_REGEX, NULL, &re_pattern);
if (ret != EOK) goto done;
}
/* If not found in the domain, look in globals */
if (re_pattern == NULL) {
ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
CONFDB_NAME_REGEX, NULL, &re_pattern);
if (ret != EOK) goto done;
}
if (re_pattern == NULL && conf_path != NULL) {
ret = get_id_provider_default_re(tmpctx, cdb, conf_path, &re_pattern);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to get provider default regular " \
"expression for domain [%s].\n", domain);
goto done;
}
}
if (!re_pattern) {
re_pattern = talloc_strdup(tmpctx,
"(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
if (!re_pattern) {
ret = ENOMEM;
goto done;
}
#ifdef HAVE_LIBPCRE_LESSER_THAN_7
} else {
DEBUG(SSSDBG_OP_FAILURE,
"This binary was build with a version of libpcre that does "
"not support non-unique named subpatterns.\n");
DEBUG(SSSDBG_OP_FAILURE,
"Please make sure that your pattern [%s] only contains "
"subpatterns with a unique name and uses "
"the Python syntax (?P<name>).\n", re_pattern);
#endif
}
if (conf_path != NULL) {
ret = confdb_get_string(cdb, tmpctx, conf_path,
CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
if (ret != EOK) goto done;
}
/* If not found in the domain, look in globals */
if (fq_fmt == NULL) {
ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
if (ret != EOK) goto done;
}
if (!fq_fmt) {
fq_fmt = talloc_strdup(tmpctx, CONFDB_DEFAULT_FULL_NAME_FORMAT);
if (!fq_fmt) {
ret = ENOMEM;
goto done;
}
}
ret = sss_names_init_from_args(mem_ctx, re_pattern, fq_fmt, out);
done:
talloc_free(tmpctx);
return ret;
}
int sss_parse_name(TALLOC_CTX *memctx,
struct sss_names_ctx *snctx,
const char *orig, char **_domain, char **_name)
{
pcre *re = snctx->re;
const char *result;
int ovec[30];
int origlen;
int ret, strnum;
origlen = strlen(orig);
ret = pcre_exec(re, NULL, orig, origlen, 0, PCRE_NOTEMPTY, ovec, 30);
if (ret == PCRE_ERROR_NOMATCH) {
return EINVAL;
} else if (ret < 0) {
DEBUG(SSSDBG_MINOR_FAILURE, "PCRE Matching error, %d\n", ret);
return EINVAL;
}
if (ret == 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Too many matches, the pattern is invalid.\n");
}
strnum = ret;
if (_name != NULL) {
result = NULL;
ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result);
if (ret < 0 || !result) {
DEBUG(SSSDBG_OP_FAILURE, "Name not found!\n");
return EINVAL;
}
*_name = talloc_strdup(memctx, result);
pcre_free_substring(result);
if (!*_name) return ENOMEM;
}
if (_domain != NULL) {
result = NULL;
ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain",
&result);
if (ret < 0 || !result) {
DEBUG(SSSDBG_CONF_SETTINGS, "Domain not provided!\n");
*_domain = NULL;
} else {
/* ignore "" string */
if (*result) {
*_domain = talloc_strdup(memctx, result);
pcre_free_substring(result);
if (!*_domain) return ENOMEM;
} else {
pcre_free_substring(result);
*_domain = NULL;
}
}
}
return EOK;
}
int sss_parse_name_const(TALLOC_CTX *memctx,
struct sss_names_ctx *snctx, const char *orig,
const char **_domain, const char **_name)
{
char *domain;
char *name;
int ret;
ret = sss_parse_name(memctx, snctx, orig,
(_domain == NULL) ? NULL : &domain,
(_name == NULL) ? NULL : &name);
if (ret == EOK) {
if (_domain != NULL) {
*_domain = domain;
}
if (_name != NULL) {
*_name = name;
}
}
return ret;
}
static struct sss_domain_info * match_any_domain_or_subdomain_name(
struct sss_domain_info *dom,
const char *dmatch)
{
if (strcasecmp(dom->name, dmatch) == 0 ||
(dom->flat_name != NULL && strcasecmp(dom->flat_name, dmatch) == 0)) {
return dom;
}
return find_domain_by_name(dom, dmatch, true);
}
int sss_parse_name_for_domains(TALLOC_CTX *memctx,
struct sss_domain_info *domains,
const char *default_domain,
const char *orig, char **domain, char **name)
{
struct sss_domain_info *dom, *match = NULL;
char *rdomain, *rname;
char *dmatch, *nmatch;
char *candidate_name = NULL;
char *candidate_domain = NULL;
bool name_mismatch = false;
TALLOC_CTX *tmp_ctx;
int ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
rname = NULL;
rdomain = NULL;
for (dom = domains; dom != NULL; dom = get_next_domain(dom, false)) {
ret = sss_parse_name(tmp_ctx, dom->names, orig, &dmatch, &nmatch);
if (ret == 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 (candidate_name == NULL) {
candidate_name = nmatch;
} else if (strcasecmp(candidate_name, nmatch) != 0) {
name_mismatch = 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, match->name, nmatch);
rdomain = talloc_strdup(tmp_ctx, match->name);
if (rdomain == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
rname = nmatch;
break;
} else if (candidate_domain == NULL) {
candidate_domain = dmatch;
}
}
/* EINVAL is returned when name doesn't match */
} else if (ret != EINVAL) {
goto done;
}
}
if (rdomain == NULL && rname == NULL) {
if (candidate_name && !name_mismatch) {
DEBUG(SSSDBG_FUNC_DATA, "name '%s' matched without domain, " \
"user is %s\n", orig, nmatch);
rdomain = NULL;
if (default_domain != NULL) {
rdomain = talloc_strdup(tmp_ctx, default_domain);
if (rdomain == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
for (dom = domains; dom != NULL; dom = get_next_domain(dom, false)) {
match = match_any_domain_or_subdomain_name(dom, rdomain);
if (match != NULL) {
break;
}
}
if (match == NULL) {
DEBUG(SSSDBG_FUNC_DATA, "default domain [%s] is currently " \
"not known, trying to look it up.\n",
rdomain);
*domain = talloc_steal(memctx, rdomain);
ret = EAGAIN;
goto done;
}
DEBUG(SSSDBG_FUNC_DATA, "using default domain [%s]\n", rdomain);
}
rname = candidate_name;
} else if (candidate_domain) {
/* This branch is taken when the input matches the configured
* regular expression, but the domain is now known. Normally, this
* is the case with a FQDN of a user from subdomain that was not
* yet discovered
*/
*domain = talloc_steal(memctx, candidate_domain);
ret = EAGAIN;
goto done;
}
}
if (rdomain == NULL && rname == NULL) {
DEBUG(SSSDBG_TRACE_FUNC,
"name '%s' did not match any domain's expression\n", orig);
ret = EINVAL;
goto done;
}
if (domain != NULL) {
*domain = talloc_steal(memctx, rdomain);
}
if (name != NULL) {
*name = talloc_steal(memctx, rname);
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
char *
sss_get_cased_name(TALLOC_CTX *mem_ctx,
const char *orig_name,
bool case_sensitive)
{
return case_sensitive ? talloc_strdup(mem_ctx, orig_name) :
sss_tc_utf8_str_tolower(mem_ctx, orig_name);
}
errno_t
sss_get_cased_name_list(TALLOC_CTX *mem_ctx, const char * const *orig,
bool case_sensitive, const char ***_cased)
{
const char **out;
size_t num, i;
if (orig == NULL) {
*_cased = NULL;
return EOK;
}
for (num=0; orig[num]; num++); /* count the num of strings */
if (num == 0) {
*_cased = NULL;
return EOK;
}
out = talloc_array(mem_ctx, const char *, num + 1);
if (out == NULL) {
return ENOMEM;
}
for (i = 0; i < num; i++) {
out[i] = sss_get_cased_name(out, orig[i], case_sensitive);
if (out[i] == NULL) {
talloc_free(out);
return ENOMEM;
}
}
out[num] = NULL;
*_cased = out;
return EOK;
}
static inline const char *
calc_flat_name(struct sss_domain_info *domain)
{
const char *s;
s = domain->flat_name;
if (s == NULL) {
DEBUG(SSSDBG_MINOR_FAILURE, "Flat name requested but domain has no"
"flat name set, falling back to domain name\n");
s = domain->name;
}
return s;
}
char *
sss_tc_fqname(TALLOC_CTX *mem_ctx, struct sss_names_ctx *nctx,
struct sss_domain_info *domain, const char *name)
{
if (domain == NULL || nctx == NULL) return NULL;
return sss_tc_fqname2 (mem_ctx, nctx, domain->name,
calc_flat_name (domain), name);
}
static void
safe_talloc_callback (void *data,
const char *piece,
size_t len)
{
char **output = data;
if (*output != NULL)
*output = talloc_strndup_append(*output, piece, len);
}
char *
sss_tc_fqname2(TALLOC_CTX *mem_ctx, struct sss_names_ctx *nctx,
const char *domain_name, const char *flat_dom_name,
const char *name)
{
const char *args[] = { name, domain_name, flat_dom_name, NULL };
char *output;
if (nctx == NULL) return NULL;
output = talloc_strdup(mem_ctx, "");
if (safe_format_string_cb(safe_talloc_callback, &output, nctx->fq_fmt, args, 3) < 0)
output = NULL;
else if (output == NULL)
errno = ENOMEM;
return output;
}
int
sss_fqname(char *str, size_t size, struct sss_names_ctx *nctx,
struct sss_domain_info *domain, const char *name)
{
if (domain == NULL || nctx == NULL) return -EINVAL;
return safe_format_string(str, size, nctx->fq_fmt,
name, domain->name, calc_flat_name (domain), NULL);
}
char *
sss_get_domain_name(TALLOC_CTX *mem_ctx,
const char *orig_name,
struct sss_domain_info *dom)
{
char *user_name;
char *domain = NULL;
int ret;
/* check if the name already contains domain part */
if (dom->names != NULL) {
ret = sss_parse_name(mem_ctx, dom->names, orig_name, &domain, NULL);
if (ret != EOK) {
return NULL;
}
}
if (IS_SUBDOMAIN(dom) && dom->fqnames && domain == NULL) {
/* we always use the fully qualified name for subdomain users */
user_name = sss_tc_fqname(mem_ctx, dom->names, dom, orig_name);
} else {
user_name = talloc_strdup(mem_ctx, orig_name);
}
talloc_free(domain);
return user_name;
}