/* SSSD User tools Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <pwd.h> #include <pcre.h> #include <errno.h> #include <talloc.h> #include "confdb/confdb.h" #include "util/util.h" #ifdef HAVE_LIBPCRE_LESSER_THAN_7 #define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_EXTENDED) #else #define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_DUPNAMES | PCRE_EXTENDED) #endif char *get_username_from_uid(TALLOC_CTX *mem_ctx, uid_t uid) { char *username; struct passwd *pwd; pwd = getpwuid(uid); if (!pwd) return NULL; username = talloc_strdup(mem_ctx, pwd->pw_name); return username; } static int sss_names_ctx_destructor(struct sss_names_ctx *snctx) { if (snctx->re) { pcre_free(snctx->re); snctx->re = NULL; } return 0; } int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, struct sss_names_ctx **out) { struct sss_names_ctx *ctx; const char *errstr; int errval; int errpos; int ret; ctx = talloc_zero(mem_ctx, struct sss_names_ctx); 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); if (ret != EOK) goto done; if (!ctx->re_pattern) { ctx->re_pattern = talloc_strdup(ctx, "(?P<name>[^@]+)@?(?P<domain>[^@]*$)"); if (!ctx->re_pattern) { ret = ENOMEM; goto done; } #ifdef HAVE_LIBPCRE_LESSER_THAN_7 } else { DEBUG(2, ("This binary was build with a version of libpcre that does " "not support non-unique named subpatterns.\n")); DEBUG(2, ("Please make sure that your pattern [%s] only contains " "subpatterns with a unique name and uses " "the Python syntax (?P<name>).\n", ctx->re_pattern)); #endif } ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, CONFDB_MONITOR_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) { ret = ENOMEM; goto done; } } ctx->re = pcre_compile2(ctx->re_pattern, NAME_DOMAIN_PATTERN_OPTIONS, &errval, &errstr, &errpos, NULL); if (!ctx->re) { DEBUG(1, ("Invalid Regular Expression pattern at position %d." " (Error: %d [%s])\n", errpos, errval, errstr)); ret = EFAULT; goto done; } *out = ctx; ret = EOK; done: if (ret != EOK) { talloc_free(ctx); } 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 < 0) { DEBUG(2, ("PCRE Matching error, %d\n", ret)); return EINVAL; } if (ret == 0) { DEBUG(1, ("Too many matches, the pattern is invalid.\n")); } strnum = ret; result = NULL; ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result); if (ret < 0 || !result) { DEBUG(2, ("Name not found!\n")); return EINVAL; } *name = talloc_strdup(memctx, result); pcre_free_substring(result); if (!*name) return ENOMEM; result = NULL; ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain", &result); if (ret < 0 || !result) { DEBUG(4, ("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; }