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