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 (ldap_conf.debug>1) printf(" MATCH!\n");
285 /* check for !command */
288 allowed_cmnd=estrdup(*p); /* command */
291 allowed_cmnd=estrdup(1+*p); /* !command */
294 /* split optional args away from command */
295 allowed_args=strchr(allowed_cmnd,' ');
296 if (allowed_args) *allowed_args++='\0';
298 /* check the command like normal */
299 if (command_matches(allowed_cmnd,allowed_args)) {
301 ret=1; /* allowed, but keep checking for a deny match */
303 ret=-1; /* denied by match, no need to check for more */
305 if (ldap_conf.debug>1) printf(" MATCH!\n");
307 if (ldap_conf.debug>1) printf(" not\n");
315 if (v) ldap_value_free(v);
318 return ret > 0; /* say true if we found at least one ALLOW and no DENY */
322 * Read sudoOption, modify the defaults as we go.
323 * This is used once from the cn=defaults entry
324 * and also once when a final sudoRole is matched.
328 sudo_ldap_parse_options(ld,entry)
332 /* used to parse attributes */
341 v=ldap_get_values(ld,entry,"sudoOption");
343 /* walk through options */
344 for (p=v; p && *p;p++){
346 if (ldap_conf.debug>1) printf("ldap sudoOption: '%s'\n",*p);
348 /* check for = char */
351 /* check for equals sign past first char */
353 *val++='\0'; /* split on = and truncate var */
354 op=*(val-2); /* peek for += or -= cases */
355 if (op == '+' || op == '-') {
356 *(val-2)='\0'; /* found, remove extra char */
357 /* case var+=val or var-=val */
358 set_default(var,val,(int)op);
361 set_default(var,val,TRUE);
363 } else if (*var=='!'){
364 /* case !var Boolean False */
365 set_default(var+1,NULL,FALSE);
367 /* case var Boolean True */
368 set_default(var,NULL,TRUE);
374 if (v) ldap_value_free(v);
379 * Concatenate strings, dynamically growing them as necessary.
380 * Strings can be arbitrarily long and are allocated/reallocated on
381 * the fly. Make sure to free them when you are done.
388 * ncat(&s,&sz,"This ");
389 * ncat(&s,&sz,"is ");
390 * ncat(&s,&sz,"an ");
391 * ncat(&s,&sz,"arbitrarily ");
392 * ncat(&s,&sz,"long ");
393 * ncat(&s,&sz,"string!");
395 * printf("String Value='%s', but has %d bytes allocated\n",s,sz);
406 /* handle initial alloc */
414 nsz= strlen(*s) + strlen(src) + 1;
415 if (*sz < nsz) *s=erealloc( (void *)*s , *sz=nsz*2);
421 * builds together a filter to check against ldap
424 sudo_ldap_build_pass1()
437 /* build filter sudoUser=user_name */
438 ncat(&b,&sz,"(sudoUser=");
439 ncat(&b,&sz,user_name);
442 /* Append primary group */
443 grp=getgrgid(getgid());
445 ncat(&b,&sz,"(sudoUser=%");
446 ncat(&b,&sz,grp->gr_name);
450 /* handle arbitrary number of groups */
451 if (0<(ngrps=getgroups(0,NULL))){
452 grplist=calloc(ngrps,sizeof(gid_t));
453 if (grplist!=NULL && (0<getgroups(ngrps,grplist)))
454 for(i=0;i<ngrps;i++){
455 if((grp=getgrgid(grplist[i]))!=NULL){
456 ncat(&b,&sz,"(sudoUser=%");
457 ncat(&b,&sz,grp->gr_name);
464 /* Add ALL to list */
465 ncat(&b,&sz,"(sudoUser=ALL)");
473 * Map yes/true/on to 1, no/false/off to 0, else -1
479 if (!strcasecmp(s,"yes") || !strcasecmp(s,"true") || !strcasecmp(s,"on"))
481 if (!strcasecmp(s,"no") || !strcasecmp(s,"false") || !strcasecmp(s,"off"))
487 sudo_ldap_read_config()
495 ldap_conf.tls_checkpeer=-1; /* default */
497 f=fopen(_PATH_LDAP_CONF,"r");
499 while (f && fgets(buf,sizeof(buf)-1,f)){
501 if (*c == '#') continue; /* ignore comment */
502 if (*c == '\n') continue; /* skip newline */
503 if (!*c) continue; /* incomplete last line */
505 /* skip whitespace before keyword */
506 while (isspace(*c)) c++;
509 /* properly terminate keyword string */
510 while (*c && !isspace(*c)) c++;
512 *c='\0'; /* terminate keyword */
516 /* skip whitespace before value */
517 while (isspace(*c)) c++;
520 /* trim whitespace after value */
521 while (*c) c++; /* wind to end */
522 while (--c > value && isspace(*c)) *c='\0';
524 /* The following macros make the code much more readable */
526 #define MATCH_S(x,y) if (!strcasecmp(keyword,x)) \
527 { if (y) free(y); y=estrdup(value); }
528 #define MATCH_I(x,y) if (!strcasecmp(keyword,x)) { y=atoi(value); }
529 #define MATCH_B(x,y) if (!strcasecmp(keyword,x)) { y=_atobool(value); }
533 /* parse values using a continues chain of
534 * if else if else if else if else ... */
535 MATCH_S("host", ldap_conf.host)
536 else MATCH_I("port", ldap_conf.port)
537 else MATCH_S("ssl", ldap_conf.ssl)
538 else MATCH_B("tls_checkpeer", ldap_conf.tls_checkpeer)
539 else MATCH_S("tls_cacertfile", ldap_conf.tls_cacertfile)
540 else MATCH_S("tls_cacertdir", ldap_conf.tls_cacertdir)
541 else MATCH_S("tls_randfile", ldap_conf.tls_random_file)
542 else MATCH_S("tls_ciphers", ldap_conf.tls_cipher_suite)
543 else MATCH_S("tls_cert", ldap_conf.tls_certfile)
544 else MATCH_S("tls_key", ldap_conf.tls_keyfile)
545 else MATCH_I("ldap_version", ldap_conf.version)
546 else MATCH_S("uri", ldap_conf.uri)
547 else MATCH_S("binddn", ldap_conf.binddn)
548 else MATCH_S("bindpw", ldap_conf.bindpw)
549 else MATCH_S("sudoers_base", ldap_conf.base)
550 else MATCH_I("sudoers_debug", ldap_conf.debug)
553 /* The keyword was unrecognized. Since this config file is shared
554 * by multiple programs, it is appropriate to silently ignore options this
555 * program does not understand
559 } /* parse next line */
564 if (!ldap_conf.version) ldap_conf.version=3;
565 if (!ldap_conf.port) ldap_conf.port=389;
566 if (!ldap_conf.host) ldap_conf.host=estrdup("localhost");
569 if (ldap_conf.debug>1) {
570 printf("LDAP Config Summary\n");
571 printf("===================\n");
572 #ifdef HAVE_LDAP_INITIALIZE
574 printf("uri %s\n", ldap_conf.uri);
578 printf("host %s\n", ldap_conf.host ?
579 ldap_conf.host : "(NONE)");
580 printf("port %d\n", ldap_conf.port);
582 printf("ldap_version %d\n", ldap_conf.version);
584 printf("sudoers_base %s\n", ldap_conf.base ?
585 ldap_conf.base : "(NONE) <---Sudo will ignore ldap)");
586 printf("binddn %s\n", ldap_conf.binddn ?
587 ldap_conf.binddn : "(anonymous)");
588 printf("bindpw %s\n", ldap_conf.bindpw ?
589 ldap_conf.bindpw : "(anonymous)");
590 #ifdef HAVE_LDAP_START_TLS_S
591 printf("ssl %s\n", ldap_conf.ssl ?
592 ldap_conf.ssl : "(no)");
594 printf("===================\n");
597 /* if no base is defined, ignore LDAP */
598 if (!ldap_conf.base) return 0;
604 like perl's join(sep,@ARGS)
607 _ldap_join_values(sep,v)
615 /* paste values together */
616 for (p=v; p && *p;p++){
617 if (p!=v && sep!=NULL) ncat(&b,&sz,sep); /* append seperator */
618 ncat(&b,&sz,*p); /* append value */
623 /* something went wrong, put something here */
624 ncat(&b,&sz,"(empty list)"); /* append value */
631 char * sudo_ldap_cm_list=NULL;
632 size_t sudo_ldap_cm_list_size;
634 #define SAVE_LIST(x) ncat(&sudo_ldap_cm_list,&sudo_ldap_cm_list_size,(x))
636 * Walks through search result and returns true if we have a
640 sudo_ldap_add_match(ld,entry)
648 /* if we are not collecting matches, then don't print them */
649 if (printmatches != TRUE) return 1;
651 /* collect the dn, only show the rdn */
652 dn=ldap_get_dn(ld,entry);
653 edn=dn ? ldap_explode_dn(dn,1) : NULL;
654 SAVE_LIST("\nLDAP Role: ");
655 SAVE_LIST((edn && *edn) ? *edn : "UNKNOWN");
657 if (dn) ldap_memfree(dn);
658 if (edn) ldap_value_free(edn);
660 /* get the Runas Values from the entry */
661 v=ldap_get_values(ld,entry,"sudoRunAs");
663 SAVE_LIST(" RunAs: (");
664 SAVE_LIST(_ldap_join_values(", ",v));
667 if (v) ldap_value_free(v);
669 /* get the Command Values from the entry */
670 v=ldap_get_values(ld,entry,"sudoCommand");
672 SAVE_LIST(" Commands:\n ");
673 SAVE_LIST(_ldap_join_values("\n ",v));
676 SAVE_LIST(" Commands: NONE\n");
678 if (v) ldap_value_free(v);
680 return 0; /* Don't stop at the first match */
685 sudo_ldap_list_matches()
687 if (sudo_ldap_cm_list!=NULL) printf("%s",sudo_ldap_cm_list);
691 * like sudoers_lookup() - only LDAP style
696 sudo_ldap_check(pwflag)
702 /* Used for searches */
703 LDAPMessage *result=NULL;
704 LDAPMessage *entry=NULL;
705 /* used to parse attributes */
707 /* temp/final return values */
712 int ldap_user_matches=0;
713 int ldap_host_matches=0;
715 if (!sudo_ldap_read_config()) return VALIDATE_ERROR;
717 /* macro to set option, error on failure plus consistent debugging */
718 #define SET_OPT(opt,optname,val) \
719 if (ldap_conf.val!=NULL) { \
720 if (ldap_conf.debug>1) fprintf(stderr, \
721 "ldap_set_option(LDAP_OPT_%s,\"%s\")\n",optname,ldap_conf.val); \
722 rc=ldap_set_option(ld,opt,ldap_conf.val); \
723 if(rc != LDAP_OPT_SUCCESS){ \
724 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s,\"%s\")=%d: %s\n", \
725 optname, ldap_conf.val, rc, ldap_err2string(rc)); \
726 return VALIDATE_ERROR ; \
730 /* like above, but assumes val is in int */
731 #define SET_OPTI(opt,optname,val) \
732 if (ldap_conf.debug>1) fprintf(stderr, \
733 "ldap_set_option(LDAP_OPT_%s,0x%02x)\n",optname,ldap_conf.val); \
734 rc=ldap_set_option(ld,opt,&ldap_conf.val); \
735 if(rc != LDAP_OPT_SUCCESS){ \
736 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s,0x%02x)=%d: %s\n", \
737 optname, ldap_conf.val, rc, ldap_err2string(rc)); \
738 return VALIDATE_ERROR ; \
741 /* attempt to setup ssl options */
742 #ifdef LDAP_OPT_X_TLS_CACERTFILE
743 SET_OPT(LDAP_OPT_X_TLS_CACERTFILE, "X_TLS_CACERTFILE", tls_cacertfile);
744 #endif /* LDAP_OPT_X_TLS_CACERTFILE */
746 #ifdef LDAP_OPT_X_TLS_CACERTDIR
747 SET_OPT(LDAP_OPT_X_TLS_CACERTDIR, "X_TLS_CACERTDIR", tls_cacertdir);
748 #endif /* LDAP_OPT_X_TLS_CACERTDIR */
750 #ifdef LDAP_OPT_X_TLS_CERTFILE
751 SET_OPT(LDAP_OPT_X_TLS_CERTFILE, "X_TLS_CERTFILE", tls_certfile);
752 #endif /* LDAP_OPT_X_TLS_CERTFILE */
754 #ifdef LDAP_OPT_X_TLS_KEYFILE
755 SET_OPT(LDAP_OPT_X_TLS_KEYFILE, "X_TLS_KEYFILE", tls_keyfile);
756 #endif /* LDAP_OPT_X_TLS_KEYFILE */
758 #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
759 SET_OPT(LDAP_OPT_X_TLS_CIPHER_SUITE, "X_TLS_CIPHER_SUITE", tls_cipher_suite);
760 #endif /* LDAP_OPT_X_TLS_CIPHER_SUITE */
762 #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
763 SET_OPT(LDAP_OPT_X_TLS_RANDOM_FILE, "X_TLS_RANDOM_FILE", tls_random_file);
764 #endif /* LDAP_OPT_X_TLS_RANDOM_FILE */
766 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
767 /* check the server certificate? */
768 if (ldap_conf.tls_checkpeer!=-1){
769 SET_OPTI(LDAP_OPT_X_TLS_REQUIRE_CERT,"X_TLS_REQUIRE_CERT",tls_checkpeer);
771 #endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */
773 /* attempt connect */
774 #ifdef HAVE_LDAP_INITIALIZE
777 if (ldap_conf.debug>1) fprintf(stderr,
778 "ldap_initialize(ld,%s)\n",ldap_conf.uri);
780 rc=ldap_initialize(&ld,ldap_conf.uri);
782 fprintf(stderr, "ldap_initialize()=%d : %s\n",
783 rc,ldap_err2string(rc));
784 return VALIDATE_ERROR;
787 #endif /* HAVE_LDAP_INITIALIZE */
788 if (ldap_conf.host) {
790 if (ldap_conf.debug>1) fprintf(stderr,
791 "ldap_init(%s,%d)\n",ldap_conf.host,ldap_conf.port);
793 ld=ldap_init(ldap_conf.host,ldap_conf.port);
795 fprintf(stderr, "ldap_init(): errno=%d : %s\n",
796 errno, strerror(errno));
797 return VALIDATE_ERROR;
801 #ifdef LDAP_OPT_PROTOCOL_VERSION
803 /* Set the LDAP Protocol version */
804 SET_OPTI(LDAP_OPT_PROTOCOL_VERSION,"PROTOCOL_VERSION", version);
806 #endif /* LDAP_OPT_PROTOCOL_VERSION */
808 #ifdef HAVE_LDAP_START_TLS_S
810 if (ldap_conf.ssl && !strcasecmp(ldap_conf.ssl, "start_tls")){
811 rc = ldap_start_tls_s(ld, NULL, NULL);
812 if (rc != LDAP_SUCCESS) {
813 fprintf(stderr, "ldap_start_tls_s(): %d: %s\n", rc, ldap_err2string(rc));
815 return VALIDATE_ERROR;
818 if (ldap_conf.debug) printf("ldap_start_tls_s() ok\n");
820 #endif /* HAVE_LDAP_START_TLS_S */
822 /* Actually connect */
824 rc=ldap_simple_bind_s(ld,ldap_conf.binddn,ldap_conf.bindpw);
826 fprintf(stderr,"ldap_simple_bind_s()=%d : %s\n",
827 rc, ldap_err2string(rc));
828 return VALIDATE_ERROR ;
831 if (ldap_conf.debug) printf("ldap_bind() ok\n");
834 /* Parse Default Options */
836 rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL,
837 "cn=defaults",NULL,0,&result);
838 if (!rc && (entry=ldap_first_entry(ld,result))){
839 if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry));
840 sudo_ldap_parse_options(ld,entry);
842 if (ldap_conf.debug) printf("no default options found!\n");
845 if (result) ldap_msgfree(result);
849 * Okay - time to search for anything that matches this user
850 * Lets limit it to only two queries of the LDAP server
852 * The first pass will look by the username, groups, and
853 * the keyword ALL. We will then inspect the results that
854 * came back from the query. We don't need to inspect the
855 * sudoUser in this pass since the LDAP server already scanned
858 * The second pass will return all the entries that contain
859 * user netgroups. Then we take the netgroups returned and
860 * try to match them against the username.
864 for(pass=1;!ret && pass<=2;pass++){
867 /* Want the entries that match our usernames or groups */
868 filt=sudo_ldap_build_pass1();
869 } else { /* pass=2 */
870 /* Want the entries that have user netgroups in them. */
871 filt=strdup("sudoUser=+*");
873 if (ldap_conf.debug) printf("ldap search '%s'\n",filt);
874 rc=ldap_search_s(ld,ldap_conf.base,LDAP_SCOPE_ONELEVEL,
875 filt,NULL,0,&result);
877 if (ldap_conf.debug) printf("nothing found for '%s'\n",filt);
879 if (filt) free (filt);
880 /* parse each entry returned from this most recent search */
882 entry=rc ? NULL : ldap_first_entry(ld,result);
884 entry=ldap_next_entry(ld,entry))
886 if (ldap_conf.debug) printf("found:%s\n",ldap_get_dn(ld,entry));
888 /* first verify user netgroup matches - only if in pass 2 */
889 (pass!=2 || sudo_ldap_check_user_netgroup(ld,entry)) &&
890 /* remember that user matched */
891 (ldap_user_matches=-1) &&
892 /* verify host match */
893 sudo_ldap_check_host(ld,entry) &&
894 /* remember that host matched */
895 (ldap_host_matches=-1) &&
896 /* add matches for listing later */
897 sudo_ldap_add_match(ld,entry) &&
898 /* verify command match */
899 sudo_ldap_check_command(ld,entry) &&
900 /* verify runas match */
901 sudo_ldap_check_runas(ld,entry)
904 /* We have a match! */
905 if(ldap_conf.debug) printf("Perfect Matched!\n");
906 /* pick up any options */
907 sudo_ldap_parse_options(ld,entry);
908 /* make sure we dont reenter loop */
910 /* break from inside for loop */
915 if (result) ldap_msgfree(result);
920 /* shut down connection */
921 if (ld) ldap_unbind_s(ld);
924 if (ldap_conf.debug) printf("user_matches=%d\n",ldap_user_matches);
925 if (ldap_conf.debug) printf("host_matches=%d\n",ldap_host_matches);
927 /* Check for special case for -v, -k, -l options */
928 if (pwflag && ldap_user_matches && ldap_host_matches){
930 * Handle verifypw & listpw
932 * To be extra paranoid, since we haven't read any NOPASSWD options
933 * in /etc/sudoers yet, but we have to make the decission now, lets
934 * assume the worst and prefer to prompt for password unless the setting
935 * is "never". (example verifypw=never or listpw=never)
938 if (pwflag<0) { /* -k */
939 ret=VALIDATE_OK; SET(ret,FLAG_NOPASS);
940 } else if (sudo_defs_table[pwflag].sd_un.tuple == never){ /* see note above */
941 ret=VALIDATE_OK; SET(ret,FLAG_NOPASS);
943 ret=VALIDATE_OK; /* extra paranoid */
947 if (ISSET(ret,VALIDATE_OK)) {
948 /* We have a match. Should we check the password? */
949 /* Note: This could be the global or a rule specific option */
950 if (!def_authenticate) SET(ret,FLAG_NOPASS);
951 /* Same logic with noexec */
952 if (def_noexec) SET(ret,FLAG_NOEXEC);
954 /* we do not have a match */
956 if (!ldap_user_matches) SET(ret,FLAG_NO_USER);
957 else if (!ldap_host_matches) SET(ret,FLAG_NO_HOST);
960 if (ldap_conf.debug) printf("sudo_ldap_check(%d)=0x%02x\n",pwflag,ret);