diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2007-12-21 01:16:53 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2007-12-21 01:16:53 +0000 |
commit | 8b12679a963566c41b82af56575e1e605b61b538 (patch) | |
tree | 04a1fdec37fdc2121c811101035afc6bd2a6b233 | |
parent | 37c45720a0f11ffacd68a257970d89db7e2b3f8e (diff) |
update to sudo 1.6.9p10
-rw-r--r-- | usr.bin/sudo/CHANGES | 9 | ||||
-rw-r--r-- | usr.bin/sudo/Makefile.in | 4 | ||||
-rw-r--r-- | usr.bin/sudo/README.LDAP | 67 | ||||
-rw-r--r-- | usr.bin/sudo/config.h.in | 3 | ||||
-rw-r--r-- | usr.bin/sudo/configure | 63 | ||||
-rw-r--r-- | usr.bin/sudo/configure.in | 8 | ||||
-rw-r--r-- | usr.bin/sudo/ldap.c | 422 | ||||
-rw-r--r-- | usr.bin/sudo/sudo.c | 6 | ||||
-rw-r--r-- | usr.bin/sudo/version.h | 4 |
9 files changed, 386 insertions, 200 deletions
diff --git a/usr.bin/sudo/CHANGES b/usr.bin/sudo/CHANGES index ad8e0bdc06a..8aa51fc7636 100644 --- a/usr.bin/sudo/CHANGES +++ b/usr.bin/sudo/CHANGES @@ -2006,3 +2006,12 @@ Sudo 1.6.9p8 released. to be used in all cases. Also set when the -p flag is used. Sudo 1.6.9p9 released. + +634) Moved LDAP options into a table for simplified parsing/setting. + +635) Fixed a problem with how some LDAP options were being applied. + +636) Added support for connecting directly to LDAP servers via SSL + in addition to the existing start_tls support. + +Sudo 1.6.9p10 released. diff --git a/usr.bin/sudo/Makefile.in b/usr.bin/sudo/Makefile.in index 16da662fc03..8073eb32e2a 100644 --- a/usr.bin/sudo/Makefile.in +++ b/usr.bin/sudo/Makefile.in @@ -20,7 +20,7 @@ # # @configure_input@ # -# $Sudo: Makefile.in,v 1.246.2.20 2007/12/03 10:34:32 millert Exp $ +# $Sudo: Makefile.in,v 1.246.2.21 2007/12/17 19:18:14 millert Exp $ # #### Start of system configuration section. #### @@ -131,7 +131,7 @@ TESTOBJS = interfaces.o testsudoers.o $(PARSEOBJS) LIBOBJS = @LIBOBJS@ @ALLOCA@ -VERSION = 1.6.9p9 +VERSION = 1.6.9p10 DISTFILES = $(SRCS) $(HDRS) BUGS CHANGES HISTORY INSTALL INSTALL.configure \ LICENSE Makefile.in PORTING README README.LDAP \ diff --git a/usr.bin/sudo/README.LDAP b/usr.bin/sudo/README.LDAP index 030c1f9fe82..540df8d41b9 100644 --- a/usr.bin/sudo/README.LDAP +++ b/usr.bin/sudo/README.LDAP @@ -124,7 +124,8 @@ For OpenLDAP, simply copy schema.OpenLDAP to the schema directory restart slapd. For other LDAP servers, provide this to your LDAP Administrator. Make sure to index the attribute 'sudoUser'. -For the SunONE or iPlanet LDAP server, use the schema.iPlanet file. +For netscape-derived LDAP servers such as SunONE, iPlanet or Fedora +Directory, use the schema.iPlanet file. Importing /etc/sudoers to LDAP ============================== @@ -160,7 +161,17 @@ Example sudoers Entries in LDAP =============================== The equivalent of a sudoer in LDAP is a 'sudoRole'. It contains sudoUser(s), sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s). -<put an example here> + +The following example allows users in group wheel to run any +command on any host through sudo: + +dn: cn=%wheel,ou=SUDOers,dc=example,dc=com +objectClass: top +objectClass: sudoRole +cn: %wheel +sudoUser: %wheel +sudoHost: ALL +sudoCommand: ALL Managing LDAP entries ===================== @@ -180,7 +191,12 @@ I recommend using any of the following LDAP browsers to administer your SUDOers. http://www.mcs.anl.gov/~gawor/ldap http://ldapmanager.com - There are dozens of others, some open source, some free, some not. + * Apache Directory Studio - Open Source - an Eclipse-based LDAP + development platform. Includes an LDAP browser, and LDIF editor, + a schema editor and more. + http://directory.apache.org/studio + + There are dozens of others, some Open Source, some free, some not. Configure your /etc/ldap.conf @@ -188,18 +204,19 @@ Configure your /etc/ldap.conf The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap and other ldap applications and modules. IBM Secureway unfortunately uses the same filename but has a different syntax. If you need to rename where -this file is stored, recompile SUDO with the -DLDAP_CONFIG compile option. +this file is stored, re-run configure with the --with-ldap-conf-file=filename +option. Make sure you sudoers_base matches exactly with the location you specified when you imported the sudoers. Below is an example /etc/ldap.conf - # Either specify a uri or host & port + # Either specify a URI or host and port. + # If neither is specified sudo will default to localhost port 389. #host ldapserver #port 389 # - # URI will override host & port settings - # but only works with LDAP SDK's that support - # ldap_initialize() such as OpenLDAP + # URI will override host & port settings but only works with LDAP + # SDK's that support ldap_initialize() such as OpenLDAP. uri ldap://ldapserver #uri ldaps://secureldapserver # @@ -214,21 +231,27 @@ when you imported the sudoers. Below is an example /etc/ldap.conf #bindpw <password> #rootbinddn <who to search as, uses /etc/ldap.passwd for bindpw> # - # LDAP Protocol Version defaults to 3 + # LDAP protocol version, defaults to 3 #ldap_version 3 # + # Define if you want to use an encrypted LDAP connection. + # Typically, you must also set the port to 636 (ldaps). + #ssl on + # # Define if you want to use port 389 and switch to - # encryption before the bind credentials are sent + # encryption before the bind credentials are sent. + # Only supported by LDAP servers that support the start_tls + # extension such as OpenLDAP. #ssl start_tls # - # Additional TLS options follow that allow tweaking - # of the SSL/TLS connection + # Additional TLS options follow that allow tweaking of the + # SSL/TLS connection. Only supported when using OpenLDAP. # #tls_checkpeer yes # verify server SSL certificate #tls_checkpeer no # ignore server SSL certificate # # If you enable tls_checkpeer, specify either tls_cacertfile - # or tls_cacertdir. + # or tls_cacertdir. Only supported when using OpenLDAP. # #tls_cacertfile /etc/certs/trusted_signers.pem #tls_cacertdir /etc/certs @@ -236,11 +259,13 @@ when you imported the sudoers. Below is an example /etc/ldap.conf # For systems that don't have /dev/random # use this along with PRNGD or EGD.pl to seed the # random number pool to generate cryptographic session keys. + # Only supported when using OpenLDAP. # #tls_randfile /etc/egd-pool # # You may restrict which ciphers are used. Consult your SSL # documentation for which options go here. + # Only supported when using OpenLDAP. # #tls_ciphers <cipher-list> # @@ -251,9 +276,16 @@ when you imported the sudoers. Below is an example /etc/ldap.conf # * Do not password protect the key file. # * Ensure the keyfile is only readable by root. # + # For OpenLDAP: #tls_cert /etc/certs/client_cert.pem #tls_key /etc/certs/client_key.pem # + # For SunONE or iPlanet LDAP, the file specified by tls_cert may + # contain CA certs and/or the client's cert. If the client's + # cert is included, tls_key should be specified as well. + # For backward compatibility, sslpath may be used in place of tls_cert. + #tls_cert /var/ldap/cert7.db + #tls_key /var/ldap/key3.db Debugging your LDAP configuration ================================= @@ -321,12 +353,3 @@ seem. If you desperately want this to be changed, contact Aaron Spangler # rather, matches all hosts including web01 sudoHost: ALL sudoHost: !web01 - - -Configure your /etc/nsswitch.conf -================================= -At the time of this writing, sudo does not consult nsswitch.conf for the -search order. But if it did, it would look like this: -This might be implemented in the future. For now just skip this step. - - sudoers: files ldap diff --git a/usr.bin/sudo/config.h.in b/usr.bin/sudo/config.h.in index 2cf853dd0b0..2d45f3cb695 100644 --- a/usr.bin/sudo/config.h.in +++ b/usr.bin/sudo/config.h.in @@ -224,6 +224,9 @@ /* Define to 1 if you have the `ldap_start_tls_s' function. */ #undef HAVE_LDAP_START_TLS_S +/* Define to 1 if you have the `ldapssl_init' function. */ +#undef HAVE_LDAPSSL_INIT + /* Define to 1 if you have the `lockf' function. */ #undef HAVE_LOCKF diff --git a/usr.bin/sudo/configure b/usr.bin/sudo/configure index dd7fab20b1b..29b474fc02c 100644 --- a/usr.bin/sudo/configure +++ b/usr.bin/sudo/configure @@ -1562,7 +1562,7 @@ Optional Packages: --with-goons-insults include the insults from the "Goon Show" --with-ldap[=DIR] enable LDAP support --with-ldap-conf-file path to LDAP configuration file - --with-ldap-secret-file path to LDAP secret pasdword file + --with-ldap-secret-file path to LDAP secret password file --with-pc-insults replace politically incorrect insults with less offensive ones --with-secure-path override the user's path with a built-in one --without-interfaces don't try to read the ip addr of ether interfaces @@ -21059,6 +21059,64 @@ sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lk5crypto -lcom_err" + { echo "$as_me:$LINENO: checking for main in -lkrb5support" >&5 +echo $ECHO_N "checking for main in -lkrb5support... $ECHO_C" >&6; } +if test "${ac_cv_lib_krb5support_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkrb5support $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_krb5support_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_krb5support_main=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_krb5support_main" >&5 +echo "${ECHO_T}$ac_cv_lib_krb5support_main" >&6; } +if test $ac_cv_lib_krb5support_main = yes; then + SUDO_LIBS="${SUDO_LIBS} -lkrb5support," +fi fi @@ -22378,7 +22436,8 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ -for ac_func in ldap_initialize ldap_start_tls_s + +for ac_func in ldap_initialize ldap_start_tls_s ldapssl_init do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/usr.bin/sudo/configure.in b/usr.bin/sudo/configure.in index b87a8639747..a64fb6978cc 100644 --- a/usr.bin/sudo/configure.in +++ b/usr.bin/sudo/configure.in @@ -1,6 +1,6 @@ dnl dnl Process this file with GNU autoconf to produce a configure script. -dnl $Sudo: configure.in,v 1.413.2.30 2007/12/02 00:35:20 millert Exp $ +dnl $Sudo: configure.in,v 1.413.2.34 2007/12/19 19:29:29 millert Exp $ dnl dnl Copyright (c) 1994-1996,1998-2007 Todd C. Miller <Todd.Miller@courtesan.com> dnl @@ -909,7 +909,7 @@ AC_ARG_WITH(ldap, [ --with-ldap[[=DIR]] enable LDAP support], esac]) AC_ARG_WITH(ldap-conf-file, [ --with-ldap-conf-file path to LDAP configuration file], [AC_DEFINE_UNQUOTED(_PATH_LDAP_CONF, "$with_ldap_conf_file", [Path to the ldap.conf file])]) -AC_ARG_WITH(ldap-secret-file, [ --with-ldap-secret-file path to LDAP secret pasdword file], +AC_ARG_WITH(ldap-secret-file, [ --with-ldap-secret-file path to LDAP secret password file], [AC_DEFINE_UNQUOTED(_PATH_LDAP_SECRET, "$with_ldap_secret_file", [Path to the ldap.secret file])]) AC_ARG_WITH(pc-insults, [ --with-pc-insults replace politically incorrect insults with less offensive ones], @@ -2064,7 +2064,7 @@ if test ${with_kerb5-'no'} != "no" -a -z "$KRB5CONFIG"; then ], [ AC_MSG_RESULT(no) SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lk5crypto -lcom_err" - + AC_CHECK_LIB(krb5support, main, [SUDO_LIBS="${SUDO_LIBS} -lkrb5support,"]) ]) AUTH_OBJS="$AUTH_OBJS kerb5.o" _LIBS="$LIBS" @@ -2284,7 +2284,7 @@ if test ${with_ldap-'no'} != "no"; then AC_MSG_RESULT([yes]) AC_DEFINE(HAVE_LBER_H)]) - AC_CHECK_FUNCS(ldap_initialize ldap_start_tls_s) + AC_CHECK_FUNCS(ldap_initialize ldap_start_tls_s ldapssl_init) SUDO_LIBS="${SUDO_LIBS}${LDAP_LIBS}" LIBS="$_LIBS" diff --git a/usr.bin/sudo/ldap.c b/usr.bin/sudo/ldap.c index 14d046c74be..85762ab7d99 100644 --- a/usr.bin/sudo/ldap.c +++ b/usr.bin/sudo/ldap.c @@ -65,7 +65,7 @@ #include "parse.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.20 2007/11/27 17:06:54 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.28 2007/12/19 19:29:32 millert Exp $"; #endif /* lint */ #ifndef LINE_MAX @@ -76,20 +76,33 @@ __unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.20 2007/11/27 17:06 # define LDAP_OPT_SUCCESS LDAP_SUCCESS #endif -#if defined(LDAP_X_OPT_CONNECT_TIMEOUT) && !defined(LDAP_OPT_X_CONNECT_TIMEOUT) -#define LDAP_OPT_X_CONNECT_TIMEOUT LDAP_OPT_X_CONNECT_TIMEOUT -#endif - #define DPRINTF(args, level) if (ldap_conf.debug >= level) warnx args +#define CONF_BOOL 0 +#define CONF_INT 1 +#define CONF_STR 2 + +#define SUDO_LDAP_SSL 1 +#define SUDO_LDAP_STARTTLS 2 + +struct ldap_config_table { + const char *conf_str; /* config file string */ + short type; /* CONF_BOOL, CONF_INT, CONF_STR */ + short connected; /* connection-specific value? */ + int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */ + void *valp; /* pointer into ldap_conf */ +}; + /* ldap configuration structure */ struct ldap_config { int port; int version; int debug; + int ldap_debug; int tls_checkpeer; int timelimit; int bind_timelimit; + int ssl_mode; char *host; char *uri; char *binddn; @@ -105,6 +118,67 @@ struct ldap_config { char *tls_keyfile; } ldap_conf; +struct ldap_config_table ldap_conf_table[] = { + { "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug }, + { "host", CONF_STR, FALSE, -1, &ldap_conf.host }, + { "port", CONF_INT, FALSE, -1, &ldap_conf.port }, + { "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl }, + { "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile }, + { "uri", CONF_STR, FALSE, -1, &ldap_conf.uri }, +#ifdef LDAP_OPT_DEBUG_LEVEL + { "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug }, +#endif +#ifdef LDAP_OPT_PROTOCOL_VERSION + { "ldap_version", CONF_INT, TRUE, LDAP_OPT_PROTOCOL_VERSION, + &ldap_conf.version }, +#endif +#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT + { "tls_checkpeer", CONF_BOOL, FALSE, LDAP_OPT_X_TLS_REQUIRE_CERT, + &ldap_conf.tls_checkpeer }, +#endif +#ifdef LDAP_OPT_X_TLS_CACERTFILE + { "tls_cacertfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE, + &ldap_conf.tls_cacertfile }, +#endif +#ifdef LDAP_OPT_X_TLS_CACERTDIR + { "tls_cacertdir", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTDIR, + &ldap_conf.tls_cacertdir }, +#endif +#ifdef LDAP_OPT_X_TLS_RANDOM_FILE + { "tls_randfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_RANDOM_FILE, + &ldap_conf.tls_random_file }, +#endif +#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE + { "tls_ciphers", CONF_STR, FALSE, LDAP_OPT_X_TLS_CIPHER_SUITE, + &ldap_conf.tls_cipher_suite }, +#endif +#ifdef LDAP_OPT_X_TLS_CERTFILE + { "tls_cert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CERTFILE, + &ldap_conf.tls_certfile }, +#else + { "tls_cert", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile }, +#endif +#ifdef LDAP_OPT_X_TLS_KEYFILE + { "tls_key", CONF_STR, FALSE, LDAP_OPT_X_TLS_KEYFILE, + &ldap_conf.tls_keyfile }, +#else + { "tls_key", CONF_STR, FALSE, -1, &ldap_conf.tls_keyfile }, +#endif +#ifdef LDAP_OPT_NETWORK_TIMEOUT + { "bind_timelimit", CONF_INT, TRUE, -1 /* needs timeval, set manually */, + &ldap_conf.bind_timelimit }, +#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) + { "bind_timelimit", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT, + &ldap_conf.bind_timelimit }, +#endif + { "timelimit", CONF_INT, TRUE, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit }, + { "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn }, + { "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw }, + { "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn }, + { "sudoers_base", CONF_STR, FALSE, -1, &ldap_conf.base }, + { NULL } +}; + static void sudo_ldap_update_defaults __P((LDAP *)); static void sudo_ldap_close __P((LDAP *)); static LDAP *sudo_ldap_open __P((void)); @@ -495,16 +569,18 @@ sudo_ldap_read_config() { FILE *f; char buf[LINE_MAX], *c, *keyword, *value; + struct ldap_config_table *cur; /* defaults */ ldap_conf.version = 3; - ldap_conf.port = 389; + ldap_conf.port = -1; ldap_conf.tls_checkpeer = -1; ldap_conf.timelimit = -1; ldap_conf.bind_timelimit = -1; if ((f = fopen(_PATH_LDAP_CONF, "r")) == NULL) return(FALSE); + while (fgets(buf, sizeof(buf), f)) { /* ignore text after comment character */ if ((c = strchr(buf, '#')) != NULL) @@ -535,68 +611,29 @@ sudo_ldap_read_config() while (--c > value && isspace((unsigned char) *c)) *c = '\0'; - /* The following macros make the code much more readable */ - -#define MATCH_S(x,y) if (!strcasecmp(keyword,x)) \ - { efree(y); y=estrdup(value); } -#define MATCH_I(x,y) if (!strcasecmp(keyword,x)) { y=atoi(value); } -#define MATCH_B(x,y) if (!strcasecmp(keyword,x)) { y=_atobool(value); } - - /* - * Parse values using a continues chain of if else if else if else if - * else ... - */ - MATCH_S("host", ldap_conf.host) - else - MATCH_I("port", ldap_conf.port) - else - MATCH_S("ssl", ldap_conf.ssl) - else - MATCH_B("tls_checkpeer", ldap_conf.tls_checkpeer) - else - MATCH_S("tls_cacertfile", ldap_conf.tls_cacertfile) - else - MATCH_S("tls_cacertdir", ldap_conf.tls_cacertdir) - else - MATCH_S("tls_randfile", ldap_conf.tls_random_file) - else - MATCH_S("tls_ciphers", ldap_conf.tls_cipher_suite) - else - MATCH_S("tls_cert", ldap_conf.tls_certfile) - else - MATCH_S("tls_key", ldap_conf.tls_keyfile) - else - MATCH_I("ldap_version", ldap_conf.version) - else - MATCH_I("bind_timelimit", ldap_conf.bind_timelimit) - else - MATCH_I("timelimit", ldap_conf.timelimit) - else - MATCH_S("uri", ldap_conf.uri) - else - MATCH_S("binddn", ldap_conf.binddn) - else - MATCH_S("bindpw", ldap_conf.bindpw) - else - MATCH_S("rootbinddn", ldap_conf.rootbinddn) - else - MATCH_S("sudoers_base", ldap_conf.base) - else - MATCH_I("sudoers_debug", ldap_conf.debug) - else { - - /* - * The keyword was unrecognized. Since this config file is - * shared by multiple programs, it is appropriate to silently - * ignore options this program does not understand - */ + /* Look up keyword in config table. */ + for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) { + if (strcasecmp(keyword, cur->conf_str) == 0) { + switch (cur->type) { + case CONF_BOOL: + *(int *)(cur->valp) = _atobool(value); + break; + case CONF_INT: + *(int *)(cur->valp) = atoi(value); + break; + case CONF_STR: + efree(*(char **)(cur->valp)); + *(char **)(cur->valp) = estrdup(value); + break; + } + break; + } } - } fclose(f); if (!ldap_conf.host) - ldap_conf.host = estrdup("localhost"); + ldap_conf.host = "localhost"; if (ldap_conf.bind_timelimit > 0) ldap_conf.bind_timelimit *= 1000; /* convert to ms */ @@ -622,17 +659,47 @@ sudo_ldap_read_config() ldap_conf.binddn : "(anonymous)"); fprintf(stderr, "bindpw %s\n", ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)"); - fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit); - fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit); -#ifdef HAVE_LDAP_START_TLS_S + if (ldap_conf.bind_timelimit > 0) + fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit); + if (ldap_conf.timelimit > 0) + fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit); fprintf(stderr, "ssl %s\n", ldap_conf.ssl ? ldap_conf.ssl : "(no)"); -#endif + if (ldap_conf.tls_checkpeer != -1) + fprintf(stderr, "tls_checkpeer %s\n", ldap_conf.tls_checkpeer ? + "(yes)" : "(no)"); + if (ldap_conf.tls_cacertfile != NULL) + fprintf(stderr, "tls_cacertfile %s\n", ldap_conf.tls_cacertfile); + if (ldap_conf.tls_cacertdir != NULL) + fprintf(stderr, "tls_cacertdir %s\n", ldap_conf.tls_cacertdir); + if (ldap_conf.tls_random_file != NULL) + fprintf(stderr, "tls_random_file %s\n", ldap_conf.tls_random_file); + if (ldap_conf.tls_cipher_suite != NULL) + fprintf(stderr, "tls_cipher_suite %s\n", ldap_conf.tls_cipher_suite); + if (ldap_conf.tls_certfile != NULL) + fprintf(stderr, "tls_certfile %s\n", ldap_conf.tls_certfile); + if (ldap_conf.tls_keyfile != NULL) + fprintf(stderr, "tls_keyfile %s\n", ldap_conf.tls_keyfile); fprintf(stderr, "===================\n"); } if (!ldap_conf.base) return(FALSE); /* if no base is defined, ignore LDAP */ + /* + * Interpret SSL option + */ + if (ldap_conf.ssl != NULL) { + if (strcasecmp(ldap_conf.ssl, "start_tls") == 0) + ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS; + else if (_atobool(ldap_conf.ssl)) + ldap_conf.ssl_mode = SUDO_LDAP_SSL; + } + + /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */ + if (ldap_conf.port < 0) + ldap_conf.port = + ldap_conf.ssl_mode == SUDO_LDAP_SSL ? LDAPS_PORT : LDAP_PORT; + /* If rootbinddn set, read in /etc/ldap.secret if it exists. */ if (ldap_conf.rootbinddn) { if ((f = fopen(_PATH_LDAP_SECRET, "r")) != NULL) { @@ -746,148 +813,171 @@ sudo_ldap_list_matches() printf("%s", sudo_ldap_cm_list); } -/* macros to set option, error on failure plus consistent debugging */ -#define SET_OPTS(opt, val) do { \ - if (ldap_conf.val != NULL) { \ - if (ldap_conf.debug > 1) \ - fprintf(stderr, \ - "ldap_set_option(LDAP_OPT_%s, \"%s\")\n", #opt, ldap_conf.val);\ - rc = ldap_set_option(ld, LDAP_OPT_ ## opt, ldap_conf.val); \ - if (rc != LDAP_OPT_SUCCESS) { \ - fprintf(stderr,"ldap_set_option(LDAP_OPT_%s, \"%s\")=%d: %s\n", \ - #opt, ldap_conf.val, rc, ldap_err2string(rc)); \ - return(NULL); \ - } \ - } \ -} while(0) -#define SET_OPTI(opt, val) do { \ - if (ldap_conf.val >= 0) { \ - if (ldap_conf.debug > 1) \ - fprintf(stderr, \ - "ldap_set_option(LDAP_OPT_%s, %d)\n", #opt, ldap_conf.val); \ - rc = ldap_set_option(ld, LDAP_OPT_ ## opt, &ldap_conf.val); \ - if (rc != LDAP_OPT_SUCCESS) { \ - fprintf(stderr,"ldap_set_option(LDAP_OPT_%s, %d)=%d: %s\n", \ - #opt, ldap_conf.val, rc, ldap_err2string(rc)); \ - return(NULL); \ - } \ - } \ -} while(0) - /* - * Open a connection to the LDAP server. + * Set LDAP options based on the config table. */ -static LDAP * -sudo_ldap_open() +int +sudo_ldap_set_options(ld) + LDAP *ld; { - LDAP *ld = NULL; + struct ldap_config_table *cur; int rc; - if (!sudo_ldap_read_config()) - return(NULL); - - /* attempt to setup ssl options */ -#ifdef LDAP_OPT_X_TLS_CACERTFILE - SET_OPTS(X_TLS_CACERTFILE, tls_cacertfile); -#endif /* LDAP_OPT_X_TLS_CACERTFILE */ - -#ifdef LDAP_OPT_X_TLS_CACERTDIR - SET_OPTS(X_TLS_CACERTDIR, tls_cacertdir); -#endif /* LDAP_OPT_X_TLS_CACERTDIR */ - -#ifdef LDAP_OPT_X_TLS_CERTFILE - SET_OPTS(X_TLS_CERTFILE, tls_certfile); -#endif /* LDAP_OPT_X_TLS_CERTFILE */ - -#ifdef LDAP_OPT_X_TLS_KEYFILE - SET_OPTS(X_TLS_KEYFILE, tls_keyfile); -#endif /* LDAP_OPT_X_TLS_KEYFILE */ - -#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE - SET_OPTS(X_TLS_CIPHER_SUITE, tls_cipher_suite); -#endif /* LDAP_OPT_X_TLS_CIPHER_SUITE */ + /* Set ber options */ +#ifdef LBER_OPT_DEBUG_LEVEL + if (ldap_conf.ldap_debug) + ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug); +#endif -#ifdef LDAP_OPT_X_TLS_RANDOM_FILE - SET_OPTS(X_TLS_RANDOM_FILE, tls_random_file); -#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ + /* Set simple LDAP options */ + for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) { + LDAP *conn; + int ival; + char *sval; -#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT - /* check the server certificate? */ - SET_OPTI(X_TLS_REQUIRE_CERT, tls_checkpeer); -#endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */ + if (cur->opt_val == -1) + continue; - /* set timelimit options */ - SET_OPTI(TIMELIMIT, timelimit); + conn = cur->connected ? ld : NULL; + switch (cur->type) { + case CONF_BOOL: + case CONF_INT: + ival = *(int *)(cur->valp); + if (ival >= 0) { + rc = ldap_set_option(conn, cur->opt_val, &ival); + if (rc != LDAP_OPT_SUCCESS) { + warnx("ldap_set_option: %s -> %d: %s", + cur->conf_str, ival, ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_set_option: %s -> %d", cur->conf_str, ival), 1); + } + break; + case CONF_STR: + sval = *(char **)(cur->valp); + if (sval != NULL) { + rc = ldap_set_option(conn, cur->opt_val, sval); + if (rc != LDAP_OPT_SUCCESS) { + warnx("ldap_set_option: %s -> %s: %s", + cur->conf_str, sval, ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_set_option: %s -> %s", cur->conf_str, sval), 1); + } + break; + } + } #ifdef LDAP_OPT_NETWORK_TIMEOUT + /* Convert bind_timelimit to a timeval */ if (ldap_conf.bind_timelimit > 0) { struct timeval tv; tv.tv_sec = ldap_conf.bind_timelimit / 1000; tv.tv_usec = 0; - if (ldap_conf.debug > 1) - fprintf(stderr, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)\n", - tv.tv_sec); rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); if (rc != LDAP_OPT_SUCCESS) { - fprintf(stderr,"ldap_set_option(NETWORK_TIMEOUT, %ld)=%d: %s\n", - tv.tv_sec, rc, ldap_err2string(rc)); - return(NULL); + warnx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s", + (long)tv.tv_sec, ldap_err2string(rc)); + return(-1); } + DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)\n", + (long)tv.tv_sec), 1); } #endif - /* attempt connect */ -#ifdef HAVE_LDAP_INITIALIZE - if (ldap_conf.uri) { +#if defined(LDAP_OPT_X_TLS) && !defined(HAVE_LDAPSSL_INIT) + if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { + int val = LDAP_OPT_X_TLS_HARD; + rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val); + if (rc != LDAP_SUCCESS) { + warnx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s", + ldap_err2string(rc)); + return(-1); + } + + } +#endif + return(0); +} + +/* + * Open a connection to the LDAP server. + */ +static LDAP * +sudo_ldap_open() +{ + LDAP *ld = NULL; + int rc; + + if (!sudo_ldap_read_config()) + return(NULL); - DPRINTF(("ldap_initialize(ld,%s)", ldap_conf.uri), 2); +#ifdef HAVE_LDAPSSL_INIT + if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { + DPRINTF(("ldapssl_clientauth_init(%s, %s)", + ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", + ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2); + rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, + ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); + if (rc != LDAP_SUCCESS) { + warnx("unable to initialize SSL cert and key db: %s", + ldapssl_err2string(rc)); + return(NULL); + } + } +#endif /* HAVE_LDAPSSL_INIT */ + /* Connect to LDAP server */ +#ifdef HAVE_LDAP_INITIALIZE + if (ldap_conf.uri) { + DPRINTF(("ldap_initialize(ld, %s)", ldap_conf.uri), 2); rc = ldap_initialize(&ld, ldap_conf.uri); - if (rc) { - fprintf(stderr, "ldap_initialize()=%d : %s\n", - rc, ldap_err2string(rc)); + if (rc != LDAP_SUCCESS) { + warnx("unable to initialize LDAP: %s", ldap_err2string(rc)); return(NULL); } } else #endif /* HAVE_LDAP_INITIALIZE */ - if (ldap_conf.host) { - - DPRINTF(("ldap_init(%s,%d)", ldap_conf.host, ldap_conf.port), 2); - - if ((ld = ldap_init(ldap_conf.host, ldap_conf.port)) == NULL) { - fprintf(stderr, "ldap_init(): errno=%d : %s\n", - errno, strerror(errno)); + { +#ifdef HAVE_LDAPSSL_INIT + DPRINTF(("ldapssl_init(%s, %d, %d)", ldap_conf.host, ldap_conf.port, + ldap_conf.ssl_mode == SUDO_LDAP_SSL), 2); + ld = ldapssl_init(ldap_conf.host, ldap_conf.port, + ldap_conf.ssl_mode == SUDO_LDAP_SSL); +#else + DPRINTF(("ldap_init(%s, %d)", ldap_conf.host, ldap_conf.port), 2); + ld = ldap_init(ldap_conf.host, ldap_conf.port); +#endif /* HAVE_LDAPSSL_INIT */ + if (ld == NULL) { + warn("unable to initialize LDAP"); return(NULL); } } -#ifdef LDAP_OPT_PROTOCOL_VERSION - - /* Set the LDAP Protocol version */ - SET_OPTI(PROTOCOL_VERSION, version); -#endif /* LDAP_OPT_PROTOCOL_VERSION */ + /* Set LDAP options */ + if (sudo_ldap_set_options(ld) < 0) + return(NULL); + if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { #ifdef HAVE_LDAP_START_TLS_S - /* Turn on TLS */ - if (ldap_conf.ssl && !strcasecmp(ldap_conf.ssl, "start_tls")) { rc = ldap_start_tls_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { - fprintf(stderr, "ldap_start_tls_s(): %d: %s\n", rc, - ldap_err2string(rc)); + warnx("ldap_start_tls_s(): %s", ldap_err2string(rc)); ldap_unbind(ld); return(NULL); } DPRINTF(("ldap_start_tls_s() ok"), 1); - } +#else + warnx("start_tls specified but LDAP libs do not support ldap_start_tls_s()"); #endif /* HAVE_LDAP_START_TLS_S */ + } /* Actually connect */ if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) { - fprintf(stderr, "ldap_simple_bind_s()=%d : %s\n", - rc, ldap_err2string(rc)); + warnx("ldap_simple_bind_s: %s", ldap_err2string(rc)); return(NULL); } - DPRINTF(("ldap_bind() ok"), 1); + DPRINTF(("ldap_simple_bind_s() ok"), 1); return(ld); } @@ -901,7 +991,7 @@ sudo_ldap_update_defaults(ld) rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, "cn=defaults", NULL, 0, &result); - if (!rc && (entry = ldap_first_entry(ld, result))) { + if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) { DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); sudo_ldap_parse_options(ld, entry); } else @@ -952,7 +1042,7 @@ sudo_ldap_check(pwflag) DPRINTF(("ldap search '%s'", filt), 1); rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, NULL, 0, &result); - if (rc) + if (rc != LDAP_SUCCESS) DPRINTF(("nothing found for '%s'", filt), 1); efree(filt); diff --git a/usr.bin/sudo/sudo.c b/usr.bin/sudo/sudo.c index d98d8c85ff5..021e0e560b7 100644 --- a/usr.bin/sudo/sudo.c +++ b/usr.bin/sudo/sudo.c @@ -102,7 +102,7 @@ #include "version.h" #ifndef lint -__unused __unused static const char rcsid[] = "$Sudo: sudo.c,v 1.369.2.33 2007/12/02 17:13:52 millert Exp $"; +__unused __unused static const char rcsid[] = "$Sudo: sudo.c,v 1.369.2.34 2007/12/13 14:12:49 millert Exp $"; #endif /* lint */ /* @@ -730,8 +730,10 @@ parse_args(argc, argv) while (NewArgc > 0) { if (NewArgv[0][0] == '-') { - if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') + if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') { warnx("please use single character options"); + usage(1); + } switch (NewArgv[0][1]) { case 'p': diff --git a/usr.bin/sudo/version.h b/usr.bin/sudo/version.h index c02a6d99b49..1c3a4f76d06 100644 --- a/usr.bin/sudo/version.h +++ b/usr.bin/sudo/version.h @@ -17,12 +17,12 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: version.h,v 1.66.2.12 2007/12/03 10:34:32 millert Exp $ + * $Sudo: version.h,v 1.66.2.13 2007/12/17 19:18:14 millert Exp $ */ #ifndef _SUDO_VERSION_H #define _SUDO_VERSION_H -static const char version[] = "1.6.9p9"; +static const char version[] = "1.6.9p10"; #endif /* _SUDO_VERSION_H */ |