]> git.gag.com Git - debian/sudo/blob - ldap.c
more bugs closed
[debian/sudo] / ldap.c
1 /*
2  * Copyright (c) 2003-2009 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * This code is derived from software contributed by Aaron Spangler.
5  *
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.
9  *
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.
17  */
18
19 #include <config.h>
20
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/param.h>
24 #include <sys/stat.h>
25 #include <stdio.h>
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 # include <stddef.h>
29 #else
30 # ifdef HAVE_STDLIB_H
31 #  include <stdlib.h>
32 # endif
33 #endif /* STDC_HEADERS */
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #else
37 # ifdef HAVE_STRINGS_H
38 #  include <strings.h>
39 # endif
40 #endif /* HAVE_STRING_H */
41 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
42 # include <malloc.h>
43 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif /* HAVE_UNISTD_H */
47 #include <ctype.h>
48 #include <pwd.h>
49 #include <grp.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <netdb.h>
53 #ifdef HAVE_LBER_H
54 # include <lber.h>
55 #endif
56 #include <ldap.h>
57 #if defined(HAVE_LDAP_SSL_H)
58 # include <ldap_ssl.h>
59 #elif defined(HAVE_MPS_LDAP_SSL_H)
60 # include <mps/ldap_ssl.h>
61 #endif
62 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
63 # ifdef HAVE_SASL_SASL_H
64 #  include <sasl/sasl.h>
65 # else
66 #  include <sasl.h>
67 # endif
68 # if HAVE_GSS_KRB5_CCACHE_NAME
69 #  if defined(HAVE_GSSAPI_GSSAPI_KRB5_H)
70 #   include <gssapi/gssapi.h>
71 #   include <gssapi/gssapi_krb5.h>
72 #  elif defined(HAVE_GSSAPI_GSSAPI_H)
73 #   include <gssapi/gssapi.h>
74 #  else
75 #   include <gssapi.h>
76 #  endif
77 # endif
78 #endif
79
80 #include "sudo.h"
81 #include "parse.h"
82 #include "lbuf.h"
83
84 #ifndef lint
85 __unused static const char rcsid[] = "$Sudo: ldap.c,v 1.108 2009/05/29 13:43:12 millert Exp $";
86 #endif /* lint */
87
88 #ifndef LDAP_OPT_SUCCESS
89 # define LDAP_OPT_SUCCESS LDAP_SUCCESS
90 #endif
91
92 #ifndef LDAPS_PORT
93 # define LDAPS_PORT 636
94 #endif
95
96 #if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET)
97 # define LDAP_SASL_QUIET        0
98 #endif
99
100 #ifndef HAVE_LDAP_UNBIND_EXT_S
101 #define ldap_unbind_ext_s(a, b, c)      ldap_unbind_s(a)
102 #endif
103
104 #ifndef HAVE_LDAP_SEARCH_EXT_S
105 #define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k)              \
106         ldap_search_s(a, b, c, d, e, f, k)
107 #endif
108
109 #define LDAP_FOREACH(var, ld, res)                                      \
110     for ((var) = ldap_first_entry((ld), (res));                         \
111         (var) != NULL;                                                  \
112         (var) = ldap_next_entry((ld), (var)))
113
114 #define DPRINTF(args, level)    if (ldap_conf.debug >= level) warningx args
115
116 #define CONF_BOOL       0
117 #define CONF_INT        1
118 #define CONF_STR        2
119
120 #define SUDO_LDAP_SSL           1
121 #define SUDO_LDAP_STARTTLS      2
122
123 struct ldap_config_table {
124     const char *conf_str;       /* config file string */
125     short type;                 /* CONF_BOOL, CONF_INT, CONF_STR */
126     short connected;            /* connection-specific value? */
127     int opt_val;                /* LDAP_OPT_* (or -1 for sudo internal) */
128     void *valp;                 /* pointer into ldap_conf */
129 };
130
131 /* ldap configuration structure */
132 static struct ldap_config {
133     int port;
134     int version;
135     int debug;
136     int ldap_debug;
137     int tls_checkpeer;
138     int timelimit;
139     int bind_timelimit;
140     int use_sasl;
141     int rootuse_sasl;
142     int ssl_mode;
143     char *host;
144     char *uri;
145     char *binddn;
146     char *bindpw;
147     char *rootbinddn;
148     char *base;
149     char *ssl;
150     char *tls_cacertfile;
151     char *tls_cacertdir;
152     char *tls_random_file;
153     char *tls_cipher_suite;
154     char *tls_certfile;
155     char *tls_keyfile;
156     char *sasl_auth_id;
157     char *rootsasl_auth_id;
158     char *sasl_secprops;
159     char *krb5_ccname;
160 } ldap_conf;
161
162 static struct ldap_config_table ldap_conf_table[] = {
163     { "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug },
164     { "host", CONF_STR, FALSE, -1, &ldap_conf.host },
165     { "port", CONF_INT, FALSE, -1, &ldap_conf.port },
166     { "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl },
167     { "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
168     { "uri", CONF_STR, FALSE, -1, &ldap_conf.uri },
169 #ifdef LDAP_OPT_DEBUG_LEVEL
170     { "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
171 #endif
172 #ifdef LDAP_OPT_PROTOCOL_VERSION
173     { "ldap_version", CONF_INT, TRUE, LDAP_OPT_PROTOCOL_VERSION,
174         &ldap_conf.version },
175 #endif
176 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
177     { "tls_checkpeer", CONF_BOOL, FALSE, LDAP_OPT_X_TLS_REQUIRE_CERT,
178         &ldap_conf.tls_checkpeer },
179 #else
180     { "tls_checkpeer", CONF_BOOL, FALSE, -1, &ldap_conf.tls_checkpeer },
181 #endif
182 #ifdef LDAP_OPT_X_TLS_CACERTFILE
183     { "tls_cacertfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE,
184         &ldap_conf.tls_cacertfile },
185 #endif
186 #ifdef LDAP_OPT_X_TLS_CACERTDIR
187     { "tls_cacertdir", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTDIR,
188         &ldap_conf.tls_cacertdir },
189 #endif
190 #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
191     { "tls_randfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_RANDOM_FILE,
192         &ldap_conf.tls_random_file },
193 #endif
194 #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
195     { "tls_ciphers", CONF_STR, FALSE, LDAP_OPT_X_TLS_CIPHER_SUITE,
196         &ldap_conf.tls_cipher_suite },
197 #endif
198 #ifdef LDAP_OPT_X_TLS_CERTFILE
199     { "tls_cert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CERTFILE,
200         &ldap_conf.tls_certfile },
201 #else
202     { "tls_cert", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
203 #endif
204 #ifdef LDAP_OPT_X_TLS_KEYFILE
205     { "tls_key", CONF_STR, FALSE, LDAP_OPT_X_TLS_KEYFILE,
206         &ldap_conf.tls_keyfile },
207 #else
208     { "tls_key", CONF_STR, FALSE, -1, &ldap_conf.tls_keyfile },
209 #endif
210 #ifdef LDAP_OPT_NETWORK_TIMEOUT
211     { "bind_timelimit", CONF_INT, TRUE, -1 /* needs timeval, set manually */,
212         &ldap_conf.bind_timelimit },
213 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
214     { "bind_timelimit", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT,
215         &ldap_conf.bind_timelimit },
216 #endif
217     { "timelimit", CONF_INT, TRUE, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
218     { "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn },
219     { "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw },
220     { "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn },
221     { "sudoers_base", CONF_STR, FALSE, -1, &ldap_conf.base },
222 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
223     { "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl },
224     { "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id },
225     { "rootuse_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.rootuse_sasl },
226     { "rootsasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.rootsasl_auth_id },
227 # ifdef LDAP_OPT_X_SASL_SECPROPS
228     { "sasl_secprops", CONF_STR, TRUE, LDAP_OPT_X_SASL_SECPROPS,
229         &ldap_conf.sasl_secprops },
230 # endif
231     { "krb5_ccname", CONF_STR, FALSE, -1, &ldap_conf.krb5_ccname },
232 #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
233     { NULL }
234 };
235
236 struct sudo_nss sudo_nss_ldap = {
237     &sudo_nss_ldap,
238     NULL,
239     sudo_ldap_open,
240     sudo_ldap_close,
241     sudo_ldap_parse,
242     sudo_ldap_setdefs,
243     sudo_ldap_lookup,
244     sudo_ldap_display_cmnd,
245     sudo_ldap_display_defaults,
246     sudo_ldap_display_bound_defaults,
247     sudo_ldap_display_privs
248 };
249
250 #ifdef HAVE_LDAP_CREATE
251 /*
252  * Rebuild the hosts list and include a specific port for each host.
253  * ldap_create() does not take a default port parameter so we must
254  * append one if we want something other than LDAP_PORT.
255  */
256 static void
257 sudo_ldap_conf_add_ports()
258 {
259
260     char *host, *port, defport[13];
261     char hostbuf[LINE_MAX * 2];
262
263     hostbuf[0] = '\0';
264     if (snprintf(defport, sizeof(defport), ":%d", ldap_conf.port) >= sizeof(defport))
265         errorx(1, "sudo_ldap_conf_add_ports: port too large");
266
267     for ((host = strtok(ldap_conf.host, " \t")); host; (host = strtok(NULL, " \t"))) {
268         if (hostbuf[0] != '\0') {
269             if (strlcat(hostbuf, " ", sizeof(hostbuf)) >= sizeof(hostbuf))
270                 goto toobig;
271         }
272
273         if (strlcat(hostbuf, host, sizeof(hostbuf)) >= sizeof(hostbuf))
274             goto toobig;
275         /* Append port if there is not one already. */
276         if ((port = strrchr(host, ':')) == NULL || !isdigit(port[1])) {
277             if (strlcat(hostbuf, defport, sizeof(hostbuf)) >= sizeof(hostbuf))
278                 goto toobig;
279         }
280     }
281
282     free(ldap_conf.host);
283     ldap_conf.host = estrdup(hostbuf);
284     return;
285
286 toobig:
287     errorx(1, "sudo_ldap_conf_add_ports: out of space expanding hostbuf");
288 }
289 #endif
290
291 #ifndef HAVE_LDAP_INITIALIZE
292 /*
293  * For each uri, convert to host:port pairs.  For ldaps:// enable SSL
294  * Accepts: uris of the form ldap:/// or ldap://hostname:portnum/
295  * where the trailing slash is optional.
296  */
297 static int
298 sudo_ldap_parse_uri(uri_list)
299     const char *uri_list;
300 {
301     char *buf, *uri, *host, *cp, *port;
302     char hostbuf[LINE_MAX];
303     int nldap = 0, nldaps = 0;
304     int rc = -1;
305
306     buf = estrdup(uri_list);
307     hostbuf[0] = '\0';
308     for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
309         if (strncasecmp(uri, "ldap://", 7) == 0) {
310             nldap++;
311             host = uri + 7;
312         } else if (strncasecmp(uri, "ldaps://", 8) == 0) {
313             nldaps++;
314             host = uri + 8;
315         } else {
316             warningx("unsupported LDAP uri type: %s", uri);
317             goto done;
318         }
319
320         /* trim optional trailing slash */
321         if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
322             *cp = '\0';
323         }
324
325         if (hostbuf[0] != '\0') {
326             if (strlcat(hostbuf, " ", sizeof(hostbuf)) >= sizeof(hostbuf))
327                 goto toobig;
328         }
329
330         if (*host == '\0')
331             host = "localhost";         /* no host specified, use localhost */
332
333         if (strlcat(hostbuf, host, sizeof(hostbuf)) >= sizeof(hostbuf))
334             goto toobig;
335
336         /* If using SSL and no port specified, add port 636 */
337         if (nldaps) {
338             if ((port = strrchr(host, ':')) == NULL || !isdigit(port[1]))
339                 if (strlcat(hostbuf, ":636", sizeof(hostbuf)) >= sizeof(hostbuf))
340                     goto toobig;
341         }
342     }
343     if (hostbuf[0] == '\0') {
344         warningx("invalid uri: %s", uri_list);
345         goto done;
346     }
347
348     if (nldaps != 0) {
349         if (nldap != 0) {
350             warningx("cannot mix ldap and ldaps URIs");
351             goto done;
352         }
353         if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
354             warningx("cannot mix ldaps and starttls");
355             goto done;
356         }
357         ldap_conf.ssl_mode = SUDO_LDAP_SSL;
358     }
359
360     free(ldap_conf.host);
361     ldap_conf.host = estrdup(hostbuf);
362     rc = 0;
363
364 done:
365     efree(buf);
366     return(rc);
367
368 toobig:
369     errorx(1, "sudo_ldap_parse_uri: out of space building hostbuf");
370 }
371 #endif /* HAVE_LDAP_INITIALIZE */
372
373 static int
374 sudo_ldap_init(ldp, host, port)
375     LDAP **ldp;
376     const char *host;
377     int port;
378 {
379     LDAP *ld = NULL;
380     int rc = LDAP_CONNECT_ERROR;
381
382 #ifdef HAVE_LDAPSSL_INIT
383     if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
384         DPRINTF(("ldapssl_clientauth_init(%s, %s)",
385             ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL",
386             ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2);
387         rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL,
388             ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL);
389         /*
390          * Mozilla-derived SDKs have a bug starting with version 5.0
391          * where the path can no longer be a file name and must be a dir.
392          */
393         if (rc != LDAP_SUCCESS) {
394             char *cp;
395             if (ldap_conf.tls_certfile) {
396                 cp = strrchr(ldap_conf.tls_certfile, '/');
397                 if (cp != NULL && strncmp(cp + 1, "cert", 4) == 0)
398                     *cp = '\0';
399             }
400             if (ldap_conf.tls_keyfile) {
401                 cp = strrchr(ldap_conf.tls_keyfile, '/');
402                 if (cp != NULL && strncmp(cp + 1, "key", 3) == 0)
403                     *cp = '\0';
404             }
405             DPRINTF(("ldapssl_clientauth_init(%s, %s)",
406                 ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL",
407                 ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2);
408             rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL,
409                 ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL);
410             if (rc != LDAP_SUCCESS) {
411                 warningx("unable to initialize SSL cert and key db: %s",
412                     ldapssl_err2string(rc));
413                 goto done;
414             }
415         }
416
417         DPRINTF(("ldapssl_init(%s, %d, 1)", host, port), 2);
418         if ((ld = ldapssl_init(host, port, 1)) != NULL)
419             rc = LDAP_SUCCESS;
420     } else
421 #endif
422     {
423 #ifdef HAVE_LDAP_CREATE
424         DPRINTF(("ldap_create()"), 2);
425         if ((rc = ldap_create(&ld)) != LDAP_SUCCESS)
426             goto done;
427         DPRINTF(("ldap_set_option(LDAP_OPT_HOST_NAME, %s)", host), 2);
428         rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, host);
429 #else
430         DPRINTF(("ldap_init(%s, %d)", host, port), 2);
431         if ((ld = ldap_init(host, port)) != NULL)
432             rc = LDAP_SUCCESS;
433 #endif
434     }
435
436 done:
437     *ldp = ld;
438     return(rc);
439 }
440
441 /*
442  * Walk through search results and return TRUE if we have a matching
443  * netgroup, else FALSE.
444  */
445 int
446 sudo_ldap_check_user_netgroup(ld, entry, user)
447     LDAP *ld;
448     LDAPMessage *entry;
449     char *user;
450 {
451     struct berval **bv, **p;
452     char *val;
453     int ret = FALSE;
454
455     if (!entry)
456         return(ret);
457
458     /* get the values from the entry */
459     bv = ldap_get_values_len(ld, entry, "sudoUser");
460     if (bv == NULL)
461         return(ret);
462
463     /* walk through values */
464     for (p = bv; *p != NULL && !ret; p++) {
465         val = (*p)->bv_val;
466         /* match any */
467         if (netgr_matches(val, NULL, NULL, user))
468             ret = TRUE;
469         DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val,
470             ret ? "MATCH!" : "not"), 2);
471     }
472
473     ldap_value_free_len(bv);    /* cleanup */
474
475     return(ret);
476 }
477
478 /*
479  * Walk through search results and return TRUE if we have a
480  * host match, else FALSE.
481  */
482 int
483 sudo_ldap_check_host(ld, entry)
484     LDAP *ld;
485     LDAPMessage *entry;
486 {
487     struct berval **bv, **p;
488     char *val;
489     int ret = FALSE;
490
491     if (!entry)
492         return(ret);
493
494     /* get the values from the entry */
495     bv = ldap_get_values_len(ld, entry, "sudoHost");
496     if (bv == NULL)
497         return(ret);
498
499     /* walk through values */
500     for (p = bv; *p != NULL && !ret; p++) {
501         val = (*p)->bv_val;
502         /* match any or address or netgroup or hostname */
503         if (!strcmp(val, "ALL") || addr_matches(val) ||
504             netgr_matches(val, user_host, user_shost, NULL) ||
505             hostname_matches(user_shost, user_host, val))
506             ret = TRUE;
507         DPRINTF(("ldap sudoHost '%s' ... %s", val,
508             ret ? "MATCH!" : "not"), 2);
509     }
510
511     ldap_value_free_len(bv);    /* cleanup */
512
513     return(ret);
514 }
515
516 int
517 sudo_ldap_check_runas_user(ld, entry)
518     LDAP *ld;
519     LDAPMessage *entry;
520 {
521     struct berval **bv, **p;
522     char *val;
523     int ret = FALSE;
524
525     if (!runas_pw)
526         return(UNSPEC);
527
528     /* get the runas user from the entry */
529     bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
530     if (bv == NULL)
531         bv = ldap_get_values_len(ld, entry, "sudoRunAs"); /* old style */
532
533     /*
534      * BUG:
535      * 
536      * if runas is not specified on the command line, the only information
537      * as to which user to run as is in the runas_default option.  We should
538      * check to see if we have the local option present.  Unfortunately we
539      * don't parse these options until after this routine says yes or no.
540      * The query has already returned, so we could peek at the attribute
541      * values here though.
542      * 
543      * For now just require users to always use -u option unless its set
544      * in the global defaults. This behaviour is no different than the global
545      * /etc/sudoers.
546      * 
547      * Sigh - maybe add this feature later
548      */
549
550     /*
551      * If there are no runas entries, match runas_default against
552      * what the user specified on the command line.
553      */
554     if (bv == NULL)
555         return(!strcasecmp(runas_pw->pw_name, def_runas_default));
556
557     /* walk through values returned, looking for a match */
558     for (p = bv; *p != NULL && !ret; p++) {
559         val = (*p)->bv_val;
560         switch (val[0]) {
561         case '+':
562             if (netgr_matches(val, NULL, NULL, runas_pw->pw_name))
563                 ret = TRUE;
564             break;
565         case '%':
566             if (usergr_matches(val, runas_pw->pw_name, runas_pw))
567                 ret = TRUE;
568             break;
569         case 'A':
570             if (strcmp(val, "ALL") == 0) {
571                 ret = TRUE;
572                 break;
573             }
574             /* FALLTHROUGH */
575         default:
576             if (strcasecmp(val, runas_pw->pw_name) == 0)
577                 ret = TRUE;
578             break;
579         }
580         DPRINTF(("ldap sudoRunAsUser '%s' ... %s", val,
581             ret ? "MATCH!" : "not"), 2);
582     }
583
584     ldap_value_free_len(bv);    /* cleanup */
585
586     return(ret);
587 }
588
589 int
590 sudo_ldap_check_runas_group(ld, entry)
591     LDAP *ld;
592     LDAPMessage *entry;
593 {
594     struct berval **bv, **p;
595     char *val;
596     int ret = FALSE;
597
598     /* runas_gr is only set if the user specified the -g flag */
599     if (!runas_gr)
600         return(UNSPEC);
601
602     /* get the values from the entry */
603     bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
604     if (bv == NULL)
605         return(ret);
606
607     /* walk through values returned, looking for a match */
608     for (p = bv; *p != NULL && !ret; p++) {
609         val = (*p)->bv_val;
610         if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr))
611             ret = TRUE;
612         DPRINTF(("ldap sudoRunAsGroup '%s' ... %s", val,
613             ret ? "MATCH!" : "not"), 2);
614     }
615
616     ldap_value_free_len(bv);    /* cleanup */
617
618     return(ret);
619 }
620
621 /*
622  * Walk through search results and return TRUE if we have a runas match,
623  * else FALSE.  RunAs info is optional.
624  */
625 int
626 sudo_ldap_check_runas(ld, entry)
627     LDAP *ld;
628     LDAPMessage *entry;
629 {
630     int ret;
631
632     if (!entry)
633         return(FALSE);
634
635     ret = sudo_ldap_check_runas_user(ld, entry) != FALSE &&
636         sudo_ldap_check_runas_group(ld, entry) != FALSE;
637
638     return(ret);
639 }
640
641 /*
642  * Walk through search results and return TRUE if we have a command match,
643  * FALSE if disallowed and UNSPEC if not matched.
644  */
645 int
646 sudo_ldap_check_command(ld, entry, setenv_implied)
647     LDAP *ld;
648     LDAPMessage *entry;
649     int *setenv_implied;
650 {
651     struct berval **bv, **p;
652     char *allowed_cmnd, *allowed_args, *val;
653     int foundbang, ret = UNSPEC;
654
655     if (!entry)
656         return(ret);
657
658     bv = ldap_get_values_len(ld, entry, "sudoCommand");
659     if (bv == NULL)
660         return(ret);
661
662     for (p = bv; *p != NULL && ret != FALSE; p++) {
663         val = (*p)->bv_val;
664         /* Match against ALL ? */
665         if (!strcmp(val, "ALL")) {
666             ret = TRUE;
667             if (setenv_implied != NULL)
668                 *setenv_implied = TRUE;
669             DPRINTF(("ldap sudoCommand '%s' ... MATCH!", val), 2);
670             continue;
671         }
672
673         /* check for !command */
674         if (*val == '!') {
675             foundbang = TRUE;
676             allowed_cmnd = estrdup(1 + val);    /* !command */
677         } else {
678             foundbang = FALSE;
679             allowed_cmnd = estrdup(val);        /* command */
680         }
681
682         /* split optional args away from command */
683         allowed_args = strchr(allowed_cmnd, ' ');
684         if (allowed_args)
685             *allowed_args++ = '\0';
686
687         /* check the command like normal */
688         if (command_matches(allowed_cmnd, allowed_args)) {
689             /*
690              * If allowed (no bang) set ret but keep on checking.
691              * If disallowed (bang), exit loop.
692              */
693             ret = foundbang ? FALSE : TRUE;
694         }
695         DPRINTF(("ldap sudoCommand '%s' ... %s", val,
696             ret == TRUE ? "MATCH!" : "not"), 2);
697
698         efree(allowed_cmnd);    /* cleanup */
699     }
700
701     ldap_value_free_len(bv);    /* more cleanup */
702
703     return(ret);
704 }
705
706 /*
707  * Search for boolean "option" in sudoOption.
708  * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC.
709  */
710 int
711 sudo_ldap_check_bool(ld, entry, option)
712     LDAP *ld;
713     LDAPMessage *entry;
714     char *option;
715 {
716     struct berval **bv, **p;
717     char ch, *var;
718     int ret = UNSPEC;
719
720     if (entry == NULL)
721         return(UNSPEC);
722
723     bv = ldap_get_values_len(ld, entry, "sudoOption");
724     if (bv == NULL)
725         return(ret);
726
727     /* walk through options */
728     for (p = bv; *p != NULL; p++) {
729         var = (*p)->bv_val;;
730         DPRINTF(("ldap sudoOption: '%s'", var), 2);
731
732         if ((ch = *var) == '!')
733             var++;
734         if (strcmp(var, option) == 0)
735             ret = (ch != '!');
736     }
737
738     ldap_value_free_len(bv);
739
740     return(ret);
741 }
742
743 /*
744  * Read sudoOption and modify the defaults as we go.  This is used once
745  * from the cn=defaults entry and also once when a final sudoRole is matched.
746  */
747 void
748 sudo_ldap_parse_options(ld, entry)
749     LDAP *ld;
750     LDAPMessage *entry;
751 {
752     struct berval **bv, **p;
753     char op, *var, *val;
754
755     if (entry == NULL)
756         return;
757
758     bv = ldap_get_values_len(ld, entry, "sudoOption");
759     if (bv == NULL)
760         return;
761
762     /* walk through options */
763     for (p = bv; *p != NULL; p++) {
764         var = estrdup((*p)->bv_val);
765         DPRINTF(("ldap sudoOption: '%s'", var), 2);
766
767         /* check for equals sign past first char */
768         val = strchr(var, '=');
769         if (val > var) {
770             *val++ = '\0';      /* split on = and truncate var */
771             op = *(val - 2);    /* peek for += or -= cases */
772             if (op == '+' || op == '-') {
773                 *(val - 2) = '\0';      /* found, remove extra char */
774                 /* case var+=val or var-=val */
775                 set_default(var, val, (int) op);
776             } else {
777                 /* case var=val */
778                 set_default(var, val, TRUE);
779             }
780         } else if (*var == '!') {
781             /* case !var Boolean False */
782             set_default(var + 1, NULL, FALSE);
783         } else {
784             /* case var Boolean True */
785             set_default(var, NULL, TRUE);
786         }
787         efree(var);
788     }
789
790     ldap_value_free_len(bv);
791 }
792
793 /*
794  * builds together a filter to check against ldap
795  */
796 char *
797 sudo_ldap_build_pass1(pw)
798     struct passwd *pw;
799 {
800     struct group *grp;
801     size_t sz;
802     char *buf;
803     int i;
804
805     /* Start with (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */
806     sz = 29 + strlen(pw->pw_name);
807
808     /* Add space for groups */
809     if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL)
810         sz += 12 + strlen(grp->gr_name);        /* primary group */
811     for (i = 0; i < user_ngroups; i++) {
812         if (user_groups[i] == pw->pw_gid)
813             continue;
814         if ((grp = sudo_getgrgid(user_groups[i])) != NULL)
815             sz += 12 + strlen(grp->gr_name);    /* supplementary group */
816     }
817     buf = emalloc(sz);
818
819     /* Global OR + sudoUser=user_name filter */
820     (void) strlcpy(buf, "(|(sudoUser=", sz);
821     (void) strlcat(buf, pw->pw_name, sz);
822     (void) strlcat(buf, ")", sz);
823
824     /* Append primary group */
825     if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
826         (void) strlcat(buf, "(sudoUser=%", sz);
827         (void) strlcat(buf, grp->gr_name, sz);
828         (void) strlcat(buf, ")", sz);
829     }
830
831     /* Append supplementary groups */
832     for (i = 0; i < user_ngroups; i++) {
833         if (user_groups[i] == pw->pw_gid)
834             continue;
835         if ((grp = sudo_getgrgid(user_groups[i])) != NULL) {
836             (void) strlcat(buf, "(sudoUser=%", sz);
837             (void) strlcat(buf, grp->gr_name, sz);
838             (void) strlcat(buf, ")", sz);
839         }
840     }
841
842     /* Add ALL to list and end the global OR */
843     if (strlcat(buf, "(sudoUser=ALL))", sz) >= sz)
844         errorx(1, "sudo_ldap_build_pass1 allocation mismatch");
845
846     return(buf);
847 }
848
849 /*
850  * Map yes/true/on to TRUE, no/false/off to FALSE, else -1
851  */
852 int
853 _atobool(s)
854     const char *s;
855 {
856     switch (*s) {
857         case 'y':
858         case 'Y':
859             if (strcasecmp(s, "yes") == 0)
860                 return(TRUE);
861             break;
862         case 't':
863         case 'T':
864             if (strcasecmp(s, "true") == 0)
865                 return(TRUE);
866             break;
867         case 'o':
868         case 'O':
869             if (strcasecmp(s, "on") == 0)
870                 return(TRUE);
871             if (strcasecmp(s, "off") == 0)
872                 return(FALSE);
873             break;
874         case 'n':
875         case 'N':
876             if (strcasecmp(s, "no") == 0)
877                 return(FALSE);
878             break;
879         case 'f':
880         case 'F':
881             if (strcasecmp(s, "false") == 0)
882                 return(FALSE);
883             break;
884     }
885     return(-1);
886 }
887
888 static void
889 sudo_ldap_read_secret(path)
890     const char *path;
891 {
892     FILE *fp;
893     char buf[LINE_MAX], *cp;
894
895     if ((fp = fopen(_PATH_LDAP_SECRET, "r")) != NULL) {
896         if (fgets(buf, sizeof(buf), fp) != NULL) {
897             if ((cp = strchr(buf, '\n')) != NULL)
898                 *cp = '\0';
899             /* copy to bindpw and binddn */
900             efree(ldap_conf.bindpw);
901             ldap_conf.bindpw = estrdup(buf);
902             efree(ldap_conf.binddn);
903             ldap_conf.binddn = ldap_conf.rootbinddn;
904             ldap_conf.rootbinddn = NULL;
905         }
906         fclose(fp);
907     }
908 }
909
910 int
911 sudo_ldap_read_config()
912 {
913     FILE *fp;
914     char *cp, *keyword, *value;
915     struct ldap_config_table *cur;
916
917     /* defaults */
918     ldap_conf.version = 3;
919     ldap_conf.port = -1;
920     ldap_conf.tls_checkpeer = -1;
921     ldap_conf.timelimit = -1;
922     ldap_conf.bind_timelimit = -1;
923     ldap_conf.use_sasl = -1;
924     ldap_conf.rootuse_sasl = -1;
925
926     if ((fp = fopen(_PATH_LDAP_CONF, "r")) == NULL)
927         return(FALSE);
928
929     while ((cp = sudo_parseln(fp)) != NULL) {
930         if (*cp == '\0')
931             continue;           /* skip empty line */
932
933         /* split into keyword and value */
934         keyword = cp;
935         while (*cp && !isblank((unsigned char) *cp))
936             cp++;
937         if (*cp)
938             *cp++ = '\0';       /* terminate keyword */
939
940         /* skip whitespace before value */
941         while (isblank((unsigned char) *cp))
942             cp++;
943         value = cp;
944
945         /* Look up keyword in config table. */
946         for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) {
947             if (strcasecmp(keyword, cur->conf_str) == 0) {
948                 switch (cur->type) {
949                 case CONF_BOOL:
950                     *(int *)(cur->valp) = _atobool(value);
951                     break;
952                 case CONF_INT:
953                     *(int *)(cur->valp) = atoi(value);
954                     break;
955                 case CONF_STR:
956                     efree(*(char **)(cur->valp));
957                     *(char **)(cur->valp) = estrdup(value);
958                     break;
959                 }
960                 break;
961             }
962         }
963     }
964     fclose(fp);
965
966     if (!ldap_conf.host)
967         ldap_conf.host = estrdup("localhost");
968
969     if (ldap_conf.bind_timelimit > 0)
970         ldap_conf.bind_timelimit *= 1000;       /* convert to ms */
971
972     if (ldap_conf.debug > 1) {
973         fprintf(stderr, "LDAP Config Summary\n");
974         fprintf(stderr, "===================\n");
975         if (ldap_conf.uri) {
976             fprintf(stderr, "uri              %s\n", ldap_conf.uri);
977         } else {
978             fprintf(stderr, "host             %s\n", ldap_conf.host ?
979                 ldap_conf.host : "(NONE)");
980             fprintf(stderr, "port             %d\n", ldap_conf.port);
981         }
982         fprintf(stderr, "ldap_version     %d\n", ldap_conf.version);
983
984         fprintf(stderr, "sudoers_base     %s\n", ldap_conf.base ?
985             ldap_conf.base : "(NONE) <---Sudo will ignore ldap)");
986         fprintf(stderr, "binddn           %s\n", ldap_conf.binddn ?
987             ldap_conf.binddn : "(anonymous)");
988         fprintf(stderr, "bindpw           %s\n", ldap_conf.bindpw ?
989             ldap_conf.bindpw : "(anonymous)");
990         if (ldap_conf.bind_timelimit > 0)
991             fprintf(stderr, "bind_timelimit   %d\n", ldap_conf.bind_timelimit);
992         if (ldap_conf.timelimit > 0)
993             fprintf(stderr, "timelimit        %d\n", ldap_conf.timelimit);
994         fprintf(stderr, "ssl              %s\n", ldap_conf.ssl ?
995             ldap_conf.ssl : "(no)");
996         if (ldap_conf.tls_checkpeer != -1)
997             fprintf(stderr, "tls_checkpeer    %s\n", ldap_conf.tls_checkpeer ?
998                 "(yes)" : "(no)");
999         if (ldap_conf.tls_cacertfile != NULL)
1000             fprintf(stderr, "tls_cacertfile   %s\n", ldap_conf.tls_cacertfile);
1001         if (ldap_conf.tls_cacertdir != NULL)
1002             fprintf(stderr, "tls_cacertdir    %s\n", ldap_conf.tls_cacertdir);
1003         if (ldap_conf.tls_random_file != NULL)
1004             fprintf(stderr, "tls_random_file  %s\n", ldap_conf.tls_random_file);
1005         if (ldap_conf.tls_cipher_suite != NULL)
1006             fprintf(stderr, "tls_cipher_suite %s\n", ldap_conf.tls_cipher_suite);
1007         if (ldap_conf.tls_certfile != NULL)
1008             fprintf(stderr, "tls_certfile     %s\n", ldap_conf.tls_certfile);
1009         if (ldap_conf.tls_keyfile != NULL)
1010             fprintf(stderr, "tls_keyfile      %s\n", ldap_conf.tls_keyfile);
1011 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
1012         if (ldap_conf.use_sasl != -1) {
1013             fprintf(stderr, "use_sasl         %s\n",
1014                 ldap_conf.use_sasl ? "yes" : "no");
1015             fprintf(stderr, "sasl_auth_id     %s\n", ldap_conf.sasl_auth_id ?
1016                 ldap_conf.sasl_auth_id : "(NONE)");
1017             fprintf(stderr, "rootuse_sasl     %d\n", ldap_conf.rootuse_sasl);
1018             fprintf(stderr, "rootsasl_auth_id %s\n", ldap_conf.rootsasl_auth_id ?
1019                 ldap_conf.rootsasl_auth_id : "(NONE)");
1020             fprintf(stderr, "sasl_secprops    %s\n", ldap_conf.sasl_secprops ?
1021                 ldap_conf.sasl_secprops : "(NONE)");
1022             fprintf(stderr, "krb5_ccname      %s\n", ldap_conf.krb5_ccname ?
1023                 ldap_conf.krb5_ccname : "(NONE)");
1024         }
1025 #endif
1026         fprintf(stderr, "===================\n");
1027     }
1028     if (!ldap_conf.base)
1029         return(FALSE);          /* if no base is defined, ignore LDAP */
1030
1031     /*
1032      * Interpret SSL option
1033      */
1034     if (ldap_conf.ssl != NULL) {
1035         if (strcasecmp(ldap_conf.ssl, "start_tls") == 0)
1036             ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS;
1037         else if (_atobool(ldap_conf.ssl))
1038             ldap_conf.ssl_mode = SUDO_LDAP_SSL;
1039     }
1040
1041 #if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(LDAP_OPT_X_TLS_REQUIRE_CERT)
1042     if (ldap_conf.tls_checkpeer != -1) {
1043         ldapssl_set_strength(NULL,
1044             ldap_conf.tls_checkpeer ? LDAPSSL_AUTH_CERT : LDAPSSL_AUTH_WEAK);
1045     }
1046 #endif
1047
1048 #ifndef HAVE_LDAP_INITIALIZE
1049     /* Convert uri list to host list if no ldap_initialize(). */
1050     if (ldap_conf.uri) {
1051         if (sudo_ldap_parse_uri(ldap_conf.uri) != 0)
1052             return(FALSE);
1053         free(ldap_conf.uri);
1054         ldap_conf.uri = NULL;
1055         ldap_conf.port = LDAP_PORT;
1056     }
1057 #endif
1058
1059     if (!ldap_conf.uri) {
1060         /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */
1061         if (ldap_conf.port < 0)
1062             ldap_conf.port =
1063                 ldap_conf.ssl_mode == SUDO_LDAP_SSL ? LDAPS_PORT : LDAP_PORT;
1064
1065 #ifdef HAVE_LDAP_CREATE
1066         /*
1067          * Cannot specify port directly to ldap_create(), each host must
1068          * include :port to override the default.
1069          */
1070         if (ldap_conf.port != LDAP_PORT)
1071             sudo_ldap_conf_add_ports();
1072 #endif
1073     }
1074
1075     /* If rootbinddn set, read in /etc/ldap.secret if it exists. */
1076     if (ldap_conf.rootbinddn)
1077         sudo_ldap_read_secret(_PATH_LDAP_SECRET);
1078
1079 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
1080     /*
1081      * Make sure we can open the file specified by krb5_ccname.
1082      */
1083     if (ldap_conf.krb5_ccname != NULL) {
1084         if (strncasecmp(ldap_conf.krb5_ccname, "FILE:", 5) == 0 ||
1085             strncasecmp(ldap_conf.krb5_ccname, "WRFILE:", 7) == 0) {
1086             value = ldap_conf.krb5_ccname +
1087                 (ldap_conf.krb5_ccname[4] == ':' ? 5 : 7);
1088             if ((fp = fopen(value, "r")) != NULL) {
1089                 DPRINTF(("using krb5 credential cache: %s", value), 1);
1090                 fclose(fp);
1091             } else {
1092                 /* Can't open it, just ignore the entry. */
1093                 DPRINTF(("unable to open krb5 credential cache: %s", value), 1);
1094                 efree(ldap_conf.krb5_ccname);
1095                 ldap_conf.krb5_ccname = NULL;
1096             }
1097         }
1098     }
1099 #endif
1100     return(TRUE);
1101 }
1102
1103 /*
1104  * Extract the dn from an entry and return the first rdn from it.
1105  */
1106 static char *
1107 sudo_ldap_get_first_rdn(ld, entry)
1108     LDAP *ld;
1109     LDAPMessage *entry;
1110 {
1111 #ifdef HAVE_LDAP_STR2DN
1112     char *dn, *rdn = NULL;
1113     LDAPDN tmpDN;
1114
1115     if ((dn = ldap_get_dn(ld, entry)) == NULL)
1116         return(NULL);
1117     if (ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP) == LDAP_SUCCESS) {
1118         ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN);
1119         ldap_dnfree(tmpDN);
1120     }
1121     ldap_memfree(dn);
1122     return(rdn);
1123 #else
1124     char *dn, **edn;
1125
1126     if ((dn = ldap_get_dn(ld, entry)) == NULL)
1127         return(NULL);
1128     edn = ldap_explode_dn(dn, 1);
1129     ldap_memfree(dn);
1130     return(edn ? edn[0] : NULL);
1131 #endif
1132 }
1133
1134 /*
1135  * Fetch and display the global Options.
1136  */
1137 int
1138 sudo_ldap_display_defaults(nss, pw, lbuf)
1139     struct sudo_nss *nss;
1140     struct passwd *pw;
1141     struct lbuf *lbuf;
1142 {
1143     struct berval **bv, **p;
1144     LDAP *ld = (LDAP *) nss->handle;
1145     LDAPMessage *entry = NULL, *result = NULL;
1146     char *prefix = NULL;
1147     int rc, count = 0;
1148
1149     if (ld == NULL)
1150         return(-1);
1151
1152     rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
1153         "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
1154     if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
1155         bv = ldap_get_values_len(ld, entry, "sudoOption");
1156         if (bv != NULL) {
1157             if (lbuf->len == 0)
1158                 prefix = "    ";
1159             else
1160                 prefix = ", ";
1161             for (p = bv; *p != NULL; p++) {
1162                 lbuf_append(lbuf, prefix, (*p)->bv_val, NULL);
1163                 prefix = ", ";
1164                 count++;
1165             }
1166             ldap_value_free_len(bv);
1167         }
1168     }
1169     if (result)
1170         ldap_msgfree(result);
1171     return(count);
1172 }
1173
1174 /*
1175  * STUB
1176  */
1177 int
1178 sudo_ldap_display_bound_defaults(nss, pw, lbuf)
1179     struct sudo_nss *nss;
1180     struct passwd *pw;
1181     struct lbuf *lbuf;
1182 {
1183     return(1);
1184 }
1185
1186 /*
1187  * Print a record in the short form, ala file sudoers.
1188  */
1189 int
1190 sudo_ldap_display_entry_short(ld, entry, lbuf)
1191     LDAP *ld;
1192     LDAPMessage *entry;
1193     struct lbuf *lbuf;
1194 {
1195     struct berval **bv, **p;
1196     int count = 0;
1197
1198     lbuf_append(lbuf, "    (", NULL);
1199
1200     /* get the RunAsUser Values from the entry */
1201     bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
1202     if (bv == NULL)
1203         bv = ldap_get_values_len(ld, entry, "sudoRunAs");
1204     if (bv != NULL) {
1205         for (p = bv; *p != NULL; p++) {
1206             if (p != bv)
1207                 lbuf_append(lbuf, ", ", NULL);
1208             lbuf_append(lbuf, (*p)->bv_val, NULL);
1209         }
1210         ldap_value_free_len(bv);
1211     } else
1212         lbuf_append(lbuf, def_runas_default, NULL);
1213
1214     /* get the RunAsGroup Values from the entry */
1215     bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
1216     if (bv != NULL) {
1217         lbuf_append(lbuf, " : ", NULL);
1218         for (p = bv; *p != NULL; p++) {
1219             if (p != bv)
1220                 lbuf_append(lbuf, ", ", NULL);
1221             lbuf_append(lbuf, (*p)->bv_val, NULL);
1222         }
1223         ldap_value_free_len(bv);
1224     }
1225     lbuf_append(lbuf, ") ", NULL);
1226
1227     /* get the Option Values from the entry */
1228     bv = ldap_get_values_len(ld, entry, "sudoOption");
1229     if (bv != NULL) {
1230         char *cp, *tag;
1231
1232         for (p = bv; *p != NULL; p++) {
1233             cp = (*p)->bv_val;
1234             if (*cp == '!')
1235                 cp++;
1236             tag = NULL;
1237             if (strcmp(cp, "authenticate") == 0)
1238                 tag = (*p)->bv_val[0] == '!' ?
1239                     "NOPASSWD: " : "PASSWD: ";
1240             else if (strcmp(cp, "noexec") == 0)
1241                 tag = (*p)->bv_val[0] == '!' ?
1242                     "EXEC: " : "NOEXEC: ";
1243             else if (strcmp(cp, "setenv") == 0)
1244                 tag = (*p)->bv_val[0] == '!' ?
1245                     "NOSETENV: " : "SETENV: ";
1246             if (tag != NULL)
1247                 lbuf_append(lbuf, tag, NULL);
1248             /* XXX - ignores other options */
1249         }
1250         ldap_value_free_len(bv);
1251     }
1252
1253     /* get the Command Values from the entry */
1254     bv = ldap_get_values_len(ld, entry, "sudoCommand");
1255     if (bv != NULL) {
1256         for (p = bv; *p != NULL; p++) {
1257             if (p != bv)
1258                 lbuf_append(lbuf, ", ", NULL);
1259             lbuf_append(lbuf, (*p)->bv_val, NULL);
1260             count++;
1261         }
1262         ldap_value_free_len(bv);
1263     }
1264
1265     lbuf_print(lbuf);           /* forces a newline */
1266     return(count);
1267 }
1268
1269 /*
1270  * Print a record in the long form.
1271  */
1272 int
1273 sudo_ldap_display_entry_long(ld, entry, lbuf)
1274     LDAP *ld;
1275     LDAPMessage *entry;
1276     struct lbuf *lbuf;
1277 {
1278     struct berval **bv, **p;
1279     char *rdn;
1280     int count = 0;
1281
1282     /* extract the dn, only show the first rdn */
1283     rdn = sudo_ldap_get_first_rdn(ld, entry);
1284     lbuf_print(lbuf);   /* force a newline */
1285     lbuf_append(lbuf, "LDAP Role: ", rdn ? rdn : "UNKNOWN", NULL);
1286     lbuf_print(lbuf);
1287     if (rdn)
1288         ldap_memfree(rdn);
1289
1290     /* get the RunAsUser Values from the entry */
1291     lbuf_append(lbuf, "    RunAsUsers: ", NULL);
1292     bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
1293     if (bv == NULL)
1294         bv = ldap_get_values_len(ld, entry, "sudoRunAs");
1295     if (bv != NULL) {
1296         for (p = bv; *p != NULL; p++) {
1297             if (p != bv)
1298                 lbuf_append(lbuf, ", ", NULL);
1299             lbuf_append(lbuf, (*p)->bv_val, NULL);
1300         }
1301         ldap_value_free_len(bv);
1302     } else
1303         lbuf_append(lbuf, def_runas_default, NULL);
1304     lbuf_print(lbuf);
1305
1306     /* get the RunAsGroup Values from the entry */
1307     bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
1308     if (bv != NULL) {
1309         lbuf_append(lbuf, "    RunAsGroups: ", NULL);
1310         for (p = bv; *p != NULL; p++) {
1311             if (p != bv)
1312                 lbuf_append(lbuf, ", ", NULL);
1313             lbuf_append(lbuf, (*p)->bv_val, NULL);
1314         }
1315         ldap_value_free_len(bv);
1316         lbuf_print(lbuf);
1317     }
1318
1319     /* get the Option Values from the entry */
1320     bv = ldap_get_values_len(ld, entry, "sudoOption");
1321     if (bv != NULL) {
1322         lbuf_append(lbuf, "    Options: ", NULL);
1323         for (p = bv; *p != NULL; p++) {
1324             if (p != bv)
1325                 lbuf_append(lbuf, ", ", NULL);
1326             lbuf_append(lbuf, (*p)->bv_val, NULL);
1327         }
1328         ldap_value_free_len(bv);
1329         lbuf_print(lbuf);
1330     }
1331
1332     /* get the Command Values from the entry */
1333     bv = ldap_get_values_len(ld, entry, "sudoCommand");
1334     if (bv != NULL) {
1335         lbuf_append(lbuf, "    Commands:", NULL);
1336         lbuf_print(lbuf);
1337         for (p = bv; *p != NULL; p++) {
1338             lbuf_append(lbuf, "\t", (*p)->bv_val, NULL);
1339             lbuf_print(lbuf);
1340             count++;
1341         }
1342         ldap_value_free_len(bv);
1343     }
1344
1345     return(count);
1346 }
1347
1348 /*
1349  * Like sudo_ldap_lookup(), except we just print entries.
1350  */
1351 int
1352 sudo_ldap_display_privs(nss, pw, lbuf)
1353     struct sudo_nss *nss;
1354     struct passwd *pw;
1355     struct lbuf *lbuf;
1356 {
1357     LDAP *ld = (LDAP *) nss->handle;
1358     LDAPMessage *entry = NULL, *result = NULL;
1359     char *filt;
1360     int rc, do_netgr, count = 0;
1361
1362     if (ld == NULL)
1363         return(-1);
1364
1365     /*
1366      * Okay - time to search for anything that matches this user
1367      * Lets limit it to only two queries of the LDAP server
1368      *
1369      * The first pass will look by the username, groups, and
1370      * the keyword ALL.  We will then inspect the results that
1371      * came back from the query.  We don't need to inspect the
1372      * sudoUser in this pass since the LDAP server already scanned
1373      * it for us.
1374      *
1375      * The second pass will return all the entries that contain
1376      * user netgroups.  Then we take the netgroups returned and
1377      * try to match them against the username.
1378      */
1379     for (do_netgr = 0; do_netgr < 2; do_netgr++) {
1380         filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
1381         DPRINTF(("ldap search '%s'", filt), 1);
1382         rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
1383             NULL, 0, NULL, NULL, NULL, 0, &result);
1384         efree(filt);
1385         if (rc != LDAP_SUCCESS)
1386             continue;   /* no entries for this pass */
1387
1388         /* print each matching entry */
1389         LDAP_FOREACH(entry, ld, result) {
1390             if ((!do_netgr ||
1391                 sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
1392                 sudo_ldap_check_host(ld, entry)) {
1393
1394                 if (long_list)
1395                     count += sudo_ldap_display_entry_long(ld, entry, lbuf);
1396                 else
1397                     count += sudo_ldap_display_entry_short(ld, entry, lbuf);
1398             }
1399         }
1400         ldap_msgfree(result);
1401         result = NULL;
1402     }
1403     return(count);
1404 }
1405
1406 int
1407 sudo_ldap_display_cmnd(nss, pw)
1408     struct sudo_nss *nss;
1409     struct passwd *pw;
1410 {
1411     LDAP *ld = (LDAP *) nss->handle;
1412     LDAPMessage *entry = NULL, *result = NULL;  /* used for searches */
1413     char *filt;                                 /* used to parse attributes */
1414     int rc, found, do_netgr;                    /* temp/final return values */
1415
1416     if (ld == NULL)
1417         return(1);
1418
1419     /*
1420      * Okay - time to search for anything that matches this user
1421      * Lets limit it to only two queries of the LDAP server
1422      *
1423      * The first pass will look by the username, groups, and
1424      * the keyword ALL.  We will then inspect the results that
1425      * came back from the query.  We don't need to inspect the
1426      * sudoUser in this pass since the LDAP server already scanned
1427      * it for us.
1428      *
1429      * The second pass will return all the entries that contain
1430      * user netgroups.  Then we take the netgroups returned and
1431      * try to match them against the username.
1432      */
1433     for (found = FALSE, do_netgr = 0; !found && do_netgr < 2; do_netgr++) {
1434         filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
1435         DPRINTF(("ldap search '%s'", filt), 1);
1436         rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
1437             NULL, 0, NULL, NULL, NULL, 0, &result);
1438         efree(filt);
1439         if (rc != LDAP_SUCCESS)
1440             continue;   /* no entries for this pass */
1441
1442         LDAP_FOREACH(entry, ld, result) {
1443             if ((!do_netgr ||
1444                 sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
1445                 sudo_ldap_check_host(ld, entry) &&
1446                 sudo_ldap_check_command(ld, entry, NULL) &&
1447                 sudo_ldap_check_runas(ld, entry)) {
1448
1449                 found = TRUE;
1450                 break;
1451             }
1452         }
1453         ldap_msgfree(result);
1454         result = NULL;
1455     }
1456
1457     if (found)
1458         printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd,
1459             user_args ? " " : "", user_args ? user_args : "");
1460    return(!found);
1461 }
1462
1463 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
1464 static int
1465 sudo_ldap_sasl_interact(ld, flags, _auth_id, _interact)
1466     LDAP *ld;
1467     unsigned int flags;
1468     void *_auth_id;
1469     void *_interact;
1470 {
1471     char *auth_id = (char *)_auth_id;
1472     sasl_interact_t *interact = (sasl_interact_t *)_interact;
1473
1474     for (; interact->id != SASL_CB_LIST_END; interact++) {
1475         if (interact->id != SASL_CB_USER)
1476             return(LDAP_PARAM_ERROR);
1477
1478         if (auth_id != NULL)
1479             interact->result = auth_id;
1480         else if (interact->defresult != NULL)
1481             interact->result = interact->defresult;
1482         else
1483             interact->result = "";
1484
1485         interact->len = strlen(interact->result);
1486 #if SASL_VERSION_MAJOR < 2
1487         interact->result = estrdup(interact->result);
1488 #endif /* SASL_VERSION_MAJOR < 2 */
1489     }
1490     return(LDAP_SUCCESS);
1491 }
1492 #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
1493
1494 /*
1495  * Set LDAP options based on the config table.
1496  */
1497 int
1498 sudo_ldap_set_options(ld)
1499     LDAP *ld;
1500 {
1501     struct ldap_config_table *cur;
1502     int rc;
1503
1504     /* Set ber options */
1505 #ifdef LBER_OPT_DEBUG_LEVEL
1506     if (ldap_conf.ldap_debug)
1507         ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug);
1508 #endif
1509
1510     /* Set simple LDAP options */
1511     for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) {
1512         LDAP *conn;
1513         int ival;
1514         char *sval;
1515
1516         if (cur->opt_val == -1)
1517             continue;
1518
1519         conn = cur->connected ? ld : NULL;
1520         switch (cur->type) {
1521         case CONF_BOOL:
1522         case CONF_INT:
1523             ival = *(int *)(cur->valp);
1524             if (ival >= 0) {
1525                 rc = ldap_set_option(conn, cur->opt_val, &ival);
1526                 if (rc != LDAP_OPT_SUCCESS) {
1527                     warningx("ldap_set_option: %s -> %d: %s",
1528                         cur->conf_str, ival, ldap_err2string(rc));
1529                     return(-1);
1530                 }
1531                 DPRINTF(("ldap_set_option: %s -> %d", cur->conf_str, ival), 1);
1532             }
1533             break;
1534         case CONF_STR:
1535             sval = *(char **)(cur->valp);
1536             if (sval != NULL) {
1537                 rc = ldap_set_option(conn, cur->opt_val, sval);
1538                 if (rc != LDAP_OPT_SUCCESS) {
1539                     warningx("ldap_set_option: %s -> %s: %s",
1540                         cur->conf_str, sval, ldap_err2string(rc));
1541                     return(-1);
1542                 }
1543                 DPRINTF(("ldap_set_option: %s -> %s", cur->conf_str, sval), 1);
1544             }
1545             break;
1546         }
1547     }
1548
1549 #ifdef LDAP_OPT_NETWORK_TIMEOUT
1550     /* Convert bind_timelimit to a timeval */
1551     if (ldap_conf.bind_timelimit > 0) {
1552         struct timeval tv;
1553         tv.tv_sec = ldap_conf.bind_timelimit / 1000;
1554         tv.tv_usec = 0;
1555         rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
1556         if (rc != LDAP_OPT_SUCCESS) {
1557             warningx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s",
1558                 (long)tv.tv_sec, ldap_err2string(rc));
1559             return(-1);
1560         }
1561         DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)\n",
1562             (long)tv.tv_sec), 1);
1563     }
1564 #endif
1565
1566 #if defined(LDAP_OPT_X_TLS) && !defined(HAVE_LDAPSSL_INIT)
1567     if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
1568         int val = LDAP_OPT_X_TLS_HARD;
1569         rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val);
1570         if (rc != LDAP_SUCCESS) {
1571             warningx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s",
1572                 ldap_err2string(rc));
1573             return(-1);
1574         }
1575         DPRINTF(("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)\n"), 1);
1576     }
1577 #endif
1578     return(0);
1579 }
1580
1581 /*
1582  * Connect to the LDAP server specified by ld
1583  */
1584 static int
1585 sudo_ldap_bind_s(ld)
1586     LDAP *ld;
1587 {
1588     int rc;
1589     const char *old_ccname = user_ccname;
1590 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
1591     unsigned int status;
1592 #endif
1593
1594 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
1595     if (ldap_conf.rootuse_sasl == TRUE ||
1596         (ldap_conf.rootuse_sasl != FALSE && ldap_conf.use_sasl == TRUE)) {
1597         void *auth_id = ldap_conf.rootsasl_auth_id ?
1598             ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id;
1599
1600         if (ldap_conf.krb5_ccname != NULL) {
1601 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
1602             if (gss_krb5_ccache_name(&status, ldap_conf.krb5_ccname, &old_ccname)
1603                 != GSS_S_COMPLETE) {
1604                 old_ccname = NULL;
1605                 DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
1606             }
1607 #else
1608             setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE);
1609 #endif
1610         }
1611         rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI",
1612             NULL, NULL, LDAP_SASL_QUIET, sudo_ldap_sasl_interact, auth_id);
1613         if (ldap_conf.krb5_ccname != NULL) {
1614 #ifdef HAVE_GSS_KRB5_CCACHE_NAME
1615             if (gss_krb5_ccache_name(&status, old_ccname, NULL) != GSS_S_COMPLETE)
1616                     DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
1617 #else
1618             if (old_ccname != NULL)
1619                 setenv("KRB5CCNAME", old_ccname, TRUE);
1620             else
1621                 unsetenv("KRB5CCNAME");
1622 #endif
1623         }
1624         if (rc != LDAP_SUCCESS) {
1625             warningx("ldap_sasl_interactive_bind_s(): %s", ldap_err2string(rc));
1626             return(-1);
1627         }
1628         DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1);
1629     } else
1630 #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
1631 #ifdef HAVE_LDAP_SASL_BIND_S
1632     {
1633         struct berval bv;
1634
1635         bv.bv_val = ldap_conf.bindpw ? ldap_conf.bindpw : "";
1636         bv.bv_len = strlen(bv.bv_val);
1637
1638         rc = ldap_sasl_bind_s(ld, ldap_conf.binddn, LDAP_SASL_SIMPLE, &bv,
1639             NULL, NULL, NULL);
1640         if (rc != LDAP_SUCCESS) {
1641             warningx("ldap_sasl_bind_s(): %s", ldap_err2string(rc));
1642             return(-1);
1643         }
1644         DPRINTF(("ldap_sasl_bind_s() ok"), 1);
1645     }
1646 #else
1647     {
1648         rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw);
1649         if (rc != LDAP_SUCCESS) {
1650             warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc));
1651             return(-1);
1652         }
1653         DPRINTF(("ldap_simple_bind_s() ok"), 1);
1654     }
1655 #endif
1656     return(0);
1657 }
1658
1659 /*
1660  * Open a connection to the LDAP server.
1661  * Returns 0 on success and non-zero on failure.
1662  */
1663 int
1664 sudo_ldap_open(nss)
1665     struct sudo_nss *nss;
1666 {
1667     LDAP *ld;
1668     int rc, ldapnoinit = FALSE;
1669
1670     if (!sudo_ldap_read_config())
1671         return(-1);
1672
1673     /* Prevent reading of user ldaprc and system defaults. */
1674     if (getenv("LDAPNOINIT") == NULL) {
1675         ldapnoinit = TRUE;
1676         setenv("LDAPNOINIT", "1", TRUE);
1677     }
1678
1679     /* Connect to LDAP server */
1680 #ifdef HAVE_LDAP_INITIALIZE
1681     if (ldap_conf.uri != NULL) {
1682         DPRINTF(("ldap_initialize(ld, %s)", ldap_conf.uri), 2);
1683         rc = ldap_initialize(&ld, ldap_conf.uri);
1684     } else
1685 #endif
1686         rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port);
1687     if (rc != LDAP_SUCCESS) {
1688         warningx("unable to initialize LDAP: %s", ldap_err2string(rc));
1689         return(-1);
1690     }
1691
1692     if (ldapnoinit)
1693         unsetenv("LDAPNOINIT");
1694
1695     /* Set LDAP options */
1696     if (sudo_ldap_set_options(ld) < 0)
1697         return(-1);
1698
1699     if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
1700 #if defined(HAVE_LDAP_START_TLS_S)
1701         rc = ldap_start_tls_s(ld, NULL, NULL);
1702         if (rc != LDAP_SUCCESS) {
1703             warningx("ldap_start_tls_s(): %s", ldap_err2string(rc));
1704             return(-1);
1705         }
1706         DPRINTF(("ldap_start_tls_s() ok"), 1);
1707 #elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP)
1708         if (ldap_ssl_client_init(NULL, NULL, 0, &rc) != LDAP_SUCCESS) {
1709             warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc));
1710             return(-1);
1711         }
1712         rc = ldap_start_tls_s_np(ld, NULL);
1713         if (rc != LDAP_SUCCESS) {
1714             warningx("ldap_start_tls_s_np(): %s", ldap_err2string(rc));
1715             return(-1);
1716         }
1717         DPRINTF(("ldap_start_tls_s_np() ok"), 1);
1718 #else
1719         warningx("start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()");
1720 #endif /* !HAVE_LDAP_START_TLS_S && !HAVE_LDAP_START_TLS_S_NP */
1721     }
1722
1723     /* Actually connect */
1724     if (sudo_ldap_bind_s(ld) != 0)
1725         return(-1);
1726
1727     nss->handle = ld;
1728     return(0);
1729 }
1730
1731 int
1732 sudo_ldap_setdefs(nss)
1733     struct sudo_nss *nss;
1734 {
1735     LDAP *ld = (LDAP *) nss->handle;
1736     LDAPMessage *entry = NULL, *result = NULL;   /* used for searches */
1737     int rc;                                      /* temp return value */
1738
1739     if (ld == NULL)
1740         return(-1);
1741
1742     rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
1743         "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
1744     if (rc == 0 && (entry = ldap_first_entry(ld, result))) {
1745         DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
1746         sudo_ldap_parse_options(ld, entry);
1747     } else
1748         DPRINTF(("no default options found!"), 1);
1749
1750     if (result)
1751         ldap_msgfree(result);
1752
1753     return(0);
1754 }
1755
1756 /*
1757  * like sudoers_lookup() - only LDAP style
1758  */
1759 int
1760 sudo_ldap_lookup(nss, ret, pwflag)
1761     struct sudo_nss *nss;
1762     int ret;
1763     int pwflag;
1764 {
1765     LDAP *ld = (LDAP *) nss->handle;
1766     LDAPMessage *entry = NULL, *result = NULL;
1767     char *filt;
1768     int do_netgr, rc, matched;
1769     int setenv_implied;
1770     int ldap_user_matches = FALSE, ldap_host_matches = FALSE;
1771     struct passwd *pw = list_pw ? list_pw : sudo_user.pw;
1772
1773     if (ld == NULL)
1774         return(ret);
1775
1776     if (pwflag) {
1777         int doauth = UNSPEC;
1778         enum def_tupple pwcheck = 
1779             (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
1780
1781         for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
1782             filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
1783             rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
1784                 NULL, 0, NULL, NULL, NULL, 0, &result);
1785             efree(filt);
1786             if (rc != LDAP_SUCCESS)
1787                 continue;
1788
1789             LDAP_FOREACH(entry, ld, result) {
1790                 /* only verify netgroup matches in pass 2 */
1791                 if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name))
1792                     continue;
1793
1794                 ldap_user_matches = TRUE;
1795                 if (sudo_ldap_check_host(ld, entry)) {
1796                     ldap_host_matches = TRUE;
1797                     if ((pwcheck == any && doauth != FALSE) ||
1798                         (pwcheck == all && doauth == FALSE))
1799                         doauth = sudo_ldap_check_bool(ld, entry, "authenticate");
1800                     /* Only check the command when listing another user. */
1801                     if (user_uid == 0 || list_pw == NULL ||
1802                         user_uid == list_pw->pw_uid ||
1803                         sudo_ldap_check_command(ld, entry, NULL)) {
1804                         matched = 1;
1805                         break;  /* end foreach */
1806                     }
1807                 }
1808             }
1809             ldap_msgfree(result);
1810             result = NULL;
1811         }
1812         if (matched || user_uid == 0) {
1813             SET(ret, VALIDATE_OK);
1814             CLR(ret, VALIDATE_NOT_OK);
1815             if (def_authenticate) {
1816                 switch (pwcheck) {
1817                     case always:
1818                         SET(ret, FLAG_CHECK_USER);
1819                         break;
1820                     case all:
1821                     case any:
1822                         if (doauth == FALSE)
1823                             def_authenticate = FALSE;
1824                         break;
1825                     case never:
1826                         def_authenticate = FALSE;
1827                         break;
1828                     default:
1829                         break;
1830                 }
1831             }
1832         }
1833         goto done;
1834     }
1835
1836     /*
1837      * Okay - time to search for anything that matches this user
1838      * Lets limit it to only two queries of the LDAP server
1839      *
1840      * The first pass will look by the username, groups, and
1841      * the keyword ALL.  We will then inspect the results that
1842      * came back from the query.  We don't need to inspect the
1843      * sudoUser in this pass since the LDAP server already scanned
1844      * it for us.
1845      *
1846      * The second pass will return all the entries that contain
1847      * user netgroups.  Then we take the netgroups returned and
1848      * try to match them against the username.
1849      */
1850     setenv_implied = FALSE;
1851     for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
1852         filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
1853         DPRINTF(("ldap search '%s'", filt), 1);
1854         rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
1855             NULL, 0, NULL, NULL, NULL, 0, &result);
1856         if (rc != LDAP_SUCCESS)
1857             DPRINTF(("nothing found for '%s'", filt), 1);
1858         efree(filt);
1859
1860         /* parse each entry returned from this most recent search */
1861         if (rc == LDAP_SUCCESS) {
1862             LDAP_FOREACH(entry, ld, result) {
1863                 DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
1864                 if (
1865                 /* first verify user netgroup matches - only if in pass 2 */
1866                     (!do_netgr || sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
1867                 /* remember that user matched */
1868                     (ldap_user_matches = TRUE) &&
1869                 /* verify host match */
1870                     sudo_ldap_check_host(ld, entry) &&
1871                 /* remember that host matched */
1872                     (ldap_host_matches = TRUE) &&
1873                 /* verify runas match */
1874                     sudo_ldap_check_runas(ld, entry) &&
1875                 /* verify command match */
1876                     (rc = sudo_ldap_check_command(ld, entry, &setenv_implied)) != UNSPEC
1877                     ) {
1878                     /* We have a match! */
1879                     DPRINTF(("Command %sallowed", rc == TRUE ? "" : "NOT "), 1);
1880                     matched = TRUE;
1881                     if (rc == TRUE) {
1882                         /* pick up any options */
1883                         if (setenv_implied)
1884                             def_setenv = TRUE;
1885                         sudo_ldap_parse_options(ld, entry);
1886 #ifdef HAVE_SELINUX
1887                         /* Set role and type if not specified on command line. */
1888                         if (user_role == NULL)
1889                             user_role = def_role;
1890                         if (user_type == NULL)
1891                             user_type = def_type;
1892 #endif /* HAVE_SELINUX */
1893                         /* make sure we don't reenter loop */
1894                         SET(ret, VALIDATE_OK);
1895                         CLR(ret, VALIDATE_NOT_OK);
1896                     } else {
1897                         SET(ret, VALIDATE_NOT_OK);
1898                         CLR(ret, VALIDATE_OK);
1899                     }
1900                     /* break from inside for loop */
1901                     break;
1902                 }
1903             }
1904             ldap_msgfree(result);
1905             result = NULL;
1906         }
1907     }
1908
1909 done:
1910     DPRINTF(("user_matches=%d", ldap_user_matches), 1);
1911     DPRINTF(("host_matches=%d", ldap_host_matches), 1);
1912
1913     if (!ISSET(ret, VALIDATE_OK)) {
1914         /* we do not have a match */
1915         if (pwflag && list_pw == NULL)
1916             SET(ret, FLAG_NO_CHECK);
1917     }
1918     if (ldap_user_matches)
1919         CLR(ret, FLAG_NO_USER);
1920     if (ldap_host_matches)
1921         CLR(ret, FLAG_NO_HOST);
1922     DPRINTF(("sudo_ldap_lookup(%d)=0x%02x", pwflag, ret), 1);
1923
1924     return(ret);
1925 }
1926
1927 /*
1928  * shut down LDAP connection
1929  */
1930 int
1931 sudo_ldap_close(nss)
1932     struct sudo_nss *nss;
1933 {
1934     if (nss->handle != NULL) {
1935         ldap_unbind_ext_s((LDAP *) nss->handle, NULL, NULL);
1936         nss->handle = NULL;
1937     }
1938     return(0);
1939 }
1940
1941 /*
1942  * STUB
1943  */
1944 int
1945 sudo_ldap_parse(nss)
1946     struct sudo_nss *nss;
1947 {
1948     return(0);
1949 }