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

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

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