2 * Copyright (c) 2003-2005 Todd C. Miller <Todd.Miller@courtesan.com>
4 * This code is derived from software contributed by Aaron Spangler.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/types.h>
23 #include <sys/param.h>
33 #endif /* STDC_HEADERS */
37 # ifdef HAVE_STRINGS_H
40 #endif /* HAVE_STRING_H */
41 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
43 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
46 #endif /* HAVE_UNISTD_H */
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
56 # include "emul/err.h"
57 #endif /* HAVE_ERR_H */
68 __unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.20 2007/11/27 17:06:54 millert Exp $";
72 # define LINE_MAX 2048
75 #ifndef LDAP_OPT_SUCCESS
76 # define LDAP_OPT_SUCCESS LDAP_SUCCESS
79 #if defined(LDAP_X_OPT_CONNECT_TIMEOUT) && !defined(LDAP_OPT_X_CONNECT_TIMEOUT)
80 #define LDAP_OPT_X_CONNECT_TIMEOUT LDAP_OPT_X_CONNECT_TIMEOUT
83 #define DPRINTF(args, level) if (ldap_conf.debug >= level) warnx args
85 /* ldap configuration structure */
100 char *tls_cacertfile;
102 char *tls_random_file;
103 char *tls_cipher_suite;
108 static void sudo_ldap_update_defaults __P((LDAP *));
109 static void sudo_ldap_close __P((LDAP *));
110 static LDAP *sudo_ldap_open __P((void));
113 * Walk through search results and return TRUE if we have a matching
114 * netgroup, else FALSE.
117 sudo_ldap_check_user_netgroup(ld, entry)
121 char **v = NULL, **p = NULL;
127 /* get the values from the entry */
128 v = ldap_get_values(ld, entry, "sudoUser");
130 /* walk through values */
131 for (p = v; p && *p && !ret; p++) {
133 if (netgr_matches(*p, NULL, NULL, user_name))
135 DPRINTF(("ldap sudoUser netgroup '%s' ... %s", *p,
136 ret ? "MATCH!" : "not"), 2);
140 ldap_value_free(v); /* cleanup */
146 * Walk through search results and return TRUE if we have a
147 * host match, else FALSE.
150 sudo_ldap_check_host(ld, entry)
154 char **v = NULL, **p = NULL;
160 /* get the values from the entry */
161 v = ldap_get_values(ld, entry, "sudoHost");
163 /* walk through values */
164 for (p = v; p && *p && !ret; p++) {
165 /* match any or address or netgroup or hostname */
166 if (!strcmp(*p, "ALL") || addr_matches(*p) ||
167 netgr_matches(*p, user_host, user_shost, NULL) ||
168 !hostname_matches(user_shost, user_host, *p))
170 DPRINTF(("ldap sudoHost '%s' ... %s", *p,
171 ret ? "MATCH!" : "not"), 2);
175 ldap_value_free(v); /* cleanup */
181 * Walk through search results and return TRUE if we have a runas match,
183 * Since the runas directive in /etc/sudoers is optional, so is sudoRunAs.
186 sudo_ldap_check_runas(ld, entry)
190 char **v = NULL, **p = NULL;
196 /* get the values from the entry */
197 v = ldap_get_values(ld, entry, "sudoRunAs");
202 * if runas is not specified on the command line, the only information
203 * as to which user to run as is in the runas_default option. We should
204 * check to see if we have the local option present. Unfortunately we
205 * don't parse these options until after this routine says yes or no.
206 * The query has already returned, so we could peek at the attribute
207 * values here though.
209 * For now just require users to always use -u option unless its set
210 * in the global defaults. This behaviour is no different than the global
213 * Sigh - maybe add this feature later
218 * If there are no runas entries, match runas_default against
219 * what the user specified on the command line.
222 ret = !strcasecmp(runas_pw->pw_name, def_runas_default);
224 /* walk through values returned, looking for a match */
225 for (p = v; p && *p && !ret; p++) {
228 if (netgr_matches(*p, NULL, NULL, runas_pw->pw_name))
232 if (usergr_matches(*p, runas_pw->pw_name, runas_pw))
236 if (strcmp(*p, "ALL") == 0) {
242 if (strcasecmp(*p, runas_pw->pw_name) == 0)
246 DPRINTF(("ldap sudoRunAs '%s' ... %s", *p,
247 ret ? "MATCH!" : "not"), 2);
251 ldap_value_free(v); /* cleanup */
257 * Walk through search results and return TRUE if we have a command match.
260 sudo_ldap_check_command(ld, entry, setenv_implied)
265 char *allowed_cmnd, *allowed_args, **v = NULL, **p = NULL;
266 int foundbang, ret = FALSE;
271 v = ldap_get_values(ld, entry, "sudoCommand");
273 /* get_first_entry */
274 for (p = v; p && *p && ret >= 0; p++) {
275 /* Match against ALL ? */
276 if (!strcmp(*p, "ALL")) {
278 if (setenv_implied != NULL)
279 *setenv_implied = TRUE;
280 DPRINTF(("ldap sudoCommand '%s' ... MATCH!", *p), 2);
284 /* check for !command */
287 allowed_cmnd = estrdup(1 + *p); /* !command */
290 allowed_cmnd = estrdup(*p); /* command */
293 /* split optional args away from command */
294 allowed_args = strchr(allowed_cmnd, ' ');
296 *allowed_args++ = '\0';
298 /* check the command like normal */
299 if (command_matches(allowed_cmnd, allowed_args)) {
301 * If allowed (no bang) set ret but keep on checking.
302 * If disallowed (bang), exit loop.
304 ret = foundbang ? -1 : TRUE;
306 DPRINTF(("ldap sudoCommand '%s' ... %s", *p,
307 ret == TRUE ? "MATCH!" : "not"), 2);
309 efree(allowed_cmnd); /* cleanup */
313 ldap_value_free(v); /* more cleanup */
315 /* return TRUE if we found at least one ALLOW and no DENY */
320 * Read sudoOption and modify the defaults as we go. This is used once
321 * from the cn=defaults entry and also once when a final sudoRole is matched.
324 sudo_ldap_parse_options(ld, entry)
328 char op, *var, *val, **v = NULL, **p = NULL;
333 v = ldap_get_values(ld, entry, "sudoOption");
335 /* walk through options */
336 for (p = v; p && *p; p++) {
338 DPRINTF(("ldap sudoOption: '%s'", *p), 2);
341 /* check for equals sign past first char */
342 val = strchr(var, '=');
344 *val++ = '\0'; /* split on = and truncate var */
345 op = *(val - 2); /* peek for += or -= cases */
346 if (op == '+' || op == '-') {
347 *(val - 2) = '\0'; /* found, remove extra char */
348 /* case var+=val or var-=val */
349 set_default(var, val, (int) op);
352 set_default(var, val, TRUE);
354 } else if (*var == '!') {
355 /* case !var Boolean False */
356 set_default(var + 1, NULL, FALSE);
358 /* case var Boolean True */
359 set_default(var, NULL, TRUE);
369 * Concatenate strings, dynamically growing them as necessary.
370 * Strings can be arbitrarily long and are allocated/reallocated on
371 * the fly. Make sure to free them when you are done.
378 * ncat(&s,&sz,"This ");
379 * ncat(&s,&sz,"is ");
380 * ncat(&s,&sz,"an ");
381 * ncat(&s,&sz,"arbitrarily ");
382 * ncat(&s,&sz,"long ");
383 * ncat(&s,&sz,"string!");
385 * printf("String Value='%s', but has %d bytes allocated\n",s,sz);
396 /* handle initial alloc */
399 *sz = strlen(src) + 1;
403 nsz = strlen(*s) + strlen(src) + 1;
405 *s = erealloc((void *) *s, *sz = nsz * 2);
406 strlcat(*s, src, *sz);
410 * builds together a filter to check against ldap
413 sudo_ldap_build_pass1()
423 /* build filter sudoUser=user_name */
424 ncat(&b, &sz, "(sudoUser=");
425 ncat(&b, &sz, user_name);
428 /* Append primary group */
429 grp = getgrgid(user_gid);
431 ncat(&b, &sz, "(sudoUser=%");
432 ncat(&b, &sz, grp -> gr_name);
436 /* Append supplementary groups */
437 for (i = 0; i < user_ngroups; i++) {
438 if ((grp = getgrgid(user_groups[i])) != NULL) {
439 ncat(&b, &sz, "(sudoUser=%");
440 ncat(&b, &sz, grp -> gr_name);
445 /* Add ALL to list */
446 ncat(&b, &sz, "(sudoUser=ALL)");
455 * Map yes/true/on to TRUE, no/false/off to FALSE, else -1
464 if (strcasecmp(s, "yes") == 0)
469 if (strcasecmp(s, "true") == 0)
474 if (strcasecmp(s, "on") == 0)
476 if (strcasecmp(s, "off") == 0)
481 if (strcasecmp(s, "no") == 0)
486 if (strcasecmp(s, "false") == 0)
494 sudo_ldap_read_config()
497 char buf[LINE_MAX], *c, *keyword, *value;
500 ldap_conf.version = 3;
501 ldap_conf.port = 389;
502 ldap_conf.tls_checkpeer = -1;
503 ldap_conf.timelimit = -1;
504 ldap_conf.bind_timelimit = -1;
506 if ((f = fopen(_PATH_LDAP_CONF, "r")) == NULL)
508 while (fgets(buf, sizeof(buf), f)) {
509 /* ignore text after comment character */
510 if ((c = strchr(buf, '#')) != NULL)
513 /* skip leading whitespace */
514 for (c = buf; isspace((unsigned char) *c); c++)
517 if (*c == '\0' || *c == '\n')
518 continue; /* skip empty line */
520 /* properly terminate keyword string */
522 while (*c && !isspace((unsigned char) *c))
525 *c++ = '\0'; /* terminate keyword */
527 /* skip whitespace before value */
528 while (isspace((unsigned char) *c))
532 /* trim whitespace after value */
534 c++; /* wind to end */
535 while (--c > value && isspace((unsigned char) *c))
538 /* The following macros make the code much more readable */
540 #define MATCH_S(x,y) if (!strcasecmp(keyword,x)) \
541 { efree(y); y=estrdup(value); }
542 #define MATCH_I(x,y) if (!strcasecmp(keyword,x)) { y=atoi(value); }
543 #define MATCH_B(x,y) if (!strcasecmp(keyword,x)) { y=_atobool(value); }
546 * Parse values using a continues chain of if else if else if else if
549 MATCH_S("host", ldap_conf.host)
551 MATCH_I("port", ldap_conf.port)
553 MATCH_S("ssl", ldap_conf.ssl)
555 MATCH_B("tls_checkpeer", ldap_conf.tls_checkpeer)
557 MATCH_S("tls_cacertfile", ldap_conf.tls_cacertfile)
559 MATCH_S("tls_cacertdir", ldap_conf.tls_cacertdir)
561 MATCH_S("tls_randfile", ldap_conf.tls_random_file)
563 MATCH_S("tls_ciphers", ldap_conf.tls_cipher_suite)
565 MATCH_S("tls_cert", ldap_conf.tls_certfile)
567 MATCH_S("tls_key", ldap_conf.tls_keyfile)
569 MATCH_I("ldap_version", ldap_conf.version)
571 MATCH_I("bind_timelimit", ldap_conf.bind_timelimit)
573 MATCH_I("timelimit", ldap_conf.timelimit)
575 MATCH_S("uri", ldap_conf.uri)
577 MATCH_S("binddn", ldap_conf.binddn)
579 MATCH_S("bindpw", ldap_conf.bindpw)
581 MATCH_S("rootbinddn", ldap_conf.rootbinddn)
583 MATCH_S("sudoers_base", ldap_conf.base)
585 MATCH_I("sudoers_debug", ldap_conf.debug)
589 * The keyword was unrecognized. Since this config file is
590 * shared by multiple programs, it is appropriate to silently
591 * ignore options this program does not understand
599 ldap_conf.host = estrdup("localhost");
601 if (ldap_conf.bind_timelimit > 0)
602 ldap_conf.bind_timelimit *= 1000; /* convert to ms */
604 if (ldap_conf.debug > 1) {
605 fprintf(stderr, "LDAP Config Summary\n");
606 fprintf(stderr, "===================\n");
607 #ifdef HAVE_LDAP_INITIALIZE
609 fprintf(stderr, "uri %s\n", ldap_conf.uri);
613 fprintf(stderr, "host %s\n", ldap_conf.host ?
614 ldap_conf.host : "(NONE)");
615 fprintf(stderr, "port %d\n", ldap_conf.port);
617 fprintf(stderr, "ldap_version %d\n", ldap_conf.version);
619 fprintf(stderr, "sudoers_base %s\n", ldap_conf.base ?
620 ldap_conf.base : "(NONE) <---Sudo will ignore ldap)");
621 fprintf(stderr, "binddn %s\n", ldap_conf.binddn ?
622 ldap_conf.binddn : "(anonymous)");
623 fprintf(stderr, "bindpw %s\n", ldap_conf.bindpw ?
624 ldap_conf.bindpw : "(anonymous)");
625 fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit);
626 fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit);
627 #ifdef HAVE_LDAP_START_TLS_S
628 fprintf(stderr, "ssl %s\n", ldap_conf.ssl ?
629 ldap_conf.ssl : "(no)");
631 fprintf(stderr, "===================\n");
634 return(FALSE); /* if no base is defined, ignore LDAP */
636 /* If rootbinddn set, read in /etc/ldap.secret if it exists. */
637 if (ldap_conf.rootbinddn) {
638 if ((f = fopen(_PATH_LDAP_SECRET, "r")) != NULL) {
639 if (fgets(buf, sizeof(buf), f) != NULL) {
640 /* removing trailing newlines */
641 for (c = buf; *c != '\0'; c++)
643 while (--c > buf && *c == '\n')
645 /* copy to bindpw and binddn */
646 efree(ldap_conf.bindpw);
647 ldap_conf.bindpw = estrdup(buf);
648 efree(ldap_conf.binddn);
649 ldap_conf.binddn = ldap_conf.rootbinddn;
650 ldap_conf.rootbinddn = NULL;
659 * like perl's join(sep,@ARGS)
662 _ldap_join_values(sep, v)
666 char *b = NULL, **p = NULL;
669 /* paste values together */
670 for (p = v; p && *p; p++) {
671 if (p != v && sep != NULL)
672 ncat(&b, &sz, sep); /* append separator */
673 ncat(&b, &sz, *p); /* append value */
678 /* something went wrong, put something here */
679 ncat(&b, &sz, "(empty list)"); /* append value */
685 char *sudo_ldap_cm_list = NULL;
686 size_t sudo_ldap_cm_list_size;
688 #define SAVE_LIST(x) ncat(&sudo_ldap_cm_list,&sudo_ldap_cm_list_size,(x))
690 * Walks through search result and returns TRUE if we have a
694 sudo_ldap_add_match(ld, entry, pwflag)
699 char *dn, **edn, **v = NULL;
701 /* if we are not collecting matches, then don't save them */
702 if (pwflag != I_LISTPW)
705 /* collect the dn, only show the rdn */
706 dn = ldap_get_dn(ld, entry);
707 edn = dn ? ldap_explode_dn(dn, 1) : NULL;
708 SAVE_LIST("\nLDAP Role: ");
709 SAVE_LIST((edn && *edn) ? *edn : "UNKNOWN");
714 ldap_value_free(edn);
716 /* get the Runas Values from the entry */
717 v = ldap_get_values(ld, entry, "sudoRunAs");
719 SAVE_LIST(" RunAs: (");
720 SAVE_LIST(_ldap_join_values(", ", v));
726 /* get the Command Values from the entry */
727 v = ldap_get_values(ld, entry, "sudoCommand");
729 SAVE_LIST(" Commands:\n ");
730 SAVE_LIST(_ldap_join_values("\n ", v));
733 SAVE_LIST(" Commands: NONE\n");
738 return(FALSE); /* Don't stop at the first match */
743 sudo_ldap_list_matches()
745 if (sudo_ldap_cm_list != NULL)
746 printf("%s", sudo_ldap_cm_list);
749 /* macros to set option, error on failure plus consistent debugging */
750 #define SET_OPTS(opt, val) do { \
751 if (ldap_conf.val != NULL) { \
752 if (ldap_conf.debug > 1) \
754 "ldap_set_option(LDAP_OPT_%s, \"%s\")\n", #opt, ldap_conf.val);\
755 rc = ldap_set_option(ld, LDAP_OPT_ ## opt, ldap_conf.val); \
756 if (rc != LDAP_OPT_SUCCESS) { \
757 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s, \"%s\")=%d: %s\n", \
758 #opt, ldap_conf.val, rc, ldap_err2string(rc)); \
763 #define SET_OPTI(opt, val) do { \
764 if (ldap_conf.val >= 0) { \
765 if (ldap_conf.debug > 1) \
767 "ldap_set_option(LDAP_OPT_%s, %d)\n", #opt, ldap_conf.val); \
768 rc = ldap_set_option(ld, LDAP_OPT_ ## opt, &ldap_conf.val); \
769 if (rc != LDAP_OPT_SUCCESS) { \
770 fprintf(stderr,"ldap_set_option(LDAP_OPT_%s, %d)=%d: %s\n", \
771 #opt, ldap_conf.val, rc, ldap_err2string(rc)); \
778 * Open a connection to the LDAP server.
786 if (!sudo_ldap_read_config())
789 /* attempt to setup ssl options */
790 #ifdef LDAP_OPT_X_TLS_CACERTFILE
791 SET_OPTS(X_TLS_CACERTFILE, tls_cacertfile);
792 #endif /* LDAP_OPT_X_TLS_CACERTFILE */
794 #ifdef LDAP_OPT_X_TLS_CACERTDIR
795 SET_OPTS(X_TLS_CACERTDIR, tls_cacertdir);
796 #endif /* LDAP_OPT_X_TLS_CACERTDIR */
798 #ifdef LDAP_OPT_X_TLS_CERTFILE
799 SET_OPTS(X_TLS_CERTFILE, tls_certfile);
800 #endif /* LDAP_OPT_X_TLS_CERTFILE */
802 #ifdef LDAP_OPT_X_TLS_KEYFILE
803 SET_OPTS(X_TLS_KEYFILE, tls_keyfile);
804 #endif /* LDAP_OPT_X_TLS_KEYFILE */
806 #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
807 SET_OPTS(X_TLS_CIPHER_SUITE, tls_cipher_suite);
808 #endif /* LDAP_OPT_X_TLS_CIPHER_SUITE */
810 #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
811 SET_OPTS(X_TLS_RANDOM_FILE, tls_random_file);
812 #endif /* LDAP_OPT_X_TLS_RANDOM_FILE */
814 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
815 /* check the server certificate? */
816 SET_OPTI(X_TLS_REQUIRE_CERT, tls_checkpeer);
817 #endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */
819 /* set timelimit options */
820 SET_OPTI(TIMELIMIT, timelimit);
822 #ifdef LDAP_OPT_NETWORK_TIMEOUT
823 if (ldap_conf.bind_timelimit > 0) {
825 tv.tv_sec = ldap_conf.bind_timelimit / 1000;
827 if (ldap_conf.debug > 1)
828 fprintf(stderr, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)\n",
830 rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
831 if (rc != LDAP_OPT_SUCCESS) {
832 fprintf(stderr,"ldap_set_option(NETWORK_TIMEOUT, %ld)=%d: %s\n",
833 tv.tv_sec, rc, ldap_err2string(rc));
839 /* attempt connect */
840 #ifdef HAVE_LDAP_INITIALIZE
843 DPRINTF(("ldap_initialize(ld,%s)", ldap_conf.uri), 2);
845 rc = ldap_initialize(&ld, ldap_conf.uri);
847 fprintf(stderr, "ldap_initialize()=%d : %s\n",
848 rc, ldap_err2string(rc));
852 #endif /* HAVE_LDAP_INITIALIZE */
853 if (ldap_conf.host) {
855 DPRINTF(("ldap_init(%s,%d)", ldap_conf.host, ldap_conf.port), 2);
857 if ((ld = ldap_init(ldap_conf.host, ldap_conf.port)) == NULL) {
858 fprintf(stderr, "ldap_init(): errno=%d : %s\n",
859 errno, strerror(errno));
863 #ifdef LDAP_OPT_PROTOCOL_VERSION
865 /* Set the LDAP Protocol version */
866 SET_OPTI(PROTOCOL_VERSION, version);
868 #endif /* LDAP_OPT_PROTOCOL_VERSION */
870 #ifdef HAVE_LDAP_START_TLS_S
872 if (ldap_conf.ssl && !strcasecmp(ldap_conf.ssl, "start_tls")) {
873 rc = ldap_start_tls_s(ld, NULL, NULL);
874 if (rc != LDAP_SUCCESS) {
875 fprintf(stderr, "ldap_start_tls_s(): %d: %s\n", rc,
876 ldap_err2string(rc));
880 DPRINTF(("ldap_start_tls_s() ok"), 1);
882 #endif /* HAVE_LDAP_START_TLS_S */
884 /* Actually connect */
885 if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) {
886 fprintf(stderr, "ldap_simple_bind_s()=%d : %s\n",
887 rc, ldap_err2string(rc));
890 DPRINTF(("ldap_bind() ok"), 1);
896 sudo_ldap_update_defaults(ld)
899 LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
900 int rc; /* temp return value */
902 rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
903 "cn=defaults", NULL, 0, &result);
904 if (!rc && (entry = ldap_first_entry(ld, result))) {
905 DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
906 sudo_ldap_parse_options(ld, entry);
908 DPRINTF(("no default options found!"), 1);
911 ldap_msgfree(result);
915 * like sudoers_lookup() - only LDAP style
918 sudo_ldap_check(pwflag)
922 LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
923 char *filt; /* used to parse attributes */
924 int rc, ret = FALSE, do_netgr; /* temp/final return values */
926 int ldap_user_matches = FALSE, ldap_host_matches = FALSE; /* flags */
928 /* Open a connection to the LDAP server. */
929 if ((ld = sudo_ldap_open()) == NULL)
930 return(VALIDATE_ERROR);
932 /* Parse Default options. */
933 sudo_ldap_update_defaults(ld);
936 * Okay - time to search for anything that matches this user
937 * Lets limit it to only two queries of the LDAP server
939 * The first pass will look by the username, groups, and
940 * the keyword ALL. We will then inspect the results that
941 * came back from the query. We don't need to inspect the
942 * sudoUser in this pass since the LDAP server already scanned
945 * The second pass will return all the entries that contain
946 * user netgroups. Then we take the netgroups returned and
947 * try to match them against the username.
949 setenv_implied = FALSE;
950 for (do_netgr = 0; !ret && do_netgr < 2; do_netgr++) {
951 filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1();
952 DPRINTF(("ldap search '%s'", filt), 1);
953 rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
956 DPRINTF(("nothing found for '%s'", filt), 1);
959 /* parse each entry returned from this most recent search */
960 entry = rc ? NULL : ldap_first_entry(ld, result);
961 while (entry != NULL) {
962 DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
964 /* first verify user netgroup matches - only if in pass 2 */
965 (!do_netgr || sudo_ldap_check_user_netgroup(ld, entry)) &&
966 /* remember that user matched */
967 (ldap_user_matches = -1) &&
968 /* verify host match */
969 sudo_ldap_check_host(ld, entry) &&
970 /* remember that host matched */
971 (ldap_host_matches = -1) &&
972 /* add matches for listing later */
973 sudo_ldap_add_match(ld, entry, pwflag) &&
974 /* verify command match */
975 sudo_ldap_check_command(ld, entry, &setenv_implied) &&
976 /* verify runas match */
977 sudo_ldap_check_runas(ld, entry)
979 /* We have a match! */
980 DPRINTF(("Perfect Matched!"), 1);
981 /* pick up any options */
984 sudo_ldap_parse_options(ld, entry);
985 /* make sure we don't reenter loop */
987 /* break from inside for loop */
990 entry = ldap_next_entry(ld, entry);
993 ldap_msgfree(result);
997 sudo_ldap_close(ld); /* shut down connection */
999 DPRINTF(("user_matches=%d", ldap_user_matches), 1);
1000 DPRINTF(("host_matches=%d", ldap_host_matches), 1);
1002 /* Check for special case for -v, -k, -l options */
1003 if (pwflag && ldap_user_matches && ldap_host_matches) {
1005 * Handle verifypw & listpw
1007 * To be extra paranoid, since we haven't read any NOPASSWD options
1008 * in /etc/sudoers yet, but we have to make the decission now, lets
1009 * assume the worst and prefer to prompt for password unless the setting
1010 * is "never". (example verifypw=never or listpw=never)
1015 SET(ret, FLAG_NOPASS); /* -k or -K */
1017 switch (sudo_defs_table[pwflag].sd_un.tuple) {
1019 SET(ret, FLAG_NOPASS);
1022 if (def_authenticate)
1023 SET(ret, FLAG_CHECK_USER);
1030 if (ISSET(ret, VALIDATE_OK)) {
1031 /* we have a match, should we check the password? */
1032 if (!def_authenticate)
1033 SET(ret, FLAG_NOPASS);
1035 SET(ret, FLAG_NOEXEC);
1037 SET(ret, FLAG_SETENV);
1039 /* we do not have a match */
1040 ret = VALIDATE_NOT_OK;
1042 SET(ret, FLAG_NO_CHECK);
1043 else if (!ldap_user_matches)
1044 SET(ret, FLAG_NO_USER);
1045 else if (!ldap_host_matches)
1046 SET(ret, FLAG_NO_HOST);
1048 DPRINTF(("sudo_ldap_check(%d)=0x%02x", pwflag, ret), 1);
1054 * shut down LDAP connection
1057 sudo_ldap_close(LDAP *ld)