Move LDAP configuration bits into ldap_conf.c
This commit is contained in:
2
MANIFEST
2
MANIFEST
@@ -305,6 +305,7 @@ plugins/sudoers/iolog.h
|
|||||||
plugins/sudoers/iolog_path.c
|
plugins/sudoers/iolog_path.c
|
||||||
plugins/sudoers/ldap.c
|
plugins/sudoers/ldap.c
|
||||||
plugins/sudoers/ldap_common.c
|
plugins/sudoers/ldap_common.c
|
||||||
|
plugins/sudoers/ldap_conf.c
|
||||||
plugins/sudoers/linux_audit.c
|
plugins/sudoers/linux_audit.c
|
||||||
plugins/sudoers/linux_audit.h
|
plugins/sudoers/linux_audit.h
|
||||||
plugins/sudoers/locale.c
|
plugins/sudoers/locale.c
|
||||||
@@ -553,6 +554,7 @@ plugins/sudoers/sssd.c
|
|||||||
plugins/sudoers/starttime.c
|
plugins/sudoers/starttime.c
|
||||||
plugins/sudoers/stubs.c
|
plugins/sudoers/stubs.c
|
||||||
plugins/sudoers/sudo_ldap.h
|
plugins/sudoers/sudo_ldap.h
|
||||||
|
plugins/sudoers/sudo_ldap_conf.h
|
||||||
plugins/sudoers/sudo_nss.c
|
plugins/sudoers/sudo_nss.c
|
||||||
plugins/sudoers/sudo_nss.h
|
plugins/sudoers/sudo_nss.h
|
||||||
plugins/sudoers/sudo_printf.c
|
plugins/sudoers/sudo_printf.c
|
||||||
|
2
configure
vendored
2
configure
vendored
@@ -24492,7 +24492,7 @@ fi
|
|||||||
|
|
||||||
with_ldap=yes
|
with_ldap=yes
|
||||||
fi
|
fi
|
||||||
SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo"
|
SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo ldap_conf.lo"
|
||||||
case "$SUDOERS_OBJS" in
|
case "$SUDOERS_OBJS" in
|
||||||
*ldap_common.lo*) ;;
|
*ldap_common.lo*) ;;
|
||||||
*) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";;
|
*) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";;
|
||||||
|
@@ -3730,7 +3730,7 @@ if test ${with_ldap-'no'} != "no"; then
|
|||||||
AX_APPEND_FLAG([-I${with_ldap}/include], [CPPFLAGS])
|
AX_APPEND_FLAG([-I${with_ldap}/include], [CPPFLAGS])
|
||||||
with_ldap=yes
|
with_ldap=yes
|
||||||
fi
|
fi
|
||||||
SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo"
|
SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo ldap_conf.lo"
|
||||||
case "$SUDOERS_OBJS" in
|
case "$SUDOERS_OBJS" in
|
||||||
*ldap_common.lo*) ;;
|
*ldap_common.lo*) ;;
|
||||||
*) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";;
|
*) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";;
|
||||||
|
2
mkdep.pl
2
mkdep.pl
@@ -79,7 +79,7 @@ sub mkdep {
|
|||||||
$makefile =~ s:\@DEV\@::g;
|
$makefile =~ s:\@DEV\@::g;
|
||||||
$makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
|
$makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
|
||||||
$makefile =~ s:\@SUDO_OBJS\@:openbsd.o preload.o selinux.o sesh.o solaris.o:;
|
$makefile =~ s:\@SUDO_OBJS\@:openbsd.o preload.o selinux.o sesh.o solaris.o:;
|
||||||
$makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo ldap_common.lo solaris_audit.lo sssd.lo:;
|
$makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo ldap_common.lo ldap_conf.lo solaris_audit.lo sssd.lo:;
|
||||||
# XXX - fill in AUTH_OBJS from contents of the auth dir instead
|
# XXX - fill in AUTH_OBJS from contents of the auth dir instead
|
||||||
$makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
|
$makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
|
||||||
$makefile =~ s:\@FILEDIGEST\@:filedigest.lo filedigest_openssl.lo filedigest_gcrypt.lo:;
|
$makefile =~ s:\@FILEDIGEST\@:filedigest.lo filedigest_openssl.lo filedigest_gcrypt.lo:;
|
||||||
|
@@ -987,6 +987,17 @@ ldap_common.lo: $(srcdir)/ldap_common.c $(devdir)/def_data.h $(devdir)/gram.h \
|
|||||||
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
|
||||||
$(top_builddir)/pathnames.h
|
$(top_builddir)/pathnames.h
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/ldap_common.c
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/ldap_common.c
|
||||||
|
ldap_conf.lo: $(srcdir)/ldap_conf.c $(devdir)/def_data.h $(devdir)/gram.h \
|
||||||
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_dso.h $(incdir)/sudo_fatal.h \
|
||||||
|
$(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
|
||||||
|
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
$(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
|
||||||
|
$(srcdir)/parse.h $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
|
||||||
|
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
|
||||||
|
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/ldap_conf.c
|
||||||
linux_audit.lo: $(srcdir)/linux_audit.c $(devdir)/def_data.h \
|
linux_audit.lo: $(srcdir)/linux_audit.c $(devdir)/def_data.h \
|
||||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
|
||||||
|
@@ -36,9 +36,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#ifdef HAVE_LBER_H
|
#ifdef HAVE_LBER_H
|
||||||
# include <lber.h>
|
# include <lber.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -61,25 +58,9 @@
|
|||||||
#include "gram.h"
|
#include "gram.h"
|
||||||
#include "sudo_lbuf.h"
|
#include "sudo_lbuf.h"
|
||||||
#include "sudo_ldap.h"
|
#include "sudo_ldap.h"
|
||||||
|
#include "sudo_ldap_conf.h"
|
||||||
#include "sudo_dso.h"
|
#include "sudo_dso.h"
|
||||||
|
|
||||||
/* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */
|
|
||||||
#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H)
|
|
||||||
extern int ldapssl_set_strength(LDAP *ldap, int strength);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT)
|
|
||||||
# define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LDAP_OPT_SUCCESS
|
|
||||||
# define LDAP_OPT_SUCCESS LDAP_SUCCESS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LDAPS_PORT
|
|
||||||
# define LDAPS_PORT 636
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET)
|
#if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET)
|
||||||
# define LDAP_SASL_QUIET 0
|
# define LDAP_SASL_QUIET 0
|
||||||
#endif
|
#endif
|
||||||
@@ -103,60 +84,6 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength);
|
|||||||
(var) != NULL; \
|
(var) != NULL; \
|
||||||
(var) = ldap_next_entry((ld), (var)))
|
(var) = ldap_next_entry((ld), (var)))
|
||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ == 2
|
|
||||||
# define DPRINTF1(fmt...) do { \
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, fmt); \
|
|
||||||
if (ldap_conf.debug >= 1) \
|
|
||||||
sudo_warnx_nodebug(fmt); \
|
|
||||||
} while (0)
|
|
||||||
# define DPRINTF2(fmt...) do { \
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, fmt); \
|
|
||||||
if (ldap_conf.debug >= 2) \
|
|
||||||
sudo_warnx_nodebug(fmt); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
# define DPRINTF1(...) do { \
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, __VA_ARGS__); \
|
|
||||||
if (ldap_conf.debug >= 1) \
|
|
||||||
sudo_warnx_nodebug(__VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
# define DPRINTF2(...) do { \
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, __VA_ARGS__); \
|
|
||||||
if (ldap_conf.debug >= 2) \
|
|
||||||
sudo_warnx_nodebug(__VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Macros for checking strlcpy/strlcat/sudo_ldap_value_cat return value. */
|
|
||||||
#define CHECK_STRLCPY(d, s, l) do { \
|
|
||||||
if (strlcpy((d), (s), (l)) >= (l)) \
|
|
||||||
goto overflow; \
|
|
||||||
} while (0)
|
|
||||||
#define CHECK_STRLCAT(d, s, l) do { \
|
|
||||||
if (strlcat((d), (s), (l)) >= (l)) \
|
|
||||||
goto overflow; \
|
|
||||||
} while (0)
|
|
||||||
#define CHECK_LDAP_VCAT(d, s, l) do { \
|
|
||||||
if (sudo_ldap_value_cat((d), (s), (l)) >= (l)) \
|
|
||||||
goto overflow; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define CONF_BOOL 0
|
|
||||||
#define CONF_INT 1
|
|
||||||
#define CONF_STR 2
|
|
||||||
#define CONF_LIST_STR 4
|
|
||||||
#define CONF_DEREF_VAL 5
|
|
||||||
|
|
||||||
#define SUDO_LDAP_CLEAR 0
|
|
||||||
#define SUDO_LDAP_SSL 1
|
|
||||||
#define SUDO_LDAP_STARTTLS 2
|
|
||||||
|
|
||||||
/* Default search filter. */
|
|
||||||
#define DEFAULT_SEARCH_FILTER "(objectClass=sudoRole)"
|
|
||||||
|
|
||||||
/* Default netgroup search filter. */
|
|
||||||
#define DEFAULT_NETGROUP_SEARCH_FILTER "(objectClass=nisNetgroup)"
|
|
||||||
|
|
||||||
/* The TIMEFILTER_LENGTH is the length of the filter when timed entries
|
/* The TIMEFILTER_LENGTH is the length of the filter when timed entries
|
||||||
are used. The length is computed as follows:
|
are used. The length is computed as follows:
|
||||||
81 for the filter itself
|
81 for the filter itself
|
||||||
@@ -212,160 +139,6 @@ struct ldap_netgroup {
|
|||||||
};
|
};
|
||||||
STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
|
STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
|
||||||
|
|
||||||
struct ldap_config_table {
|
|
||||||
const char *conf_str; /* config file string */
|
|
||||||
int type; /* CONF_BOOL, CONF_INT, CONF_STR */
|
|
||||||
int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */
|
|
||||||
void *valp; /* pointer into ldap_conf */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ldap_config_str {
|
|
||||||
STAILQ_ENTRY(ldap_config_str) entries;
|
|
||||||
char val[1];
|
|
||||||
};
|
|
||||||
STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
|
|
||||||
|
|
||||||
/* LDAP configuration structure */
|
|
||||||
static struct ldap_config {
|
|
||||||
int port;
|
|
||||||
int version;
|
|
||||||
int debug;
|
|
||||||
int ldap_debug;
|
|
||||||
int tls_checkpeer;
|
|
||||||
int timelimit;
|
|
||||||
int timeout;
|
|
||||||
int bind_timelimit;
|
|
||||||
int use_sasl;
|
|
||||||
int rootuse_sasl;
|
|
||||||
int ssl_mode;
|
|
||||||
int timed;
|
|
||||||
int deref;
|
|
||||||
char *host;
|
|
||||||
struct ldap_config_str_list uri;
|
|
||||||
char *binddn;
|
|
||||||
char *bindpw;
|
|
||||||
char *rootbinddn;
|
|
||||||
struct ldap_config_str_list base;
|
|
||||||
struct ldap_config_str_list netgroup_base;
|
|
||||||
char *search_filter;
|
|
||||||
char *netgroup_search_filter;
|
|
||||||
char *ssl;
|
|
||||||
char *tls_cacertfile;
|
|
||||||
char *tls_cacertdir;
|
|
||||||
char *tls_random_file;
|
|
||||||
char *tls_cipher_suite;
|
|
||||||
char *tls_certfile;
|
|
||||||
char *tls_keyfile;
|
|
||||||
char *tls_keypw;
|
|
||||||
char *sasl_mech;
|
|
||||||
char *sasl_auth_id;
|
|
||||||
char *rootsasl_auth_id;
|
|
||||||
char *sasl_secprops;
|
|
||||||
char *krb5_ccname;
|
|
||||||
} ldap_conf;
|
|
||||||
|
|
||||||
static struct ldap_config_table ldap_conf_global[] = {
|
|
||||||
{ "sudoers_debug", CONF_INT, -1, &ldap_conf.debug },
|
|
||||||
{ "host", CONF_STR, -1, &ldap_conf.host },
|
|
||||||
{ "port", CONF_INT, -1, &ldap_conf.port },
|
|
||||||
{ "ssl", CONF_STR, -1, &ldap_conf.ssl },
|
|
||||||
{ "sslpath", CONF_STR, -1, &ldap_conf.tls_certfile },
|
|
||||||
{ "uri", CONF_LIST_STR, -1, &ldap_conf.uri },
|
|
||||||
#ifdef LDAP_OPT_DEBUG_LEVEL
|
|
||||||
{ "debug", CONF_INT, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
|
|
||||||
{ "tls_checkpeer", CONF_BOOL, LDAP_OPT_X_TLS_REQUIRE_CERT,
|
|
||||||
&ldap_conf.tls_checkpeer },
|
|
||||||
#else
|
|
||||||
{ "tls_checkpeer", CONF_BOOL, -1, &ldap_conf.tls_checkpeer },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_CACERTFILE
|
|
||||||
{ "tls_cacertfile", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
|
|
||||||
&ldap_conf.tls_cacertfile },
|
|
||||||
{ "tls_cacert", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
|
|
||||||
&ldap_conf.tls_cacertfile },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_CACERTDIR
|
|
||||||
{ "tls_cacertdir", CONF_STR, LDAP_OPT_X_TLS_CACERTDIR,
|
|
||||||
&ldap_conf.tls_cacertdir },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_RANDOM_FILE
|
|
||||||
{ "tls_randfile", CONF_STR, LDAP_OPT_X_TLS_RANDOM_FILE,
|
|
||||||
&ldap_conf.tls_random_file },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
|
|
||||||
{ "tls_ciphers", CONF_STR, LDAP_OPT_X_TLS_CIPHER_SUITE,
|
|
||||||
&ldap_conf.tls_cipher_suite },
|
|
||||||
#elif defined(LDAP_OPT_SSL_CIPHER)
|
|
||||||
{ "tls_ciphers", CONF_STR, LDAP_OPT_SSL_CIPHER,
|
|
||||||
&ldap_conf.tls_cipher_suite },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_CERTFILE
|
|
||||||
{ "tls_cert", CONF_STR, LDAP_OPT_X_TLS_CERTFILE,
|
|
||||||
&ldap_conf.tls_certfile },
|
|
||||||
#else
|
|
||||||
{ "tls_cert", CONF_STR, -1, &ldap_conf.tls_certfile },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_TLS_KEYFILE
|
|
||||||
{ "tls_key", CONF_STR, LDAP_OPT_X_TLS_KEYFILE,
|
|
||||||
&ldap_conf.tls_keyfile },
|
|
||||||
#else
|
|
||||||
{ "tls_key", CONF_STR, -1, &ldap_conf.tls_keyfile },
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_LDAP_SSL_CLIENT_INIT
|
|
||||||
{ "tls_keypw", CONF_STR, -1, &ldap_conf.tls_keypw },
|
|
||||||
#endif
|
|
||||||
{ "binddn", CONF_STR, -1, &ldap_conf.binddn },
|
|
||||||
{ "bindpw", CONF_STR, -1, &ldap_conf.bindpw },
|
|
||||||
{ "rootbinddn", CONF_STR, -1, &ldap_conf.rootbinddn },
|
|
||||||
{ "sudoers_base", CONF_LIST_STR, -1, &ldap_conf.base },
|
|
||||||
{ "sudoers_timed", CONF_BOOL, -1, &ldap_conf.timed },
|
|
||||||
{ "sudoers_search_filter", CONF_STR, -1, &ldap_conf.search_filter },
|
|
||||||
{ "netgroup_base", CONF_LIST_STR, -1, &ldap_conf.netgroup_base },
|
|
||||||
{ "netgroup_search_filter", CONF_STR, -1, &ldap_conf.netgroup_search_filter },
|
|
||||||
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
|
||||||
{ "use_sasl", CONF_BOOL, -1, &ldap_conf.use_sasl },
|
|
||||||
{ "sasl_mech", CONF_STR, -1, &ldap_conf.sasl_mech },
|
|
||||||
{ "sasl_auth_id", CONF_STR, -1, &ldap_conf.sasl_auth_id },
|
|
||||||
{ "rootuse_sasl", CONF_BOOL, -1, &ldap_conf.rootuse_sasl },
|
|
||||||
{ "rootsasl_auth_id", CONF_STR, -1, &ldap_conf.rootsasl_auth_id },
|
|
||||||
{ "krb5_ccname", CONF_STR, -1, &ldap_conf.krb5_ccname },
|
|
||||||
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct ldap_config_table ldap_conf_conn[] = {
|
|
||||||
#ifdef LDAP_OPT_PROTOCOL_VERSION
|
|
||||||
{ "ldap_version", CONF_INT, LDAP_OPT_PROTOCOL_VERSION,
|
|
||||||
&ldap_conf.version },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
|
||||||
{ "bind_timelimit", CONF_INT, -1 /* needs timeval, set manually */,
|
|
||||||
&ldap_conf.bind_timelimit },
|
|
||||||
{ "network_timeout", CONF_INT, -1 /* needs timeval, set manually */,
|
|
||||||
&ldap_conf.bind_timelimit },
|
|
||||||
#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
|
|
||||||
{ "bind_timelimit", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
|
|
||||||
&ldap_conf.bind_timelimit },
|
|
||||||
{ "network_timeout", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
|
|
||||||
&ldap_conf.bind_timelimit },
|
|
||||||
#endif
|
|
||||||
{ "timelimit", CONF_INT, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
|
|
||||||
#ifdef LDAP_OPT_TIMEOUT
|
|
||||||
{ "timeout", CONF_INT, -1 /* needs timeval, set manually */,
|
|
||||||
&ldap_conf.timeout },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_DEREF
|
|
||||||
{ "deref", CONF_DEREF_VAL, LDAP_OPT_DEREF, &ldap_conf.deref },
|
|
||||||
#endif
|
|
||||||
#ifdef LDAP_OPT_X_SASL_SECPROPS
|
|
||||||
{ "sasl_secprops", CONF_STR, LDAP_OPT_X_SASL_SECPROPS,
|
|
||||||
&ldap_conf.sasl_secprops },
|
|
||||||
#endif
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* sudo_nss implementation */
|
/* sudo_nss implementation */
|
||||||
static int sudo_ldap_open(struct sudo_nss *nss);
|
static int sudo_ldap_open(struct sudo_nss *nss);
|
||||||
static int sudo_ldap_close(struct sudo_nss *nss);
|
static int sudo_ldap_close(struct sudo_nss *nss);
|
||||||
@@ -410,140 +183,7 @@ struct sudo_nss sudo_nss_ldap = {
|
|||||||
sudo_ldap_display_privs
|
sudo_ldap_display_privs
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LDAP_CREATE
|
#ifdef HAVE_LDAP_INITIALIZE
|
||||||
/*
|
|
||||||
* Rebuild the hosts list and include a specific port for each host.
|
|
||||||
* ldap_create() does not take a default port parameter so we must
|
|
||||||
* append one if we want something other than LDAP_PORT.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
sudo_ldap_conf_add_ports(void)
|
|
||||||
{
|
|
||||||
char *host, *last, *port, defport[13];
|
|
||||||
char hostbuf[LINE_MAX * 2];
|
|
||||||
int len;
|
|
||||||
debug_decl(sudo_ldap_conf_add_ports, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
hostbuf[0] = '\0';
|
|
||||||
len = snprintf(defport, sizeof(defport), ":%d", ldap_conf.port);
|
|
||||||
if (len <= 0 || (size_t)len >= sizeof(defport)) {
|
|
||||||
sudo_warnx(U_("sudo_ldap_conf_add_ports: port too large"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((host = strtok_r(ldap_conf.host, " \t", &last)); host; (host = strtok_r(NULL, " \t", &last))) {
|
|
||||||
if (hostbuf[0] != '\0')
|
|
||||||
CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
|
|
||||||
CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
|
|
||||||
|
|
||||||
/* Append port if there is not one already. */
|
|
||||||
if ((port = strrchr(host, ':')) == NULL ||
|
|
||||||
!isdigit((unsigned char)port[1])) {
|
|
||||||
CHECK_STRLCAT(hostbuf, defport, sizeof(hostbuf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ldap_conf.host);
|
|
||||||
if ((ldap_conf.host = strdup(hostbuf)) == NULL)
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(ldap_conf.host != NULL);
|
|
||||||
|
|
||||||
overflow:
|
|
||||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_LDAP_INITIALIZE
|
|
||||||
/*
|
|
||||||
* For each uri, convert to host:port pairs. For ldaps:// enable SSL
|
|
||||||
* Accepts: uris of the form ldap:/// or ldap://hostname:portnum/
|
|
||||||
* where the trailing slash is optional.
|
|
||||||
* Returns LDAP_SUCCESS on success, else non-zero.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
|
|
||||||
{
|
|
||||||
const struct ldap_config_str *entry;
|
|
||||||
char *buf, hostbuf[LINE_MAX];
|
|
||||||
int nldap = 0, nldaps = 0;
|
|
||||||
int ret = -1;
|
|
||||||
debug_decl(sudo_ldap_parse_uri, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
hostbuf[0] = '\0';
|
|
||||||
STAILQ_FOREACH(entry, uri_list, entries) {
|
|
||||||
char *cp, *host, *last, *port, *uri;
|
|
||||||
|
|
||||||
buf = strdup(entry->val);
|
|
||||||
if (buf == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
for ((uri = strtok_r(buf, " \t", &last)); uri != NULL; (uri = strtok_r(NULL, " \t", &last))) {
|
|
||||||
if (strncasecmp(uri, "ldap://", 7) == 0) {
|
|
||||||
nldap++;
|
|
||||||
host = uri + 7;
|
|
||||||
} else if (strncasecmp(uri, "ldaps://", 8) == 0) {
|
|
||||||
nldaps++;
|
|
||||||
host = uri + 8;
|
|
||||||
} else {
|
|
||||||
sudo_warnx(U_("unsupported LDAP uri type: %s"), uri);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* trim optional trailing slash */
|
|
||||||
if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
|
|
||||||
*cp = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostbuf[0] != '\0')
|
|
||||||
CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
|
|
||||||
|
|
||||||
if (*host == '\0')
|
|
||||||
host = "localhost"; /* no host specified, use localhost */
|
|
||||||
|
|
||||||
CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
|
|
||||||
|
|
||||||
/* If using SSL and no port specified, add port 636 */
|
|
||||||
if (nldaps) {
|
|
||||||
if ((port = strrchr(host, ':')) == NULL ||
|
|
||||||
!isdigit((unsigned char)port[1]))
|
|
||||||
CHECK_STRLCAT(hostbuf, ":636", sizeof(hostbuf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nldaps != 0) {
|
|
||||||
if (nldap != 0) {
|
|
||||||
sudo_warnx(U_("unable to mix ldap and ldaps URIs"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS)
|
|
||||||
sudo_warnx(U_("starttls not supported when using ldaps"));
|
|
||||||
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
buf = NULL;
|
|
||||||
|
|
||||||
/* Store parsed URI(s) in host for ldap_create() or ldap_init(). */
|
|
||||||
free(ldap_conf.host);
|
|
||||||
if ((ldap_conf.host = strdup(hostbuf)) == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = LDAP_SUCCESS;
|
|
||||||
|
|
||||||
done:
|
|
||||||
free(buf);
|
|
||||||
debug_return_int(ret);
|
|
||||||
|
|
||||||
overflow:
|
|
||||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
|
||||||
free(buf);
|
|
||||||
debug_return_int(-1);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static char *
|
static char *
|
||||||
sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
|
sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
|
||||||
{
|
{
|
||||||
@@ -1746,464 +1386,6 @@ sudo_ldap_build_pass2(void)
|
|||||||
debug_return_str(filt);
|
debug_return_str(filt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode a secret if it is base64 encoded, else return NULL.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
sudo_ldap_decode_secret(const char *secret)
|
|
||||||
{
|
|
||||||
unsigned char *result = NULL;
|
|
||||||
size_t len, reslen;
|
|
||||||
debug_decl(sudo_ldap_decode_secret, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
if (strncasecmp(secret, "base64:", sizeof("base64:") - 1) == 0) {
|
|
||||||
/*
|
|
||||||
* Decode a base64 secret. The decoded length is 3/4 the encoded
|
|
||||||
* length but padding may be missing so round up to a multiple of 4.
|
|
||||||
*/
|
|
||||||
secret += sizeof("base64:") - 1;
|
|
||||||
reslen = ((strlen(secret) + 3) / 4 * 3);
|
|
||||||
result = malloc(reslen + 1);
|
|
||||||
if (result == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
} else {
|
|
||||||
len = base64_decode(secret, result, reslen);
|
|
||||||
if (len == (size_t)-1) {
|
|
||||||
free(result);
|
|
||||||
result = NULL;
|
|
||||||
} else {
|
|
||||||
result[len] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_str((char *)result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sudo_ldap_read_secret(const char *path)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char *line = NULL;
|
|
||||||
size_t linesize = 0;
|
|
||||||
ssize_t len;
|
|
||||||
debug_decl(sudo_ldap_read_secret, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
if ((fp = fopen(path_ldap_secret, "r")) != NULL) {
|
|
||||||
len = getline(&line, &linesize, fp);
|
|
||||||
if (len != -1) {
|
|
||||||
/* trim newline */
|
|
||||||
while (len > 0 && line[len - 1] == '\n')
|
|
||||||
line[--len] = '\0';
|
|
||||||
/* copy to bindpw and binddn */
|
|
||||||
free(ldap_conf.bindpw);
|
|
||||||
ldap_conf.bindpw = sudo_ldap_decode_secret(line);
|
|
||||||
if (ldap_conf.bindpw == NULL) {
|
|
||||||
/* not base64 encoded, use directly */
|
|
||||||
ldap_conf.bindpw = line;
|
|
||||||
line = NULL;
|
|
||||||
}
|
|
||||||
free(ldap_conf.binddn);
|
|
||||||
ldap_conf.binddn = ldap_conf.rootbinddn;
|
|
||||||
ldap_conf.rootbinddn = NULL;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
free(line);
|
|
||||||
}
|
|
||||||
debug_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up keyword in config tables.
|
|
||||||
* Returns true if found, else false.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
sudo_ldap_parse_keyword(const char *keyword, const char *value,
|
|
||||||
struct ldap_config_table *table)
|
|
||||||
{
|
|
||||||
struct ldap_config_table *cur;
|
|
||||||
const char *errstr;
|
|
||||||
debug_decl(sudo_ldap_parse_keyword, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* Look up keyword in config tables */
|
|
||||||
for (cur = table; cur->conf_str != NULL; cur++) {
|
|
||||||
if (strcasecmp(keyword, cur->conf_str) == 0) {
|
|
||||||
switch (cur->type) {
|
|
||||||
case CONF_DEREF_VAL:
|
|
||||||
if (strcasecmp(value, "searching") == 0)
|
|
||||||
*(int *)(cur->valp) = LDAP_DEREF_SEARCHING;
|
|
||||||
else if (strcasecmp(value, "finding") == 0)
|
|
||||||
*(int *)(cur->valp) = LDAP_DEREF_FINDING;
|
|
||||||
else if (strcasecmp(value, "always") == 0)
|
|
||||||
*(int *)(cur->valp) = LDAP_DEREF_ALWAYS;
|
|
||||||
else
|
|
||||||
*(int *)(cur->valp) = LDAP_DEREF_NEVER;
|
|
||||||
break;
|
|
||||||
case CONF_BOOL:
|
|
||||||
*(int *)(cur->valp) = sudo_strtobool(value) == true;
|
|
||||||
break;
|
|
||||||
case CONF_INT:
|
|
||||||
*(int *)(cur->valp) = strtonum(value, INT_MIN, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s: %s: %s"),
|
|
||||||
path_ldap_conf, keyword, value, U_(errstr));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONF_STR:
|
|
||||||
{
|
|
||||||
char *cp = NULL;
|
|
||||||
|
|
||||||
free(*(char **)(cur->valp));
|
|
||||||
if (*value && (cp = strdup(value)) == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
*(char **)(cur->valp) = cp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CONF_LIST_STR:
|
|
||||||
{
|
|
||||||
struct ldap_config_str_list *head;
|
|
||||||
struct ldap_config_str *str;
|
|
||||||
size_t len = strlen(value);
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
head = (struct ldap_config_str_list *)cur->valp;
|
|
||||||
if ((str = malloc(sizeof(*str) + len)) == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
memcpy(str->val, value, len + 1);
|
|
||||||
STAILQ_INSERT_TAIL(head, str, entries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
|
||||||
static const char *
|
|
||||||
sudo_krb5_ccname_path(const char *old_ccname)
|
|
||||||
{
|
|
||||||
const char *ccname = old_ccname;
|
|
||||||
debug_decl(sudo_krb5_ccname_path, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* Strip off leading FILE: or WRFILE: prefix. */
|
|
||||||
switch (ccname[0]) {
|
|
||||||
case 'F':
|
|
||||||
case 'f':
|
|
||||||
if (strncasecmp(ccname, "FILE:", 5) == 0)
|
|
||||||
ccname += 5;
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
case 'w':
|
|
||||||
if (strncasecmp(ccname, "WRFILE:", 7) == 0)
|
|
||||||
ccname += 7;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
"ccache %s -> %s", old_ccname, ccname);
|
|
||||||
|
|
||||||
/* Credential cache must be a fully-qualified path name. */
|
|
||||||
debug_return_const_str(*ccname == '/' ? ccname : NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
sudo_check_krb5_ccname(const char *ccname)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
const char *ccname_path;
|
|
||||||
debug_decl(sudo_check_krb5_ccname, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* Strip off prefix to get path name. */
|
|
||||||
ccname_path = sudo_krb5_ccname_path(ccname);
|
|
||||||
if (ccname_path == NULL) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
|
||||||
"unsupported krb5 credential cache path: %s", ccname);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
/* Make sure credential cache is fully-qualified and exists. */
|
|
||||||
fd = open(ccname_path, O_RDONLY|O_NONBLOCK, 0);
|
|
||||||
if (fd == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
|
||||||
"unable to open krb5 credential cache: %s", ccname_path);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
|
||||||
"using krb5 credential cache: %s", ccname_path);
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
sudo_ldap_read_config(void)
|
|
||||||
{
|
|
||||||
char *cp, *keyword, *value, *line = NULL;
|
|
||||||
struct ldap_config_str *conf_str;
|
|
||||||
size_t linesize = 0;
|
|
||||||
FILE *fp;
|
|
||||||
debug_decl(sudo_ldap_read_config, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* defaults */
|
|
||||||
ldap_conf.version = 3;
|
|
||||||
ldap_conf.port = -1;
|
|
||||||
ldap_conf.tls_checkpeer = -1;
|
|
||||||
ldap_conf.timelimit = -1;
|
|
||||||
ldap_conf.timeout = -1;
|
|
||||||
ldap_conf.bind_timelimit = -1;
|
|
||||||
ldap_conf.use_sasl = -1;
|
|
||||||
ldap_conf.rootuse_sasl = -1;
|
|
||||||
ldap_conf.deref = -1;
|
|
||||||
ldap_conf.search_filter = strdup(DEFAULT_SEARCH_FILTER);
|
|
||||||
ldap_conf.netgroup_search_filter = strdup(DEFAULT_NETGROUP_SEARCH_FILTER);
|
|
||||||
STAILQ_INIT(&ldap_conf.uri);
|
|
||||||
STAILQ_INIT(&ldap_conf.base);
|
|
||||||
STAILQ_INIT(&ldap_conf.netgroup_base);
|
|
||||||
|
|
||||||
if (ldap_conf.search_filter == NULL || ldap_conf.netgroup_search_filter == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fp = fopen(path_ldap_conf, "r")) == NULL)
|
|
||||||
debug_return_bool(false);
|
|
||||||
|
|
||||||
while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_COMM_BOL|PARSELN_CONT_IGN) != -1) {
|
|
||||||
if (*line == '\0')
|
|
||||||
continue; /* skip empty line */
|
|
||||||
|
|
||||||
/* split into keyword and value */
|
|
||||||
keyword = cp = line;
|
|
||||||
while (*cp && !isblank((unsigned char) *cp))
|
|
||||||
cp++;
|
|
||||||
if (*cp)
|
|
||||||
*cp++ = '\0'; /* terminate keyword */
|
|
||||||
|
|
||||||
/* skip whitespace before value */
|
|
||||||
while (isblank((unsigned char) *cp))
|
|
||||||
cp++;
|
|
||||||
value = cp;
|
|
||||||
|
|
||||||
/* Look up keyword in config tables */
|
|
||||||
if (!sudo_ldap_parse_keyword(keyword, value, ldap_conf_global))
|
|
||||||
sudo_ldap_parse_keyword(keyword, value, ldap_conf_conn);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (!ldap_conf.host) {
|
|
||||||
ldap_conf.host = strdup("localhost");
|
|
||||||
if (ldap_conf.host == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF1("LDAP Config Summary");
|
|
||||||
DPRINTF1("===================");
|
|
||||||
if (!STAILQ_EMPTY(&ldap_conf.uri)) {
|
|
||||||
STAILQ_FOREACH(conf_str, &ldap_conf.uri, entries) {
|
|
||||||
DPRINTF1("uri %s", conf_str->val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DPRINTF1("host %s",
|
|
||||||
ldap_conf.host ? ldap_conf.host : "(NONE)");
|
|
||||||
DPRINTF1("port %d", ldap_conf.port);
|
|
||||||
}
|
|
||||||
DPRINTF1("ldap_version %d", ldap_conf.version);
|
|
||||||
|
|
||||||
if (!STAILQ_EMPTY(&ldap_conf.base)) {
|
|
||||||
STAILQ_FOREACH(conf_str, &ldap_conf.base, entries) {
|
|
||||||
DPRINTF1("sudoers_base %s", conf_str->val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)");
|
|
||||||
}
|
|
||||||
if (ldap_conf.search_filter) {
|
|
||||||
DPRINTF1("search_filter %s", ldap_conf.search_filter);
|
|
||||||
}
|
|
||||||
if (!STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
|
|
||||||
STAILQ_FOREACH(conf_str, &ldap_conf.netgroup_base, entries) {
|
|
||||||
DPRINTF1("netgroup_base %s", conf_str->val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DPRINTF1("netgroup_base %s", "(NONE: will use nsswitch)");
|
|
||||||
}
|
|
||||||
if (ldap_conf.netgroup_search_filter) {
|
|
||||||
DPRINTF1("netgroup_search_filter %s", ldap_conf.netgroup_search_filter);
|
|
||||||
}
|
|
||||||
DPRINTF1("binddn %s",
|
|
||||||
ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)");
|
|
||||||
DPRINTF1("bindpw %s",
|
|
||||||
ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)");
|
|
||||||
if (ldap_conf.bind_timelimit > 0) {
|
|
||||||
DPRINTF1("bind_timelimit %d", ldap_conf.bind_timelimit);
|
|
||||||
}
|
|
||||||
if (ldap_conf.timelimit > 0) {
|
|
||||||
DPRINTF1("timelimit %d", ldap_conf.timelimit);
|
|
||||||
}
|
|
||||||
if (ldap_conf.deref != -1) {
|
|
||||||
DPRINTF1("deref %d", ldap_conf.deref);
|
|
||||||
}
|
|
||||||
DPRINTF1("ssl %s", ldap_conf.ssl ? ldap_conf.ssl : "(no)");
|
|
||||||
if (ldap_conf.tls_checkpeer != -1) {
|
|
||||||
DPRINTF1("tls_checkpeer %s",
|
|
||||||
ldap_conf.tls_checkpeer ? "(yes)" : "(no)");
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_cacertfile != NULL) {
|
|
||||||
DPRINTF1("tls_cacertfile %s", ldap_conf.tls_cacertfile);
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_cacertdir != NULL) {
|
|
||||||
DPRINTF1("tls_cacertdir %s", ldap_conf.tls_cacertdir);
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_random_file != NULL) {
|
|
||||||
DPRINTF1("tls_random_file %s", ldap_conf.tls_random_file);
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_cipher_suite != NULL) {
|
|
||||||
DPRINTF1("tls_cipher_suite %s", ldap_conf.tls_cipher_suite);
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_certfile != NULL) {
|
|
||||||
DPRINTF1("tls_certfile %s", ldap_conf.tls_certfile);
|
|
||||||
}
|
|
||||||
if (ldap_conf.tls_keyfile != NULL) {
|
|
||||||
DPRINTF1("tls_keyfile %s", ldap_conf.tls_keyfile);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
|
||||||
if (ldap_conf.use_sasl != -1) {
|
|
||||||
if (ldap_conf.sasl_mech == NULL) {
|
|
||||||
/* Default mechanism is GSSAPI. */
|
|
||||||
ldap_conf.sasl_mech = strdup("GSSAPI");
|
|
||||||
if (ldap_conf.sasl_mech == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__,
|
|
||||||
U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DPRINTF1("use_sasl %s", ldap_conf.use_sasl ? "yes" : "no");
|
|
||||||
DPRINTF1("sasl_mech %s", ldap_conf.sasl_mech);
|
|
||||||
DPRINTF1("sasl_auth_id %s",
|
|
||||||
ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)");
|
|
||||||
DPRINTF1("rootuse_sasl %d",
|
|
||||||
ldap_conf.rootuse_sasl);
|
|
||||||
DPRINTF1("rootsasl_auth_id %s",
|
|
||||||
ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)");
|
|
||||||
DPRINTF1("sasl_secprops %s",
|
|
||||||
ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)");
|
|
||||||
DPRINTF1("krb5_ccname %s",
|
|
||||||
ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
DPRINTF1("===================");
|
|
||||||
|
|
||||||
if (STAILQ_EMPTY(&ldap_conf.base))
|
|
||||||
debug_return_bool(false); /* if no base is defined, ignore LDAP */
|
|
||||||
|
|
||||||
if (ldap_conf.bind_timelimit > 0)
|
|
||||||
ldap_conf.bind_timelimit *= 1000; /* convert to ms */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 (sudo_strtobool(ldap_conf.ssl) == true)
|
|
||||||
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(LDAP_OPT_X_TLS_REQUIRE_CERT)
|
|
||||||
if (ldap_conf.tls_checkpeer != -1) {
|
|
||||||
ldapssl_set_strength(NULL,
|
|
||||||
ldap_conf.tls_checkpeer ? LDAPSSL_AUTH_CERT : LDAPSSL_AUTH_WEAK);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_LDAP_INITIALIZE
|
|
||||||
/* Convert uri list to host list if no ldap_initialize(). */
|
|
||||||
if (!STAILQ_EMPTY(&ldap_conf.uri)) {
|
|
||||||
struct ldap_config_str *uri;
|
|
||||||
|
|
||||||
if (sudo_ldap_parse_uri(&ldap_conf.uri) != LDAP_SUCCESS)
|
|
||||||
debug_return_bool(false);
|
|
||||||
while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
|
|
||||||
STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
|
|
||||||
free(uri);
|
|
||||||
}
|
|
||||||
ldap_conf.port = LDAP_PORT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (STAILQ_EMPTY(&ldap_conf.uri)) {
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
#ifdef HAVE_LDAP_CREATE
|
|
||||||
/*
|
|
||||||
* Cannot specify port directly to ldap_create(), each host must
|
|
||||||
* include :port to override the default.
|
|
||||||
*/
|
|
||||||
if (ldap_conf.port != LDAP_PORT) {
|
|
||||||
if (!sudo_ldap_conf_add_ports())
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If search filter is not parenthesized, make it so. */
|
|
||||||
if (ldap_conf.search_filter && ldap_conf.search_filter[0] != '(') {
|
|
||||||
size_t len = strlen(ldap_conf.search_filter);
|
|
||||||
cp = ldap_conf.search_filter;
|
|
||||||
ldap_conf.search_filter = malloc(len + 3);
|
|
||||||
if (ldap_conf.search_filter == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
ldap_conf.search_filter[0] = '(';
|
|
||||||
memcpy(ldap_conf.search_filter + 1, cp, len);
|
|
||||||
ldap_conf.search_filter[len + 1] = ')';
|
|
||||||
ldap_conf.search_filter[len + 2] = '\0';
|
|
||||||
free(cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If rootbinddn set, read in /etc/ldap.secret if it exists. */
|
|
||||||
if (ldap_conf.rootbinddn) {
|
|
||||||
sudo_ldap_read_secret(path_ldap_secret);
|
|
||||||
} else if (ldap_conf.bindpw) {
|
|
||||||
cp = sudo_ldap_decode_secret(ldap_conf.bindpw);
|
|
||||||
if (cp != NULL) {
|
|
||||||
free(ldap_conf.bindpw);
|
|
||||||
ldap_conf.bindpw = cp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ldap_conf.tls_keypw) {
|
|
||||||
cp = sudo_ldap_decode_secret(ldap_conf.tls_keypw);
|
|
||||||
if (cp != NULL) {
|
|
||||||
free(ldap_conf.tls_keypw);
|
|
||||||
ldap_conf.tls_keypw = cp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
|
||||||
/*
|
|
||||||
* Make sure we can open the file specified by krb5_ccname.
|
|
||||||
*/
|
|
||||||
if (ldap_conf.krb5_ccname != NULL) {
|
|
||||||
if (!sudo_check_krb5_ccname(ldap_conf.krb5_ccname))
|
|
||||||
ldap_conf.krb5_ccname = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the dn from an entry and return the first rdn from it.
|
* Extract the dn from an entry and return the first rdn from it.
|
||||||
*/
|
*/
|
||||||
@@ -2646,137 +1828,6 @@ sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags, void *_auth_id,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
||||||
|
|
||||||
/*
|
|
||||||
* Set LDAP options from the specified options table
|
|
||||||
* Returns LDAP_SUCCESS on success, else non-zero.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sudo_ldap_set_options_table(LDAP *ld, struct ldap_config_table *table)
|
|
||||||
{
|
|
||||||
struct ldap_config_table *cur;
|
|
||||||
int ival, rc, errors = 0;
|
|
||||||
char *sval;
|
|
||||||
debug_decl(sudo_ldap_set_options_table, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
for (cur = table; cur->conf_str != NULL; cur++) {
|
|
||||||
if (cur->opt_val == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (cur->type) {
|
|
||||||
case CONF_BOOL:
|
|
||||||
case CONF_INT:
|
|
||||||
ival = *(int *)(cur->valp);
|
|
||||||
if (ival >= 0) {
|
|
||||||
DPRINTF1("ldap_set_option: %s -> %d", cur->conf_str, ival);
|
|
||||||
rc = ldap_set_option(ld, cur->opt_val, &ival);
|
|
||||||
if (rc != LDAP_OPT_SUCCESS) {
|
|
||||||
sudo_warnx("ldap_set_option: %s -> %d: %s",
|
|
||||||
cur->conf_str, ival, ldap_err2string(rc));
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONF_STR:
|
|
||||||
sval = *(char **)(cur->valp);
|
|
||||||
if (sval != NULL) {
|
|
||||||
DPRINTF1("ldap_set_option: %s -> %s", cur->conf_str, sval);
|
|
||||||
rc = ldap_set_option(ld, cur->opt_val, sval);
|
|
||||||
if (rc != LDAP_OPT_SUCCESS) {
|
|
||||||
sudo_warnx("ldap_set_option: %s -> %s: %s",
|
|
||||||
cur->conf_str, sval, ldap_err2string(rc));
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_int(errors ? -1 : LDAP_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set LDAP options based on the global config table.
|
|
||||||
* Returns LDAP_SUCCESS on success, else non-zero.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sudo_ldap_set_options_global(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
debug_decl(sudo_ldap_set_options_global, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
|
|
||||||
/* Parse global LDAP options table. */
|
|
||||||
ret = sudo_ldap_set_options_table(NULL, ldap_conf_global);
|
|
||||||
debug_return_int(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set LDAP options based on the per-connection config table.
|
|
||||||
* Returns LDAP_SUCCESS on success, else non-zero.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sudo_ldap_set_options_conn(LDAP *ld)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
debug_decl(sudo_ldap_set_options_conn, SUDOERS_DEBUG_LDAP)
|
|
||||||
|
|
||||||
/* Parse per-connection LDAP options table. */
|
|
||||||
rc = sudo_ldap_set_options_table(ld, ldap_conf_conn);
|
|
||||||
if (rc == -1)
|
|
||||||
debug_return_int(-1);
|
|
||||||
|
|
||||||
#ifdef LDAP_OPT_TIMEOUT
|
|
||||||
/* Convert timeout to a timeval */
|
|
||||||
if (ldap_conf.timeout > 0) {
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = ldap_conf.timeout;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
DPRINTF1("ldap_set_option(LDAP_OPT_TIMEOUT, %d)", ldap_conf.timeout);
|
|
||||||
rc = ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv);
|
|
||||||
if (rc != LDAP_OPT_SUCCESS) {
|
|
||||||
sudo_warnx("ldap_set_option(TIMEOUT, %d): %s",
|
|
||||||
ldap_conf.timeout, ldap_err2string(rc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#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;
|
|
||||||
DPRINTF1("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %d)",
|
|
||||||
ldap_conf.bind_timelimit / 1000);
|
|
||||||
rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
|
|
||||||
# if !defined(LDAP_OPT_CONNECT_TIMEOUT) || LDAP_VENDOR_VERSION != 510
|
|
||||||
/* Tivoli Directory Server 6.3 libs always return a (bogus) error. */
|
|
||||||
if (rc != LDAP_OPT_SUCCESS) {
|
|
||||||
sudo_warnx("ldap_set_option(NETWORK_TIMEOUT, %d): %s",
|
|
||||||
ldap_conf.bind_timelimit / 1000, ldap_err2string(rc));
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
|
||||||
DPRINTF1("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)");
|
|
||||||
rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val);
|
|
||||||
if (rc != LDAP_SUCCESS) {
|
|
||||||
sudo_warnx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s",
|
|
||||||
ldap_err2string(rc));
|
|
||||||
debug_return_int(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
debug_return_int(LDAP_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new sudo_ldap_result structure.
|
* Create a new sudo_ldap_result structure.
|
||||||
*/
|
*/
|
||||||
|
902
plugins/sudoers/ldap_conf.c
Normal file
902
plugins/sudoers/ldap_conf.c
Normal file
@@ -0,0 +1,902 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2018 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed by Aaron Spangler.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif /* HAVE_STRING_H */
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif /* HAVE_STRINGS_H */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifdef HAVE_LBER_H
|
||||||
|
# include <lber.h>
|
||||||
|
#endif
|
||||||
|
#include <ldap.h>
|
||||||
|
#if defined(HAVE_LDAP_SSL_H)
|
||||||
|
# include <ldap_ssl.h>
|
||||||
|
#elif defined(HAVE_MPS_LDAP_SSL_H)
|
||||||
|
# include <mps/ldap_ssl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "sudoers.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "sudo_lbuf.h"
|
||||||
|
#include "sudo_ldap.h"
|
||||||
|
#include "sudo_ldap_conf.h"
|
||||||
|
|
||||||
|
/* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */
|
||||||
|
#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H)
|
||||||
|
extern int ldapssl_set_strength(LDAP *ldap, int strength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT)
|
||||||
|
# define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LDAP_OPT_SUCCESS
|
||||||
|
# define LDAP_OPT_SUCCESS LDAP_SUCCESS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LDAPS_PORT
|
||||||
|
# define LDAPS_PORT 636
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Default search filter. */
|
||||||
|
#define DEFAULT_SEARCH_FILTER "(objectClass=sudoRole)"
|
||||||
|
|
||||||
|
/* Default netgroup search filter. */
|
||||||
|
#define DEFAULT_NETGROUP_SEARCH_FILTER "(objectClass=nisNetgroup)"
|
||||||
|
|
||||||
|
/* LDAP configuration structure */
|
||||||
|
struct ldap_config ldap_conf;
|
||||||
|
|
||||||
|
static struct ldap_config_table ldap_conf_global[] = {
|
||||||
|
{ "sudoers_debug", CONF_INT, -1, &ldap_conf.debug },
|
||||||
|
{ "host", CONF_STR, -1, &ldap_conf.host },
|
||||||
|
{ "port", CONF_INT, -1, &ldap_conf.port },
|
||||||
|
{ "ssl", CONF_STR, -1, &ldap_conf.ssl },
|
||||||
|
{ "sslpath", CONF_STR, -1, &ldap_conf.tls_certfile },
|
||||||
|
{ "uri", CONF_LIST_STR, -1, &ldap_conf.uri },
|
||||||
|
#ifdef LDAP_OPT_DEBUG_LEVEL
|
||||||
|
{ "debug", CONF_INT, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
|
||||||
|
{ "tls_checkpeer", CONF_BOOL, LDAP_OPT_X_TLS_REQUIRE_CERT,
|
||||||
|
&ldap_conf.tls_checkpeer },
|
||||||
|
#else
|
||||||
|
{ "tls_checkpeer", CONF_BOOL, -1, &ldap_conf.tls_checkpeer },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_CACERTFILE
|
||||||
|
{ "tls_cacertfile", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
|
||||||
|
&ldap_conf.tls_cacertfile },
|
||||||
|
{ "tls_cacert", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
|
||||||
|
&ldap_conf.tls_cacertfile },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_CACERTDIR
|
||||||
|
{ "tls_cacertdir", CONF_STR, LDAP_OPT_X_TLS_CACERTDIR,
|
||||||
|
&ldap_conf.tls_cacertdir },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_RANDOM_FILE
|
||||||
|
{ "tls_randfile", CONF_STR, LDAP_OPT_X_TLS_RANDOM_FILE,
|
||||||
|
&ldap_conf.tls_random_file },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
|
||||||
|
{ "tls_ciphers", CONF_STR, LDAP_OPT_X_TLS_CIPHER_SUITE,
|
||||||
|
&ldap_conf.tls_cipher_suite },
|
||||||
|
#elif defined(LDAP_OPT_SSL_CIPHER)
|
||||||
|
{ "tls_ciphers", CONF_STR, LDAP_OPT_SSL_CIPHER,
|
||||||
|
&ldap_conf.tls_cipher_suite },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_CERTFILE
|
||||||
|
{ "tls_cert", CONF_STR, LDAP_OPT_X_TLS_CERTFILE,
|
||||||
|
&ldap_conf.tls_certfile },
|
||||||
|
#else
|
||||||
|
{ "tls_cert", CONF_STR, -1, &ldap_conf.tls_certfile },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_TLS_KEYFILE
|
||||||
|
{ "tls_key", CONF_STR, LDAP_OPT_X_TLS_KEYFILE,
|
||||||
|
&ldap_conf.tls_keyfile },
|
||||||
|
#else
|
||||||
|
{ "tls_key", CONF_STR, -1, &ldap_conf.tls_keyfile },
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LDAP_SSL_CLIENT_INIT
|
||||||
|
{ "tls_keypw", CONF_STR, -1, &ldap_conf.tls_keypw },
|
||||||
|
#endif
|
||||||
|
{ "binddn", CONF_STR, -1, &ldap_conf.binddn },
|
||||||
|
{ "bindpw", CONF_STR, -1, &ldap_conf.bindpw },
|
||||||
|
{ "rootbinddn", CONF_STR, -1, &ldap_conf.rootbinddn },
|
||||||
|
{ "sudoers_base", CONF_LIST_STR, -1, &ldap_conf.base },
|
||||||
|
{ "sudoers_timed", CONF_BOOL, -1, &ldap_conf.timed },
|
||||||
|
{ "sudoers_search_filter", CONF_STR, -1, &ldap_conf.search_filter },
|
||||||
|
{ "netgroup_base", CONF_LIST_STR, -1, &ldap_conf.netgroup_base },
|
||||||
|
{ "netgroup_search_filter", CONF_STR, -1, &ldap_conf.netgroup_search_filter },
|
||||||
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
||||||
|
{ "use_sasl", CONF_BOOL, -1, &ldap_conf.use_sasl },
|
||||||
|
{ "sasl_mech", CONF_STR, -1, &ldap_conf.sasl_mech },
|
||||||
|
{ "sasl_auth_id", CONF_STR, -1, &ldap_conf.sasl_auth_id },
|
||||||
|
{ "rootuse_sasl", CONF_BOOL, -1, &ldap_conf.rootuse_sasl },
|
||||||
|
{ "rootsasl_auth_id", CONF_STR, -1, &ldap_conf.rootsasl_auth_id },
|
||||||
|
{ "krb5_ccname", CONF_STR, -1, &ldap_conf.krb5_ccname },
|
||||||
|
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ldap_config_table ldap_conf_conn[] = {
|
||||||
|
#ifdef LDAP_OPT_PROTOCOL_VERSION
|
||||||
|
{ "ldap_version", CONF_INT, LDAP_OPT_PROTOCOL_VERSION,
|
||||||
|
&ldap_conf.version },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
||||||
|
{ "bind_timelimit", CONF_INT, -1 /* needs timeval, set manually */,
|
||||||
|
&ldap_conf.bind_timelimit },
|
||||||
|
{ "network_timeout", CONF_INT, -1 /* needs timeval, set manually */,
|
||||||
|
&ldap_conf.bind_timelimit },
|
||||||
|
#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
|
||||||
|
{ "bind_timelimit", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
|
||||||
|
&ldap_conf.bind_timelimit },
|
||||||
|
{ "network_timeout", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
|
||||||
|
&ldap_conf.bind_timelimit },
|
||||||
|
#endif
|
||||||
|
{ "timelimit", CONF_INT, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
|
||||||
|
#ifdef LDAP_OPT_TIMEOUT
|
||||||
|
{ "timeout", CONF_INT, -1 /* needs timeval, set manually */,
|
||||||
|
&ldap_conf.timeout },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_DEREF
|
||||||
|
{ "deref", CONF_DEREF_VAL, LDAP_OPT_DEREF, &ldap_conf.deref },
|
||||||
|
#endif
|
||||||
|
#ifdef LDAP_OPT_X_SASL_SECPROPS
|
||||||
|
{ "sasl_secprops", CONF_STR, LDAP_OPT_X_SASL_SECPROPS,
|
||||||
|
&ldap_conf.sasl_secprops },
|
||||||
|
#endif
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LDAP_CREATE
|
||||||
|
/*
|
||||||
|
* Rebuild the hosts list and include a specific port for each host.
|
||||||
|
* ldap_create() does not take a default port parameter so we must
|
||||||
|
* append one if we want something other than LDAP_PORT.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
sudo_ldap_conf_add_ports(void)
|
||||||
|
{
|
||||||
|
char *host, *last, *port, defport[13];
|
||||||
|
char hostbuf[LINE_MAX * 2];
|
||||||
|
int len;
|
||||||
|
debug_decl(sudo_ldap_conf_add_ports, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
hostbuf[0] = '\0';
|
||||||
|
len = snprintf(defport, sizeof(defport), ":%d", ldap_conf.port);
|
||||||
|
if (len <= 0 || (size_t)len >= sizeof(defport)) {
|
||||||
|
sudo_warnx(U_("sudo_ldap_conf_add_ports: port too large"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((host = strtok_r(ldap_conf.host, " \t", &last)); host; (host = strtok_r(NULL, " \t", &last))) {
|
||||||
|
if (hostbuf[0] != '\0')
|
||||||
|
CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
|
||||||
|
CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
|
||||||
|
|
||||||
|
/* Append port if there is not one already. */
|
||||||
|
if ((port = strrchr(host, ':')) == NULL ||
|
||||||
|
!isdigit((unsigned char)port[1])) {
|
||||||
|
CHECK_STRLCAT(hostbuf, defport, sizeof(hostbuf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ldap_conf.host);
|
||||||
|
if ((ldap_conf.host = strdup(hostbuf)) == NULL)
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(ldap_conf.host != NULL);
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_LDAP_INITIALIZE
|
||||||
|
/*
|
||||||
|
* For each uri, convert to host:port pairs. For ldaps:// enable SSL
|
||||||
|
* Accepts: uris of the form ldap:/// or ldap://hostname:portnum/
|
||||||
|
* where the trailing slash is optional.
|
||||||
|
* Returns LDAP_SUCCESS on success, else non-zero.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
|
||||||
|
{
|
||||||
|
const struct ldap_config_str *entry;
|
||||||
|
char *buf, hostbuf[LINE_MAX];
|
||||||
|
int nldap = 0, nldaps = 0;
|
||||||
|
int ret = -1;
|
||||||
|
debug_decl(sudo_ldap_parse_uri, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
hostbuf[0] = '\0';
|
||||||
|
STAILQ_FOREACH(entry, uri_list, entries) {
|
||||||
|
char *cp, *host, *last, *port, *uri;
|
||||||
|
|
||||||
|
buf = strdup(entry->val);
|
||||||
|
if (buf == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for ((uri = strtok_r(buf, " \t", &last)); uri != NULL; (uri = strtok_r(NULL, " \t", &last))) {
|
||||||
|
if (strncasecmp(uri, "ldap://", 7) == 0) {
|
||||||
|
nldap++;
|
||||||
|
host = uri + 7;
|
||||||
|
} else if (strncasecmp(uri, "ldaps://", 8) == 0) {
|
||||||
|
nldaps++;
|
||||||
|
host = uri + 8;
|
||||||
|
} else {
|
||||||
|
sudo_warnx(U_("unsupported LDAP uri type: %s"), uri);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trim optional trailing slash */
|
||||||
|
if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
|
||||||
|
*cp = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostbuf[0] != '\0')
|
||||||
|
CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
|
||||||
|
|
||||||
|
if (*host == '\0')
|
||||||
|
host = "localhost"; /* no host specified, use localhost */
|
||||||
|
|
||||||
|
CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
|
||||||
|
|
||||||
|
/* If using SSL and no port specified, add port 636 */
|
||||||
|
if (nldaps) {
|
||||||
|
if ((port = strrchr(host, ':')) == NULL ||
|
||||||
|
!isdigit((unsigned char)port[1]))
|
||||||
|
CHECK_STRLCAT(hostbuf, ":636", sizeof(hostbuf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nldaps != 0) {
|
||||||
|
if (nldap != 0) {
|
||||||
|
sudo_warnx(U_("unable to mix ldap and ldaps URIs"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS)
|
||||||
|
sudo_warnx(U_("starttls not supported when using ldaps"));
|
||||||
|
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
|
/* Store parsed URI(s) in host for ldap_create() or ldap_init(). */
|
||||||
|
free(ldap_conf.host);
|
||||||
|
if ((ldap_conf.host = strdup(hostbuf)) == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
done:
|
||||||
|
free(buf);
|
||||||
|
debug_return_int(ret);
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||||
|
free(buf);
|
||||||
|
debug_return_int(-1);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LDAP_INITIALIZE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode a secret if it is base64 encoded, else return NULL.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
sudo_ldap_decode_secret(const char *secret)
|
||||||
|
{
|
||||||
|
unsigned char *result = NULL;
|
||||||
|
size_t len, reslen;
|
||||||
|
debug_decl(sudo_ldap_decode_secret, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
if (strncasecmp(secret, "base64:", sizeof("base64:") - 1) == 0) {
|
||||||
|
/*
|
||||||
|
* Decode a base64 secret. The decoded length is 3/4 the encoded
|
||||||
|
* length but padding may be missing so round up to a multiple of 4.
|
||||||
|
*/
|
||||||
|
secret += sizeof("base64:") - 1;
|
||||||
|
reslen = ((strlen(secret) + 3) / 4 * 3);
|
||||||
|
result = malloc(reslen + 1);
|
||||||
|
if (result == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
} else {
|
||||||
|
len = base64_decode(secret, result, reslen);
|
||||||
|
if (len == (size_t)-1) {
|
||||||
|
free(result);
|
||||||
|
result = NULL;
|
||||||
|
} else {
|
||||||
|
result[len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_str((char *)result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sudo_ldap_read_secret(const char *path)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t linesize = 0;
|
||||||
|
ssize_t len;
|
||||||
|
debug_decl(sudo_ldap_read_secret, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
if ((fp = fopen(path_ldap_secret, "r")) != NULL) {
|
||||||
|
len = getline(&line, &linesize, fp);
|
||||||
|
if (len != -1) {
|
||||||
|
/* trim newline */
|
||||||
|
while (len > 0 && line[len - 1] == '\n')
|
||||||
|
line[--len] = '\0';
|
||||||
|
/* copy to bindpw and binddn */
|
||||||
|
free(ldap_conf.bindpw);
|
||||||
|
ldap_conf.bindpw = sudo_ldap_decode_secret(line);
|
||||||
|
if (ldap_conf.bindpw == NULL) {
|
||||||
|
/* not base64 encoded, use directly */
|
||||||
|
ldap_conf.bindpw = line;
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
|
free(ldap_conf.binddn);
|
||||||
|
ldap_conf.binddn = ldap_conf.rootbinddn;
|
||||||
|
ldap_conf.rootbinddn = NULL;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
debug_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up keyword in config tables.
|
||||||
|
* Returns true if found, else false.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
sudo_ldap_parse_keyword(const char *keyword, const char *value,
|
||||||
|
struct ldap_config_table *table)
|
||||||
|
{
|
||||||
|
struct ldap_config_table *cur;
|
||||||
|
const char *errstr;
|
||||||
|
debug_decl(sudo_ldap_parse_keyword, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* Look up keyword in config tables */
|
||||||
|
for (cur = table; cur->conf_str != NULL; cur++) {
|
||||||
|
if (strcasecmp(keyword, cur->conf_str) == 0) {
|
||||||
|
switch (cur->type) {
|
||||||
|
case CONF_DEREF_VAL:
|
||||||
|
if (strcasecmp(value, "searching") == 0)
|
||||||
|
*(int *)(cur->valp) = LDAP_DEREF_SEARCHING;
|
||||||
|
else if (strcasecmp(value, "finding") == 0)
|
||||||
|
*(int *)(cur->valp) = LDAP_DEREF_FINDING;
|
||||||
|
else if (strcasecmp(value, "always") == 0)
|
||||||
|
*(int *)(cur->valp) = LDAP_DEREF_ALWAYS;
|
||||||
|
else
|
||||||
|
*(int *)(cur->valp) = LDAP_DEREF_NEVER;
|
||||||
|
break;
|
||||||
|
case CONF_BOOL:
|
||||||
|
*(int *)(cur->valp) = sudo_strtobool(value) == true;
|
||||||
|
break;
|
||||||
|
case CONF_INT:
|
||||||
|
*(int *)(cur->valp) = strtonum(value, INT_MIN, INT_MAX, &errstr);
|
||||||
|
if (errstr != NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s: %s: %s"),
|
||||||
|
path_ldap_conf, keyword, value, U_(errstr));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONF_STR:
|
||||||
|
{
|
||||||
|
char *cp = NULL;
|
||||||
|
|
||||||
|
free(*(char **)(cur->valp));
|
||||||
|
if (*value && (cp = strdup(value)) == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
*(char **)(cur->valp) = cp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONF_LIST_STR:
|
||||||
|
{
|
||||||
|
struct ldap_config_str_list *head;
|
||||||
|
struct ldap_config_str *str;
|
||||||
|
size_t len = strlen(value);
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
head = (struct ldap_config_str_list *)cur->valp;
|
||||||
|
if ((str = malloc(sizeof(*str) + len)) == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
memcpy(str->val, value, len + 1);
|
||||||
|
STAILQ_INSERT_TAIL(head, str, entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
||||||
|
const char *
|
||||||
|
sudo_krb5_ccname_path(const char *old_ccname)
|
||||||
|
{
|
||||||
|
const char *ccname = old_ccname;
|
||||||
|
debug_decl(sudo_krb5_ccname_path, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* Strip off leading FILE: or WRFILE: prefix. */
|
||||||
|
switch (ccname[0]) {
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
if (strncasecmp(ccname, "FILE:", 5) == 0)
|
||||||
|
ccname += 5;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
case 'w':
|
||||||
|
if (strncasecmp(ccname, "WRFILE:", 7) == 0)
|
||||||
|
ccname += 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
|
"ccache %s -> %s", old_ccname, ccname);
|
||||||
|
|
||||||
|
/* Credential cache must be a fully-qualified path name. */
|
||||||
|
debug_return_const_str(*ccname == '/' ? ccname : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sudo_check_krb5_ccname(const char *ccname)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
const char *ccname_path;
|
||||||
|
debug_decl(sudo_check_krb5_ccname, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* Strip off prefix to get path name. */
|
||||||
|
ccname_path = sudo_krb5_ccname_path(ccname);
|
||||||
|
if (ccname_path == NULL) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
"unsupported krb5 credential cache path: %s", ccname);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
/* Make sure credential cache is fully-qualified and exists. */
|
||||||
|
fd = open(ccname_path, O_RDONLY|O_NONBLOCK, 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
"unable to open krb5 credential cache: %s", ccname_path);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
|
"using krb5 credential cache: %s", ccname_path);
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
|
||||||
|
|
||||||
|
bool
|
||||||
|
sudo_ldap_read_config(void)
|
||||||
|
{
|
||||||
|
char *cp, *keyword, *value, *line = NULL;
|
||||||
|
struct ldap_config_str *conf_str;
|
||||||
|
size_t linesize = 0;
|
||||||
|
FILE *fp;
|
||||||
|
debug_decl(sudo_ldap_read_config, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* defaults */
|
||||||
|
ldap_conf.version = 3;
|
||||||
|
ldap_conf.port = -1;
|
||||||
|
ldap_conf.tls_checkpeer = -1;
|
||||||
|
ldap_conf.timelimit = -1;
|
||||||
|
ldap_conf.timeout = -1;
|
||||||
|
ldap_conf.bind_timelimit = -1;
|
||||||
|
ldap_conf.use_sasl = -1;
|
||||||
|
ldap_conf.rootuse_sasl = -1;
|
||||||
|
ldap_conf.deref = -1;
|
||||||
|
ldap_conf.search_filter = strdup(DEFAULT_SEARCH_FILTER);
|
||||||
|
ldap_conf.netgroup_search_filter = strdup(DEFAULT_NETGROUP_SEARCH_FILTER);
|
||||||
|
STAILQ_INIT(&ldap_conf.uri);
|
||||||
|
STAILQ_INIT(&ldap_conf.base);
|
||||||
|
STAILQ_INIT(&ldap_conf.netgroup_base);
|
||||||
|
|
||||||
|
if (ldap_conf.search_filter == NULL || ldap_conf.netgroup_search_filter == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fp = fopen(path_ldap_conf, "r")) == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_COMM_BOL|PARSELN_CONT_IGN) != -1) {
|
||||||
|
if (*line == '\0')
|
||||||
|
continue; /* skip empty line */
|
||||||
|
|
||||||
|
/* split into keyword and value */
|
||||||
|
keyword = cp = line;
|
||||||
|
while (*cp && !isblank((unsigned char) *cp))
|
||||||
|
cp++;
|
||||||
|
if (*cp)
|
||||||
|
*cp++ = '\0'; /* terminate keyword */
|
||||||
|
|
||||||
|
/* skip whitespace before value */
|
||||||
|
while (isblank((unsigned char) *cp))
|
||||||
|
cp++;
|
||||||
|
value = cp;
|
||||||
|
|
||||||
|
/* Look up keyword in config tables */
|
||||||
|
if (!sudo_ldap_parse_keyword(keyword, value, ldap_conf_global))
|
||||||
|
sudo_ldap_parse_keyword(keyword, value, ldap_conf_conn);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (!ldap_conf.host) {
|
||||||
|
ldap_conf.host = strdup("localhost");
|
||||||
|
if (ldap_conf.host == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF1("LDAP Config Summary");
|
||||||
|
DPRINTF1("===================");
|
||||||
|
if (!STAILQ_EMPTY(&ldap_conf.uri)) {
|
||||||
|
STAILQ_FOREACH(conf_str, &ldap_conf.uri, entries) {
|
||||||
|
DPRINTF1("uri %s", conf_str->val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DPRINTF1("host %s",
|
||||||
|
ldap_conf.host ? ldap_conf.host : "(NONE)");
|
||||||
|
DPRINTF1("port %d", ldap_conf.port);
|
||||||
|
}
|
||||||
|
DPRINTF1("ldap_version %d", ldap_conf.version);
|
||||||
|
|
||||||
|
if (!STAILQ_EMPTY(&ldap_conf.base)) {
|
||||||
|
STAILQ_FOREACH(conf_str, &ldap_conf.base, entries) {
|
||||||
|
DPRINTF1("sudoers_base %s", conf_str->val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)");
|
||||||
|
}
|
||||||
|
if (ldap_conf.search_filter) {
|
||||||
|
DPRINTF1("search_filter %s", ldap_conf.search_filter);
|
||||||
|
}
|
||||||
|
if (!STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
|
||||||
|
STAILQ_FOREACH(conf_str, &ldap_conf.netgroup_base, entries) {
|
||||||
|
DPRINTF1("netgroup_base %s", conf_str->val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DPRINTF1("netgroup_base %s", "(NONE: will use nsswitch)");
|
||||||
|
}
|
||||||
|
if (ldap_conf.netgroup_search_filter) {
|
||||||
|
DPRINTF1("netgroup_search_filter %s", ldap_conf.netgroup_search_filter);
|
||||||
|
}
|
||||||
|
DPRINTF1("binddn %s",
|
||||||
|
ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)");
|
||||||
|
DPRINTF1("bindpw %s",
|
||||||
|
ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)");
|
||||||
|
if (ldap_conf.bind_timelimit > 0) {
|
||||||
|
DPRINTF1("bind_timelimit %d", ldap_conf.bind_timelimit);
|
||||||
|
}
|
||||||
|
if (ldap_conf.timelimit > 0) {
|
||||||
|
DPRINTF1("timelimit %d", ldap_conf.timelimit);
|
||||||
|
}
|
||||||
|
if (ldap_conf.deref != -1) {
|
||||||
|
DPRINTF1("deref %d", ldap_conf.deref);
|
||||||
|
}
|
||||||
|
DPRINTF1("ssl %s", ldap_conf.ssl ? ldap_conf.ssl : "(no)");
|
||||||
|
if (ldap_conf.tls_checkpeer != -1) {
|
||||||
|
DPRINTF1("tls_checkpeer %s",
|
||||||
|
ldap_conf.tls_checkpeer ? "(yes)" : "(no)");
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_cacertfile != NULL) {
|
||||||
|
DPRINTF1("tls_cacertfile %s", ldap_conf.tls_cacertfile);
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_cacertdir != NULL) {
|
||||||
|
DPRINTF1("tls_cacertdir %s", ldap_conf.tls_cacertdir);
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_random_file != NULL) {
|
||||||
|
DPRINTF1("tls_random_file %s", ldap_conf.tls_random_file);
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_cipher_suite != NULL) {
|
||||||
|
DPRINTF1("tls_cipher_suite %s", ldap_conf.tls_cipher_suite);
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_certfile != NULL) {
|
||||||
|
DPRINTF1("tls_certfile %s", ldap_conf.tls_certfile);
|
||||||
|
}
|
||||||
|
if (ldap_conf.tls_keyfile != NULL) {
|
||||||
|
DPRINTF1("tls_keyfile %s", ldap_conf.tls_keyfile);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
||||||
|
if (ldap_conf.use_sasl != -1) {
|
||||||
|
if (ldap_conf.sasl_mech == NULL) {
|
||||||
|
/* Default mechanism is GSSAPI. */
|
||||||
|
ldap_conf.sasl_mech = strdup("GSSAPI");
|
||||||
|
if (ldap_conf.sasl_mech == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
|
U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DPRINTF1("use_sasl %s", ldap_conf.use_sasl ? "yes" : "no");
|
||||||
|
DPRINTF1("sasl_mech %s", ldap_conf.sasl_mech);
|
||||||
|
DPRINTF1("sasl_auth_id %s",
|
||||||
|
ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)");
|
||||||
|
DPRINTF1("rootuse_sasl %d",
|
||||||
|
ldap_conf.rootuse_sasl);
|
||||||
|
DPRINTF1("rootsasl_auth_id %s",
|
||||||
|
ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)");
|
||||||
|
DPRINTF1("sasl_secprops %s",
|
||||||
|
ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)");
|
||||||
|
DPRINTF1("krb5_ccname %s",
|
||||||
|
ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
DPRINTF1("===================");
|
||||||
|
|
||||||
|
if (STAILQ_EMPTY(&ldap_conf.base))
|
||||||
|
debug_return_bool(false); /* if no base is defined, ignore LDAP */
|
||||||
|
|
||||||
|
if (ldap_conf.bind_timelimit > 0)
|
||||||
|
ldap_conf.bind_timelimit *= 1000; /* convert to ms */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 (sudo_strtobool(ldap_conf.ssl) == true)
|
||||||
|
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(LDAP_OPT_X_TLS_REQUIRE_CERT)
|
||||||
|
if (ldap_conf.tls_checkpeer != -1) {
|
||||||
|
ldapssl_set_strength(NULL,
|
||||||
|
ldap_conf.tls_checkpeer ? LDAPSSL_AUTH_CERT : LDAPSSL_AUTH_WEAK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_LDAP_INITIALIZE
|
||||||
|
/* Convert uri list to host list if no ldap_initialize(). */
|
||||||
|
if (!STAILQ_EMPTY(&ldap_conf.uri)) {
|
||||||
|
struct ldap_config_str *uri;
|
||||||
|
|
||||||
|
if (sudo_ldap_parse_uri(&ldap_conf.uri) != LDAP_SUCCESS)
|
||||||
|
debug_return_bool(false);
|
||||||
|
while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
|
||||||
|
STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
|
||||||
|
free(uri);
|
||||||
|
}
|
||||||
|
ldap_conf.port = LDAP_PORT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (STAILQ_EMPTY(&ldap_conf.uri)) {
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
#ifdef HAVE_LDAP_CREATE
|
||||||
|
/*
|
||||||
|
* Cannot specify port directly to ldap_create(), each host must
|
||||||
|
* include :port to override the default.
|
||||||
|
*/
|
||||||
|
if (ldap_conf.port != LDAP_PORT) {
|
||||||
|
if (!sudo_ldap_conf_add_ports())
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If search filter is not parenthesized, make it so. */
|
||||||
|
if (ldap_conf.search_filter && ldap_conf.search_filter[0] != '(') {
|
||||||
|
size_t len = strlen(ldap_conf.search_filter);
|
||||||
|
cp = ldap_conf.search_filter;
|
||||||
|
ldap_conf.search_filter = malloc(len + 3);
|
||||||
|
if (ldap_conf.search_filter == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
ldap_conf.search_filter[0] = '(';
|
||||||
|
memcpy(ldap_conf.search_filter + 1, cp, len);
|
||||||
|
ldap_conf.search_filter[len + 1] = ')';
|
||||||
|
ldap_conf.search_filter[len + 2] = '\0';
|
||||||
|
free(cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If rootbinddn set, read in /etc/ldap.secret if it exists. */
|
||||||
|
if (ldap_conf.rootbinddn) {
|
||||||
|
sudo_ldap_read_secret(path_ldap_secret);
|
||||||
|
} else if (ldap_conf.bindpw) {
|
||||||
|
cp = sudo_ldap_decode_secret(ldap_conf.bindpw);
|
||||||
|
if (cp != NULL) {
|
||||||
|
free(ldap_conf.bindpw);
|
||||||
|
ldap_conf.bindpw = cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ldap_conf.tls_keypw) {
|
||||||
|
cp = sudo_ldap_decode_secret(ldap_conf.tls_keypw);
|
||||||
|
if (cp != NULL) {
|
||||||
|
free(ldap_conf.tls_keypw);
|
||||||
|
ldap_conf.tls_keypw = cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
|
||||||
|
/*
|
||||||
|
* Make sure we can open the file specified by krb5_ccname.
|
||||||
|
*/
|
||||||
|
if (ldap_conf.krb5_ccname != NULL) {
|
||||||
|
if (!sudo_check_krb5_ccname(ldap_conf.krb5_ccname))
|
||||||
|
ldap_conf.krb5_ccname = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set LDAP options from the specified options table
|
||||||
|
* Returns LDAP_SUCCESS on success, else non-zero.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sudo_ldap_set_options_table(LDAP *ld, struct ldap_config_table *table)
|
||||||
|
{
|
||||||
|
struct ldap_config_table *cur;
|
||||||
|
int ival, rc, errors = 0;
|
||||||
|
char *sval;
|
||||||
|
debug_decl(sudo_ldap_set_options_table, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
for (cur = table; cur->conf_str != NULL; cur++) {
|
||||||
|
if (cur->opt_val == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (cur->type) {
|
||||||
|
case CONF_BOOL:
|
||||||
|
case CONF_INT:
|
||||||
|
ival = *(int *)(cur->valp);
|
||||||
|
if (ival >= 0) {
|
||||||
|
DPRINTF1("ldap_set_option: %s -> %d", cur->conf_str, ival);
|
||||||
|
rc = ldap_set_option(ld, cur->opt_val, &ival);
|
||||||
|
if (rc != LDAP_OPT_SUCCESS) {
|
||||||
|
sudo_warnx("ldap_set_option: %s -> %d: %s",
|
||||||
|
cur->conf_str, ival, ldap_err2string(rc));
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONF_STR:
|
||||||
|
sval = *(char **)(cur->valp);
|
||||||
|
if (sval != NULL) {
|
||||||
|
DPRINTF1("ldap_set_option: %s -> %s", cur->conf_str, sval);
|
||||||
|
rc = ldap_set_option(ld, cur->opt_val, sval);
|
||||||
|
if (rc != LDAP_OPT_SUCCESS) {
|
||||||
|
sudo_warnx("ldap_set_option: %s -> %s: %s",
|
||||||
|
cur->conf_str, sval, ldap_err2string(rc));
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_int(errors ? -1 : LDAP_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set LDAP options based on the global config table.
|
||||||
|
* Returns LDAP_SUCCESS on success, else non-zero.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sudo_ldap_set_options_global(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
debug_decl(sudo_ldap_set_options_global, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* Parse global LDAP options table. */
|
||||||
|
ret = sudo_ldap_set_options_table(NULL, ldap_conf_global);
|
||||||
|
debug_return_int(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set LDAP options based on the per-connection config table.
|
||||||
|
* Returns LDAP_SUCCESS on success, else non-zero.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sudo_ldap_set_options_conn(LDAP *ld)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
debug_decl(sudo_ldap_set_options_conn, SUDOERS_DEBUG_LDAP)
|
||||||
|
|
||||||
|
/* Parse per-connection LDAP options table. */
|
||||||
|
rc = sudo_ldap_set_options_table(ld, ldap_conf_conn);
|
||||||
|
if (rc == -1)
|
||||||
|
debug_return_int(-1);
|
||||||
|
|
||||||
|
#ifdef LDAP_OPT_TIMEOUT
|
||||||
|
/* Convert timeout to a timeval */
|
||||||
|
if (ldap_conf.timeout > 0) {
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = ldap_conf.timeout;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
DPRINTF1("ldap_set_option(LDAP_OPT_TIMEOUT, %d)", ldap_conf.timeout);
|
||||||
|
rc = ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv);
|
||||||
|
if (rc != LDAP_OPT_SUCCESS) {
|
||||||
|
sudo_warnx("ldap_set_option(TIMEOUT, %d): %s",
|
||||||
|
ldap_conf.timeout, ldap_err2string(rc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#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;
|
||||||
|
DPRINTF1("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %d)",
|
||||||
|
ldap_conf.bind_timelimit / 1000);
|
||||||
|
rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
|
||||||
|
# if !defined(LDAP_OPT_CONNECT_TIMEOUT) || LDAP_VENDOR_VERSION != 510
|
||||||
|
/* Tivoli Directory Server 6.3 libs always return a (bogus) error. */
|
||||||
|
if (rc != LDAP_OPT_SUCCESS) {
|
||||||
|
sudo_warnx("ldap_set_option(NETWORK_TIMEOUT, %d): %s",
|
||||||
|
ldap_conf.bind_timelimit / 1000, ldap_err2string(rc));
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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;
|
||||||
|
DPRINTF1("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)");
|
||||||
|
rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val);
|
||||||
|
if (rc != LDAP_SUCCESS) {
|
||||||
|
sudo_warnx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s",
|
||||||
|
ldap_err2string(rc));
|
||||||
|
debug_return_int(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
debug_return_int(LDAP_SUCCESS);
|
||||||
|
}
|
@@ -17,8 +17,10 @@
|
|||||||
#ifndef SUDOERS_LDAP_H
|
#ifndef SUDOERS_LDAP_H
|
||||||
#define SUDOERS_LDAP_H
|
#define SUDOERS_LDAP_H
|
||||||
|
|
||||||
|
/* Iterators used by sudo_ldap_role_to_priv() to handle bervar ** or char ** */
|
||||||
typedef char * (*sudo_ldap_iter_t)(void **);
|
typedef char * (*sudo_ldap_iter_t)(void **);
|
||||||
|
|
||||||
|
/* ldap_common.c */
|
||||||
bool sudo_ldap_is_negated(char **valp);
|
bool sudo_ldap_is_negated(char **valp);
|
||||||
int sudo_ldap_parse_option(char *optstr, char **varp, char **valp);
|
int sudo_ldap_parse_option(char *optstr, char **varp, char **valp);
|
||||||
struct privilege *sudo_ldap_role_to_priv(const char *cn, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, sudo_ldap_iter_t iter);
|
struct privilege *sudo_ldap_role_to_priv(const char *cn, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, sudo_ldap_iter_t iter);
|
||||||
|
127
plugins/sudoers/sudo_ldap_conf.h
Normal file
127
plugins/sudoers/sudo_ldap_conf.h
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUDOERS_LDAP_CONF_H
|
||||||
|
#define SUDOERS_LDAP_CONF_H
|
||||||
|
|
||||||
|
/* Macros for checking strlcpy/strlcat/sudo_ldap_value_cat return value. */
|
||||||
|
#define CHECK_STRLCPY(d, s, l) do { \
|
||||||
|
if (strlcpy((d), (s), (l)) >= (l)) \
|
||||||
|
goto overflow; \
|
||||||
|
} while (0)
|
||||||
|
#define CHECK_STRLCAT(d, s, l) do { \
|
||||||
|
if (strlcat((d), (s), (l)) >= (l)) \
|
||||||
|
goto overflow; \
|
||||||
|
} while (0)
|
||||||
|
#define CHECK_LDAP_VCAT(d, s, l) do { \
|
||||||
|
if (sudo_ldap_value_cat((d), (s), (l)) >= (l)) \
|
||||||
|
goto overflow; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__ == 2
|
||||||
|
# define DPRINTF1(fmt...) do { \
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_DIAG, fmt); \
|
||||||
|
if (ldap_conf.debug >= 1) \
|
||||||
|
sudo_warnx_nodebug(fmt); \
|
||||||
|
} while (0)
|
||||||
|
# define DPRINTF2(fmt...) do { \
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO, fmt); \
|
||||||
|
if (ldap_conf.debug >= 2) \
|
||||||
|
sudo_warnx_nodebug(fmt); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define DPRINTF1(...) do { \
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_DIAG, __VA_ARGS__); \
|
||||||
|
if (ldap_conf.debug >= 1) \
|
||||||
|
sudo_warnx_nodebug(__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
# define DPRINTF2(...) do { \
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO, __VA_ARGS__); \
|
||||||
|
if (ldap_conf.debug >= 2) \
|
||||||
|
sudo_warnx_nodebug(__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CONF_BOOL 0
|
||||||
|
#define CONF_INT 1
|
||||||
|
#define CONF_STR 2
|
||||||
|
#define CONF_LIST_STR 4
|
||||||
|
#define CONF_DEREF_VAL 5
|
||||||
|
|
||||||
|
#define SUDO_LDAP_CLEAR 0
|
||||||
|
#define SUDO_LDAP_SSL 1
|
||||||
|
#define SUDO_LDAP_STARTTLS 2
|
||||||
|
|
||||||
|
struct ldap_config_table {
|
||||||
|
const char *conf_str; /* config file string */
|
||||||
|
int type; /* CONF_BOOL, CONF_INT, CONF_STR */
|
||||||
|
int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */
|
||||||
|
void *valp; /* pointer into ldap_conf */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ldap_config_str {
|
||||||
|
STAILQ_ENTRY(ldap_config_str) entries;
|
||||||
|
char val[1];
|
||||||
|
};
|
||||||
|
STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
|
||||||
|
|
||||||
|
/* LDAP configuration structure */
|
||||||
|
struct ldap_config {
|
||||||
|
int port;
|
||||||
|
int version;
|
||||||
|
int debug;
|
||||||
|
int ldap_debug;
|
||||||
|
int tls_checkpeer;
|
||||||
|
int timelimit;
|
||||||
|
int timeout;
|
||||||
|
int bind_timelimit;
|
||||||
|
int use_sasl;
|
||||||
|
int rootuse_sasl;
|
||||||
|
int ssl_mode;
|
||||||
|
int timed;
|
||||||
|
int deref;
|
||||||
|
char *host;
|
||||||
|
struct ldap_config_str_list uri;
|
||||||
|
char *binddn;
|
||||||
|
char *bindpw;
|
||||||
|
char *rootbinddn;
|
||||||
|
struct ldap_config_str_list base;
|
||||||
|
struct ldap_config_str_list netgroup_base;
|
||||||
|
char *search_filter;
|
||||||
|
char *netgroup_search_filter;
|
||||||
|
char *ssl;
|
||||||
|
char *tls_cacertfile;
|
||||||
|
char *tls_cacertdir;
|
||||||
|
char *tls_random_file;
|
||||||
|
char *tls_cipher_suite;
|
||||||
|
char *tls_certfile;
|
||||||
|
char *tls_keyfile;
|
||||||
|
char *tls_keypw;
|
||||||
|
char *sasl_mech;
|
||||||
|
char *sasl_auth_id;
|
||||||
|
char *rootsasl_auth_id;
|
||||||
|
char *sasl_secprops;
|
||||||
|
char *krb5_ccname;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ldap_config ldap_conf;
|
||||||
|
|
||||||
|
const char *sudo_krb5_ccname_path(const char *old_ccname);
|
||||||
|
bool sudo_ldap_read_config(void);
|
||||||
|
int sudo_ldap_set_options_global(void);
|
||||||
|
int sudo_ldap_set_options_conn(LDAP *ld);
|
||||||
|
|
||||||
|
#endif /* SUDOERS_LDAP_CONF_H */
|
Reference in New Issue
Block a user