Annotation of embedaddon/sudo/plugins/sudoers/sssd.c, revision 1.1.1.4
1.1 misho 1: /*
1.1.1.2 misho 2: * Copyright (c) 2003-2013 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 misho 3: * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
4: *
5: * This code is derived from software contributed by Aaron Spangler.
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <config.h>
21:
22: #include <sys/types.h>
23: #include <sys/time.h>
24: #include <sys/stat.h>
25: #include <stdio.h>
26: #ifdef STDC_HEADERS
27: # include <stdlib.h>
28: # include <stddef.h>
29: #else
30: # ifdef HAVE_STDLIB_H
31: # include <stdlib.h>
32: # endif
33: #endif /* STDC_HEADERS */
34: #ifdef HAVE_STRING_H
35: # include <string.h>
36: #endif /* HAVE_STRING_H */
37: #ifdef HAVE_STRINGS_H
38: # include <strings.h>
39: #endif /* HAVE_STRINGS_H */
40: #ifdef HAVE_UNISTD_H
41: # include <unistd.h>
42: #endif /* HAVE_UNISTD_H */
1.1.1.4 ! misho 43: #ifdef TIME_WITH_SYS_TIME
1.1 misho 44: # include <time.h>
45: #endif
46: #include <ctype.h>
47: #include <pwd.h>
48: #include <grp.h>
49:
50: #include <errno.h>
51: #include <stdint.h>
52:
53: #include "sudoers.h"
54: #include "parse.h"
55: #include "lbuf.h"
1.1.1.4 ! misho 56: #include "sudo_dso.h"
1.1 misho 57: #include "sudo_debug.h"
58:
59: /* SSSD <--> SUDO interface - do not change */
60: struct sss_sudo_attr {
61: char *name;
62: char **values;
63: unsigned int num_values;
64: };
65:
66: struct sss_sudo_rule {
67: unsigned int num_attrs;
68: struct sss_sudo_attr *attrs;
69: };
70:
71: struct sss_sudo_result {
72: unsigned int num_rules;
73: struct sss_sudo_rule *rules;
74: };
75:
76: typedef int (*sss_sudo_send_recv_t)(uid_t, const char*, const char*,
77: uint32_t*, struct sss_sudo_result**);
78:
79: typedef int (*sss_sudo_send_recv_defaults_t)(uid_t, const char*, uint32_t*,
80: char**, struct sss_sudo_result**);
81:
82: typedef void (*sss_sudo_free_result_t)(struct sss_sudo_result*);
83:
84: typedef int (*sss_sudo_get_values_t)(struct sss_sudo_rule*, const char*,
85: char***);
86:
87: typedef void (*sss_sudo_free_values_t)(char**);
88:
89: /* sudo_nss implementation */
90:
91: struct sudo_sss_handle {
92: char *domainname;
93: struct passwd *pw;
94: void *ssslib;
95: sss_sudo_send_recv_t fn_send_recv;
96: sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
97: sss_sudo_free_result_t fn_free_result;
98: sss_sudo_get_values_t fn_get_values;
99: sss_sudo_free_values_t fn_free_values;
100: };
101:
102: static int sudo_sss_open(struct sudo_nss *nss);
103: static int sudo_sss_close(struct sudo_nss *nss);
104: static int sudo_sss_parse(struct sudo_nss *nss);
105: static void sudo_sss_parse_options(struct sudo_sss_handle *handle,
106: struct sss_sudo_rule *rule);
107: static int sudo_sss_setdefs(struct sudo_nss *nss);
108: static int sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag);
109: static int sudo_sss_display_cmnd(struct sudo_nss *nss, struct passwd *pw);
110: static int sudo_sss_display_defaults(struct sudo_nss *nss, struct passwd *pw,
111: struct lbuf *lbuf);
112:
113: static int sudo_sss_display_bound_defaults(struct sudo_nss *nss,
114: struct passwd *pw, struct lbuf *lbuf);
115:
116: static int sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw,
117: struct lbuf *lbuf);
118:
119:
120: static struct sss_sudo_result *sudo_sss_result_get(struct sudo_nss *nss,
121: struct passwd *pw,
122: uint32_t *state);
123:
124: static void
125: sudo_sss_attrcpy(struct sss_sudo_attr *dst, const struct sss_sudo_attr *src)
126: {
127: int i;
128: debug_decl(sudo_sss_attrcpy, SUDO_DEBUG_SSSD)
129:
130: sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
131: sudo_debug_printf(SUDO_DEBUG_INFO, "emalloc: cnt=%d", src->num_values);
132:
133: dst->name = estrdup(src->name);
134: dst->num_values = src->num_values;
135: dst->values = emalloc2(dst->num_values, sizeof(char *));
136:
137: for (i = 0; i < dst->num_values; ++i)
138: dst->values[i] = estrdup(src->values[i]);
139:
140: debug_return;
141: }
142:
143: static void
144: sudo_sss_rulecpy(struct sss_sudo_rule *dst, const struct sss_sudo_rule *src)
145: {
146: int i;
147: debug_decl(sudo_sss_rulecpy, SUDO_DEBUG_SSSD)
148:
149: sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
150: sudo_debug_printf(SUDO_DEBUG_INFO, "emalloc: cnt=%d", src->num_attrs);
151:
152: dst->num_attrs = src->num_attrs;
153: dst->attrs = emalloc2(dst->num_attrs, sizeof(struct sss_sudo_attr));
154:
155: for (i = 0; i < dst->num_attrs; ++i)
156: sudo_sss_attrcpy(dst->attrs + i, src->attrs + i);
157:
158: debug_return;
159: }
160:
161: #define _SUDO_SSS_FILTER_INCLUDE 0
162: #define _SUDO_SSS_FILTER_EXCLUDE 1
163:
164: #define _SUDO_SSS_STATE_HOSTMATCH 0x01
165: #define _SUDO_SSS_STATE_USERMATCH 0x02
166:
167: static struct sss_sudo_result *
168: sudo_sss_filter_result(struct sudo_sss_handle *handle,
169: struct sss_sudo_result *in_res,
170: int (*filterp)(struct sudo_sss_handle *, struct sss_sudo_rule *, void *),
171: int act, void *filterp_arg)
172: {
173: struct sss_sudo_result *out_res;
174: int i, l, r;
175: debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD)
176:
177: sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s",
1.1.1.4 ! misho 178: in_res, in_res ? in_res->num_rules : 0,
1.1 misho 179: act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE");
180:
181: if (in_res == NULL)
182: debug_return_ptr(NULL);
183:
184: sudo_debug_printf(SUDO_DEBUG_DEBUG, "emalloc: cnt=%d", in_res->num_rules);
185:
186: out_res = emalloc(sizeof(struct sss_sudo_result));
187: out_res->rules = in_res->num_rules > 0 ?
188: emalloc2(in_res->num_rules, sizeof(struct sss_sudo_rule)) : NULL;
189: out_res->num_rules = 0;
190:
191: for (i = l = 0; i < in_res->num_rules; ++i) {
192: r = filterp(handle, in_res->rules + i, filterp_arg);
193:
194: if (( r && act == _SUDO_SSS_FILTER_INCLUDE) ||
195: (!r && act == _SUDO_SSS_FILTER_EXCLUDE)) {
196: sudo_debug_printf(SUDO_DEBUG_DEBUG,
197: "COPY (%s): %p[%u] => %p[%u] (= %p)",
198: act == _SUDO_SSS_FILTER_EXCLUDE ? "not excluded" : "included",
199: in_res->rules, i, out_res->rules, l, in_res->rules + i);
200:
201: sudo_sss_rulecpy(out_res->rules + l, in_res->rules + i);
202: ++l;
203: }
204: }
205:
206: if (l < in_res->num_rules) {
207: sudo_debug_printf(SUDO_DEBUG_DEBUG,
208: "reallocating result: %p (count: %u -> %u)", out_res->rules,
209: in_res->num_rules, l);
1.1.1.2 misho 210: if (l > 0) {
211: out_res->rules =
212: erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule));
213: } else {
214: efree(out_res->rules);
215: out_res->rules = NULL;
216: }
1.1 misho 217: }
218:
219: out_res->num_rules = l;
220:
221: debug_return_ptr(out_res);
222: }
223:
224: struct sudo_nss sudo_nss_sss = {
1.1.1.4 ! misho 225: { NULL, NULL },
1.1 misho 226: sudo_sss_open,
227: sudo_sss_close,
228: sudo_sss_parse,
229: sudo_sss_setdefs,
230: sudo_sss_lookup,
231: sudo_sss_display_cmnd,
232: sudo_sss_display_defaults,
233: sudo_sss_display_bound_defaults,
234: sudo_sss_display_privs
235: };
236:
237: /* sudo_nss implementation */
238: // ok
239: static int sudo_sss_open(struct sudo_nss *nss)
240: {
241: struct sudo_sss_handle *handle;
242: static const char path[] = _PATH_SSSD_LIB"/libsss_sudo.so";
243: debug_decl(sudo_sss_open, SUDO_DEBUG_SSSD);
244:
245: /* Create a handle container. */
246: handle = emalloc(sizeof(struct sudo_sss_handle));
247:
248: /* Load symbols */
1.1.1.4 ! misho 249: handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
1.1 misho 250: if (handle->ssslib == NULL) {
1.1.1.4 ! misho 251: warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror());
! 252: warningx(U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
1.1 misho 253: debug_return_int(EFAULT);
254: }
255:
1.1.1.4 ! misho 256: handle->fn_send_recv =
! 257: sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv");
1.1 misho 258: if (handle->fn_send_recv == NULL) {
1.1.1.4 ! misho 259: warningx(U_("unable to find symbol \"%s\" in %s"), path,
1.1 misho 260: "sss_sudo_send_recv");
261: debug_return_int(EFAULT);
262: }
263:
264: handle->fn_send_recv_defaults =
1.1.1.4 ! misho 265: sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults");
1.1 misho 266: if (handle->fn_send_recv_defaults == NULL) {
1.1.1.4 ! misho 267: warningx(U_("unable to find symbol \"%s\" in %s"), path,
1.1 misho 268: "sss_sudo_send_recv_defaults");
269: debug_return_int(EFAULT);
270: }
271:
1.1.1.4 ! misho 272: handle->fn_free_result =
! 273: sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result");
1.1 misho 274: if (handle->fn_free_result == NULL) {
1.1.1.4 ! misho 275: warningx(U_("unable to find symbol \"%s\" in %s"), path,
1.1 misho 276: "sss_sudo_free_result");
277: debug_return_int(EFAULT);
278: }
279:
1.1.1.4 ! misho 280: handle->fn_get_values =
! 281: sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values");
1.1 misho 282: if (handle->fn_get_values == NULL) {
1.1.1.4 ! misho 283: warningx(U_("unable to find symbol \"%s\" in %s"), path,
1.1 misho 284: "sss_sudo_get_values");
285: debug_return_int(EFAULT);
286: }
287:
1.1.1.4 ! misho 288: handle->fn_free_values =
! 289: sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values");
1.1 misho 290: if (handle->fn_free_values == NULL) {
1.1.1.4 ! misho 291: warningx(U_("unable to find symbol \"%s\" in %s"), path,
1.1 misho 292: "sss_sudo_free_values");
293: debug_return_int(EFAULT);
294: }
295:
296: handle->domainname = NULL;
297: handle->pw = sudo_user.pw;
298: nss->handle = handle;
299:
300: sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
301:
302: debug_return_int(0);
303: }
304:
305: // ok
306: static int sudo_sss_close(struct sudo_nss *nss)
307: {
308: struct sudo_sss_handle *handle;
309: debug_decl(sudo_sss_close, SUDO_DEBUG_SSSD);
310:
311: if (nss && nss->handle) {
312: handle = nss->handle;
1.1.1.4 ! misho 313: sudo_dso_unload(handle->ssslib);
! 314: efree(nss->handle);
1.1 misho 315: }
316: debug_return_int(0);
317: }
318:
319: // ok
320: static int sudo_sss_parse(struct sudo_nss *nss)
321: {
322: debug_decl(sudo_sss_parse, SUDO_DEBUG_SSSD);
323: debug_return_int(0);
324: }
325:
326: static int sudo_sss_setdefs(struct sudo_nss *nss)
327: {
328: struct sudo_sss_handle *handle = nss->handle;
329:
330: struct sss_sudo_result *sss_result;
331: struct sss_sudo_rule *sss_rule;
332: uint32_t sss_error;
333: int i;
334: debug_decl(sudo_sss_setdefs, SUDO_DEBUG_SSSD);
335:
336: if (handle == NULL)
337: debug_return_int(-1);
338:
339: sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
340:
341: if (handle->fn_send_recv_defaults(handle->pw->pw_uid, handle->pw->pw_name,
342: &sss_error, &handle->domainname,
343: &sss_result) != 0) {
344: sudo_debug_printf(SUDO_DEBUG_INFO,
345: "handle->fn_send_recv_defaults: != 0, sss_error=%u", sss_error);
346: debug_return_int(-1);
347: }
348:
349: if (sss_error == ENOENT) {
350: sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
1.1.1.2 misho 351: debug_return_int(0);
1.1 misho 352: } else if(sss_error != 0) {
353: sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
354: debug_return_int(-1);
355: }
356:
357: for (i = 0; i < sss_result->num_rules; ++i) {
358: sudo_debug_printf(SUDO_DEBUG_DIAG,
359: "Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
360: sss_rule = sss_result->rules + i;
361: sudo_sss_parse_options(handle, sss_rule);
362: }
363:
364: handle->fn_free_result(sss_result);
365: debug_return_int(0);
366: }
367:
368: static int sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw)
369: {
370: struct sudo_sss_handle *handle = nss->handle;
371: debug_decl(sudo_sss_checkpw, SUDO_DEBUG_SSSD);
372:
373: if (pw->pw_name != handle->pw->pw_name ||
374: pw->pw_uid != handle->pw->pw_uid) {
375: sudo_debug_printf(SUDO_DEBUG_DIAG,
376: "Requested name or uid don't match the initial once, reinitializing...");
377: handle->pw = pw;
378:
379: if (sudo_sss_setdefs(nss) != 0)
380: debug_return_int(-1);
381: }
382:
383: debug_return_int(0);
384: }
385:
386: static int
387: sudo_sss_check_runas_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *sss_rule)
388: {
389: char **val_array = NULL;
390: char *val;
391: int ret = false, i;
392: debug_decl(sudo_sss_check_runas_user, SUDO_DEBUG_SSSD);
393:
394: if (!runas_pw)
395: debug_return_int(UNSPEC);
396:
397: /* get the runas user from the entry */
398: switch (handle->fn_get_values(sss_rule, "sudoRunAsUser", &val_array)) {
399: case 0:
400: break;
401: case ENOENT:
402: sudo_debug_printf(SUDO_DEBUG_INFO, "No result. Trying old style (sudoRunAs)");
403:
404: /* try old style */
405: switch (handle->fn_get_values(sss_rule, "sudoRunAs", &val_array)) {
406: case 0:
407: break;
408: case ENOENT:
409: sudo_debug_printf(SUDO_DEBUG_INFO, "No result. Matching against runas_default");
410: /*
411: * If there are no runas entries, match runas_default against
412: * what the user specified on the command line.
413: */
414: return !strcasecmp(runas_pw->pw_name, def_runas_default);
415: default:
416: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAs): != 0");
417: debug_return_int(UNSPEC);
418: }
419: break;
420: default:
421: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsUser): != 0");
422: debug_return_int(UNSPEC);
423: }
424:
425: /*
426: * BUG:
427: *
428: * if runas is not specified on the command line, the only information
429: * as to which user to run as is in the runas_default option. We should
430: * check to see if we have the local option present. Unfortunately we
431: * don't parse these options until after this routine says yes or no.
432: * The query has already returned, so we could peek at the attribute
433: * values here though.
434: *
435: * For now just require users to always use -u option unless its set
436: * in the global defaults. This behaviour is no different than the global
437: * /etc/sudoers.
438: *
439: * Sigh - maybe add this feature later
440: */
441:
442: /* walk through values returned, looking for a match */
443: for (i = 0; val_array[i] != NULL && !ret; ++i) {
444: val = val_array[i];
445:
446: sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
447:
448: switch (val[0]) {
449: case '+':
450: sudo_debug_printf(SUDO_DEBUG_DEBUG, "netgr_");
451: if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) {
452: sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match");
453: ret = true;
454: }
455: break;
456: case '%':
457: sudo_debug_printf(SUDO_DEBUG_DEBUG, "usergr_");
458: if (usergr_matches(val, runas_pw->pw_name, runas_pw)) {
459: sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match");
460: ret = true;
461: }
462: break;
463: case 'A':
464: if (strcmp(val, "ALL") == 0) {
465: sudo_debug_printf(SUDO_DEBUG_DEBUG, "ALL => match");
466: ret = true;
467: break;
468: }
469: /* FALLTHROUGH */
470: sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH");
471: default:
1.1.1.2 misho 472: if (userpw_matches(val, runas_pw->pw_name, runas_pw)) {
1.1 misho 473: sudo_debug_printf(SUDO_DEBUG_DEBUG,
474: "%s == %s (pw_name) => match", val, runas_pw->pw_name);
475: ret = true;
476: }
477: break;
478: }
479:
480: sudo_debug_printf(SUDO_DEBUG_INFO,
481: "sssd/ldap sudoRunAsUser '%s' ... %s", val, ret ? "MATCH!" : "not");
482: }
483:
484: handle->fn_free_values(val_array); /* cleanup */
485:
486: debug_return_int(ret);
487: }
488:
489: static int
490: sudo_sss_check_runas_group(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
491: {
492: char **val_array = NULL;
493: char *val;
494: int ret = false, i;
495: debug_decl(sudo_sss_check_runas_group, SUDO_DEBUG_SSSD);
496:
497: /* runas_gr is only set if the user specified the -g flag */
498: if (!runas_gr)
499: debug_return_int(UNSPEC);
500:
501: /* get the values from the entry */
502: switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
503: case 0:
504: break;
505: case ENOENT:
506: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
507: debug_return_int(false);
508: default:
509: sudo_debug_printf(SUDO_DEBUG_INFO,
510: "handle->fn_get_values(sudoRunAsGroup): != 0");
511: debug_return_int(UNSPEC);
512: }
513:
514: /* walk through values returned, looking for a match */
515: for (i = 0; val_array[i] != NULL; ++i) {
516: val = val_array[i];
517: sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
518:
519: if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr))
520: ret = true;
521:
522: sudo_debug_printf(SUDO_DEBUG_INFO,
523: "sssd/ldap sudoRunAsGroup '%s' ... %s", val, ret ? "MATCH!" : "not");
524: }
525:
526: handle->fn_free_values(val_array);
527:
528: debug_return_int(ret);
529: }
530:
531: /*
532: * Walk through search results and return true if we have a runas match,
533: * else false. RunAs info is optional.
534: */
1.1.1.4 ! misho 535: static bool
1.1 misho 536: sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
537: {
1.1.1.4 ! misho 538: bool ret;
1.1 misho 539: debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD);
540:
541: if (rule == NULL)
1.1.1.4 ! misho 542: debug_return_bool(false);
1.1 misho 543:
544: ret = sudo_sss_check_runas_user(handle, rule) != false &&
545: sudo_sss_check_runas_group(handle, rule) != false;
546:
1.1.1.4 ! misho 547: debug_return_bool(ret);
1.1 misho 548: }
549:
1.1.1.4 ! misho 550: static bool
1.1 misho 551: sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
552: {
553: char **val_array, *val;
1.1.1.4 ! misho 554: bool ret = false;
! 555: int i;
1.1 misho 556: debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD);
557:
558: if (rule == NULL)
1.1.1.4 ! misho 559: debug_return_bool(ret);
1.1 misho 560:
561: /* get the values from the rule */
562: switch (handle->fn_get_values(rule, "sudoHost", &val_array))
563: {
564: case 0:
565: break;
566: case ENOENT:
567: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1.1.1.4 ! misho 568: debug_return_bool(false);
1.1 misho 569: default:
570: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0");
1.1.1.4 ! misho 571: debug_return_bool(ret);
1.1 misho 572: }
573:
574: /* walk through values */
575: for (i = 0; val_array[i] != NULL; ++i) {
576: val = val_array[i];
577: sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
578:
579: /* match any or address or netgroup or hostname */
580: if (!strcmp(val, "ALL") || addr_matches(val) ||
581: netgr_matches(val, user_host, user_shost, NULL) ||
582: hostname_matches(user_shost, user_host, val))
583: ret = true;
584:
585: sudo_debug_printf(SUDO_DEBUG_INFO,
586: "sssd/ldap sudoHost '%s' ... %s", val, ret ? "MATCH!" : "not");
587: }
588:
589: handle->fn_free_values(val_array);
590:
1.1.1.4 ! misho 591: debug_return_bool(ret);
! 592: }
! 593:
! 594: /*
! 595: * Look for netgroup specifcations in the sudoUser attribute and
! 596: * if found, filter according to netgroup membership.
! 597: * returns:
! 598: * true -> netgroup spec found && netgroup member
! 599: * false -> netgroup spec found && not a member of netgroup
! 600: * true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception)
! 601: */
! 602: static bool
! 603: sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
! 604: {
! 605: bool ret = false, netgroup_spec_found = false;
! 606: char **val_array, *val;
! 607: int i;
! 608: debug_decl(sudo_sss_filter_user_netgroup, SUDO_DEBUG_SSSD);
! 609:
! 610: if (!handle || !rule)
! 611: debug_return_bool(ret);
! 612:
! 613: switch (handle->fn_get_values(rule, "sudoUser", &val_array)) {
! 614: case 0:
! 615: break;
! 616: case ENOENT:
! 617: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
! 618: debug_return_bool(ret);
! 619: default:
! 620: sudo_debug_printf(SUDO_DEBUG_INFO,
! 621: "handle->fn_get_values(sudoUser): != 0");
! 622: debug_return_bool(ret);
! 623: }
! 624:
! 625: for (i = 0; val_array[i] != NULL && !ret; ++i) {
! 626: val = val_array[i];
! 627: if (*val == '+') {
! 628: netgroup_spec_found = true;
! 629: }
! 630: sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
! 631: if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, handle->pw->pw_name)) {
! 632: ret = true;
! 633: sudo_debug_printf(SUDO_DEBUG_DIAG,
! 634: "sssd/ldap sudoUser '%s' ... MATCH! (%s)",
! 635: val, handle->pw->pw_name);
! 636: break;
! 637: }
! 638: }
! 639: handle->fn_free_values(val_array);
! 640: debug_return_bool(netgroup_spec_found ? ret : true);
1.1 misho 641: }
642:
643: static int
644: sudo_sss_result_filterp(struct sudo_sss_handle *handle,
645: struct sss_sudo_rule *rule, void *unused)
646: {
647: (void)unused;
648: debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD);
649:
1.1.1.4 ! misho 650: if (sudo_sss_check_host(handle, rule) &&
! 651: sudo_sss_filter_user_netgroup(handle, rule))
1.1 misho 652: debug_return_int(1);
653: else
654: debug_return_int(0);
655: }
656:
657: static struct sss_sudo_result *
658: sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw, uint32_t *state)
659: {
660: struct sudo_sss_handle *handle = nss->handle;
661: struct sss_sudo_result *u_sss_result, *f_sss_result;
662: uint32_t sss_error = 0, ret;
663: debug_decl(sudo_sss_result_get, SUDO_DEBUG_SSSD);
664:
665: if (sudo_sss_checkpw(nss, pw) != 0)
666: debug_return_ptr(NULL);
667:
668: sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", handle->pw->pw_name);
1.1.1.4 ! misho 669: sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
! 670: handle->domainname ? handle->domainname : "NULL");
1.1 misho 671:
672: u_sss_result = f_sss_result = NULL;
673:
674: ret = handle->fn_send_recv(handle->pw->pw_uid, handle->pw->pw_name,
675: handle->domainname, &sss_error, &u_sss_result);
676:
677: switch (ret) {
678: case 0:
679: switch (sss_error) {
680: case 0:
681: if (u_sss_result != NULL) {
682: if (state != NULL) {
683: sudo_debug_printf(SUDO_DEBUG_DEBUG, "state |= USERMATCH");
684: *state |= _SUDO_SSS_STATE_USERMATCH;
685: }
686: sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
687: u_sss_result->num_rules);
688: } else {
689: sudo_debug_printf(SUDO_DEBUG_INFO,
690: "Internal error: u_sss_result == NULL && sss_error == 0");
691: debug_return_ptr(NULL);
692: }
693: break;
694: case ENOENT:
695: sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
696: default:
697: sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
698: debug_return_ptr(NULL);
699: }
700: break;
701: default:
702: sudo_debug_printf(SUDO_DEBUG_INFO,
703: "handle->fn_send_recv: != 0: ret=%d", ret);
704: debug_return_ptr(NULL);
705: }
706:
707: f_sss_result = sudo_sss_filter_result(handle, u_sss_result,
708: sudo_sss_result_filterp, _SUDO_SSS_FILTER_INCLUDE, NULL);
709:
710: if (f_sss_result != NULL) {
711: if (f_sss_result->num_rules > 0) {
712: if (state != NULL) {
713: sudo_debug_printf(SUDO_DEBUG_DEBUG, "state |= HOSTMATCH");
714: *state |= _SUDO_SSS_STATE_HOSTMATCH;
715: }
716: }
1.1.1.4 ! misho 717: sudo_debug_printf(SUDO_DEBUG_DEBUG,
! 718: "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result,
! 719: u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules);
! 720: } else {
! 721: sudo_debug_printf(SUDO_DEBUG_DEBUG,
! 722: "u_sss_result=(%p, %u) => f_sss_result=NULL", u_sss_result,
! 723: u_sss_result->num_rules);
1.1 misho 724: }
725:
726: handle->fn_free_result(u_sss_result);
727:
728: debug_return_ptr(f_sss_result);
729: }
730:
731: /*
732: * Search for boolean "option" in sudoOption.
733: * Returns true if found and allowed, false if negated, else UNSPEC.
734: */
735: static int
736: sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule,
737: char *option)
738: {
739: char ch, *var, **val_array = NULL;
740: int i, ret = UNSPEC;
741: debug_decl(sudo_sss_check_bool, SUDO_DEBUG_SSSD);
742:
743: if (rule == NULL)
744: debug_return_int(ret);
745:
746: switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
747: case 0:
748: break;
749: case ENOENT:
750: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
751: debug_return_int(ret);
752: default:
753: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
754: debug_return_int(ret);
755: }
756:
757: /* walk through options */
758: for (i = 0; val_array[i] != NULL; ++i) {
759: var = val_array[i];
760: sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", var);
761:
762: if ((ch = *var) == '!')
763: var++;
764: if (strcmp(var, option) == 0)
765: ret = (ch != '!');
766: }
767:
768: handle->fn_free_values(val_array);
769:
770: debug_return_int(ret);
771: }
772:
773: /*
1.1.1.2 misho 774: * If a digest prefix is present, fills in struct sudo_digest
775: * and returns a pointer to it, updating cmnd to point to the
776: * command after the digest.
777: */
778: static struct sudo_digest *
779: sudo_sss_extract_digest(char **cmnd, struct sudo_digest *digest)
780: {
781: char *ep, *cp = *cmnd;
782: int digest_type = SUDO_DIGEST_INVALID;
783: debug_decl(sudo_sss_check_command, SUDO_DEBUG_LDAP)
784:
785: /*
786: * Check for and extract a digest prefix, e.g.
787: * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
788: */
789: if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') {
790: switch (cp[3]) {
791: case '2':
792: if (cp[4] == '2' && cp[5] == '4')
793: digest_type = SUDO_DIGEST_SHA224;
794: else if (cp[4] == '5' && cp[5] == '6')
795: digest_type = SUDO_DIGEST_SHA256;
796: break;
797: case '3':
798: if (cp[4] == '8' && cp[5] == '4')
799: digest_type = SUDO_DIGEST_SHA384;
800: break;
801: case '5':
802: if (cp[4] == '1' && cp[5] == '2')
803: digest_type = SUDO_DIGEST_SHA512;
804: break;
805: }
806: if (digest_type != SUDO_DIGEST_INVALID) {
807: cp += 6;
808: while (isblank((unsigned char)*cp))
809: cp++;
810: if (*cp == ':') {
811: cp++;
812: while (isblank((unsigned char)*cp))
813: cp++;
814: ep = cp;
815: while (*ep != '\0' && !isblank((unsigned char)*ep))
816: ep++;
817: if (*ep != '\0') {
818: digest->digest_type = digest_type;
819: digest->digest_str = estrndup(cp, (size_t)(ep - cp));
820: cp = ep + 1;
821: while (isblank((unsigned char)*cp))
822: cp++;
823: *cmnd = cp;
824: sudo_debug_printf(SUDO_DEBUG_INFO,
825: "%s digest %s for %s",
826: digest_type == SUDO_DIGEST_SHA224 ? "sha224" :
827: digest_type == SUDO_DIGEST_SHA256 ? "sha256" :
828: digest_type == SUDO_DIGEST_SHA384 ? "sha384" :
829: "sha512", digest->digest_str, cp);
830: debug_return_ptr(digest);
831: }
832: }
833: }
834: }
835: debug_return_ptr(NULL);
836: }
837:
838: /*
1.1 misho 839: * Walk through search results and return true if we have a command match,
840: * false if disallowed and UNSPEC if not matched.
841: */
842: static int
843: sudo_sss_check_command(struct sudo_sss_handle *handle,
844: struct sss_sudo_rule *rule, int *setenv_implied)
845: {
846: char **val_array = NULL, *val;
847: char *allowed_cmnd, *allowed_args;
848: int i, foundbang, ret = UNSPEC;
1.1.1.2 misho 849: struct sudo_digest digest, *allowed_digest = NULL;
1.1 misho 850: debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD);
851:
852: if (rule == NULL)
853: debug_return_int(ret);
854:
855: switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) {
856: case 0:
857: break;
858: case ENOENT:
859: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
860: debug_return_int(ret);
861: default:
862: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
863: debug_return_int(ret);
864: }
865:
866: for (i = 0; val_array[i] != NULL && ret != false; ++i) {
867: val = val_array[i];
868:
869: sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
870:
871: /* Match against ALL ? */
872: if (!strcmp(val, "ALL")) {
873: ret = true;
874: if (setenv_implied != NULL)
875: *setenv_implied = true;
876: sudo_debug_printf(SUDO_DEBUG_INFO,
877: "sssd/ldap sudoCommand '%s' ... MATCH!", val);
878: continue;
879: }
880:
1.1.1.2 misho 881: /* check for sha-2 digest */
1.1.1.3 misho 882: allowed_digest = sudo_sss_extract_digest(&val, &digest);
1.1.1.2 misho 883:
1.1 misho 884: /* check for !command */
885: if (*val == '!') {
886: foundbang = true;
887: allowed_cmnd = estrdup(1 + val); /* !command */
888: } else {
889: foundbang = false;
890: allowed_cmnd = estrdup(val); /* command */
891: }
892:
893: /* split optional args away from command */
894: allowed_args = strchr(allowed_cmnd, ' ');
895: if (allowed_args)
896: *allowed_args++ = '\0';
897:
898: /* check the command like normal */
1.1.1.2 misho 899: if (command_matches(allowed_cmnd, allowed_args, NULL)) {
1.1 misho 900: /*
901: * If allowed (no bang) set ret but keep on checking.
902: * If disallowed (bang), exit loop.
903: */
904: ret = foundbang ? false : true;
905: }
906:
907: sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoCommand '%s' ... %s",
908: val, ret == true ? "MATCH!" : "not");
909: efree(allowed_cmnd); /* cleanup */
910: }
911:
912: handle->fn_free_values(val_array); /* more cleanup */
913:
914: debug_return_int(ret);
915: }
916:
917: static void
918: sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
919: {
920: int i;
921: char op, *v, *val;
922: char **val_array = NULL;
923: debug_decl(sudo_sss_parse_options, SUDO_DEBUG_SSSD);
924:
925: if (rule == NULL)
926: debug_return;
927:
928: switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
929: case 0:
930: break;
931: case ENOENT:
932: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
933: debug_return;
934: default:
935: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
936: debug_return;
937: }
938:
939: /* walk through options */
940: for (i = 0; val_array[i] != NULL; i++) {
941: sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'",
942: val_array[i]);
943: v = estrdup(val_array[i]);
944:
945: /* check for equals sign past first char */
946: val = strchr(v, '=');
947: if (val > v) {
948: *val++ = '\0'; /* split on = and truncate var */
949: op = *(val - 2); /* peek for += or -= cases */
950: if (op == '+' || op == '-') {
951: *(val - 2) = '\0'; /* found, remove extra char */
952: /* case var+=val or var-=val */
953: set_default(v, val, (int) op);
954: } else {
955: /* case var=val */
956: set_default(v, val, true);
957: }
958: } else if (*v == '!') {
959: /* case !var Boolean False */
960: set_default(v + 1, NULL, false);
961: } else {
962: /* case var Boolean True */
963: set_default(v, NULL, true);
964: }
965: efree(v);
966: }
967:
968: handle->fn_free_values(val_array);
969: debug_return;
970: }
971:
972: static int
973: sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag)
974: {
975: int rc, setenv_implied;
976:
977: struct sudo_sss_handle *handle = nss->handle;
978: struct sss_sudo_result *sss_result = NULL;
979: struct sss_sudo_rule *rule;
980: uint32_t i, state = 0;
981: debug_decl(sudo_sss_lookup, SUDO_DEBUG_SSSD);
982:
983: /* Fetch list of sudoRole entries that match user and host. */
984: sss_result = sudo_sss_result_get(nss, sudo_user.pw, &state);
985:
986: /*
987: * The following queries are only determine whether or not a
988: * password is required, so the order of the entries doesn't matter.
989: */
990: if (pwflag) {
991: int doauth = UNSPEC;
992: int matched = UNSPEC;
993: enum def_tuple pwcheck =
994: (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
995:
996: sudo_debug_printf(SUDO_DEBUG_INFO, "perform search for pwflag %d", pwflag);
997: if (sss_result != NULL) {
998: for (i = 0; i < sss_result->num_rules; i++) {
999: rule = sss_result->rules + i;
1000: if ((pwcheck == any && doauth != false) ||
1001: (pwcheck == all && doauth == false)) {
1002: doauth = sudo_sss_check_bool(handle, rule, "authenticate");
1003: }
1004: /* Only check the command when listing another user. */
1005: if (user_uid == 0 || list_pw == NULL ||
1006: user_uid == list_pw->pw_uid ||
1007: sudo_sss_check_command(handle, rule, NULL)) {
1008: matched = true;
1009: break;
1010: }
1011: }
1012: }
1013: if (matched || user_uid == 0) {
1014: SET(ret, VALIDATE_OK);
1015: CLR(ret, VALIDATE_NOT_OK);
1016: if (def_authenticate) {
1017: switch (pwcheck) {
1018: case always:
1019: SET(ret, FLAG_CHECK_USER);
1020: break;
1021: case all:
1022: case any:
1023: if (doauth == false)
1024: def_authenticate = false;
1025: break;
1026: case never:
1027: def_authenticate = false;
1028: break;
1029: default:
1030: break;
1031: }
1032: }
1033: }
1034: goto done;
1035: }
1036:
1037: sudo_debug_printf(SUDO_DEBUG_DIAG,
1038: "searching SSSD/LDAP for sudoers entries");
1039:
1040: setenv_implied = false;
1041: if (sss_result != NULL) {
1042: for (i = 0; i < sss_result->num_rules; i++) {
1043: rule = sss_result->rules + i;
1044: if (!sudo_sss_check_runas(handle, rule))
1045: continue;
1046: rc = sudo_sss_check_command(handle, rule, &setenv_implied);
1047: if (rc != UNSPEC) {
1048: /* We have a match. */
1049: sudo_debug_printf(SUDO_DEBUG_DIAG, "Command %sallowed",
1050: rc == true ? "" : "NOT ");
1051: if (rc == true) {
1052: sudo_debug_printf(SUDO_DEBUG_DEBUG, "SSSD rule: %p", rule);
1053: /* Apply entry-specific options. */
1054: if (setenv_implied)
1055: def_setenv = true;
1056: sudo_sss_parse_options(handle, rule);
1057: #ifdef HAVE_SELINUX
1058: /* Set role and type if not specified on command line. */
1059: if (user_role == NULL)
1060: user_role = def_role;
1061: if (user_type == NULL)
1062: user_type = def_type;
1063: #endif /* HAVE_SELINUX */
1064: SET(ret, VALIDATE_OK);
1065: CLR(ret, VALIDATE_NOT_OK);
1066: } else {
1067: SET(ret, VALIDATE_NOT_OK);
1068: CLR(ret, VALIDATE_OK);
1069: }
1070: break;
1071: }
1072: }
1073: }
1074: done:
1075: sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
1076:
1077: if (!ISSET(ret, VALIDATE_OK)) {
1078: /* No matching entries. */
1079: if (pwflag && list_pw == NULL)
1080: SET(ret, FLAG_NO_CHECK);
1081: }
1082:
1083: if (state & _SUDO_SSS_STATE_USERMATCH)
1084: CLR(ret, FLAG_NO_USER);
1085: if (state & _SUDO_SSS_STATE_HOSTMATCH)
1086: CLR(ret, FLAG_NO_HOST);
1087:
1088: sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_sss_lookup(%d)=0x%02x",
1089: pwflag, ret);
1090:
1091: debug_return_int(ret);
1092: }
1093:
1094: static int
1095: sudo_sss_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
1096: {
1097: struct sudo_sss_handle *handle = nss->handle;
1098: struct sss_sudo_result *sss_result = NULL;
1099: struct sss_sudo_rule *rule;
1100: int i, found = false;
1101: debug_decl(sudo_sss_display_cmnd, SUDO_DEBUG_SSSD);
1102:
1103: if (handle == NULL)
1104: goto done;
1105:
1106: if (sudo_sss_checkpw(nss, pw) != 0)
1107: debug_return_int(-1);
1108:
1109: /*
1110: * The sudo_sss_result_get() function returns all nodes that match
1111: * the user and the host.
1112: */
1113: sudo_debug_printf(SUDO_DEBUG_DIAG, "sssd/ldap search for command list");
1114: sss_result = sudo_sss_result_get(nss, pw, NULL);
1115:
1116: if (sss_result == NULL)
1117: goto done;
1118:
1119: for (i = 0; i < sss_result->num_rules; i++) {
1120: rule = sss_result->rules + i;
1121: if (sudo_sss_check_command(handle, rule, NULL) &&
1122: sudo_sss_check_runas(handle, rule)) {
1123: found = true;
1124: goto done;
1125: }
1126: }
1127:
1128: done:
1129: if (found)
1130: printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd,
1131: user_args ? " " : "", user_args ? user_args : "");
1132:
1133: if (sss_result != NULL)
1134: handle->fn_free_result(sss_result);
1135:
1136: debug_return_int(!found);
1137: }
1138:
1139: static int
1140: sudo_sss_display_defaults(struct sudo_nss *nss, struct passwd *pw,
1141: struct lbuf *lbuf)
1142: {
1143: struct sudo_sss_handle *handle = nss->handle;
1144:
1145: struct sss_sudo_rule *rule;
1146: struct sss_sudo_result *sss_result = NULL;
1147:
1148: uint32_t sss_error = 0;
1149:
1150: char *prefix, *val, **val_array = NULL;
1151: int count = 0, i, j;
1152:
1153: debug_decl(sudo_sss_display_defaults, SUDO_DEBUG_SSSD);
1154:
1155: if (handle == NULL)
1156: goto done;
1157:
1158: if (handle->fn_send_recv_defaults(pw->pw_uid, pw->pw_name,
1159: &sss_error, &handle->domainname,
1160: &sss_result) != 0) {
1161: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_send_recv_defaults: !=0, sss_error=%u", sss_error);
1162: goto done;
1163: }
1164:
1165: if (sss_error == ENOENT) {
1166: sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
1167: goto done;
1168: } else if(sss_error != 0) {
1169: sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
1170: goto done;
1171: }
1172:
1173: handle->pw = pw;
1174:
1175: for (i = 0; i < sss_result->num_rules; ++i) {
1176: rule = sss_result->rules + i;
1177:
1178: switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
1179: case 0:
1180: break;
1181: case ENOENT:
1182: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1183: continue;
1184: default:
1185: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
1186: continue;
1187: }
1188:
1189: if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
1190: prefix = " ";
1191: else
1192: prefix = ", ";
1193:
1194: for (j = 0; val_array[j] != NULL; ++j) {
1195: val = val_array[j];
1196: lbuf_append(lbuf, "%s%s", prefix, val);
1197: prefix = ", ";
1198: count++;
1199: }
1200:
1201: handle->fn_free_values(val_array);
1202: val_array = NULL;
1203: }
1204:
1205: handle->fn_free_result(sss_result);
1206: done:
1207: debug_return_int(count);
1208: }
1209:
1210: // ok
1211: static int
1212: sudo_sss_display_bound_defaults(struct sudo_nss *nss,
1213: struct passwd *pw, struct lbuf *lbuf)
1214: {
1215: debug_decl(sudo_sss_display_bound_defaults, SUDO_DEBUG_SSSD);
1216: debug_return_int(0);
1217: }
1218:
1219: static int
1220: sudo_sss_display_entry_long(struct sudo_sss_handle *handle,
1221: struct sss_sudo_rule *rule, struct lbuf *lbuf)
1222: {
1223: char **val_array = NULL;
1224: int count = 0, i;
1225: debug_decl(sudo_sss_display_entry_long, SUDO_DEBUG_SSSD);
1226:
1227: /* get the RunAsUser Values from the entry */
1228: lbuf_append(lbuf, " RunAsUsers: ");
1229: switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) {
1230: case 0:
1231: for (i = 0; val_array[i] != NULL; ++i)
1232: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1233: handle->fn_free_values(val_array);
1234: break;
1235: case ENOENT:
1236: switch (handle->fn_get_values(rule, "sudoRunAs", &val_array)) {
1237: case 0:
1238: for (i = 0; val_array[i] != NULL; ++i)
1239: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1240: handle->fn_free_values(val_array);
1241: break;
1242: case ENOENT:
1243: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1244: lbuf_append(lbuf, "%s", def_runas_default);
1245: break;
1246: default:
1247: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAs): != 0");
1248: debug_return_int(count);
1249: }
1250: break;
1251: default:
1252: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsUser): != 0");
1253: debug_return_int(count);
1254: }
1255: lbuf_append(lbuf, "\n");
1256:
1257: /* get the RunAsGroup Values from the entry */
1258: switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
1259: case 0:
1260: lbuf_append(lbuf, " RunAsGroups: ");
1261: for (i = 0; val_array[i] != NULL; ++i)
1262: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1263: handle->fn_free_values(val_array);
1264: lbuf_append(lbuf, "\n");
1265: break;
1266: case ENOENT:
1267: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1268: break;
1269: default:
1270: sudo_debug_printf(SUDO_DEBUG_INFO,
1271: "handle->fn_get_values(sudoRunAsGroup): != 0");
1272: debug_return_int(count);
1273: }
1274:
1275: /* get the Option Values from the entry */
1276: switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
1277: case 0:
1278: lbuf_append(lbuf, " Options: ");
1279: for (i = 0; val_array[i] != NULL; ++i)
1280: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1281: handle->fn_free_values(val_array);
1282: lbuf_append(lbuf, "\n");
1283: break;
1284: case ENOENT:
1285: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1286: break;
1287: default:
1288: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
1289: debug_return_int(count);
1290: }
1291:
1292: /* Get the command values from the entry. */
1293: switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) {
1294: case 0:
1295: lbuf_append(lbuf, _(" Commands:\n"));
1296: for (i = 0; val_array[i] != NULL; ++i) {
1297: lbuf_append(lbuf, "\t%s\n", val_array[i]);
1298: count++;
1299: }
1300: handle->fn_free_values(val_array);
1301: break;
1302: case ENOENT:
1303: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1304: break;
1305: default:
1306: sudo_debug_printf(SUDO_DEBUG_INFO,
1307: "handle->fn_get_values(sudoCommand): != 0");
1308: debug_return_int(count);
1309: }
1310:
1311: debug_return_int(count);
1312: }
1313:
1314: static int
1315: sudo_sss_display_entry_short(struct sudo_sss_handle *handle,
1316: struct sss_sudo_rule *rule, struct lbuf *lbuf)
1317: {
1318: char **val_array = NULL;
1319: int count = 0, i;
1320: debug_decl(sudo_sss_display_entry_short, SUDO_DEBUG_SSSD);
1321:
1322: lbuf_append(lbuf, " (");
1323:
1324: /* get the RunAsUser Values from the entry */
1325: switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) {
1326: case 0:
1327: for (i = 0; val_array[i] != NULL; ++i)
1328: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1329: handle->fn_free_values(val_array);
1330: break;
1331: case ENOENT:
1332: sudo_debug_printf(SUDO_DEBUG_INFO, "No result. Trying old style (sudoRunAs).");
1333: /* try old style */
1334: switch (handle->fn_get_values(rule, "sudoRunAs", &val_array)) {
1335: case 0:
1336: for (i = 0; val_array[i] != NULL; ++i)
1337: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1338: handle->fn_free_values(val_array);
1339: break;
1340: case ENOENT:
1341: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1342: lbuf_append(lbuf, "%s", def_runas_default);
1343: break;
1344: default:
1345: sudo_debug_printf(SUDO_DEBUG_INFO,
1346: "handle->fn_get_values(sudoRunAs): != 0");
1347: debug_return_int(count);
1348: }
1349: break;
1350: default:
1351: sudo_debug_printf(SUDO_DEBUG_INFO,
1352: "handle->fn_get_values(sudoRunAsUser): != 0");
1353: debug_return_int(count);
1354: }
1355:
1356: /* get the RunAsGroup Values from the entry */
1357: switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
1358: case 0:
1359: lbuf_append(lbuf, " : ");
1360: for (i = 0; val_array[i] != NULL; ++i)
1361: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1362: handle->fn_free_values(val_array);
1363: break;
1364: case ENOENT:
1365: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1366: break;
1367: default:
1368: sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsGroup): != 0");
1369: debug_return_int(count);
1370: }
1371:
1372: lbuf_append(lbuf, ") ");
1373:
1374: /* get the Option Values from the entry */
1375: switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
1376: case 0:
1377: for (i = 0; val_array[i] != NULL; ++i) {
1378: char *cp = val_array[i];
1379: if (*cp == '!')
1380: cp++;
1381: if (strcmp(cp, "authenticate") == 0)
1382: lbuf_append(lbuf, val_array[i][0] == '!' ?
1383: "NOPASSWD: " : "PASSWD: ");
1384: else if (strcmp(cp, "noexec") == 0)
1385: lbuf_append(lbuf, val_array[i][0] == '!' ?
1386: "EXEC: " : "NOEXEC: ");
1387: else if (strcmp(cp, "setenv") == 0)
1388: lbuf_append(lbuf, val_array[i][0] == '!' ?
1389: "NOSETENV: " : "SETENV: ");
1390: }
1391: handle->fn_free_values(val_array);
1392: break;
1393: case ENOENT:
1394: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1395: break;
1396: default:
1397: sudo_debug_printf(SUDO_DEBUG_INFO,
1398: "handle->fn_get_values(sudoOption): != 0");
1399: debug_return_int(count);
1400: }
1401:
1402: /* get the Command Values from the entry */
1403: switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) {
1404: case 0:
1405: for (i = 0; val_array[i] != NULL; ++i) {
1406: lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]);
1407: count++;
1408: }
1409: handle->fn_free_values(val_array);
1410: break;
1411: case ENOENT:
1412: sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
1413: break;
1414: default:
1415: sudo_debug_printf(SUDO_DEBUG_INFO,
1416: "handle->fn_get_values(sudoCommand): != 0");
1417: debug_return_int(count);
1418: }
1419: lbuf_append(lbuf, "\n");
1420:
1421: debug_return_int(count);
1422: }
1423:
1424: static int
1425: sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw,
1426: struct lbuf *lbuf)
1427: {
1428: struct sudo_sss_handle *handle = nss->handle;
1429:
1430: struct sss_sudo_result *sss_result = NULL;
1431: struct sss_sudo_rule *rule;
1432: unsigned int i, count = 0;
1433: debug_decl(sudo_sss_display_privs, SUDO_DEBUG_SSSD);
1434:
1435: if (handle == NULL)
1436: debug_return_int(-1);
1437: if (sudo_sss_checkpw(nss, pw) != 0)
1438: debug_return_int(-1);
1439:
1440: sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap search for command list");
1441:
1442: sss_result = sudo_sss_result_get(nss, pw, NULL);
1443:
1444: if (sss_result == NULL)
1445: debug_return_int(count);
1446:
1447: /* Display all matching entries. */
1448: for (i = 0; i < sss_result->num_rules; ++i) {
1449: rule = sss_result->rules + i;
1450: if (long_list)
1451: count += sudo_sss_display_entry_long(handle, rule, lbuf);
1452: else
1453: count += sudo_sss_display_entry_short(handle, rule, lbuf);
1454: }
1455:
1456: if (sss_result != NULL)
1457: handle->fn_free_result(sss_result);
1458:
1459: debug_return_int(count);
1460: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>