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

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

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