Annotation of embedaddon/sudo/plugins/sudoers/sssd.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>