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