2 * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
20 #include <sys/param.h>
30 #endif /* STDC_HEADERS */
34 # ifdef HAVE_STRINGS_H
37 #endif /* HAVE_STRING_H */
38 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
40 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
43 #endif /* HAVE_UNISTD_H */
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
60 static const char rcsid[] = "$Sudo: ldap.c,v 1.14 2004/09/02 04:03:25 aaron Exp $";
69 #ifndef LDAP_OPT_SUCCESS
70 #define LDAP_OPT_SUCCESS LDAP_SUCCESS
73 extern int printmatches;
75 /* ldap configuration structure */
88 char *tls_random_file;
89 char *tls_cipher_suite;
96 * Walks through search result and returns true if we have a
97 * netgroup that matches our user
102 sudo_ldap_check_user_netgroup(ld,entry)
111 if (!entry) return ret;
113 /* get the values from the entry */
114 v=ldap_get_values(ld,entry,"sudoUser");
116 /* walk through values */
117 for (p=v; p && *p && !ret;p++)
119 if (ldap_conf.debug>1) printf("ldap sudoUser netgroup '%s' ...",*p);
122 if (netgr_matches(*p,NULL,NULL,user_name)) ret=1;
124 if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not");
128 if (v) ldap_value_free(v);
136 * Walks through search result and returns true if we have a
140 sudo_ldap_check_host(ld,entry)
149 if (!entry) return ret;
151 /* get the values from the entry */
152 v=ldap_get_values(ld,entry,"sudoHost");
154 /* walk through values */
155 for (p=v; p && *p && !ret;p++)
157 if (ldap_conf.debug>1) printf("ldap sudoHost '%s' ...",*p);
159 /* match any or address or netgroup or hostname */
161 !strcasecmp(*p,"ALL") ||
163 netgr_matches(*p,user_host,user_shost,NULL) ||
164 !hostname_matches(user_shost,user_host,*p)
171 if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not");
175 if (v) ldap_value_free(v);
182 * Walks through search result and returns true if we have a
183 * runas match. Since the runas directive in /etc/sudoers is optional,
184 * so is the sudoRunAs attribute.
188 int sudo_ldap_check_runas(ld,entry)
197 if (!entry) return ret;
199 /* get the values from the entry */
200 v=ldap_get_values(ld,entry,"sudoRunAs");
204 * if runas is not specified on the command line, the only information as
205 * to which user to run as is in the runas_default option.
206 * We should check check to see if we have the local option present.
207 * Unfortunately we don't parse these options until after this routine
208 * says yes * or no. The query has already returned, so we could peek at the
209 * attribute values here though.
211 * For now just require users to always use -u option unless its set
212 * in the global defaults. This behaviour is no different than the global
215 * Sigh - maybe add this feature later
219 /* If there are no runas entries, then match the runas_default with
220 * whats on the command line
224 ret=!strcasecmp(*user_runas,def_runas_default);
227 /* what about the case where exactly one runas is specified in
228 * the config and the user forgets the -u option, should we
229 * switch it? - Probably not
232 /* walk through values returned, looking for a match*/
233 for (p=v; p && *p && !ret;p++)
235 if (ldap_conf.debug>1) printf("ldap sudoRunAs '%s' ...",*p);
238 !strcasecmp(*p,*user_runas) ||
239 !strcasecmp(*p,"ALL")
245 if (ldap_conf.debug>1) printf(" %s\n",ret ? "MATCH!" : "not");
249 if (v) ldap_value_free(v);
256 * Walks through search result and returns true if we have a
259 int sudo_ldap_check_command(ld,entry)
270 if (!entry) return ret;
272 v=ldap_get_values(ld,entry,"sudoCommand");
274 /* get_first_entry */
275 for (p=v; p && *p && ret>=0;p++){
276 if (ldap_conf.debug>1) printf("ldap sudoCommand '%s' ...",*p);
278 /* Match against ALL ? */
279 if (!strcasecmp(*p,"ALL")) {
281 if (safe_cmnd) free (safe_cmnd);
282 safe_cmnd=estrdup(user_cmnd);
283 if (ldap_conf.debug>1) printf(" MATCH!\n");
287 /* check for !command */
290 allowed_cmnd=estrdup(*p); /* command */
293 allowed_cmnd=estrdup(1+*p); /* !command */
296 /* split optional args away from command */
297 allowed_args=strchr(allowed_cmnd,' ');
298 if (allowed_args) *allowed_args++='\0';
300 /* check the command like normal */
301 if (command_matches(allowed_cmnd,allowed_args)) {
303 ret=1; /* allowed, but keep checking for a deny match */
305 ret=-1; /* denied by match, no need to check for more */
307 if (ldap_conf.debug>1) printf(" MATCH!\n");
309 if (ldap_conf.debug>1) printf(" not\n");
317 if (v) ldap_value_free(v);
320 return ret > 0; /* say true if we found at least one ALLOW and no DENY */
324 * Read sudoOption, modify the defaults as we go.
325 * This is used once from the cn=defaults entry
326 * and also once when a final sudoRole is matched.
330 sudo_ldap_parse_options(ld,entry)
334 /* used to parse attributes */
343 v=ldap_get_values(ld,entry,"sudoOption");
345 /* walk through options */
346 for (p=v; p && *p;p++){
348 if (ldap_conf.debug>1) printf("ldap sudoOption: '%s'\n",*p);
350 /* check for = char */
353 /* check for equals sign past first char */
355 *val++='\0'; /* split on = and truncate var */
356 op=*(val-2); /* peek for += or -= cases */
357 if (op == '+' || op == '-') {
358 *(val-2)='\0'; /* found, remove extra char */
359 /* case var+=val or var-=val */
360 set_default(var,val,(int)op);
363 set_default(var,val,TRUE);
365 } else if (*var=='!'){
366 /* case !var Boolean False */
367 set_default(var+1,NULL,FALSE);
369 /* case var Boolean True */
370 set_default(var,NULL,TRUE);
376 if (v) ldap_value_free(v);
381 * Concatenate strings, dynamically growing them as necessary.
382 * Strings can be arbitrarily long and are allocated/reallocated on
383 * the fly. Make sure to free them when you are done.
390 * ncat(&s,&sz,"This ");
391 * ncat(&s,&sz,"is ");
392 * ncat(&s,&sz,"an ");
393 * ncat(&s,&sz,"arbitrarily ");
394 * ncat(&s,&sz,"long ");
395 * ncat(&s,&sz,"string!");
397 * printf("String Value='%s', but has %d bytes allocated\n",s,sz);
408 /* handle initial alloc */
416 nsz= strlen(*s) + strlen(src) + 1;
417 if (*sz < nsz) *s=erealloc( (void *)*s , *sz=nsz*2);
423 * builds together a filter to check against ldap
426 sudo_ldap_build_pass1()
439 /* build filter sudoUser=user_name */
440 ncat(&b,&sz,"(sudoUser=");
441 ncat(&b,&sz,user_name);
444 /* Append primary group */
445 grp=getgrgid(getgid());
447 ncat(&b,&sz,"(sudoUser=%");
448 ncat(&b,&sz,grp->gr_name);
452 /* handle arbitrary number of groups */
453 if (0<(ngrps=getgroups(0,NULL))){
454 grplist=calloc(ngrps,sizeof(gid_t));
455 if (grplist!=NULL && (0<getgroups(ngrps,grplist)))
456 for(i=0;i<ngrps;i++){
457 if((grp=getgrgid(grplist[i]))!=NULL){
458 ncat(&b,&sz,"(sudoUser=%");
459 ncat(&b,&sz,grp->gr_name);
466 /* Add ALL to list */
467 ncat(&b,&sz,"(sudoUser=ALL)");
475 * Map yes/true/on to 1, no/false/off to 0, else -1
481 if (!strcasecmp(s,"yes") || !strcasecmp(s,"true") || !strcasecmp(s,"on"))
483 if (!strcasecmp(s,"no") || !strcasecmp(s,"false") || !strcasecmp(s,"off"))
489 sudo_ldap_read_config()
497 ldap_conf.tls_checkpeer=-1; /* default */
499 f=fopen(_PATH_LDAP_CONF,"r");
501 while (f && fgets(buf,sizeof(buf)-1,f)){
503 if (*c == '#') continue; /* ignore comment */
504 if (*c == '\n') continue; /* skip newline */
505 if (!*c) continue; /* incomplete last line */
507 /* skip whitespace before keyword */
508 while (isspace(*c)) c++;
511 /* properly terminate keyword string */
512 while (*c && !isspace(*c)) c++;
514 *c='\0'; /* terminate keyword */
518 /* skip whitespace before value */
519 while (isspace(*c)) c++;
522 /* trim whitespace after value */
523 while (*c) c++; /* wind to end */
524 while (--c > value && isspace(*c)) *c='\0';
526 /* The following macros make the code much more readable */
528 #define MATCH_S(x,y) if (!strcasecmp(keyword,x)) \
529 { if (y) free(y); y=estrdup(value); }
530 #define MATCH_I(x,y) if (!strcasecmp(keyword,x)) { y=atoi(value); }
531 #define MATCH_B(x,y) if (!strcasecmp(keyword,x)) { y=_atobool(value); }
535 /* parse values using a continues chain of
536 * if else if else if else if else ... */
537 MATCH_S("host", ldap_conf.host)
538 else MATCH_I("port", ldap_conf.port)
539 else MATCH_S("ssl", ldap_conf.ssl)
540 else MATCH_B("tls_checkpeer", ldap_conf.tls_checkpeer)
541 else MATCH_S("tls_cacertfile", ldap_conf.tls_cacertfile)
542 else MATCH_S("tls_cacertdir", ldap_conf.tls_cacertdir)
543 else MATCH_S("tls_randfile", ldap_conf.tls_random_file)
544 else MATCH_S("tls_ciphers", ldap_conf.tls_cipher_suite)
545 else MATCH_S("tls_cert", ldap_conf.tls_certfile)
546 else MATCH_S("tls_key", ldap_conf.tls_keyfile)
547 else MATCH_I("ldap_version", ldap_conf.version)
548 else MATCH_S("uri", ldap_conf.uri)
549 else MATCH_S("binddn", ldap_conf.binddn)
550 else MATCH_S("bindpw", ldap_conf.bindpw)
551 else MATCH_S("sudoers_base", ldap_conf.base)
552 else MATCH_I("sudoers_debug", ldap_conf.debug)
555 /* The keyword was unrecognized. Since this config file is shared
556 * by multiple programs, it is appropriate to silently ignore options this
557 * program does not understand
561 } /* parse next line */
566 if (!ldap_conf.version) ldap_conf.version=3;
567 if (!ldap_conf.port) ldap_conf.port=389;
568 if (!ldap_conf.host) ldap_conf.host=estrdup("localhost");
571 if (ldap_conf.debug>1) {
572 printf("LDAP Config Summary\n");
573 printf("===================\n");
574 #ifdef HAVE_LDAP_INITIALIZE
576 printf("uri %s\n", ldap_conf.uri);
580 printf("host %s\n", ldap_conf.host ?
581 ldap_conf.host : "(NONE)");
582 printf("port %d\n", ldap_conf.port);
584 printf("ldap_version %d\n", ldap_conf.version);
586 printf("sudoers_base %s\n", ldap_conf.base ?
587 ldap_conf.base : "(NONE) <---Sudo will ignore ldap)");
588 printf("binddn %s\n", ldap_conf.binddn ?
589 ldap_conf.binddn : "(anonymous)");
590 printf("bindpw %s\n", ldap_conf.bindpw ?
591 ldap_conf.bindpw : "(anonymous)");
592 #ifdef HAVE_LDAP_START_TLS_S
593 printf("ssl %s\n", ldap_conf.ssl ?
594 ldap_conf.ssl : "(no)");
596 printf("===================\n");
599 /* if no base is defined, ignore LDAP */
600 if (!ldap_conf.base) return 0;
606 like perl's join(sep,@ARGS)
609 _ldap_join_values(sep,v)
617 /* paste values together */
618 for (p=v; p && *p;p++){
619 if (p!=v && sep!=NULL) ncat(&b,&sz,sep); /* append seperator */
620 ncat(&b,&sz,*p); /* append value */
625 /* something went wrong, put something here */
626 ncat(&b,&sz,"(empty list)"); /* append value */
633 char * sudo_ldap_cm_list=NULL;
634 size_t sudo_ldap_cm_list_size;
636 #define SAVE_LIST(x) ncat(&sudo_ldap_cm_list,&sudo_ldap_cm_list_size,(x))
638 * Walks through search result and returns true if we have a
642 sudo_ldap_add_match(ld,entry)
650 /* if we are not collecting matches, then don't print them */
651 if (printmatches != TRUE) return 1;
653 /* collect the dn, only show the rdn */
654 dn=ldap_get_dn(ld,entry);
655 edn=dn ? ldap_explode_dn(dn,1) : NULL;
656 SAVE_LIST("\nLDAP Role: ");
657 SAVE_LIST((edn && *edn) ? *edn : "UNKNOWN");
659 if (dn) ldap_memfree(dn);
660 if (edn) ldap_value_free(edn);
662 /* get the Runas Values from the entry */
663 v=ldap_get_values(ld,entry,"sudoRunAs");
665 SAVE_LIST(" RunAs: (");
666 SAVE_LIST(_ldap_join_values(", ",v));
669 if (v) ldap_value_free(v);
671 /* get the Command Values from the entry */
672 v=ldap_get_values(ld,entry,"sudoCommand");
674 SAVE_LIST(" Commands:\n ");
675 SAVE_LIST(_ldap_join_values("\n ",v));
678 SAVE_LIST(" Commands: NONE\n");
680 if (v) ldap_value_free(v);
682 return 0; /* Don't stop at the first match */
687 sudo_ldap_list_matches()
689 if (sudo_ldap_cm_list!=NULL) printf("%s",sudo_ldap_cm_list);
693 * like sudoers_lookup() - only LDAP style
698 sudo_ldap_check(pwflag)
704 /* Used for searches */
705 LDAPMessage *result=NULL;
706 LDAPMessage *entry=NULL;
707 /* used to parse attributes */
709 /* temp/final return values */
714 int ldap_user_matches=0;
715 int ldap_host_matches=0;
717 if (!sudo_ldap_read_config()) return VALIDATE_ERROR;
719 /* macro to set option, error on failure plus consistent debugging */
720 #define SET_OPT(opt,optname,val) \
721 if (ldap_conf.val!=NULL) { \
722 if (ldap_conf.debug>1) fprintf(stderr, \
723 "ldap_set_option(LDAP_OPT_%s,\"%s\")\n",optname,ldap_conf.val); \
724 rc=ldap_set_option(ld,opt,ldap_conf.val); \
725 if(rc != LDAP_OPT_SUCCESS){ \
726 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s,\"%s\")=%d: %s\n", \
727 optname, ldap_conf.val, rc, ldap_err2string(rc)); \
728 return VALIDATE_ERROR ; \
732 /* like above, but assumes val is in int */
733 #define SET_OPTI(opt,optname,val) \
734 if (ldap_conf.debug>1) fprintf(stderr, \
735 "ldap_set_option(LDAP_OPT_%s,0x%02x)\n",optname,ldap_conf.val); \
736 rc=ldap_set_option(ld,opt,&ldap_conf.val); \
737 if(rc != LDAP_OPT_SUCCESS){ \
738 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s,0x%02x)=%d: %s\n", \
739 optname, ldap_conf.val, rc, ldap_err2string(rc)); \
740 return VALIDATE_ERROR ; \
743 /* attempt to setup ssl options */
744 #ifdef LDAP_OPT_X_TLS_CACERTFILE
745 SET_OPT(LDAP_OPT_X_TLS_CACERTFILE, "X_TLS_CACERTFILE", tls_cacertfile);
746 #endif /* LDAP_OPT_X_TLS_CACERTFILE */
748 #ifdef LDAP_OPT_X_TLS_CACERTDIR
749 SET_OPT(LDAP_OPT_X_TLS_CACERTDIR, "X_TLS_CACERTDIR", tls_cacertdir);
750 #endif /* LDAP_OPT_X_TLS_CACERTDIR */
752 #ifdef LDAP_OPT_X_TLS_CERTFILE
753 SET_OPT(LDAP_OPT_X_TLS_CERTFILE, "X_TLS_CERTFILE", tls_certfile);
754 #endif /* LDAP_OPT_X_TLS_CERTFILE */
756 #ifdef LDAP_OPT_X_TLS_KEYFILE
757 SET_OPT(LDAP_OPT_X_TLS_KEYFILE, "X_TLS_KEYFILE", tls_keyfile);
758 #endif /* LDAP_OPT_X_TLS_KEYFILE */
760 #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
761 SET_OPT(LDAP_OPT_X_TLS_CIPHER_SUITE, "X_TLS_CIPHER_SUITE", tls_cipher_suite);
762 #endif /* LDAP_OPT_X_TLS_CIPHER_SUITE */
764 #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
765 SET_OPT(LDAP_OPT_X_TLS_RANDOM_FILE, "X_TLS_RANDOM_FILE", tls_random_file);
766 #endif /* LDAP_OPT_X_TLS_RANDOM_FILE */
768 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
769 /* check the server certificate? */
770 if (ldap_conf.tls_checkpeer!=-1){
771 SET_OPTI(LDAP_OPT_X_TLS_REQUIRE_CERT,"X_TLS_REQUIRE_CERT",tls_checkpeer);
773 #endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */
775 /* attempt connect */
776 #ifdef HAVE_LDAP_INITIALIZE
779 if (ldap_conf.debug>1) fprintf(stderr,
780 "ldap_initialize(ld,%s)\n",ldap_conf.uri);
782 rc=ldap_initialize(&ld,ldap_conf.uri);
784 fprintf(stderr, "ldap_initialize()=%d : %s\n",
785 rc,ldap_err2string(rc));
786 return VALIDATE_ERROR;
789 #endif /* HAVE_LDAP_INITIALIZE */
790 if (ldap_conf.host) {
792 if (ldap_conf.debug>1) fprintf(stderr,
793 "ldap_init(%s,%d)\n",ldap_conf.host,ldap_conf.port);
795 ld=ldap_init(ldap_conf.host,ldap_conf.port);
797 fprintf(stderr, "ldap_init(): errno=%d : %s\n",
798 errno, strerror(errno));
799 return VALIDATE_ERROR;
803 #ifdef LDAP_OPT_PROTOCOL_VERSION
805 /* Set the LDAP Protocol version */
806 SET_OPTI(LDAP_OPT_PROTOCOL_VERSION,"PROTOCOL_VERSION", version);
808 #endif /* LDAP_OPT_PROTOCOL_VERSION */
810 #ifdef HAVE_LDAP_START_TLS_S
812 if (ldap_conf.ssl && !strcasecmp(ldap_conf.ssl, "start_tls")){
813 rc = ldap_start_tls_s(ld, NULL, NULL);
814 if (rc != LDAP_SUCCESS) {
815 fprintf(stderr, "ldap_start_tls_s(): %d: %s\n", rc, ldap_err2string(rc));
817 return VALIDATE_ERROR;
820 if (ldap_conf.debug) printf("ldap_start_tls_s() ok\n");
822 #endif /* HAVE_LDAP_START_TLS_S */
824 /* Actually connect */
826 rc=ldap_simple_bind_s(ld,ldap_conf.binddn,ldap_conf.bindpw);
828 fprintf(stderr,"ldap_simple_bind_s()=%d : %s\n",
829 rc, ldap_err2string(rc));
830 return VALIDATE_ERROR ;
833 if (ldap_conf.debug) printf("ldap_bind() ok\n");
836 /* Parse Default Options */
838 rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL,
839 "cn=defaults",NULL,0,&result);
840 if (!rc && (entry=ldap_first_entry(ld,result))){
841 if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry));
842 sudo_ldap_parse_options(ld,entry);
844 if (ldap_conf.debug) printf("no default options found!\n");
847 if (result) ldap_msgfree(result);
851 * Okay - time to search for anything that matches this user
852 * Lets limit it to only two queries of the LDAP server
854 * The first pass will look by the username, groups, and
855 * the keyword ALL. We will then inspect the results that
856 * came back from the query. We don't need to inspect the
857 * sudoUser in this pass since the LDAP server already scanned
860 * The second pass will return all the entries that contain
861 * user netgroups. Then we take the netgroups returned and
862 * try to match them against the username.
866 for(pass=1;!ret && pass<=2;pass++){
869 /* Want the entries that match our usernames or groups */
870 filt=sudo_ldap_build_pass1();
871 } else { /* pass=2 */
872 /* Want the entries that have user netgroups in them. */
873 filt=strdup("sudoUser=+*");
875 if (ldap_conf.debug) printf("ldap search '%s'\n",filt);
876 rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL,
877 filt,NULL,0,&result);
879 if (ldap_conf.debug) printf("nothing found for '%s'\n",filt);
881 if (filt) free (filt);
882 /* parse each entry returned from this most recent search */
884 entry=rc ? NULL : ldap_first_entry(ld,result);
886 entry=ldap_next_entry(ld,entry))
888 if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry));
890 /* first verify user netgroup matches - only if in pass 2 */
891 (pass!=2 || sudo_ldap_check_user_netgroup(ld,entry)) &&
892 /* remember that user matched */
893 (ldap_user_matches=-1) &&
894 /* verify host match */
895 sudo_ldap_check_host(ld,entry) &&
896 /* remember that host matched */
897 (ldap_host_matches=-1) &&
898 /* add matches for listing later */
899 sudo_ldap_add_match(ld,entry) &&
900 /* verify command match */
901 sudo_ldap_check_command(ld,entry) &&
902 /* verify runas match */
903 sudo_ldap_check_runas(ld,entry)
906 /* We have a match! */
907 if(ldap_conf.debug) printf("Perfect Matched!\n");
908 /* pick up any options */
909 sudo_ldap_parse_options(ld,entry);
910 /* make sure we dont reenter loop */
912 /* break from inside for loop */
917 if (result) ldap_msgfree(result);
922 /* shut down connection */
923 if (ld) ldap_unbind_s(ld);
926 if (ldap_conf.debug) printf("user_matches=%d\n",ldap_user_matches);
927 if (ldap_conf.debug) printf("host_matches=%d\n",ldap_host_matches);
929 /* Check for special case for -v, -k, -l options */
930 if (pwflag && ldap_user_matches && ldap_host_matches){
932 * Handle verifypw & listpw
934 * To be extra paranoid, since we haven't read any NOPASSWD options
935 * in /etc/sudoers yet, but we have to make the decission now, lets
936 * assume the worst and prefer to prompt for password unless the setting
937 * is "never". (example verifypw=never or listpw=never)
940 if (pwflag<0) { /* -k */
941 ret=VALIDATE_OK; SET(ret,FLAG_NOPASS);
942 } else if (sudo_defs_table[pwflag].sd_un.tuple == never){ /* see note above */
943 ret=VALIDATE_OK; SET(ret,FLAG_NOPASS);
945 ret=VALIDATE_OK; /* extra paranoid */
949 if (ISSET(ret,VALIDATE_OK)) {
950 /* We have a match. Should we check the password? */
951 /* Note: This could be the global or a rule specific option */
952 if (!def_authenticate) SET(ret,FLAG_NOPASS);
953 /* Same logic with noexec */
954 if (def_noexec) SET(ret,FLAG_NOEXEC);
956 /* we do not have a match */
958 if (!ldap_user_matches) SET(ret,FLAG_NO_USER);
959 else if (!ldap_host_matches) SET(ret,FLAG_NO_HOST);
962 if (ldap_conf.debug) printf("sudo_ldap_check(%d)=0x%02x\n",pwflag,ret);