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 : }
|