From b0226e939bed27cf70d7ea80aa894e80bdccac65 Mon Sep 17 00:00:00 2001 From: Aaron Spangler Date: Fri, 13 Feb 2004 02:08:27 +0000 Subject: [PATCH] Merged in LDAP Support --- ldap.c | 860 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sudo.c | 28 +- sudo.h | 3 + 3 files changed, 888 insertions(+), 3 deletions(-) create mode 100644 ldap.c diff --git a/ldap.c b/ldap.c new file mode 100644 index 000000000..907138f92 --- /dev/null +++ b/ldap.c @@ -0,0 +1,860 @@ +/* + * Copyright (c) 1996, 1998-2002 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. Products derived from this software may not be called "Sudo" nor + * may "Sudo" appear in their names without specific prior written + * permission from the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LBER_H +#include +#endif + +#include "sudo.h" +#include "parse.h" + +#ifndef lint +static const char rcsid[] = "$Sudo$"; +#endif /* lint */ + +/* LDAP code below */ + +#ifndef LDAP_CONFIG +#define LDAP_CONFIG "/etc/ldap.conf" +#endif + +#ifndef BUF_SIZ +#define BUF_SIZ 1024 +#endif + +extern int printmatches; + +/* ldap configuration structure */ +struct ldap_config { + char *host; + int port; + int version; + char *uri; + char *binddn; + char *bindpw; + char *base; + int debug; +} ldap_conf; + +/* + * Walks through search result and returns true if we have a + * netgroup that matches our user + */ + + +int +sudo_ldap_check_user_netgroup(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + char **v=NULL; + char **p=NULL; + + int ret=0; + + if (!entry) return ret; + + /* get the values from the entry */ + v=ldap_get_values(ld,entry,"sudoUser"); + + /* walk through values */ + for (p=v; p && *p && !ret;p++) + { + if (ldap_conf.debug>1) printf("ldap sudoUser netgroup '%s' ...",*p); + + /* match any */ + if (netgr_matches(*p,NULL,NULL,user_name)) ret=1; + + if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not"); + } + + /* cleanup */ + if (v) ldap_value_free(v); + + /* all done */ + return ret; +} + + +/* + * Walks through search result and returns true if we have a + * host match + */ +int +sudo_ldap_check_host(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + char **v=NULL; + char **p=NULL; + + int ret=0; + + if (!entry) return ret; + + /* get the values from the entry */ + v=ldap_get_values(ld,entry,"sudoHost"); + + /* walk through values */ + for (p=v; p && *p && !ret;p++) + { + if (ldap_conf.debug>1) printf("ldap sudoHost '%s' ...",*p); + + /* match any or address or netgroup or hostname */ + if ( + !strcasecmp(*p,"ALL") || + addr_matches(*p) || + netgr_matches(*p,user_host,user_shost,NULL) || + !hostname_matches(user_shost,user_host,*p) + ) + { + ret=1; + } + + + if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not"); + } + + /* cleanup */ + if (v) ldap_value_free(v); + + /* all done */ + return ret; +} + +/* + * Walks through search result and returns true if we have a + * runas match. Since the runas directive in /etc/sudoers is optional, + * so is the sudoRunAs attribute. + * + */ + +int sudo_ldap_check_runas(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + char **v=NULL; + char **p=NULL; + + int ret=0; + + if (!entry) return ret; + + /* get the values from the entry */ + v=ldap_get_values(ld,entry,"sudoRunAs"); + + /* BUG: + * + * if runas is not specified on the command line, the only information as + * to which user to run as is in the runas_default option. + * We should check check to see if we have the local option present. + * Unfortunately we don't parse these options until after this routine + * says yes * or no. The query has already returned, so we could peek at the + * attribute values here though. + * + * For now just require users to always use -u option unless its set + * in the global defaults. This behaviour is no different than the global + * /etc/sudoers. + * + * Sigh - maybe add this feature later + * + */ + + /* If there are no runas entries, then match the runas_default with + * whats on the command line + */ + if (!v) + { + ret=!strcasecmp(*user_runas,def_runas_default); + } + + /* what about the case where exactly one runas is specified in + * the config and the user forgets the -u option, should we + * switch it? - Probably not + */ + + /* walk through values returned, looking for a match*/ + for (p=v; p && *p && !ret;p++) + { + if (ldap_conf.debug>1) printf("ldap sudoRunAs '%s' ...",*p); + + if ( + !strcasecmp(*p,*user_runas) || + !strcasecmp(*p,"ALL") + ) + { + ret = 1; + } + + if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not"); + } + + /* cleanup */ + if (v) ldap_value_free(v); + + /* all done */ + return ret; +} + +/* + * Walks through search result and returns true if we have a + * command match + */ +int sudo_ldap_check_command(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + char **v=NULL; + char **p=NULL; + char *allowed_cmnd; + char *allowed_args; + int ret=0; + + if (!entry) return ret; + + v=ldap_get_values(ld,entry,"sudoCommand"); + + /* get_first_entry */ + for (p=v; p && *p && !ret;p++){ + if (ldap_conf.debug>1) printf("ldap sudoCommand '%s' ...",*p); + + /* Match against ALL ? */ + if (!strcasecmp(*p,"ALL")) { + ret=1; + if (safe_cmnd) free (safe_cmnd); + safe_cmnd=estrdup(user_cmnd); + } + + /* split optional args away from command */ + allowed_cmnd=estrdup(*p); + allowed_args=strchr(allowed_cmnd,' '); + if (allowed_args) *allowed_args++='\0'; + + /* check the command like normal */ + if (command_matches(user_cmnd, user_args,allowed_cmnd,allowed_args)) ret=1; + + /* cleanup */ + free(allowed_cmnd); + if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not"); + } + + /* more cleanup */ + if (v) ldap_value_free(v); + + /* all done */ + return ret; +} + +/* + * Read sudoOption, modify the defaults as we go. + * This is used once from the cn=defaults entry + * and also once when a final sudoRole is matched. + * + */ +void +sudo_ldap_parse_options(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + /* used to parse attributes */ + char **v=NULL; + char **p=NULL; + char *var; + char *val; + char op; + + if (!entry) return; + + v=ldap_get_values(ld,entry,"sudoOption"); + + /* walk through options */ + for (p=v; p && *p;p++){ + + if (ldap_conf.debug>1) printf("ldap sudoOption: '%s'\n",*p); + var=estrdup(*p); + /* check for = char */ + val=strchr(var,'='); + + /* check for equals sign past first char */ + if (val>var){ + *val++='\0'; /* split on = and truncate var */ + op=*(val-2); /* peek for += or -= cases */ + if (op == '+' || op == '-') { + *(val-2)='\0'; /* found, remove extra char */ + /* case var+=val or var-=val */ + set_default(var,val,(int)op); + } else { + /* case var=val */ + set_default(var,val,TRUE); + } + } else if (*var=='!'){ + /* case !var Boolean False */ + set_default(var+1,NULL,FALSE); + } else { + /* case var Boolean True */ + set_default(var,NULL,TRUE); + } + free(var); + + } + + if (v) ldap_value_free(v); + +} + +/* + * Concatenate strings, dynamically growing them as necessary. + * Strings can be arbitrarily long and are allocated/reallocated on + * the fly. Make sure to free them when you are done. + * + * Usage: + * + * char *s=NULL; + * size_t sz; + * + * ncat(&s,&sz,"This "); + * ncat(&s,&sz,"is "); + * ncat(&s,&sz,"an "); + * ncat(&s,&sz,"arbitrarily "); + * ncat(&s,&sz,"long "); + * ncat(&s,&sz,"string!"); + * + * printf("String Value='%s', but has %d bytes allocated\n",s,sz); + * + */ +void +ncat(s,sz,src) + char **s; + size_t *sz; + char *src; +{ + size_t nsz; + + /* handle initial alloc */ + if (*s == NULL){ + *s=estrdup(src); + *sz=strlen(src)+1; + return; + } + + /* handle realloc */ + nsz= strlen(*s) + strlen(src) + 1; + if (*sz < nsz) *s=erealloc( (void *)*s , *sz=nsz*2); + strlcat(*s,src,*sz); +} + + +/* + * builds together a filter to check against ldap + */ +char * +sudo_ldap_build_pass1() +{ + struct group *grp; + gid_t *grplist=NULL; + int ngrps; + int i; + + char *b=NULL; + size_t sz; + + /* global OR */ + ncat(&b,&sz,"(|"); + + /* build filter sudoUser=user_name */ + ncat(&b,&sz,"(sudoUser="); + ncat(&b,&sz,user_name); + ncat(&b,&sz,")"); + + /* Append primary group */ + grp=getgrgid(getgid()); + if (grp!=NULL){ + ncat(&b,&sz,"(sudoUser=%"); + ncat(&b,&sz,grp->gr_name); + ncat(&b,&sz,")"); + } + + /* handle arbitrary number of groups */ + if (0<(ngrps=getgroups(0,NULL))){ + grplist=calloc(ngrps,sizeof(gid_t)); + if (grplist!=NULL && (0gr_name); + ncat(&b,&sz,")"); + } + } + } + + + /* Add ALL to list */ + ncat(&b,&sz,"(sudoUser=ALL)"); + + /* End of OR List */ + ncat(&b,&sz,")"); + return b ; +} + + +int +sudo_ldap_read_config() +{ + FILE *f; + char buf[BUF_SIZ]; + char *c; + char *keyword; + char *value; + + f=fopen(LDAP_CONFIG,"r"); + if (!f) return 0; + while (f && fgets(buf,sizeof(buf)-1,f)){ + c=buf; + if (*c == '#') continue; /* ignore comment */ + if (*c == '\n') continue; /* skip newline */ + if (!*c) continue; /* incomplete last line */ + + /* skip whitespace before keyword */ + while (isspace(*c)) c++; + keyword=c; + + /* properly terminate keyword string */ + while (*c && !isspace(*c)) c++; + if (*c) { + *c='\0'; /* terminate keyword */ + c++; + } + + /* skip whitespace before value */ + while (isspace(*c)) c++; + value=c; + + /* trim whitespace after value */ + while (*c) c++; /* wind to end */ + while (--c > value && isspace(*c)) *c='\0'; + + /* The following macros make the code much more readable */ + +#define MATCH_S(x,y) if (!strcasecmp(keyword,x)) \ + { if (y) free(y); y=estrdup(value); } +#define MATCH_I(x,y) if (!strcasecmp(keyword,x)) { y=atoi(value); } + + + + /* parse values using a continues chain of + * if else if else if else if else ... */ + MATCH_S("host", ldap_conf.host) + else MATCH_I("port", ldap_conf.port) + else MATCH_I("ldap_version", ldap_conf.version) + else MATCH_S("uri", ldap_conf.uri) + else MATCH_S("binddn", ldap_conf.binddn) + else MATCH_S("bindpw", ldap_conf.bindpw) + else MATCH_S("sudoers_base", ldap_conf.base) + else MATCH_I("sudoers_debug", ldap_conf.debug) + else { + + /* The keyword was unrecognized. Since this config file is shared + * by multiple programs, it is appropriate to silently ignore options this + * program does not understand + */ + } + + } /* parse next line */ + + if (f) fclose(f); + + /* defaults */ + if (!ldap_conf.version) ldap_conf.version=3; + if (!ldap_conf.port) ldap_conf.port=389; + if (!ldap_conf.host) ldap_conf.host=estrdup("localhost"); + + + if (ldap_conf.debug>1) { + printf("LDAP Config Summary\n"); + printf("===================\n"); + printf("host %s\n", ldap_conf.host ? + ldap_conf.host : "(NONE)"); + printf("port %d\n", ldap_conf.port); + printf("ldap_version %d\n", ldap_conf.version); + + printf("uri %s\n", ldap_conf.uri ? + ldap_conf.uri : "(NONE)"); + printf("sudoers_base %s\n", ldap_conf.base ? + ldap_conf.base : "(NONE) <---Sudo will ignore ldap)"); + printf("binddn %s\n", ldap_conf.binddn ? + ldap_conf.binddn : "(anonymous)"); + printf("bindpw %s\n", ldap_conf.bindpw ? + ldap_conf.bindpw : "(anonymous)"); + printf("===================\n"); + } + + /* if no base is defined, ignore LDAP */ + if (!ldap_conf.base) return 0; + /* All is good */ + return 1; +} + +/* + like perl's join(sep,@ARGS) +*/ +char * +_ldap_join_values(sep,v) + char *sep; + char **v; +{ + char **p=NULL; + char *b=NULL; + size_t sz=0; + + /* paste values together */ + for (p=v; p && *p;p++){ + if (p!=v && sep!=NULL) ncat(&b,&sz,sep); /* append seperator */ + ncat(&b,&sz,*p); /* append value */ + } + + /* sanity check */ + if (b[0]=='\0'){ + /* something went wrong, put something here */ + ncat(&b,&sz,"(empty list)"); /* append value */ + } + + /* all done */ + return b; +} + +char * sudo_ldap_cm_list=NULL; +size_t sudo_ldap_cm_list_size; + +#define SAVE_LIST(x) ncat(&sudo_ldap_cm_list,&sudo_ldap_cm_list_size,(x)) +/* + * Walks through search result and returns true if we have a + * command match + */ +int +sudo_ldap_add_match(ld,entry) + LDAP *ld; + LDAPMessage *entry; +{ + char **v=NULL; + char *dn; + char **edn; + + /* if we are not collecting matches, then don't print them */ + if (printmatches != TRUE) return 1; + + /* collect the dn, only show the rdn */ + dn=ldap_get_dn(ld,entry); + if (dn) edn=ldap_explode_dn(dn,1); + SAVE_LIST("\nLDAP Role: "); + SAVE_LIST((edn && *edn) ? *edn : "UNKNOWN"); + SAVE_LIST("\n"); + if (dn) ldap_memfree(dn); + if (edn) ldap_value_free(edn); + + /* get the Runas Values from the entry */ + v=ldap_get_values(ld,entry,"sudoRunAs"); + if (v && *v){ + SAVE_LIST(" RunAs: ("); + SAVE_LIST(_ldap_join_values(", ",v)); + SAVE_LIST(")\n"); + } + if (v) ldap_value_free(v); + + /* get the Command Values from the entry */ + v=ldap_get_values(ld,entry,"sudoCommand"); + if (v && *v){ + SAVE_LIST(" Commands:\n "); + SAVE_LIST(_ldap_join_values("\n ",v)); + SAVE_LIST("\n"); + } else { + SAVE_LIST(" Commands: NONE\n"); + } + if (v) ldap_value_free(v); + + return 0; /* Don't stop at the first match */ +} +#undef SAVE_LIST + +void +sudo_ldap_list_matches() +{ + if (sudo_ldap_cm_list!=NULL) printf("%s",sudo_ldap_cm_list); +} + +/* + * like sudoers_lookup() - only LDAP style + * + */ + +int +sudo_ldap_check(pwflag) +int pwflag; +{ + + LDAP *ld=NULL; + + /* Used for searches */ + LDAPMessage *result=NULL; + LDAPMessage *entry=NULL; + /* used to parse attributes */ + char *filt; + /* temp/final return values */ + int rc=0; + int ret=0; + int pass=0; + /* flags */ + int ldap_user_matches=0; + int ldap_host_matches=0; + + if (!sudo_ldap_read_config()) return VALIDATE_ERROR; + + + /* attempt connect */ +#ifdef HAVE_LDAP_INITIALIZE + if (ldap_conf.uri) { + + if (ldap_conf.debug>1) fprintf(stderr, + "ldap_initialize(ld,%s)\n",ldap_conf.uri); + + rc=ldap_initialize(&ld,ldap_conf.uri); + if(rc){ + fprintf(stderr, "ldap_initialize()=%d : %s\n", + rc,ldap_err2string(rc)); + return VALIDATE_ERROR; + } + } else +#endif /* HAVE_LDAP_INITIALIZE */ + if (ldap_conf.host) { + + if (ldap_conf.debug>1) fprintf(stderr, + "ldap_init(%s,%d)\n",ldap_conf.host,ldap_conf.port); + + ld=ldap_init(ldap_conf.host,ldap_conf.port); + if (!ld) { + fprintf(stderr, "ldap_init(): errno=%d : %s\n", + errno, strerror(errno)); + return VALIDATE_ERROR; + } + } + +#ifdef LDAP_OPT_PROTOCOL_VERSION + + /* Set the LDAP Protocol version */ + + rc=ldap_set_option(ld,LDAP_OPT_PROTOCOL_VERSION,&ldap_conf.version); + if(rc){ + fprintf(stderr,"ldap_set_option(protocol=%d)=%d : %s\n", + ldap_conf.version, rc, ldap_err2string(rc)); + return VALIDATE_ERROR ; + } + +#endif /* LDAP_OPT_PROTOCOL_VERSION */ + + /* Actually connect */ + + rc=ldap_simple_bind_s(ld,ldap_conf.binddn,ldap_conf.bindpw); + if(rc){ + fprintf(stderr,"ldap_simple_bind_s()=%d : %s\n", + rc, ldap_err2string(rc)); + return VALIDATE_ERROR ; + } + + if (ldap_conf.debug) printf("ldap_bind() ok\n"); + + + /* Parse Default Options */ + + rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL, + "cn=defaults",NULL,0,&result); + if (!rc && (entry=ldap_first_entry(ld,result))){ + if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry)); + sudo_ldap_parse_options(ld,entry); + } else { + if (ldap_conf.debug) printf("no default options found!\n"); + } + + if (result) ldap_msgfree(result); + result=NULL; + + /* + * Okay - time to search for anything that matches this user + * Lets limit it to only two queries of the LDAP server + * + * The first pass will look by the username, groups, and + * the keyword ALL. We will then inspect the results that + * came back from the query. We don't need to inspect the + * sudoUser in this pass since the LDAP server already scanned + * it for us. + * + * The second pass will return all the entries that contain + * user netgroups. Then we take the netgroups returned and + * try to match them against the username. + * + */ + + for(pass=1;!ret && pass<=2;pass++){ + + if (pass==1) { + /* Want the entries that match our usernames or groups */ + filt=sudo_ldap_build_pass1(); + } else { /* pass=2 */ + /* Want the entries that have user netgroups in them. */ + filt=strdup("sudoUser=+*"); + } + if (ldap_conf.debug) printf("ldap search '%s'\n",filt); + rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL, + filt,NULL,0,&result); + if (rc) { + if (ldap_conf.debug) printf("nothing found for '%s'\n",filt); + } + if (filt) free (filt); + /* parse each entry returned from this most recent search */ + for( + entry=rc ? NULL : ldap_first_entry(ld,result); + entry!=NULL; + entry=ldap_next_entry(ld,entry)) + { + if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry)); + if ( + /* first verify user netgroup matches - only if in pass 2 */ + (pass!=2 || sudo_ldap_check_user_netgroup(ld,entry)) && + /* remember that user matched */ + (ldap_user_matches=-1) && + /* verify host match */ + sudo_ldap_check_host(ld,entry) && + /* remember that host matched */ + (ldap_host_matches=-1) && + /* add matches for listing later */ + sudo_ldap_add_match(ld,entry) && + /* verify command match */ + sudo_ldap_check_command(ld,entry) && + /* verify runas match */ + sudo_ldap_check_runas(ld,entry) + ) + { + /* We have a match! */ + if(ldap_conf.debug) printf("Perfect Matched!\n"); + /* pick up any options */ + sudo_ldap_parse_options(ld,entry); + /* make sure we dont reenter loop */ + ret=VALIDATE_OK; + /* break from inside for loop */ + break; + } + + } + if (result) ldap_msgfree(result); + result=NULL; + + } + + /* shut down connection */ + if (ld) ldap_unbind_s(ld); + + + if (ldap_conf.debug) printf("user_matches=%d\n",ldap_user_matches); + if (ldap_conf.debug) printf("host_matches=%d\n",ldap_host_matches); + + /* Check for special case for -v, -k, -l options */ + if (pwflag && ldap_user_matches && ldap_host_matches){ + /* + * Handle verifypw & listpw + * + * To be extra paranoid, since we haven't read any NOPASSWD options + * in /etc/sudoers yet, but we have to make the decission now, lets + * assume the worst and prefer to prompt for password unless the setting + * is "never". (example verifypw=never or listpw=never) + * + */ + if (pwflag<0) { /* -k */ + ret=VALIDATE_OK; SET(ret,FLAG_NOPASS); + } else if (sudo_defs_table[pwflag].sd_un.tuple == never){ /* see note above */ + ret=VALIDATE_OK; SET(ret,FLAG_NOPASS); + } else { + ret=VALIDATE_OK; /* extra paranoid */ + } + } + + if (ISSET(ret,VALIDATE_OK)) { + /* We have a match. Should we check the password? */ + /* Note: This could be the global or a rule specific option */ + if (!def_authenticate) SET(ret,FLAG_NOPASS); + /* Same logic with noexec */ + if (def_noexec) SET(ret,FLAG_NOEXEC); + } else { + /* we do not have a match */ + ret=VALIDATE_NOT_OK; + if (!ldap_user_matches) SET(ret,FLAG_NO_USER); + else if (!ldap_host_matches) SET(ret,FLAG_NO_HOST); + } + + if (ldap_conf.debug) printf("sudo_ldap_check(%d)=0x%02x\n",pwflag,ret); + + return ret ; +} diff --git a/sudo.c b/sudo.c index f42dbf317..b1ff52db6 100644 --- a/sudo.c +++ b/sudo.c @@ -265,10 +265,29 @@ main(argc, argv, envp) cmnd_status = init_vars(sudo_mode); - check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ +#ifdef HAVE_LDAP + validated = sudo_ldap_check(pwflag); + + /* Skip reading /etc/sudoers if LDAP told us to */ + if (def_ignore_local_sudoers); /* skips */ + else if (ISSET(validated, VALIDATE_OK) && !printmatches); /* skips */ + else if (ISSET(validated, VALIDATE_OK) && printmatches) + { + check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ + + /* User is found in LDAP and we want a list of all sudo commands the + * user can do, so consult sudoers but throw away result. + */ + sudoers_lookup(pwflag); + } + else +#endif + { + check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ - /* Validate the user but don't search for pseudo-commands. */ - validated = sudoers_lookup(pwflag); + /* Validate the user but don't search for pseudo-commands. */ + validated = sudoers_lookup(pwflag); + } /* * If we are using set_perms_posix() and the stay_setuid flag was not set, @@ -379,6 +398,9 @@ main(argc, argv, envp) exit(0); else if (sudo_mode == MODE_LIST) { list_matches(); +#ifdef HAVE_LDAP + sudo_ldap_list_matches(); +#endif exit(0); } diff --git a/sudo.h b/sudo.h index c755f63d2..9cd46fb68 100644 --- a/sudo.h +++ b/sudo.h @@ -208,6 +208,9 @@ int find_path __P((char *, char **, char *)); void check_user __P((int)); void verify_user __P((struct passwd *, char *)); int sudoers_lookup __P((int)); +#ifdef HAVE_LDAP +int sudo_ldap_check __P((int)); +#endif void set_perms_nosuid __P((int)); void set_perms_posix __P((int)); void set_perms_suid __P((int)); -- 2.40.0