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

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

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