LCOV - code coverage report
Current view: top level - util - usertools.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 226 310 72.9 %
Date: 2016-06-29 Functions: 18 20 90.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    User tools
       5             : 
       6             :    Copyright (C) Stephen Gallagher <sgallagh@redhat.com>  2009
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <pwd.h>
      23             : #include <pcre.h>
      24             : #include <errno.h>
      25             : #include <talloc.h>
      26             : #include <pwd.h>
      27             : #include <grp.h>
      28             : 
      29             : #include "confdb/confdb.h"
      30             : #include "util/strtonum.h"
      31             : #include "util/util.h"
      32             : #include "util/safe-format-string.h"
      33             : #include "responder/common/responder.h"
      34             : 
      35             : #ifdef HAVE_LIBPCRE_LESSER_THAN_7
      36             : #define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_EXTENDED)
      37             : #else
      38             : #define NAME_DOMAIN_PATTERN_OPTIONS (PCRE_DUPNAMES | PCRE_EXTENDED)
      39             : #endif
      40             : 
      41             : /* Function returns given realm name as new uppercase string */
      42           0 : char *get_uppercase_realm(TALLOC_CTX *memctx, const char *name)
      43             : {
      44             :     char *realm;
      45             :     char *c;
      46             : 
      47           0 :     realm = talloc_strdup(memctx, name);
      48           0 :     if (!realm) {
      49           0 :         return NULL;
      50             :     }
      51             : 
      52           0 :     c = realm;
      53           0 :     while(*c != '\0') {
      54           0 :         *c = toupper(*c);
      55           0 :         c++;
      56             :     }
      57             : 
      58           0 :     return realm;
      59             : }
      60             : 
      61             : 
      62         440 : static int sss_names_ctx_destructor(struct sss_names_ctx *snctx)
      63             : {
      64         440 :     if (snctx->re) {
      65         439 :         pcre_free(snctx->re);
      66         439 :         snctx->re = NULL;
      67             :     }
      68         440 :     return 0;
      69             : }
      70             : 
      71             : #define IPA_AD_DEFAULT_RE "(((?P<domain>[^\\\\]+)\\\\(?P<name>.+$))|" \
      72             :                          "((?P<name>[^@]+)@(?P<domain>.+$))|" \
      73             :                          "(^(?P<name>[^@\\\\]+)$))"
      74             : 
      75          98 : static errno_t get_id_provider_default_re(TALLOC_CTX *mem_ctx,
      76             :                                           struct confdb_ctx *cdb,
      77             :                                           const char *conf_path,
      78             :                                           char **re_pattern)
      79             : {
      80             : #ifdef HAVE_LIBPCRE_LESSER_THAN_7
      81             :     DEBUG(SSSDBG_MINOR_FAILURE,
      82             :           "The libpcre version on this system is too old. Only "
      83             :            "the user@DOMAIN name fully qualified name format will "
      84             :            "be supported\n");
      85             :     *re_pattern = NULL;
      86             :     return EOK;
      87             : #else
      88             :     int ret;
      89             :     size_t c;
      90          98 :     char *id_provider = NULL;
      91             : 
      92             :     struct provider_default_re {
      93             :         const char *name;
      94             :         const char *re;
      95          98 :     } provider_default_re[] = {{"ipa", IPA_AD_DEFAULT_RE},
      96             :                                {"ad", IPA_AD_DEFAULT_RE},
      97             :                                {NULL, NULL}};
      98             : 
      99          98 :     ret = confdb_get_string(cdb, mem_ctx, conf_path, CONFDB_DOMAIN_ID_PROVIDER,
     100             :                             NULL, &id_provider);
     101          98 :     if (ret != EOK) {
     102           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to read ID provider " \
     103             :                                   "from conf db.\n");
     104           0 :         goto done;
     105             :     }
     106             : 
     107          98 :     if (id_provider == NULL) {
     108           0 :         *re_pattern = NULL;
     109             :     } else {
     110         294 :         for (c = 0; provider_default_re[c].name != NULL; c++) {
     111         196 :             if (strcmp(id_provider, provider_default_re[c].name) == 0) {
     112           0 :                 *re_pattern = talloc_strdup(mem_ctx, provider_default_re[c].re);
     113           0 :                 if (*re_pattern == NULL) {
     114           0 :                     DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     115           0 :                     ret = ENOMEM;
     116           0 :                     goto done;
     117             :                 }
     118           0 :                 break;
     119             :             }
     120             :         }
     121             :     }
     122             : 
     123          98 :     ret = EOK;
     124             : 
     125             : done:
     126          98 :     talloc_free(id_provider);
     127          98 :     return ret;
     128             : #endif
     129             : }
     130             : 
     131         450 : static errno_t sss_fqnames_init(struct sss_names_ctx *nctx, const char *fq_fmt)
     132             : {
     133             :     char *fq;
     134             : 
     135         450 :     nctx->fq_fmt = talloc_strdup(nctx, fq_fmt);
     136         450 :     if (nctx->fq_fmt == NULL) {
     137           0 :         return ENOMEM;
     138             :     }
     139             : 
     140         450 :     DEBUG(SSSDBG_CONF_SETTINGS, "Using fq format [%s].\n", nctx->fq_fmt);
     141             : 
     142             :     /* Fail if the name specifier is missing, or if the format is
     143             :      * invalid */
     144         450 :     fq = sss_tc_fqname2 (nctx, nctx, "unused.example.com", "unused", "the-test-user");
     145         450 :     if (fq == NULL) {
     146           0 :         DEBUG(SSSDBG_OP_FAILURE,
     147             :               "The fq format is invalid [%s]\n", nctx->fq_fmt);
     148           0 :         return EINVAL;
     149         450 :     } else if (strstr (fq, "the-test-user") == NULL) {
     150           1 :         DEBUG(SSSDBG_OP_FAILURE,
     151             :               "Username pattern not found in [%s]\n", nctx->fq_fmt);
     152           1 :         return ENOENT;
     153             :     }
     154             : 
     155         449 :     talloc_free (fq);
     156         449 :     return EOK;
     157             : }
     158             : 
     159         450 : int sss_names_init_from_args(TALLOC_CTX *mem_ctx, const char *re_pattern,
     160             :                              const char *fq_fmt, struct sss_names_ctx **out)
     161             : {
     162             :     struct sss_names_ctx *ctx;
     163             :     const char *errstr;
     164             :     int errval;
     165             :     int errpos;
     166             :     int ret;
     167             : 
     168         450 :     ctx = talloc_zero(mem_ctx, struct sss_names_ctx);
     169         450 :     if (!ctx) return ENOMEM;
     170         450 :     talloc_set_destructor(ctx, sss_names_ctx_destructor);
     171             : 
     172         450 :     ctx->re_pattern = talloc_strdup(ctx, re_pattern);
     173         450 :     if (ctx->re_pattern == NULL) {
     174           0 :         ret = ENOMEM;
     175           0 :         goto done;
     176             :     }
     177             : 
     178         450 :     DEBUG(SSSDBG_CONF_SETTINGS, "Using re [%s].\n", ctx->re_pattern);
     179             : 
     180         450 :     ret = sss_fqnames_init(ctx, fq_fmt);
     181         450 :     if (ret != EOK) {
     182           1 :         DEBUG(SSSDBG_OP_FAILURE, "Could not check the FQ names format"
     183             :               "[%d]: %s\n", ret, sss_strerror(ret));
     184           1 :         goto done;
     185             :     }
     186             : 
     187         449 :     ctx->re = pcre_compile2(ctx->re_pattern,
     188             :                             NAME_DOMAIN_PATTERN_OPTIONS,
     189             :                             &errval, &errstr, &errpos, NULL);
     190         449 :     if (!ctx->re) {
     191           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     192             :               "Invalid Regular Expression pattern at position %d."
     193             :                   " (Error: %d [%s])\n", errpos, errval, errstr);
     194           0 :         ret = EFAULT;
     195           0 :         goto done;
     196             :     }
     197             : 
     198         449 :     *out = ctx;
     199         449 :     ret = EOK;
     200             : 
     201             : done:
     202         450 :     if (ret != EOK) {
     203           1 :         talloc_free(ctx);
     204             :     }
     205         450 :     return ret;
     206             : }
     207             : 
     208         101 : int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
     209             :                    const char *domain, struct sss_names_ctx **out)
     210             : {
     211         101 :     TALLOC_CTX *tmpctx = NULL;
     212         101 :     char *conf_path = NULL;
     213         101 :     char *re_pattern = NULL;;
     214         101 :     char *fq_fmt = NULL;
     215             :     int ret;
     216             : 
     217         101 :     tmpctx = talloc_new(NULL);
     218         101 :     if (tmpctx == NULL) {
     219           0 :         ret = ENOMEM;
     220           0 :         goto done;
     221             :     }
     222             : 
     223         101 :     if (domain != NULL) {
     224          99 :         conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, domain);
     225          99 :         if (conf_path == NULL) {
     226           0 :             ret = ENOMEM;
     227           0 :             goto done;
     228             :         }
     229             : 
     230          99 :         ret = confdb_get_string(cdb, tmpctx, conf_path,
     231             :                                 CONFDB_NAME_REGEX, NULL, &re_pattern);
     232          99 :         if (ret != EOK) goto done;
     233             :     }
     234             : 
     235             :     /* If not found in the domain, look in globals */
     236         101 :     if (re_pattern == NULL) {
     237         100 :         ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
     238             :                                 CONFDB_NAME_REGEX, NULL, &re_pattern);
     239         100 :         if (ret != EOK) goto done;
     240             :     }
     241             : 
     242         101 :     if (re_pattern == NULL && conf_path != NULL) {
     243          98 :         ret = get_id_provider_default_re(tmpctx, cdb, conf_path, &re_pattern);
     244          98 :         if (ret != EOK) {
     245           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to get provider default regular " \
     246             :                                       "expression for domain [%s].\n", domain);
     247           0 :             goto done;
     248             :         }
     249             :     }
     250             : 
     251         101 :     if (!re_pattern) {
     252          98 :         re_pattern = talloc_strdup(tmpctx,
     253             :                                    "(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
     254          98 :         if (!re_pattern) {
     255           0 :             ret = ENOMEM;
     256           0 :             goto done;
     257             :         }
     258             : #ifdef HAVE_LIBPCRE_LESSER_THAN_7
     259             :     } else {
     260             :         DEBUG(SSSDBG_OP_FAILURE,
     261             :               "This binary was build with a version of libpcre that does "
     262             :                   "not support non-unique named subpatterns.\n");
     263             :         DEBUG(SSSDBG_OP_FAILURE,
     264             :               "Please make sure that your pattern [%s] only contains "
     265             :                   "subpatterns with a unique name and uses "
     266             :                   "the Python syntax (?P<name>).\n", re_pattern);
     267             : #endif
     268             :     }
     269             : 
     270         101 :     if (conf_path != NULL) {
     271          99 :         ret = confdb_get_string(cdb, tmpctx, conf_path,
     272             :                                 CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
     273          99 :         if (ret != EOK) goto done;
     274             :     }
     275             : 
     276             :     /* If not found in the domain, look in globals */
     277         101 :     if (fq_fmt == NULL) {
     278          62 :         ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
     279             :                                 CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
     280          62 :         if (ret != EOK) goto done;
     281             :     }
     282             : 
     283         101 :     if (!fq_fmt) {
     284          60 :         fq_fmt = talloc_strdup(tmpctx, CONFDB_DEFAULT_FULL_NAME_FORMAT);
     285          60 :         if (!fq_fmt) {
     286           0 :             ret = ENOMEM;
     287           0 :             goto done;
     288             :         }
     289             :     }
     290             : 
     291         101 :     ret = sss_names_init_from_args(mem_ctx, re_pattern, fq_fmt, out);
     292             : 
     293             : done:
     294         101 :     talloc_free(tmpctx);
     295         101 :     return ret;
     296             : }
     297             : 
     298          46 : int sss_ad_default_names_ctx(TALLOC_CTX *mem_ctx,
     299             :                              struct sss_names_ctx **_out)
     300             : {
     301          46 :     return sss_names_init_from_args(mem_ctx, IPA_AD_DEFAULT_RE,
     302             :                                     CONFDB_DEFAULT_FULL_NAME_FORMAT,
     303             :                                     _out);
     304             : }
     305             : 
     306         465 : int sss_parse_name(TALLOC_CTX *memctx,
     307             :                    struct sss_names_ctx *snctx,
     308             :                    const char *orig, char **_domain, char **_name)
     309             : {
     310         465 :     pcre *re = snctx->re;
     311             :     const char *result;
     312             :     int ovec[30];
     313             :     int origlen;
     314             :     int ret, strnum;
     315             : 
     316         465 :     origlen = strlen(orig);
     317             : 
     318         465 :     ret = pcre_exec(re, NULL, orig, origlen, 0, PCRE_NOTEMPTY, ovec, 30);
     319         465 :     if (ret == PCRE_ERROR_NOMATCH) {
     320          14 :         return ERR_REGEX_NOMATCH;
     321         451 :     } else if (ret < 0) {
     322           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "PCRE Matching error, %d\n", ret);
     323           0 :         return EINVAL;
     324             :     }
     325             : 
     326         451 :     if (ret == 0) {
     327           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     328             :               "Too many matches, the pattern is invalid.\n");
     329             :     }
     330             : 
     331         451 :     strnum = ret;
     332             : 
     333         451 :     if (_name != NULL) {
     334         255 :         result = NULL;
     335         255 :         ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result);
     336         255 :         if (ret < 0  || !result) {
     337           0 :             DEBUG(SSSDBG_OP_FAILURE, "Name not found!\n");
     338           0 :             return EINVAL;
     339             :         }
     340         255 :         *_name = talloc_strdup(memctx, result);
     341         255 :         pcre_free_substring(result);
     342         255 :         if (!*_name) return ENOMEM;
     343             :     }
     344             : 
     345         451 :     if (_domain != NULL) {
     346         437 :         result = NULL;
     347         437 :         ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain",
     348             :                                        &result);
     349         437 :         if (ret < 0  || !result) {
     350           0 :             DEBUG(SSSDBG_CONF_SETTINGS, "Domain not provided!\n");
     351           0 :             *_domain = NULL;
     352             :         } else {
     353             :             /* ignore "" string */
     354         437 :             if (*result) {
     355          85 :                 *_domain = talloc_strdup(memctx, result);
     356          85 :                 pcre_free_substring(result);
     357          85 :                 if (!*_domain) return ENOMEM;
     358             :             } else {
     359         352 :                 pcre_free_substring(result);
     360         352 :                 *_domain = NULL;
     361             :             }
     362             :         }
     363             :     }
     364             : 
     365         451 :     return EOK;
     366             : }
     367             : 
     368          26 : int sss_parse_name_const(TALLOC_CTX *memctx,
     369             :                          struct sss_names_ctx *snctx, const char *orig,
     370             :                          const char **_domain, const char **_name)
     371             : {
     372             :     char *domain;
     373             :     char *name;
     374             :     int ret;
     375             : 
     376          26 :     ret = sss_parse_name(memctx, snctx, orig,
     377             :                          (_domain == NULL) ? NULL : &domain,
     378             :                          (_name == NULL) ? NULL : &name);
     379          26 :     if (ret == EOK) {
     380          19 :         if (_domain != NULL) {
     381           6 :             *_domain = domain;
     382             :         }
     383             : 
     384          19 :         if (_name != NULL) {
     385          18 :             *_name = name;
     386             :         }
     387             :     }
     388             : 
     389          26 :     return ret;
     390             : }
     391             : 
     392          51 : static struct sss_domain_info * match_any_domain_or_subdomain_name(
     393             :                                                 struct sss_domain_info *dom,
     394             :                                                 const char *dmatch)
     395             : {
     396          82 :     if (strcasecmp(dom->name, dmatch) == 0 ||
     397          42 :         (dom->flat_name != NULL && strcasecmp(dom->flat_name, dmatch) == 0)) {
     398          21 :         return dom;
     399             :     }
     400             : 
     401          30 :     return find_domain_by_name(dom, dmatch, true);
     402             : }
     403             : 
     404         178 : int sss_parse_name_for_domains(TALLOC_CTX *memctx,
     405             :                                struct sss_domain_info *domains,
     406             :                                const char *default_domain,
     407             :                                const char *orig, char **domain, char **name)
     408             : {
     409         178 :     struct sss_domain_info *dom, *match = NULL;
     410             :     char *rdomain, *rname;
     411             :     char *dmatch, *nmatch;
     412         178 :     char *candidate_name = NULL;
     413         178 :     char *candidate_domain = NULL;
     414         178 :     bool name_mismatch = false;
     415             :     TALLOC_CTX *tmp_ctx;
     416             :     int ret;
     417             : 
     418         178 :     tmp_ctx = talloc_new(NULL);
     419         178 :     if (tmp_ctx == NULL) {
     420           0 :         return ENOMEM;
     421             :     }
     422             : 
     423         178 :     rname = NULL;
     424         178 :     rdomain = NULL;
     425             : 
     426         333 :     for (dom = domains; dom != NULL; dom = get_next_domain(dom, 0)) {
     427         182 :         ret = sss_parse_name(tmp_ctx, dom->names, orig, &dmatch, &nmatch);
     428         182 :         if (ret == EOK) {
     429             :             /*
     430             :              * If the name matched without the domain part, make note of it.
     431             :              * All the other domain expressions must agree on the domain-less
     432             :              * name.
     433             :              */
     434         182 :             if (dmatch == NULL) {
     435         136 :                 if (candidate_name == NULL) {
     436         134 :                     candidate_name = nmatch;
     437           2 :                 } else if (strcasecmp(candidate_name, nmatch) != 0) {
     438           0 :                     name_mismatch = true;
     439             :                 }
     440             : 
     441             :             /*
     442             :              * If a domain was returned, then it must match the name of the
     443             :              * domain that this expression was found on, or one of the
     444             :              * subdomains.
     445             :              */
     446             :             } else {
     447          46 :                 match = match_any_domain_or_subdomain_name (dom, dmatch);
     448          46 :                 if (match != NULL) {
     449          27 :                     DEBUG(SSSDBG_FUNC_DATA, "name '%s' matched expression for "
     450             :                                              "domain '%s', user is %s\n",
     451             :                                              orig, match->name, nmatch);
     452          27 :                     rdomain = talloc_strdup(tmp_ctx, match->name);
     453          27 :                     if (rdomain == NULL) {
     454           0 :                         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     455           0 :                         ret = ENOMEM;
     456           0 :                         goto done;
     457             :                     }
     458          27 :                     rname = nmatch;
     459          27 :                     break;
     460          19 :                 } else if (candidate_domain == NULL) {
     461          17 :                     candidate_domain = dmatch;
     462             :                 }
     463             :             }
     464             : 
     465             :         /* EINVAL is returned when name doesn't match */
     466           0 :         } else if (ret != EINVAL) {
     467           0 :             goto done;
     468             :         }
     469             :     }
     470             : 
     471         178 :     if (rdomain == NULL && rname == NULL) {
     472         151 :         if (candidate_name && !name_mismatch) {
     473         134 :             DEBUG(SSSDBG_FUNC_DATA, "name '%s' matched without domain, " \
     474             :                                      "user is %s\n", orig, nmatch);
     475         134 :             rdomain = NULL;
     476         134 :             if (default_domain != NULL) {
     477           5 :                 rdomain = talloc_strdup(tmp_ctx, default_domain);
     478           5 :                 if (rdomain == NULL) {
     479           0 :                     DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     480           0 :                     ret = ENOMEM;
     481           0 :                     goto done;
     482             :                 }
     483             : 
     484           6 :                 for (dom = domains; dom != NULL; dom = get_next_domain(dom, 0)) {
     485           5 :                     match = match_any_domain_or_subdomain_name(dom, rdomain);
     486           5 :                     if (match != NULL) {
     487           4 :                         break;
     488             :                     }
     489             :                 }
     490           5 :                 if (match == NULL) {
     491           1 :                     DEBUG(SSSDBG_FUNC_DATA, "default domain [%s] is currently " \
     492             :                                             "not known\n", rdomain);
     493           1 :                     *domain = talloc_steal(memctx, rdomain);
     494           1 :                     ret = EAGAIN;
     495           1 :                     goto done;
     496             :                 }
     497           4 :                 DEBUG(SSSDBG_FUNC_DATA, "using default domain [%s]\n", rdomain);
     498             :             }
     499             : 
     500         133 :             rname = candidate_name;
     501          17 :         } else if (candidate_domain) {
     502             :             /* This branch is taken when the input matches the configured
     503             :              * regular expression, but the domain is now known. Normally, this
     504             :              * is the case with a FQDN of a user from subdomain that was not
     505             :              * yet discovered
     506             :              */
     507          17 :             *domain = talloc_steal(memctx, candidate_domain);
     508          17 :             ret = EAGAIN;
     509          17 :             goto done;
     510             :         }
     511             :     }
     512             : 
     513         160 :     if (rdomain == NULL && rname == NULL) {
     514           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     515             :               "name '%s' did not match any domain's expression\n", orig);
     516           0 :         ret = EINVAL;
     517           0 :         goto done;
     518             :     }
     519             : 
     520         160 :     if (domain != NULL) {
     521         160 :         *domain = talloc_steal(memctx, rdomain);
     522             :     }
     523             : 
     524         160 :     if (name != NULL) {
     525         160 :         *name = talloc_steal(memctx, rname);
     526             :     }
     527             : 
     528         160 :     ret = EOK;
     529             : done:
     530         178 :     talloc_free(tmp_ctx);
     531             : 
     532         178 :     return ret;
     533             : }
     534             : 
     535             : char *
     536         182 : sss_get_cased_name(TALLOC_CTX *mem_ctx,
     537             :                    const char *orig_name,
     538             :                    bool case_sensitive)
     539             : {
     540         182 :     return case_sensitive ? talloc_strdup(mem_ctx, orig_name) :
     541             :                             sss_tc_utf8_str_tolower(mem_ctx, orig_name);
     542             : }
     543             : 
     544             : errno_t
     545           0 : sss_get_cased_name_list(TALLOC_CTX *mem_ctx, const char * const *orig,
     546             :                         bool case_sensitive, const char ***_cased)
     547             : {
     548             :     const char **out;
     549             :     size_t num, i;
     550             : 
     551           0 :     if (orig == NULL) {
     552           0 :         *_cased = NULL;
     553           0 :         return EOK;
     554             :     }
     555             : 
     556           0 :     for (num=0; orig[num]; num++);  /* count the num of strings */
     557             : 
     558           0 :     if (num == 0) {
     559           0 :         *_cased = NULL;
     560           0 :         return EOK;
     561             :     }
     562             : 
     563           0 :     out = talloc_array(mem_ctx, const char *, num + 1);
     564           0 :     if (out == NULL) {
     565           0 :         return ENOMEM;
     566             :     }
     567             : 
     568           0 :     for (i = 0; i < num; i++) {
     569           0 :         out[i] = sss_get_cased_name(out, orig[i], case_sensitive);
     570           0 :         if (out[i] == NULL) {
     571           0 :             talloc_free(out);
     572           0 :             return ENOMEM;
     573             :         }
     574             :     }
     575             : 
     576           0 :     out[num] = NULL;
     577           0 :     *_cased = out;
     578           0 :     return EOK;
     579             : }
     580             : 
     581             : static inline const char *
     582          33 : calc_flat_name(struct sss_domain_info *domain)
     583             : {
     584             :     const char *s;
     585             : 
     586          33 :     s = domain->flat_name;
     587          33 :     if (s == NULL) {
     588          22 :         DEBUG(SSSDBG_MINOR_FAILURE, "Flat name requested but domain has no"
     589             :               "flat name set, falling back to domain name\n");
     590          22 :         s = domain->name;
     591             :     }
     592             : 
     593          33 :     return s;
     594             : }
     595             : 
     596             : char *
     597          11 : sss_tc_fqname(TALLOC_CTX *mem_ctx, struct sss_names_ctx *nctx,
     598             :               struct sss_domain_info *domain, const char *name)
     599             : {
     600          11 :     if (domain == NULL || nctx == NULL) return NULL;
     601             : 
     602          11 :     return sss_tc_fqname2 (mem_ctx, nctx, domain->name,
     603             :                            calc_flat_name (domain), name);
     604             : }
     605             : 
     606             : static void
     607        1393 : safe_talloc_callback (void *data,
     608             :                       const char *piece,
     609             :                       size_t len)
     610             : {
     611        1393 :     char **output = data;
     612        1393 :     if (*output != NULL)
     613        1393 :         *output = talloc_strndup_append(*output, piece, len);
     614        1393 : }
     615             : 
     616             : char *
     617         463 : sss_tc_fqname2(TALLOC_CTX *mem_ctx, struct sss_names_ctx *nctx,
     618             :                const char *domain_name, const char *flat_dom_name,
     619             :                const char *name)
     620             : {
     621         463 :     const char *args[] = { name, domain_name, flat_dom_name, NULL };
     622             :     char *output;
     623             : 
     624         463 :     if (nctx == NULL) return NULL;
     625             : 
     626         463 :     output = talloc_strdup(mem_ctx, "");
     627         463 :     if (safe_format_string_cb(safe_talloc_callback, &output, nctx->fq_fmt, args, 3) < 0)
     628           0 :         output = NULL;
     629         463 :     else if (output == NULL)
     630           0 :         errno = ENOMEM;
     631         463 :     return output;
     632             : }
     633             : 
     634             : int
     635          22 : sss_fqname(char *str, size_t size, struct sss_names_ctx *nctx,
     636             :            struct sss_domain_info *domain, const char *name)
     637             : {
     638          22 :     if (domain == NULL || nctx == NULL) return -EINVAL;
     639             : 
     640          22 :     return safe_format_string(str, size, nctx->fq_fmt,
     641             :                               name, domain->name, calc_flat_name (domain), NULL);
     642             : }
     643             : 
     644             : char *
     645         278 : sss_get_domain_name(TALLOC_CTX *mem_ctx,
     646             :                     const char *orig_name,
     647             :                     struct sss_domain_info *dom)
     648             : {
     649             :     char *user_name;
     650         278 :     char *domain = NULL;
     651             :     int ret;
     652             : 
     653             :     /* check if the name already contains domain part */
     654         278 :     if (dom->names != NULL) {
     655         152 :         ret = sss_parse_name(mem_ctx, dom->names, orig_name, &domain, NULL);
     656         152 :         if (ret == ERR_REGEX_NOMATCH) {
     657           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     658             :                   "sss_parse_name could not parse domain from [%s]. "
     659             :                   "Assuming it is not FQDN.\n", orig_name);
     660         152 :         } else if (ret != EOK) {
     661           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     662             :                   "sss_parse_name failed [%d]: %s\n", ret, sss_strerror(ret));
     663           0 :             return NULL;
     664             :         }
     665             :     }
     666             : 
     667         278 :     if (IS_SUBDOMAIN(dom) && dom->fqnames && domain == NULL) {
     668             :         /* we always use the fully qualified name for subdomain users */
     669           6 :         user_name = sss_tc_fqname(mem_ctx, dom->names, dom, orig_name);
     670             :     } else {
     671         272 :         user_name = talloc_strdup(mem_ctx, orig_name);
     672             :     }
     673             : 
     674         278 :     talloc_free(domain);
     675             : 
     676         278 :     return user_name;
     677             : }
     678             : 
     679           2 : errno_t sss_user_by_name_or_uid(const char *input, uid_t *_uid, gid_t *_gid)
     680             : {
     681             :     uid_t uid;
     682             :     errno_t ret;
     683             :     char *endptr;
     684             :     struct passwd *pwd;
     685             : 
     686             :     /* Try if it's an ID first */
     687           2 :     errno = 0;
     688           2 :     uid = strtouint32(input, &endptr, 10);
     689           2 :     if (errno != 0 || *endptr != '\0') {
     690           2 :         ret = errno;
     691           2 :         if (ret == ERANGE) {
     692           0 :             DEBUG(SSSDBG_OP_FAILURE,
     693             :                   "UID [%s] is out of range.\n", input);
     694           0 :             return ret;
     695             :         }
     696             : 
     697             :         /* Nope, maybe a username? */
     698           2 :         pwd = getpwnam(input);
     699             :     } else {
     700           0 :         pwd = getpwuid(uid);
     701             :     }
     702             : 
     703           2 :     if (pwd == NULL) {
     704           1 :         DEBUG(SSSDBG_OP_FAILURE,
     705             :               "[%s] is neither a valid UID nor a user name which could be "
     706             :               "resolved by getpwnam().\n", input);
     707           1 :         return EINVAL;
     708             :     }
     709             : 
     710           1 :     if (_uid) {
     711           1 :         *_uid = pwd->pw_uid;
     712             :     }
     713             : 
     714           1 :     if (_gid) {
     715           0 :         *_gid = pwd->pw_gid;
     716             :     }
     717           1 :     return EOK;
     718             : }

Generated by: LCOV version 1.10