version 1.1, 2012/02/21 16:23:02
|
version 1.1.1.4, 2013/07/22 10:46:12
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2003-2011 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 2003-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* This code is derived from software contributed by Aaron Spangler. |
* This code is derived from software contributed by Aaron Spangler. |
* |
* |
Line 20
|
Line 20
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/time.h> |
#include <sys/time.h> |
#include <sys/param.h> |
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
Line 48
|
Line 47
|
#include <grp.h> |
#include <grp.h> |
#include <netinet/in.h> |
#include <netinet/in.h> |
#include <arpa/inet.h> |
#include <arpa/inet.h> |
#include <netdb.h> |
|
#ifdef HAVE_LBER_H |
#ifdef HAVE_LBER_H |
# include <lber.h> |
# include <lber.h> |
#endif |
#endif |
Line 80
|
Line 78
|
#include "parse.h" |
#include "parse.h" |
#include "lbuf.h" |
#include "lbuf.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 |
#ifndef LDAP_OPT_SUCCESS |
# define LDAP_OPT_SUCCESS LDAP_SUCCESS |
# define LDAP_OPT_SUCCESS LDAP_SUCCESS |
#endif |
#endif |
Line 111
|
Line 118
|
(var) != NULL; \ |
(var) != NULL; \ |
(var) = ldap_next_entry((ld), (var))) |
(var) = ldap_next_entry((ld), (var))) |
|
|
#define DPRINTF(args, level) if (ldap_conf.debug >= level) warningx args | #if defined(__GNUC__) && __GNUC__ == 2 |
| # define DPRINTF1(fmt...) do { \ |
| if (ldap_conf.debug >= 1) \ |
| warningx(__VA_ARGS__); \ |
| sudo_debug_printf(SUDO_DEBUG_DIAG, fmt); \ |
| } while (0) |
| # define DPRINTF2(fmt...) do { \ |
| if (ldap_conf.debug >= 2) \ |
| warningx(__VA_ARGS__); \ |
| sudo_debug_printf(SUDO_DEBUG_INFO, fmt); \ |
| } while (0) |
| #else |
| # define DPRINTF1(...) do { \ |
| if (ldap_conf.debug >= 1) \ |
| warningx(__VA_ARGS__); \ |
| sudo_debug_printf(SUDO_DEBUG_DIAG, __VA_ARGS__); \ |
| } while (0) |
| # define DPRINTF2(...) do { \ |
| if (ldap_conf.debug >= 2) \ |
| warningx(__VA_ARGS__); \ |
| sudo_debug_printf(SUDO_DEBUG_INFO, __VA_ARGS__); \ |
| } while (0) |
| #endif |
|
|
#define CONF_BOOL 0 |
#define CONF_BOOL 0 |
#define CONF_INT 1 |
#define CONF_INT 1 |
Line 119
|
Line 148
|
#define CONF_LIST_STR 4 |
#define CONF_LIST_STR 4 |
#define CONF_DEREF_VAL 5 |
#define CONF_DEREF_VAL 5 |
|
|
|
#define SUDO_LDAP_CLEAR 0 |
#define SUDO_LDAP_SSL 1 |
#define SUDO_LDAP_SSL 1 |
#define SUDO_LDAP_STARTTLS 2 |
#define SUDO_LDAP_STARTTLS 2 |
|
|
/* The TIMEFILTER_LENGTH includes the filter itself plus the global AND | /* The TIMEFILTER_LENGTH is the length of the filter when timed entries |
wrapped around the user filter and the time filter when timed entries | |
are used. The length is computed as follows: |
are used. The length is computed as follows: |
85 for the filter | 81 for the filter itself |
+ 2 * 13 for the now timestamp | + 2 * 17 for the now timestamp |
+ 3 for the global AND | |
*/ |
*/ |
#define TIMEFILTER_LENGTH 114 | #define TIMEFILTER_LENGTH 115 |
|
|
/* |
/* |
* The ldap_search structure implements a linked list of ldap and |
* The ldap_search structure implements a linked list of ldap and |
Line 171 struct ldap_result {
|
Line 199 struct ldap_result {
|
|
|
struct ldap_config_table { |
struct ldap_config_table { |
const char *conf_str; /* config file string */ |
const char *conf_str; /* config file string */ |
short type; /* CONF_BOOL, CONF_INT, CONF_STR */ | int type; /* CONF_BOOL, CONF_INT, CONF_STR */ |
short connected; /* connection-specific value? */ | |
int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */ |
int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */ |
void *valp; /* pointer into ldap_conf */ |
void *valp; /* pointer into ldap_conf */ |
}; |
}; |
Line 211 static struct ldap_config {
|
Line 238 static struct ldap_config {
|
char *tls_cipher_suite; |
char *tls_cipher_suite; |
char *tls_certfile; |
char *tls_certfile; |
char *tls_keyfile; |
char *tls_keyfile; |
|
char *tls_keypw; |
char *sasl_auth_id; |
char *sasl_auth_id; |
char *rootsasl_auth_id; |
char *rootsasl_auth_id; |
char *sasl_secprops; |
char *sasl_secprops; |
char *krb5_ccname; |
char *krb5_ccname; |
} ldap_conf; |
} ldap_conf; |
|
|
static struct ldap_config_table ldap_conf_table[] = { | static struct ldap_config_table ldap_conf_global[] = { |
{ "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug }, | { "sudoers_debug", CONF_INT, -1, &ldap_conf.debug }, |
{ "host", CONF_STR, FALSE, -1, &ldap_conf.host }, | { "host", CONF_STR, -1, &ldap_conf.host }, |
{ "port", CONF_INT, FALSE, -1, &ldap_conf.port }, | { "port", CONF_INT, -1, &ldap_conf.port }, |
{ "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl }, | { "ssl", CONF_STR, -1, &ldap_conf.ssl }, |
{ "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile }, | { "sslpath", CONF_STR, -1, &ldap_conf.tls_certfile }, |
{ "uri", CONF_LIST_STR, FALSE, -1, &ldap_conf.uri }, | { "uri", CONF_LIST_STR, -1, &ldap_conf.uri }, |
#ifdef LDAP_OPT_DEBUG_LEVEL |
#ifdef LDAP_OPT_DEBUG_LEVEL |
{ "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug }, | { "debug", CONF_INT, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug }, |
#endif |
#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 |
#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT |
{ "tls_checkpeer", CONF_BOOL, FALSE, LDAP_OPT_X_TLS_REQUIRE_CERT, | { "tls_checkpeer", CONF_BOOL, LDAP_OPT_X_TLS_REQUIRE_CERT, |
&ldap_conf.tls_checkpeer }, |
&ldap_conf.tls_checkpeer }, |
#else |
#else |
{ "tls_checkpeer", CONF_BOOL, FALSE, -1, &ldap_conf.tls_checkpeer }, | { "tls_checkpeer", CONF_BOOL, -1, &ldap_conf.tls_checkpeer }, |
#endif |
#endif |
#ifdef LDAP_OPT_X_TLS_CACERTFILE |
#ifdef LDAP_OPT_X_TLS_CACERTFILE |
{ "tls_cacertfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE, | { "tls_cacertfile", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE, |
&ldap_conf.tls_cacertfile }, |
&ldap_conf.tls_cacertfile }, |
{ "tls_cacert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE, | { "tls_cacert", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE, |
&ldap_conf.tls_cacertfile }, |
&ldap_conf.tls_cacertfile }, |
#endif |
#endif |
#ifdef LDAP_OPT_X_TLS_CACERTDIR |
#ifdef LDAP_OPT_X_TLS_CACERTDIR |
{ "tls_cacertdir", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTDIR, | { "tls_cacertdir", CONF_STR, LDAP_OPT_X_TLS_CACERTDIR, |
&ldap_conf.tls_cacertdir }, |
&ldap_conf.tls_cacertdir }, |
#endif |
#endif |
#ifdef LDAP_OPT_X_TLS_RANDOM_FILE |
#ifdef LDAP_OPT_X_TLS_RANDOM_FILE |
{ "tls_randfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_RANDOM_FILE, | { "tls_randfile", CONF_STR, LDAP_OPT_X_TLS_RANDOM_FILE, |
&ldap_conf.tls_random_file }, |
&ldap_conf.tls_random_file }, |
#endif |
#endif |
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE |
#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE |
{ "tls_ciphers", CONF_STR, FALSE, LDAP_OPT_X_TLS_CIPHER_SUITE, | { "tls_ciphers", CONF_STR, LDAP_OPT_X_TLS_CIPHER_SUITE, |
&ldap_conf.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 |
#endif |
#ifdef LDAP_OPT_X_TLS_CERTFILE |
#ifdef LDAP_OPT_X_TLS_CERTFILE |
{ "tls_cert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CERTFILE, | { "tls_cert", CONF_STR, LDAP_OPT_X_TLS_CERTFILE, |
&ldap_conf.tls_certfile }, |
&ldap_conf.tls_certfile }, |
#else |
#else |
{ "tls_cert", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile }, | { "tls_cert", CONF_STR, -1, &ldap_conf.tls_certfile }, |
#endif |
#endif |
#ifdef LDAP_OPT_X_TLS_KEYFILE |
#ifdef LDAP_OPT_X_TLS_KEYFILE |
{ "tls_key", CONF_STR, FALSE, LDAP_OPT_X_TLS_KEYFILE, | { "tls_key", CONF_STR, LDAP_OPT_X_TLS_KEYFILE, |
&ldap_conf.tls_keyfile }, |
&ldap_conf.tls_keyfile }, |
#else |
#else |
{ "tls_key", CONF_STR, FALSE, -1, &ldap_conf.tls_keyfile }, | { "tls_key", CONF_STR, -1, &ldap_conf.tls_keyfile }, |
#endif |
#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 }, |
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
|
{ "use_sasl", CONF_BOOL, -1, &ldap_conf.use_sasl }, |
|
{ "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 |
#ifdef LDAP_OPT_NETWORK_TIMEOUT |
{ "bind_timelimit", CONF_INT, TRUE, -1 /* needs timeval, set manually */, | { "bind_timelimit", CONF_INT, -1 /* needs timeval, set manually */, |
&ldap_conf.bind_timelimit }, |
&ldap_conf.bind_timelimit }, |
{ "network_timeout", CONF_INT, TRUE, -1 /* needs timeval, set manually */, | { "network_timeout", CONF_INT, -1 /* needs timeval, set manually */, |
&ldap_conf.bind_timelimit }, |
&ldap_conf.bind_timelimit }, |
#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) |
#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) |
{ "bind_timelimit", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT, | { "bind_timelimit", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT, |
&ldap_conf.bind_timelimit }, |
&ldap_conf.bind_timelimit }, |
{ "network_timeout", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT, | { "network_timeout", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT, |
&ldap_conf.bind_timelimit }, |
&ldap_conf.bind_timelimit }, |
#endif |
#endif |
{ "timelimit", CONF_INT, TRUE, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit }, | { "timelimit", CONF_INT, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit }, |
#ifdef LDAP_OPT_TIMEOUT |
#ifdef LDAP_OPT_TIMEOUT |
{ "timeout", CONF_INT, TRUE, -1 /* needs timeval, set manually */, | { "timeout", CONF_INT, -1 /* needs timeval, set manually */, |
&ldap_conf.timeout }, |
&ldap_conf.timeout }, |
#endif |
#endif |
#ifdef LDAP_OPT_DEREF |
#ifdef LDAP_OPT_DEREF |
{ "deref", CONF_DEREF_VAL, TRUE, LDAP_OPT_DEREF, &ldap_conf.deref }, | { "deref", CONF_DEREF_VAL, LDAP_OPT_DEREF, &ldap_conf.deref }, |
#endif |
#endif |
{ "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn }, | #ifdef LDAP_OPT_X_SASL_SECPROPS |
{ "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw }, | { "sasl_secprops", CONF_STR, LDAP_OPT_X_SASL_SECPROPS, |
{ "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn }, | |
{ "sudoers_base", CONF_LIST_STR, FALSE, -1, &ldap_conf.base }, | |
{ "sudoers_timed", CONF_BOOL, FALSE, -1, &ldap_conf.timed }, | |
{ "sudoers_search_filter", CONF_STR, FALSE, -1, &ldap_conf.search_filter }, | |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S | |
{ "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl }, | |
{ "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id }, | |
{ "rootuse_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.rootuse_sasl }, | |
{ "rootsasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.rootsasl_auth_id }, | |
# ifdef LDAP_OPT_X_SASL_SECPROPS | |
{ "sasl_secprops", CONF_STR, TRUE, LDAP_OPT_X_SASL_SECPROPS, | |
&ldap_conf.sasl_secprops }, |
&ldap_conf.sasl_secprops }, |
# endif | #endif |
{ "krb5_ccname", CONF_STR, FALSE, -1, &ldap_conf.krb5_ccname }, | |
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ | |
{ NULL } |
{ NULL } |
}; |
}; |
|
|
Line 362 sudo_ldap_conf_add_ports(void)
|
Line 400 sudo_ldap_conf_add_ports(void)
|
|
|
char *host, *port, defport[13]; |
char *host, *port, defport[13]; |
char hostbuf[LINE_MAX * 2]; |
char hostbuf[LINE_MAX * 2]; |
|
debug_decl(sudo_ldap_conf_add_ports, SUDO_DEBUG_LDAP) |
|
|
hostbuf[0] = '\0'; |
hostbuf[0] = '\0'; |
if (snprintf(defport, sizeof(defport), ":%d", ldap_conf.port) >= sizeof(defport)) |
if (snprintf(defport, sizeof(defport), ":%d", ldap_conf.port) >= sizeof(defport)) |
errorx(1, _("sudo_ldap_conf_add_ports: port too large")); | fatalx(_("sudo_ldap_conf_add_ports: port too large")); |
|
|
for ((host = strtok(ldap_conf.host, " \t")); host; (host = strtok(NULL, " \t"))) { |
for ((host = strtok(ldap_conf.host, " \t")); host; (host = strtok(NULL, " \t"))) { |
if (hostbuf[0] != '\0') { |
if (hostbuf[0] != '\0') { |
Line 385 sudo_ldap_conf_add_ports(void)
|
Line 424 sudo_ldap_conf_add_ports(void)
|
|
|
efree(ldap_conf.host); |
efree(ldap_conf.host); |
ldap_conf.host = estrdup(hostbuf); |
ldap_conf.host = estrdup(hostbuf); |
return; | debug_return; |
|
|
toobig: |
toobig: |
errorx(1, _("sudo_ldap_conf_add_ports: out of space expanding hostbuf")); | fatalx(_("sudo_ldap_conf_add_ports: out of space expanding hostbuf")); |
} |
} |
#endif |
#endif |
|
|
Line 405 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
Line 444 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
char hostbuf[LINE_MAX]; |
char hostbuf[LINE_MAX]; |
int nldap = 0, nldaps = 0; |
int nldap = 0, nldaps = 0; |
int rc = -1; |
int rc = -1; |
|
debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP) |
|
|
do { |
do { |
buf = estrdup(uri_list->val); |
buf = estrdup(uri_list->val); |
Line 446 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
Line 486 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
} |
} |
} |
} |
if (hostbuf[0] == '\0') { |
if (hostbuf[0] == '\0') { |
warningx(_("invalid uri: %s"), uri_list); | warningx(_("invalid uri: %s"), uri_list->val); |
goto done; |
goto done; |
} |
} |
|
|
Line 472 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
Line 512 sudo_ldap_parse_uri(const struct ldap_config_list_str
|
|
|
done: |
done: |
efree(buf); |
efree(buf); |
return rc; | debug_return_int(rc); |
|
|
toobig: |
toobig: |
errorx(1, _("sudo_ldap_parse_uri: out of space building hostbuf")); | fatalx(_("sudo_ldap_parse_uri: out of space building hostbuf")); |
} |
} |
#else |
#else |
static char * |
static char * |
Line 484 sudo_ldap_join_uri(struct ldap_config_list_str *uri_li
|
Line 524 sudo_ldap_join_uri(struct ldap_config_list_str *uri_li
|
struct ldap_config_list_str *uri; |
struct ldap_config_list_str *uri; |
size_t len = 0; |
size_t len = 0; |
char *buf, *cp; |
char *buf, *cp; |
|
debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP) |
|
|
/* Usually just a single entry. */ |
/* Usually just a single entry. */ |
if (uri_list->next == NULL) |
if (uri_list->next == NULL) |
return estrdup(uri_list->val); | debug_return_str(estrdup(uri_list->val)); |
|
|
for (uri = uri_list; uri != NULL; uri = uri->next) { |
for (uri = uri_list; uri != NULL; uri = uri->next) { |
len += strlen(uri->val) + 1; |
len += strlen(uri->val) + 1; |
Line 499 sudo_ldap_join_uri(struct ldap_config_list_str *uri_li
|
Line 540 sudo_ldap_join_uri(struct ldap_config_list_str *uri_li
|
*cp++ = ' '; |
*cp++ = ' '; |
} |
} |
cp[-1] = '\0'; |
cp[-1] = '\0'; |
return buf; | debug_return_str(buf); |
} |
} |
#endif /* HAVE_LDAP_INITIALIZE */ |
#endif /* HAVE_LDAP_INITIALIZE */ |
|
|
Line 508 sudo_ldap_init(LDAP **ldp, const char *host, int port)
|
Line 549 sudo_ldap_init(LDAP **ldp, const char *host, int port)
|
{ |
{ |
LDAP *ld = NULL; |
LDAP *ld = NULL; |
int rc = LDAP_CONNECT_ERROR; |
int rc = LDAP_CONNECT_ERROR; |
|
debug_decl(sudo_ldap_init, SUDO_DEBUG_LDAP) |
|
|
#ifdef HAVE_LDAPSSL_INIT |
#ifdef HAVE_LDAPSSL_INIT |
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { | if (ldap_conf.ssl_mode != SUDO_LDAP_CLEAR) { |
DPRINTF(("ldapssl_clientauth_init(%s, %s)", | const int defsecure = ldap_conf.ssl_mode == SUDO_LDAP_SSL; |
| DPRINTF2("ldapssl_clientauth_init(%s, %s)", |
ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", |
ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", |
ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2); | ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"); |
rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, |
rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, |
ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); |
ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); |
/* |
/* |
* Mozilla-derived SDKs have a bug starting with version 5.0 | * Starting with version 5.0, Mozilla-derived LDAP SDKs require |
* where the path can no longer be a file name and must be a dir. | * the cert and key paths to be a directory, not a file. |
| * If the user specified a file and it fails, try the parent dir. |
*/ |
*/ |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
char *cp; | bool retry = false; |
if (ldap_conf.tls_certfile) { | if (ldap_conf.tls_certfile != NULL) { |
cp = strrchr(ldap_conf.tls_certfile, '/'); | char *cp = strrchr(ldap_conf.tls_certfile, '/'); |
if (cp != NULL && strncmp(cp + 1, "cert", 4) == 0) | if (cp != NULL && strncmp(cp + 1, "cert", 4) == 0) { |
*cp = '\0'; |
*cp = '\0'; |
|
retry = true; |
|
} |
} |
} |
if (ldap_conf.tls_keyfile) { | if (ldap_conf.tls_keyfile != NULL) { |
cp = strrchr(ldap_conf.tls_keyfile, '/'); | char *cp = strrchr(ldap_conf.tls_keyfile, '/'); |
if (cp != NULL && strncmp(cp + 1, "key", 3) == 0) | if (cp != NULL && strncmp(cp + 1, "key", 3) == 0) { |
*cp = '\0'; |
*cp = '\0'; |
|
retry = true; |
|
} |
} |
} |
DPRINTF(("ldapssl_clientauth_init(%s, %s)", | if (retry) { |
ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", | DPRINTF2("ldapssl_clientauth_init(%s, %s)", |
ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"), 2); | ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL", |
rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, | ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL"); |
ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); | rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, |
if (rc != LDAP_SUCCESS) { | ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); |
warningx(_("unable to initialize SSL cert and key db: %s"), | |
ldapssl_err2string(rc)); | |
goto done; | |
} |
} |
} |
} |
|
if (rc != LDAP_SUCCESS) { |
|
warningx(_("unable to initialize SSL cert and key db: %s"), |
|
ldapssl_err2string(rc)); |
|
if (ldap_conf.tls_certfile == NULL) |
|
warningx(_("you must set TLS_CERT in %s to use SSL"), |
|
path_ldap_conf); |
|
goto done; |
|
} |
|
|
DPRINTF(("ldapssl_init(%s, %d, 1)", host, port), 2); | DPRINTF2("ldapssl_init(%s, %d, %d)", host, port, defsecure); |
if ((ld = ldapssl_init(host, port, 1)) != NULL) | if ((ld = ldapssl_init(host, port, defsecure)) != NULL) |
rc = LDAP_SUCCESS; |
rc = LDAP_SUCCESS; |
} else |
} else |
|
#elif defined(HAVE_LDAP_SSL_INIT) && defined(HAVE_LDAP_SSL_CLIENT_INIT) |
|
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { |
|
if (ldap_ssl_client_init(ldap_conf.tls_keyfile, ldap_conf.tls_keypw, 0, &rc) != LDAP_SUCCESS) { |
|
warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc)); |
|
debug_return_int(-1); |
|
} |
|
DPRINTF2("ldap_ssl_init(%s, %d, NULL)", host, port); |
|
if ((ld = ldap_ssl_init((char *)host, port, NULL)) != NULL) |
|
rc = LDAP_SUCCESS; |
|
} else |
#endif |
#endif |
{ |
{ |
#ifdef HAVE_LDAP_CREATE |
#ifdef HAVE_LDAP_CREATE |
DPRINTF(("ldap_create()"), 2); | DPRINTF2("ldap_create()"); |
if ((rc = ldap_create(&ld)) != LDAP_SUCCESS) |
if ((rc = ldap_create(&ld)) != LDAP_SUCCESS) |
goto done; |
goto done; |
DPRINTF(("ldap_set_option(LDAP_OPT_HOST_NAME, %s)", host), 2); | DPRINTF2("ldap_set_option(LDAP_OPT_HOST_NAME, %s)", host); |
rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, host); |
rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, host); |
#else |
#else |
DPRINTF(("ldap_init(%s, %d)", host, port), 2); | DPRINTF2("ldap_init(%s, %d)", host, port); |
if ((ld = ldap_init(host, port)) != NULL) | if ((ld = ldap_init((char *)host, port)) != NULL) |
rc = LDAP_SUCCESS; |
rc = LDAP_SUCCESS; |
#endif |
#endif |
} |
} |
|
|
done: |
done: |
*ldp = ld; |
*ldp = ld; |
return rc; | debug_return_int(rc); |
} |
} |
|
|
/* |
/* |
* Walk through search results and return TRUE if we have a matching | * Walk through search results and return true if we have a matching |
* netgroup, else FALSE. | * non-Unix group (including netgroups), else false. |
*/ |
*/ |
static int | static bool |
sudo_ldap_check_user_netgroup(LDAP *ld, LDAPMessage *entry, char *user) | sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw) |
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
char *val; |
char *val; |
int ret = FALSE; | int ret = false; |
| debug_decl(sudo_ldap_check_non_unix_group, SUDO_DEBUG_LDAP) |
|
|
if (!entry) |
if (!entry) |
return ret; | debug_return_bool(ret); |
|
|
/* get the values from the entry */ |
/* get the values from the entry */ |
bv = ldap_get_values_len(ld, entry, "sudoUser"); |
bv = ldap_get_values_len(ld, entry, "sudoUser"); |
if (bv == NULL) |
if (bv == NULL) |
return ret; | debug_return_bool(ret); |
|
|
/* walk through values */ |
/* walk through values */ |
for (p = bv; *p != NULL && !ret; p++) { |
for (p = bv; *p != NULL && !ret; p++) { |
val = (*p)->bv_val; |
val = (*p)->bv_val; |
/* match any */ | if (*val == '+') { |
if (netgr_matches(val, NULL, NULL, user)) | if (netgr_matches(val, NULL, NULL, pw->pw_name)) |
ret = TRUE; | ret = true; |
DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val, | DPRINTF2("ldap sudoUser netgroup '%s' ... %s", val, |
ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1)); | ret ? "MATCH!" : "not"); |
| } else { |
| if (group_plugin_query(pw->pw_name, val + 2, pw)) |
| ret = true; |
| DPRINTF2("ldap sudoUser non-Unix group '%s' ... %s", val, |
| ret ? "MATCH!" : "not"); |
| } |
} |
} |
|
|
ldap_value_free_len(bv); /* cleanup */ |
ldap_value_free_len(bv); /* cleanup */ |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
/* |
/* |
* Walk through search results and return TRUE if we have a | * Walk through search results and return true if we have a |
* host match, else FALSE. | * host match, else false. |
*/ | */ |
static int | static bool |
sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry) |
sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry) |
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
char *val; |
char *val; |
int ret = FALSE; | bool ret = false; |
| debug_decl(sudo_ldap_check_host, SUDO_DEBUG_LDAP) |
|
|
if (!entry) |
if (!entry) |
return ret; | debug_return_bool(ret); |
|
|
/* get the values from the entry */ |
/* get the values from the entry */ |
bv = ldap_get_values_len(ld, entry, "sudoHost"); |
bv = ldap_get_values_len(ld, entry, "sudoHost"); |
if (bv == NULL) |
if (bv == NULL) |
return ret; | debug_return_bool(ret); |
|
|
/* walk through values */ |
/* walk through values */ |
for (p = bv; *p != NULL && !ret; p++) { |
for (p = bv; *p != NULL && !ret; p++) { |
Line 628 sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry)
|
Line 699 sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry)
|
if (!strcmp(val, "ALL") || addr_matches(val) || |
if (!strcmp(val, "ALL") || addr_matches(val) || |
netgr_matches(val, user_host, user_shost, NULL) || |
netgr_matches(val, user_host, user_shost, NULL) || |
hostname_matches(user_shost, user_host, val)) |
hostname_matches(user_shost, user_host, val)) |
ret = TRUE; | ret = true; |
DPRINTF(("ldap sudoHost '%s' ... %s", val, | DPRINTF2("ldap sudoHost '%s' ... %s", val, ret ? "MATCH!" : "not"); |
ret ? "MATCH!" : "not"), 2); | |
} |
} |
|
|
ldap_value_free_len(bv); /* cleanup */ |
ldap_value_free_len(bv); /* cleanup */ |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
static int |
static int |
Line 643 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
Line 713 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
char *val; |
char *val; |
int ret = FALSE; | bool ret = false; |
| debug_decl(sudo_ldap_check_runas_user, SUDO_DEBUG_LDAP) |
|
|
if (!runas_pw) |
if (!runas_pw) |
return UNSPEC; | debug_return_bool(UNSPEC); |
|
|
/* get the runas user from the entry */ |
/* get the runas user from the entry */ |
bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); |
bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); |
Line 675 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
Line 746 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
* what the user specified on the command line. |
* what the user specified on the command line. |
*/ |
*/ |
if (bv == NULL) |
if (bv == NULL) |
return !strcasecmp(runas_pw->pw_name, def_runas_default); | debug_return_bool(!strcasecmp(runas_pw->pw_name, def_runas_default)); |
|
|
/* walk through values returned, looking for a match */ |
/* walk through values returned, looking for a match */ |
for (p = bv; *p != NULL && !ret; p++) { |
for (p = bv; *p != NULL && !ret; p++) { |
Line 683 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
Line 754 sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entr
|
switch (val[0]) { |
switch (val[0]) { |
case '+': |
case '+': |
if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) |
if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) |
ret = TRUE; | ret = true; |
break; |
break; |
case '%': |
case '%': |
if (usergr_matches(val, runas_pw->pw_name, runas_pw)) |
if (usergr_matches(val, runas_pw->pw_name, runas_pw)) |
ret = TRUE; | ret = true; |
break; |
break; |
case 'A': |
case 'A': |
if (strcmp(val, "ALL") == 0) { |
if (strcmp(val, "ALL") == 0) { |
ret = TRUE; | ret = true; |
break; |
break; |
} |
} |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
default: |
default: |
if (strcasecmp(val, runas_pw->pw_name) == 0) | if (userpw_matches(val, runas_pw->pw_name, runas_pw)) |
ret = TRUE; | ret = true; |
break; |
break; |
} |
} |
DPRINTF(("ldap sudoRunAsUser '%s' ... %s", val, | DPRINTF2("ldap sudoRunAsUser '%s' ... %s", val, ret ? "MATCH!" : "not"); |
ret ? "MATCH!" : "not"), 2); | |
} |
} |
|
|
ldap_value_free_len(bv); /* cleanup */ |
ldap_value_free_len(bv); /* cleanup */ |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
static int |
static int |
Line 714 sudo_ldap_check_runas_group(LDAP *ld, LDAPMessage *ent
|
Line 784 sudo_ldap_check_runas_group(LDAP *ld, LDAPMessage *ent
|
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
char *val; |
char *val; |
int ret = FALSE; | bool ret = false; |
| debug_decl(sudo_ldap_check_runas_group, SUDO_DEBUG_LDAP) |
|
|
/* runas_gr is only set if the user specified the -g flag */ |
/* runas_gr is only set if the user specified the -g flag */ |
if (!runas_gr) |
if (!runas_gr) |
return UNSPEC; | debug_return_bool(UNSPEC); |
|
|
/* get the values from the entry */ |
/* get the values from the entry */ |
bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); |
bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); |
if (bv == NULL) |
if (bv == NULL) |
return ret; | debug_return_bool(ret); |
|
|
/* walk through values returned, looking for a match */ |
/* walk through values returned, looking for a match */ |
for (p = bv; *p != NULL && !ret; p++) { |
for (p = bv; *p != NULL && !ret; p++) { |
val = (*p)->bv_val; |
val = (*p)->bv_val; |
if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr)) |
if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr)) |
ret = TRUE; | ret = true; |
DPRINTF(("ldap sudoRunAsGroup '%s' ... %s", val, | DPRINTF2("ldap sudoRunAsGroup '%s' ... %s", |
ret ? "MATCH!" : "not"), 2); | val, ret ? "MATCH!" : "not"); |
} |
} |
|
|
ldap_value_free_len(bv); /* cleanup */ |
ldap_value_free_len(bv); /* cleanup */ |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
/* |
/* |
* Walk through search results and return TRUE if we have a runas match, | * Walk through search results and return true if we have a runas match, |
* else FALSE. RunAs info is optional. | * else false. RunAs info is optional. |
*/ |
*/ |
static int | static bool |
sudo_ldap_check_runas(LDAP *ld, LDAPMessage *entry) |
sudo_ldap_check_runas(LDAP *ld, LDAPMessage *entry) |
{ |
{ |
int ret; | bool ret; |
| debug_decl(sudo_ldap_check_runas, SUDO_DEBUG_LDAP) |
|
|
if (!entry) |
if (!entry) |
return FALSE; | debug_return_bool(false); |
|
|
ret = sudo_ldap_check_runas_user(ld, entry) != FALSE && | ret = sudo_ldap_check_runas_user(ld, entry) != false && |
sudo_ldap_check_runas_group(ld, entry) != FALSE; | sudo_ldap_check_runas_group(ld, entry) != false; |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
|
static struct sudo_digest * |
|
sudo_ldap_extract_digest(char **cmnd, struct sudo_digest *digest) |
|
{ |
|
char *ep, *cp = *cmnd; |
|
int digest_type = SUDO_DIGEST_INVALID; |
|
debug_decl(sudo_ldap_check_command, SUDO_DEBUG_LDAP) |
|
|
|
/* |
|
* Check for and extract a digest prefix, e.g. |
|
* sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls |
|
*/ |
|
if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') { |
|
switch (cp[3]) { |
|
case '2': |
|
if (cp[4] == '2' && cp[5] == '4') |
|
digest_type = SUDO_DIGEST_SHA224; |
|
else if (cp[4] == '5' && cp[5] == '6') |
|
digest_type = SUDO_DIGEST_SHA256; |
|
break; |
|
case '3': |
|
if (cp[4] == '8' && cp[5] == '4') |
|
digest_type = SUDO_DIGEST_SHA384; |
|
break; |
|
case '5': |
|
if (cp[4] == '1' && cp[5] == '2') |
|
digest_type = SUDO_DIGEST_SHA512; |
|
break; |
|
} |
|
if (digest_type != SUDO_DIGEST_INVALID) { |
|
cp += 6; |
|
while (isblank((unsigned char)*cp)) |
|
cp++; |
|
if (*cp == ':') { |
|
cp++; |
|
while (isblank((unsigned char)*cp)) |
|
cp++; |
|
ep = cp; |
|
while (*ep != '\0' && !isblank((unsigned char)*ep)) |
|
ep++; |
|
if (*ep != '\0') { |
|
digest->digest_type = digest_type; |
|
digest->digest_str = estrndup(cp, (size_t)(ep - cp)); |
|
cp = ep + 1; |
|
while (isblank((unsigned char)*cp)) |
|
cp++; |
|
*cmnd = cp; |
|
DPRINTF1("%s digest %s for %s", |
|
digest_type == SUDO_DIGEST_SHA224 ? "sha224" : |
|
digest_type == SUDO_DIGEST_SHA256 ? "sha256" : |
|
digest_type == SUDO_DIGEST_SHA384 ? "sha384" : |
|
"sha512", digest->digest_str, cp); |
|
debug_return_ptr(digest); |
|
} |
|
} |
|
} |
|
} |
|
debug_return_ptr(NULL); |
|
} |
|
|
/* |
/* |
* Walk through search results and return TRUE if we have a command match, | * Walk through search results and return true if we have a command match, |
* FALSE if disallowed and UNSPEC if not matched. | * false if disallowed and UNSPEC if not matched. |
*/ |
*/ |
static int |
static int |
sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied) |
sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied) |
{ |
{ |
|
struct sudo_digest digest, *allowed_digest = NULL; |
struct berval **bv, **p; |
struct berval **bv, **p; |
char *allowed_cmnd, *allowed_args, *val; |
char *allowed_cmnd, *allowed_args, *val; |
int foundbang, ret = UNSPEC; | bool foundbang; |
| int ret = UNSPEC; |
| debug_decl(sudo_ldap_check_command, SUDO_DEBUG_LDAP) |
|
|
if (!entry) |
if (!entry) |
return ret; | debug_return_bool(ret); |
|
|
bv = ldap_get_values_len(ld, entry, "sudoCommand"); |
bv = ldap_get_values_len(ld, entry, "sudoCommand"); |
if (bv == NULL) |
if (bv == NULL) |
return ret; | debug_return_bool(ret); |
|
|
for (p = bv; *p != NULL && ret != FALSE; p++) { | for (p = bv; *p != NULL && ret != false; p++) { |
val = (*p)->bv_val; |
val = (*p)->bv_val; |
/* Match against ALL ? */ |
/* Match against ALL ? */ |
if (!strcmp(val, "ALL")) { |
if (!strcmp(val, "ALL")) { |
ret = TRUE; | ret = true; |
if (setenv_implied != NULL) |
if (setenv_implied != NULL) |
*setenv_implied = TRUE; | *setenv_implied = true; |
DPRINTF(("ldap sudoCommand '%s' ... MATCH!", val), 2); | DPRINTF2("ldap sudoCommand '%s' ... MATCH!", val); |
continue; |
continue; |
} |
} |
|
|
|
/* check for sha-2 digest */ |
|
allowed_digest = sudo_ldap_extract_digest(&val, &digest); |
|
|
/* check for !command */ |
/* check for !command */ |
if (*val == '!') { |
if (*val == '!') { |
foundbang = TRUE; | foundbang = true; |
allowed_cmnd = estrdup(1 + val); /* !command */ |
allowed_cmnd = estrdup(1 + val); /* !command */ |
} else { |
} else { |
foundbang = FALSE; | foundbang = false; |
allowed_cmnd = estrdup(val); /* command */ |
allowed_cmnd = estrdup(val); /* command */ |
} |
} |
|
|
Line 801 sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry,
|
Line 938 sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry,
|
*allowed_args++ = '\0'; |
*allowed_args++ = '\0'; |
|
|
/* check the command like normal */ |
/* check the command like normal */ |
if (command_matches(allowed_cmnd, allowed_args)) { | if (command_matches(allowed_cmnd, allowed_args, allowed_digest)) { |
/* |
/* |
* If allowed (no bang) set ret but keep on checking. |
* If allowed (no bang) set ret but keep on checking. |
* If disallowed (bang), exit loop. |
* If disallowed (bang), exit loop. |
*/ |
*/ |
ret = foundbang ? FALSE : TRUE; | ret = foundbang ? false : true; |
} |
} |
DPRINTF(("ldap sudoCommand '%s' ... %s", val, | DPRINTF2("ldap sudoCommand '%s' ... %s", |
ret == TRUE ? "MATCH!" : "not"), 2); | val, ret == true ? "MATCH!" : "not"); |
|
|
efree(allowed_cmnd); /* cleanup */ |
efree(allowed_cmnd); /* cleanup */ |
|
if (allowed_digest != NULL) |
|
efree(allowed_digest->digest_str); |
} |
} |
|
|
ldap_value_free_len(bv); /* more cleanup */ |
ldap_value_free_len(bv); /* more cleanup */ |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
/* |
/* |
* Search for boolean "option" in sudoOption. |
* Search for boolean "option" in sudoOption. |
* Returns TRUE if found and allowed, FALSE if negated, else UNSPEC. | * Returns true if found and allowed, false if negated, else UNSPEC. |
*/ |
*/ |
static int |
static int |
sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option) |
sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option) |
Line 829 sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, cha
|
Line 968 sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, cha
|
struct berval **bv, **p; |
struct berval **bv, **p; |
char ch, *var; |
char ch, *var; |
int ret = UNSPEC; |
int ret = UNSPEC; |
|
debug_decl(sudo_ldap_check_bool, SUDO_DEBUG_LDAP) |
|
|
if (entry == NULL) |
if (entry == NULL) |
return UNSPEC; | debug_return_bool(ret); |
|
|
bv = ldap_get_values_len(ld, entry, "sudoOption"); |
bv = ldap_get_values_len(ld, entry, "sudoOption"); |
if (bv == NULL) |
if (bv == NULL) |
return ret; | debug_return_bool(ret); |
|
|
/* walk through options */ |
/* walk through options */ |
for (p = bv; *p != NULL; p++) { |
for (p = bv; *p != NULL; p++) { |
var = (*p)->bv_val;; |
var = (*p)->bv_val;; |
DPRINTF(("ldap sudoOption: '%s'", var), 2); | DPRINTF2("ldap sudoOption: '%s'", var); |
|
|
if ((ch = *var) == '!') |
if ((ch = *var) == '!') |
var++; |
var++; |
Line 850 sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, cha
|
Line 990 sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, cha
|
|
|
ldap_value_free_len(bv); |
ldap_value_free_len(bv); |
|
|
return ret; | debug_return_bool(ret); |
} |
} |
|
|
/* |
/* |
Line 862 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
Line 1002 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
char op, *var, *val; |
char op, *var, *val; |
|
debug_decl(sudo_ldap_parse_options, SUDO_DEBUG_LDAP) |
|
|
if (entry == NULL) |
if (entry == NULL) |
return; | debug_return; |
|
|
bv = ldap_get_values_len(ld, entry, "sudoOption"); |
bv = ldap_get_values_len(ld, entry, "sudoOption"); |
if (bv == NULL) |
if (bv == NULL) |
return; | debug_return; |
|
|
/* walk through options */ |
/* walk through options */ |
for (p = bv; *p != NULL; p++) { |
for (p = bv; *p != NULL; p++) { |
var = estrdup((*p)->bv_val); |
var = estrdup((*p)->bv_val); |
DPRINTF(("ldap sudoOption: '%s'", var), 2); | DPRINTF2("ldap sudoOption: '%s'", var); |
|
|
/* check for equals sign past first char */ |
/* check for equals sign past first char */ |
val = strchr(var, '='); |
val = strchr(var, '='); |
Line 886 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
Line 1027 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
set_default(var, val, (int) op); |
set_default(var, val, (int) op); |
} else { |
} else { |
/* case var=val */ |
/* case var=val */ |
set_default(var, val, TRUE); | set_default(var, val, true); |
} |
} |
} else if (*var == '!') { |
} else if (*var == '!') { |
/* case !var Boolean False */ |
/* case !var Boolean False */ |
set_default(var + 1, NULL, FALSE); | set_default(var + 1, NULL, false); |
} else { |
} else { |
/* case var Boolean True */ |
/* case var Boolean True */ |
set_default(var, NULL, TRUE); | set_default(var, NULL, true); |
} |
} |
efree(var); |
efree(var); |
} |
} |
|
|
ldap_value_free_len(bv); |
ldap_value_free_len(bv); |
|
|
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 928 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
Line 1071 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
{ |
{ |
struct tm *tp; |
struct tm *tp; |
time_t now; |
time_t now; |
char timebuffer[16]; | char timebuffer[sizeof("20120727121554.0Z")]; |
int bytes = 0; |
int bytes = 0; |
|
debug_decl(sudo_ldap_timefilter, SUDO_DEBUG_LDAP) |
|
|
/* Make sure we have a formatted timestamp for __now__. */ |
/* Make sure we have a formatted timestamp for __now__. */ |
time(&now); |
time(&now); |
Line 939 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
Line 1083 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
} |
} |
|
|
/* Format the timestamp according to the RFC. */ |
/* Format the timestamp according to the RFC. */ |
if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%SZ", tp) == 0) { | if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%S.0Z", tp) == 0) { |
warning(_("unable to format timestamp")); | warningx(_("unable to format timestamp")); |
goto done; |
goto done; |
} |
} |
|
|
Line 953 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
Line 1097 sudo_ldap_timefilter(char *buffer, size_t buffersize)
|
} |
} |
|
|
done: |
done: |
return bytes; | debug_return_int(bytes); |
} |
} |
|
|
/* |
/* |
* Builds up a filter to search for default settings |
* Builds up a filter to search for default settings |
*/ |
*/ |
static char * |
static char * |
sudo_ldap_build_default_filter() | sudo_ldap_build_default_filter(void) |
{ |
{ |
char *filt; |
char *filt; |
|
debug_decl(sudo_ldap_build_default_filter, SUDO_DEBUG_LDAP) |
|
|
if (ldap_conf.search_filter) |
if (ldap_conf.search_filter) |
easprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter); |
easprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter); |
else |
else |
filt = estrdup("cn=defaults"); |
filt = estrdup("cn=defaults"); |
return filt; | debug_return_str(filt); |
} |
} |
|
|
/* |
/* |
|
* Determine length of query value after escaping characters |
|
* as per RFC 4515. |
|
*/ |
|
static size_t |
|
sudo_ldap_value_len(const char *value) |
|
{ |
|
const char *s; |
|
size_t len = 0; |
|
|
|
for (s = value; *s != '\0'; s++) { |
|
switch (*s) { |
|
case '\\': |
|
case '(': |
|
case ')': |
|
case '*': |
|
len += 2; |
|
break; |
|
} |
|
} |
|
len += (size_t)(s - value); |
|
return len; |
|
} |
|
|
|
/* |
|
* Like strlcat() but escapes characters as per RFC 4515. |
|
*/ |
|
static size_t |
|
sudo_ldap_value_cat(char *dst, const char *src, size_t size) |
|
{ |
|
char *d = dst; |
|
const char *s = src; |
|
size_t n = size; |
|
size_t dlen; |
|
|
|
/* Find the end of dst and adjust bytes left but don't go past end */ |
|
while (n-- != 0 && *d != '\0') |
|
d++; |
|
dlen = d - dst; |
|
n = size - dlen; |
|
|
|
if (n == 0) |
|
return dlen + strlen(s); |
|
while (*s != '\0') { |
|
switch (*s) { |
|
case '\\': |
|
if (n < 3) |
|
goto done; |
|
*d++ = '\\'; |
|
*d++ = '5'; |
|
*d++ = 'c'; |
|
n -= 3; |
|
break; |
|
case '(': |
|
if (n < 3) |
|
goto done; |
|
*d++ = '\\'; |
|
*d++ = '2'; |
|
*d++ = '8'; |
|
n -= 3; |
|
break; |
|
case ')': |
|
if (n < 3) |
|
goto done; |
|
*d++ = '\\'; |
|
*d++ = '2'; |
|
*d++ = '9'; |
|
n -= 3; |
|
break; |
|
case '*': |
|
if (n < 3) |
|
goto done; |
|
*d++ = '\\'; |
|
*d++ = '2'; |
|
*d++ = 'a'; |
|
n -= 3; |
|
break; |
|
default: |
|
if (n < 1) |
|
goto done; |
|
*d++ = *s; |
|
n--; |
|
break; |
|
} |
|
s++; |
|
} |
|
done: |
|
*d = '\0'; |
|
while (*s != '\0') |
|
s++; |
|
return dlen + (s - src); /* count does not include NUL */ |
|
} |
|
|
|
/* |
* Builds up a filter to check against LDAP. |
* Builds up a filter to check against LDAP. |
*/ |
*/ |
static char * |
static char * |
sudo_ldap_build_pass1(struct passwd *pw) |
sudo_ldap_build_pass1(struct passwd *pw) |
{ |
{ |
struct group *grp; |
struct group *grp; |
char *buf, timebuffer[TIMEFILTER_LENGTH]; | char *buf, timebuffer[TIMEFILTER_LENGTH + 1], gidbuf[MAX_UID_T_LEN + 1]; |
struct group_list *grlist; |
struct group_list *grlist; |
size_t sz = 0; |
size_t sz = 0; |
int i; |
int i; |
|
debug_decl(sudo_ldap_build_pass1, SUDO_DEBUG_LDAP) |
|
|
/* Start with LDAP search filter length + 3 */ | /* If there is a filter, allocate space for the global AND. */ |
| if (ldap_conf.timed || ldap_conf.search_filter) |
| sz += 3; |
| |
| /* Add LDAP search filter if present. */ |
if (ldap_conf.search_filter) |
if (ldap_conf.search_filter) |
sz += strlen(ldap_conf.search_filter) + 3; | sz += strlen(ldap_conf.search_filter); |
|
|
/* Then add (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */ |
/* Then add (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */ |
sz += 29 + strlen(pw->pw_name); | sz += 29 + sudo_ldap_value_len(pw->pw_name); |
|
|
/* Add space for primary and supplementary groups */ | /* Add space for primary and supplementary groups and gids */ |
if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) { |
if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) { |
sz += 12 + strlen(grp->gr_name); | sz += 12 + sudo_ldap_value_len(grp->gr_name); |
} |
} |
if ((grlist = get_group_list(pw)) != NULL) { | sz += 13 + MAX_UID_T_LEN; |
| if ((grlist = sudo_get_grlist(pw)) != NULL) { |
for (i = 0; i < grlist->ngroups; i++) { |
for (i = 0; i < grlist->ngroups; i++) { |
if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) |
if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) |
continue; |
continue; |
sz += 12 + strlen(grlist->groups[i]); | sz += 12 + sudo_ldap_value_len(grlist->groups[i]); |
} |
} |
|
for (i = 0; i < grlist->ngids; i++) { |
|
if (pw->pw_gid == grlist->gids[i]) |
|
continue; |
|
sz += 13 + MAX_UID_T_LEN; |
|
} |
} |
} |
|
|
/* If timed, add space for time limits. */ |
/* If timed, add space for time limits. */ |
Line 1020 sudo_ldap_build_pass1(struct passwd *pw)
|
Line 1269 sudo_ldap_build_pass1(struct passwd *pw)
|
|
|
/* Global OR + sudoUser=user_name filter */ |
/* Global OR + sudoUser=user_name filter */ |
(void) strlcat(buf, "(|(sudoUser=", sz); |
(void) strlcat(buf, "(|(sudoUser=", sz); |
(void) strlcat(buf, pw->pw_name, sz); | (void) sudo_ldap_value_cat(buf, pw->pw_name, sz); |
(void) strlcat(buf, ")", sz); |
(void) strlcat(buf, ")", sz); |
|
|
/* Append primary group */ | /* Append primary group and gid */ |
if (grp != NULL) { |
if (grp != NULL) { |
(void) strlcat(buf, "(sudoUser=%", sz); |
(void) strlcat(buf, "(sudoUser=%", sz); |
(void) strlcat(buf, grp->gr_name, sz); | (void) sudo_ldap_value_cat(buf, grp->gr_name, sz); |
(void) strlcat(buf, ")", sz); |
(void) strlcat(buf, ")", sz); |
} |
} |
|
(void) snprintf(gidbuf, sizeof(gidbuf), "%u", (unsigned int)pw->pw_gid); |
|
(void) strlcat(buf, "(sudoUser=%#", sz); |
|
(void) strlcat(buf, gidbuf, sz); |
|
(void) strlcat(buf, ")", sz); |
|
|
/* Append supplementary groups */ | /* Append supplementary groups and gids */ |
if (grlist != NULL) { |
if (grlist != NULL) { |
for (i = 0; i < grlist->ngroups; i++) { |
for (i = 0; i < grlist->ngroups; i++) { |
if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) |
if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) |
continue; |
continue; |
(void) strlcat(buf, "(sudoUser=%", sz); |
(void) strlcat(buf, "(sudoUser=%", sz); |
(void) strlcat(buf, grlist->groups[i], sz); | (void) sudo_ldap_value_cat(buf, grlist->groups[i], sz); |
(void) strlcat(buf, ")", sz); |
(void) strlcat(buf, ")", sz); |
} |
} |
|
for (i = 0; i < grlist->ngids; i++) { |
|
if (pw->pw_gid == grlist->gids[i]) |
|
continue; |
|
(void) snprintf(gidbuf, sizeof(gidbuf), "%u", |
|
(unsigned int)grlist->gids[i]); |
|
(void) strlcat(buf, "(sudoUser=%#", sz); |
|
(void) strlcat(buf, gidbuf, sz); |
|
(void) strlcat(buf, ")", sz); |
|
} |
} |
} |
|
|
/* Done with groups. */ |
/* Done with groups. */ |
if (grlist != NULL) |
if (grlist != NULL) |
grlist_delref(grlist); | sudo_grlist_delref(grlist); |
if (grp != NULL) |
if (grp != NULL) |
gr_delref(grp); | sudo_gr_delref(grp); |
|
|
/* Add ALL to list and end the global OR */ |
/* Add ALL to list and end the global OR */ |
if (strlcat(buf, "(sudoUser=ALL)", sz) >= sz) |
if (strlcat(buf, "(sudoUser=ALL)", sz) >= sz) |
errorx(1, _("sudo_ldap_build_pass1 allocation mismatch")); | fatalx(_("sudo_ldap_build_pass1 allocation mismatch")); |
|
|
/* Add the time restriction, or simply end the global OR. */ |
/* Add the time restriction, or simply end the global OR. */ |
if (ldap_conf.timed) { |
if (ldap_conf.timed) { |
Line 1061 sudo_ldap_build_pass1(struct passwd *pw)
|
Line 1323 sudo_ldap_build_pass1(struct passwd *pw)
|
} |
} |
strlcat(buf, ")", sz); /* closes the global OR or the global AND */ |
strlcat(buf, ")", sz); /* closes the global OR or the global AND */ |
|
|
return buf; | debug_return_str(buf); |
} |
} |
|
|
/* |
/* |
* Builds up a filter to check against netgroup entries in LDAP. | * Builds up a filter to check against non-Unix group |
| * entries in LDAP, including netgroups. |
*/ |
*/ |
static char * |
static char * |
sudo_ldap_build_pass2(void) |
sudo_ldap_build_pass2(void) |
{ |
{ |
char *filt, timebuffer[TIMEFILTER_LENGTH]; | char *filt, timebuffer[TIMEFILTER_LENGTH + 1]; |
| debug_decl(sudo_ldap_build_pass2, SUDO_DEBUG_LDAP) |
|
|
if (ldap_conf.timed) |
if (ldap_conf.timed) |
sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)); |
sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)); |
|
|
/* |
/* |
* Match all sudoUsers beginning with a '+'. | * Match all sudoUsers beginning with '+' or '%:'. |
* If a search filter or time restriction is specified, |
* If a search filter or time restriction is specified, |
* those get ANDed in to the expression. |
* those get ANDed in to the expression. |
*/ |
*/ |
easprintf(&filt, "%s%s(sudoUser=+*)%s%s", | if (def_group_plugin) { |
(ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "", | easprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=%%:*))%s%s", |
ldap_conf.search_filter ? ldap_conf.search_filter : "", | (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "", |
ldap_conf.timed ? timebuffer : "", | ldap_conf.search_filter ? ldap_conf.search_filter : "", |
(ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); | ldap_conf.timed ? timebuffer : "", |
| (ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); |
| } else { |
| easprintf(&filt, "%s%s(sudoUser=+*)%s%s", |
| (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "", |
| ldap_conf.search_filter ? ldap_conf.search_filter : "", |
| ldap_conf.timed ? timebuffer : "", |
| (ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); |
| } |
|
|
return filt; | debug_return_str(filt); |
} |
} |
|
|
static void |
static void |
Line 1094 sudo_ldap_read_secret(const char *path)
|
Line 1366 sudo_ldap_read_secret(const char *path)
|
{ |
{ |
FILE *fp; |
FILE *fp; |
char buf[LINE_MAX], *cp; |
char buf[LINE_MAX], *cp; |
|
debug_decl(sudo_ldap_read_secret, SUDO_DEBUG_LDAP) |
|
|
if ((fp = fopen(_PATH_LDAP_SECRET, "r")) != NULL) { | if ((fp = fopen(path_ldap_secret, "r")) != NULL) { |
if (fgets(buf, sizeof(buf), fp) != NULL) { |
if (fgets(buf, sizeof(buf), fp) != NULL) { |
if ((cp = strchr(buf, '\n')) != NULL) |
if ((cp = strchr(buf, '\n')) != NULL) |
*cp = '\0'; |
*cp = '\0'; |
Line 1108 sudo_ldap_read_secret(const char *path)
|
Line 1381 sudo_ldap_read_secret(const char *path)
|
} |
} |
fclose(fp); |
fclose(fp); |
} |
} |
|
debug_return; |
} |
} |
|
|
static int | /* |
| * 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; |
| debug_decl(sudo_ldap_parse_keyword, SUDO_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) = atobool(value) == true; |
| break; |
| case CONF_INT: |
| *(int *)(cur->valp) = atoi(value); |
| break; |
| case CONF_STR: |
| efree(*(char **)(cur->valp)); |
| *(char **)(cur->valp) = estrdup(value); |
| break; |
| case CONF_LIST_STR: |
| { |
| struct ldap_config_list_str **p; |
| size_t len = strlen(value); |
| |
| if (len > 0) { |
| p = (struct ldap_config_list_str **)cur->valp; |
| while (*p != NULL) |
| p = &(*p)->next; |
| *p = emalloc(sizeof(struct ldap_config_list_str) + len); |
| memcpy((*p)->val, value, len + 1); |
| (*p)->next = NULL; |
| } |
| } |
| break; |
| } |
| debug_return_bool(true); |
| } |
| } |
| debug_return_bool(false); |
| } |
| |
| static bool |
sudo_ldap_read_config(void) |
sudo_ldap_read_config(void) |
{ |
{ |
FILE *fp; |
FILE *fp; |
char *cp, *keyword, *value; | char *cp, *keyword, *value, *line = NULL; |
struct ldap_config_table *cur; | size_t linesize = 0; |
| debug_decl(sudo_ldap_read_config, SUDO_DEBUG_LDAP) |
|
|
/* defaults */ |
/* defaults */ |
ldap_conf.version = 3; |
ldap_conf.version = 3; |
Line 1128 sudo_ldap_read_config(void)
|
Line 1460 sudo_ldap_read_config(void)
|
ldap_conf.rootuse_sasl = -1; |
ldap_conf.rootuse_sasl = -1; |
ldap_conf.deref = -1; |
ldap_conf.deref = -1; |
|
|
if ((fp = fopen(_PATH_LDAP_CONF, "r")) == NULL) | if ((fp = fopen(path_ldap_conf, "r")) == NULL) |
return FALSE; | debug_return_bool(false); |
|
|
while ((cp = sudo_parseln(fp)) != NULL) { | while (sudo_parseln(&line, &linesize, NULL, fp) != -1) { |
if (*cp == '\0') | if (*line == '\0') |
continue; /* skip empty line */ |
continue; /* skip empty line */ |
|
|
/* split into keyword and value */ |
/* split into keyword and value */ |
keyword = cp; | keyword = cp = line; |
while (*cp && !isblank((unsigned char) *cp)) |
while (*cp && !isblank((unsigned char) *cp)) |
cp++; |
cp++; |
if (*cp) |
if (*cp) |
Line 1147 sudo_ldap_read_config(void)
|
Line 1479 sudo_ldap_read_config(void)
|
cp++; |
cp++; |
value = cp; |
value = cp; |
|
|
/* Look up keyword in config table. */ | /* Look up keyword in config tables */ |
for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) { | if (!sudo_ldap_parse_keyword(keyword, value, ldap_conf_global)) |
if (strcasecmp(keyword, cur->conf_str) == 0) { | sudo_ldap_parse_keyword(keyword, value, ldap_conf_conn); |
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) = atobool(value) == TRUE; | |
break; | |
case CONF_INT: | |
*(int *)(cur->valp) = atoi(value); | |
break; | |
case CONF_STR: | |
efree(*(char **)(cur->valp)); | |
*(char **)(cur->valp) = estrdup(value); | |
break; | |
case CONF_LIST_STR: | |
{ | |
struct ldap_config_list_str **p; | |
size_t len = strlen(value); | |
| |
if (len > 0) { | |
p = (struct ldap_config_list_str **)cur->valp; | |
while (*p != NULL) | |
p = &(*p)->next; | |
*p = emalloc(sizeof(struct ldap_config_list_str) + len); | |
memcpy((*p)->val, value, len + 1); | |
(*p)->next = NULL; | |
} | |
} | |
break; | |
} | |
break; | |
} | |
} | |
} |
} |
|
free(line); |
fclose(fp); |
fclose(fp); |
|
|
if (!ldap_conf.host) |
if (!ldap_conf.host) |
ldap_conf.host = estrdup("localhost"); |
ldap_conf.host = estrdup("localhost"); |
|
|
if (ldap_conf.debug > 1) { | DPRINTF1("LDAP Config Summary"); |
sudo_printf(SUDO_CONV_ERROR_MSG, "LDAP Config Summary\n"); | DPRINTF1("==================="); |
sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n"); | if (ldap_conf.uri) { |
if (ldap_conf.uri) { | struct ldap_config_list_str *uri = ldap_conf.uri; |
struct ldap_config_list_str *uri = ldap_conf.uri; | |
|
|
do { | do { |
sudo_printf(SUDO_CONV_ERROR_MSG, "uri %s\n", | DPRINTF1("uri %s", uri->val); |
uri->val); | } while ((uri = uri->next) != NULL); |
} while ((uri = uri->next) != NULL); | } else { |
} else { | DPRINTF1("host %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "host %s\n", | ldap_conf.host ? ldap_conf.host : "(NONE)"); |
ldap_conf.host ? ldap_conf.host : "(NONE)"); | DPRINTF1("port %d", ldap_conf.port); |
sudo_printf(SUDO_CONV_ERROR_MSG, "port %d\n", | } |
ldap_conf.port); | DPRINTF1("ldap_version %d", ldap_conf.version); |
} | |
sudo_printf(SUDO_CONV_ERROR_MSG, "ldap_version %d\n", | |
ldap_conf.version); | |
|
|
if (ldap_conf.base) { | if (ldap_conf.base) { |
struct ldap_config_list_str *base = ldap_conf.base; | struct ldap_config_list_str *base = ldap_conf.base; |
do { | do { |
sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n", | DPRINTF1("sudoers_base %s", base->val); |
base->val); | } while ((base = base->next) != NULL); |
} while ((base = base->next) != NULL); | } else { |
} else { | DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)"); |
sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n", | } |
"(NONE: LDAP disabled)"); | if (ldap_conf.search_filter) { |
} | DPRINTF1("search_filter %s", ldap_conf.search_filter); |
if (ldap_conf.search_filter) { | } |
sudo_printf(SUDO_CONV_ERROR_MSG, "search_filter %s\n", | DPRINTF1("binddn %s", |
ldap_conf.search_filter); | ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)"); |
} | DPRINTF1("bindpw %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "binddn %s\n", | ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)"); |
ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)"); | if (ldap_conf.bind_timelimit > 0) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "bindpw %s\n", | DPRINTF1("bind_timelimit %d", ldap_conf.bind_timelimit); |
ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)"); | } |
if (ldap_conf.bind_timelimit > 0) { | if (ldap_conf.timelimit > 0) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "bind_timelimit %d\n", | DPRINTF1("timelimit %d", ldap_conf.timelimit); |
ldap_conf.bind_timelimit); | } |
} | if (ldap_conf.deref != -1) { |
if (ldap_conf.timelimit > 0) { | DPRINTF1("deref %d", ldap_conf.deref); |
sudo_printf(SUDO_CONV_ERROR_MSG, "timelimit %d\n", | } |
ldap_conf.timelimit); | DPRINTF1("ssl %s", ldap_conf.ssl ? ldap_conf.ssl : "(no)"); |
} | if (ldap_conf.tls_checkpeer != -1) { |
if (ldap_conf.deref != -1) { | DPRINTF1("tls_checkpeer %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "deref %d\n", | ldap_conf.tls_checkpeer ? "(yes)" : "(no)"); |
ldap_conf.deref); | } |
} | if (ldap_conf.tls_cacertfile != NULL) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "ssl %s\n", | DPRINTF1("tls_cacertfile %s", ldap_conf.tls_cacertfile); |
ldap_conf.ssl ? ldap_conf.ssl : "(no)"); | } |
if (ldap_conf.tls_checkpeer != -1) { | if (ldap_conf.tls_cacertdir != NULL) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_checkpeer %s\n", | DPRINTF1("tls_cacertdir %s", ldap_conf.tls_cacertdir); |
ldap_conf.tls_checkpeer ? "(yes)" : "(no)"); | } |
} | if (ldap_conf.tls_random_file != NULL) { |
if (ldap_conf.tls_cacertfile != NULL) { | DPRINTF1("tls_random_file %s", ldap_conf.tls_random_file); |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cacertfile %s\n", | } |
ldap_conf.tls_cacertfile); | if (ldap_conf.tls_cipher_suite != NULL) { |
} | DPRINTF1("tls_cipher_suite %s", ldap_conf.tls_cipher_suite); |
if (ldap_conf.tls_cacertdir != NULL) { | } |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cacertdir %s\n", | if (ldap_conf.tls_certfile != NULL) { |
ldap_conf.tls_cacertdir); | DPRINTF1("tls_certfile %s", ldap_conf.tls_certfile); |
} | } |
if (ldap_conf.tls_random_file != NULL) { | if (ldap_conf.tls_keyfile != NULL) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_random_file %s\n", | DPRINTF1("tls_keyfile %s", ldap_conf.tls_keyfile); |
ldap_conf.tls_random_file); | } |
} | |
if (ldap_conf.tls_cipher_suite != NULL) { | |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cipher_suite %s\n", | |
ldap_conf.tls_cipher_suite); | |
} | |
if (ldap_conf.tls_certfile != NULL) { | |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_certfile %s\n", | |
ldap_conf.tls_certfile); | |
} | |
if (ldap_conf.tls_keyfile != NULL) { | |
sudo_printf(SUDO_CONV_ERROR_MSG, "tls_keyfile %s\n", | |
ldap_conf.tls_keyfile); | |
} | |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
if (ldap_conf.use_sasl != -1) { | if (ldap_conf.use_sasl != -1) { |
sudo_printf(SUDO_CONV_ERROR_MSG, "use_sasl %s\n", | DPRINTF1("use_sasl %s", ldap_conf.use_sasl ? "yes" : "no"); |
ldap_conf.use_sasl ? "yes" : "no"); | DPRINTF1("sasl_auth_id %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "sasl_auth_id %s\n", | ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)"); |
ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)"); | DPRINTF1("rootuse_sasl %d", |
sudo_printf(SUDO_CONV_ERROR_MSG, "rootuse_sasl %d\n", | ldap_conf.rootuse_sasl); |
ldap_conf.rootuse_sasl); | DPRINTF1("rootsasl_auth_id %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "rootsasl_auth_id %s\n", | ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)"); |
ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)"); | DPRINTF1("sasl_secprops %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "sasl_secprops %s\n", | ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)"); |
ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)"); | DPRINTF1("krb5_ccname %s", |
sudo_printf(SUDO_CONV_ERROR_MSG, "krb5_ccname %s\n", | ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)"); |
ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)"); | |
} | |
#endif | |
sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n"); | |
} |
} |
|
#endif |
|
DPRINTF1("==================="); |
|
|
if (!ldap_conf.base) |
if (!ldap_conf.base) |
return FALSE; /* if no base is defined, ignore LDAP */ | debug_return_bool(false); /* if no base is defined, ignore LDAP */ |
|
|
if (ldap_conf.bind_timelimit > 0) |
if (ldap_conf.bind_timelimit > 0) |
ldap_conf.bind_timelimit *= 1000; /* convert to ms */ |
ldap_conf.bind_timelimit *= 1000; /* convert to ms */ |
Line 1305 sudo_ldap_read_config(void)
|
Line 1580 sudo_ldap_read_config(void)
|
if (ldap_conf.ssl != NULL) { |
if (ldap_conf.ssl != NULL) { |
if (strcasecmp(ldap_conf.ssl, "start_tls") == 0) |
if (strcasecmp(ldap_conf.ssl, "start_tls") == 0) |
ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS; |
ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS; |
else if (atobool(ldap_conf.ssl) == TRUE) | else if (atobool(ldap_conf.ssl) == true) |
ldap_conf.ssl_mode = SUDO_LDAP_SSL; |
ldap_conf.ssl_mode = SUDO_LDAP_SSL; |
} |
} |
|
|
Line 1321 sudo_ldap_read_config(void)
|
Line 1596 sudo_ldap_read_config(void)
|
if (ldap_conf.uri) { |
if (ldap_conf.uri) { |
struct ldap_config_list_str *uri = ldap_conf.uri; |
struct ldap_config_list_str *uri = ldap_conf.uri; |
if (sudo_ldap_parse_uri(uri) != 0) |
if (sudo_ldap_parse_uri(uri) != 0) |
return FALSE; | debug_return_bool(false); |
do { |
do { |
ldap_conf.uri = uri->next; |
ldap_conf.uri = uri->next; |
efree(uri); |
efree(uri); |
Line 1360 sudo_ldap_read_config(void)
|
Line 1635 sudo_ldap_read_config(void)
|
|
|
/* If rootbinddn set, read in /etc/ldap.secret if it exists. */ |
/* If rootbinddn set, read in /etc/ldap.secret if it exists. */ |
if (ldap_conf.rootbinddn) |
if (ldap_conf.rootbinddn) |
sudo_ldap_read_secret(_PATH_LDAP_SECRET); | sudo_ldap_read_secret(path_ldap_secret); |
|
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
/* |
/* |
Line 1372 sudo_ldap_read_config(void)
|
Line 1647 sudo_ldap_read_config(void)
|
value = ldap_conf.krb5_ccname + |
value = ldap_conf.krb5_ccname + |
(ldap_conf.krb5_ccname[4] == ':' ? 5 : 7); |
(ldap_conf.krb5_ccname[4] == ':' ? 5 : 7); |
if ((fp = fopen(value, "r")) != NULL) { |
if ((fp = fopen(value, "r")) != NULL) { |
DPRINTF(("using krb5 credential cache: %s", value), 1); | sudo_debug_printf(SUDO_DEBUG_INFO, |
| "using krb5 credential cache: %s", value); |
fclose(fp); |
fclose(fp); |
} else { |
} else { |
/* Can't open it, just ignore the entry. */ |
/* Can't open it, just ignore the entry. */ |
DPRINTF(("unable to open krb5 credential cache: %s", value), 1); | sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO, |
| "unable to open krb5 credential cache: %s", value); |
efree(ldap_conf.krb5_ccname); |
efree(ldap_conf.krb5_ccname); |
ldap_conf.krb5_ccname = NULL; |
ldap_conf.krb5_ccname = NULL; |
} |
} |
} |
} |
} |
} |
#endif |
#endif |
return TRUE; | debug_return_bool(true); |
} |
} |
|
|
/* |
/* |
Line 1395 sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry)
|
Line 1672 sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry)
|
#ifdef HAVE_LDAP_STR2DN |
#ifdef HAVE_LDAP_STR2DN |
char *dn, *rdn = NULL; |
char *dn, *rdn = NULL; |
LDAPDN tmpDN; |
LDAPDN tmpDN; |
|
debug_decl(sudo_ldap_get_first_rdn, SUDO_DEBUG_LDAP) |
|
|
if ((dn = ldap_get_dn(ld, entry)) == NULL) |
if ((dn = ldap_get_dn(ld, entry)) == NULL) |
return NULL; | debug_return_str(NULL); |
if (ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP) == LDAP_SUCCESS) { |
if (ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP) == LDAP_SUCCESS) { |
ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN); |
ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN); |
ldap_dnfree(tmpDN); |
ldap_dnfree(tmpDN); |
} |
} |
ldap_memfree(dn); |
ldap_memfree(dn); |
return rdn; | debug_return_str(rdn); |
#else |
#else |
char *dn, **edn; |
char *dn, **edn; |
|
debug_decl(sudo_ldap_get_first_rdn, SUDO_DEBUG_LDAP) |
|
|
if ((dn = ldap_get_dn(ld, entry)) == NULL) |
if ((dn = ldap_get_dn(ld, entry)) == NULL) |
return NULL; |
return NULL; |
edn = ldap_explode_dn(dn, 1); |
edn = ldap_explode_dn(dn, 1); |
ldap_memfree(dn); |
ldap_memfree(dn); |
return edn ? edn[0] : NULL; | debug_return_str(edn ? edn[0] : NULL); |
#endif |
#endif |
} |
} |
|
|
Line 1430 sudo_ldap_display_defaults(struct sudo_nss *nss, struc
|
Line 1709 sudo_ldap_display_defaults(struct sudo_nss *nss, struc
|
LDAPMessage *entry, *result; |
LDAPMessage *entry, *result; |
char *prefix, *filt; |
char *prefix, *filt; |
int rc, count = 0; |
int rc, count = 0; |
|
debug_decl(sudo_ldap_display_defaults, SUDO_DEBUG_LDAP) |
|
|
if (handle == NULL || handle->ld == NULL) |
if (handle == NULL || handle->ld == NULL) |
goto done; |
goto done; |
Line 1465 sudo_ldap_display_defaults(struct sudo_nss *nss, struc
|
Line 1745 sudo_ldap_display_defaults(struct sudo_nss *nss, struc
|
} |
} |
efree(filt); |
efree(filt); |
done: |
done: |
return count; | debug_return_int(count); |
} |
} |
|
|
/* |
/* |
Line 1475 static int
|
Line 1755 static int
|
sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, |
sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, |
struct lbuf *lbuf) |
struct lbuf *lbuf) |
{ |
{ |
return 0; | debug_decl(sudo_ldap_display_bound_defaults, SUDO_DEBUG_LDAP) |
| debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 1486 sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *e
|
Line 1767 sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *e
|
{ |
{ |
struct berval **bv, **p; |
struct berval **bv, **p; |
int count = 0; |
int count = 0; |
|
debug_decl(sudo_ldap_display_entry_short, SUDO_DEBUG_LDAP) |
|
|
lbuf_append(lbuf, " ("); |
lbuf_append(lbuf, " ("); |
|
|
Line 1543 sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *e
|
Line 1825 sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *e
|
} |
} |
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, "\n"); |
|
|
return count; | debug_return_int(count); |
} |
} |
|
|
/* |
/* |
Line 1555 sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *en
|
Line 1837 sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *en
|
struct berval **bv, **p; |
struct berval **bv, **p; |
char *rdn; |
char *rdn; |
int count = 0; |
int count = 0; |
|
debug_decl(sudo_ldap_display_entry_long, SUDO_DEBUG_LDAP) |
|
|
/* extract the dn, only show the first rdn */ |
/* extract the dn, only show the first rdn */ |
rdn = sudo_ldap_get_first_rdn(ld, entry); |
rdn = sudo_ldap_get_first_rdn(ld, entry); |
Line 1624 sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *en
|
Line 1907 sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *en
|
ldap_value_free_len(bv); |
ldap_value_free_len(bv); |
} |
} |
|
|
return count; | debug_return_int(count); |
} |
} |
|
|
/* |
/* |
Line 1639 sudo_ldap_display_privs(struct sudo_nss *nss, struct p
|
Line 1922 sudo_ldap_display_privs(struct sudo_nss *nss, struct p
|
struct ldap_result *lres; |
struct ldap_result *lres; |
LDAPMessage *entry; |
LDAPMessage *entry; |
int i, count = 0; |
int i, count = 0; |
|
debug_decl(sudo_ldap_display_privs, SUDO_DEBUG_LDAP) |
|
|
if (handle == NULL || handle->ld == NULL) |
if (handle == NULL || handle->ld == NULL) |
goto done; |
goto done; |
ld = handle->ld; |
ld = handle->ld; |
|
|
DPRINTF(("ldap search for command list"), 1); | DPRINTF1("ldap search for command list"); |
lres = sudo_ldap_result_get(nss, pw); |
lres = sudo_ldap_result_get(nss, pw); |
|
|
/* Display all matching entries. */ |
/* Display all matching entries. */ |
Line 1657 sudo_ldap_display_privs(struct sudo_nss *nss, struct p
|
Line 1941 sudo_ldap_display_privs(struct sudo_nss *nss, struct p
|
} |
} |
|
|
done: |
done: |
return count; | debug_return_int(count); |
} |
} |
|
|
static int |
static int |
Line 1667 sudo_ldap_display_cmnd(struct sudo_nss *nss, struct pa
|
Line 1951 sudo_ldap_display_cmnd(struct sudo_nss *nss, struct pa
|
LDAP *ld; |
LDAP *ld; |
struct ldap_result *lres; |
struct ldap_result *lres; |
LDAPMessage *entry; |
LDAPMessage *entry; |
int i, found = FALSE; | bool found = false; |
| int i; |
| debug_decl(sudo_ldap_display_cmnd, SUDO_DEBUG_LDAP) |
|
|
if (handle == NULL || handle->ld == NULL) |
if (handle == NULL || handle->ld == NULL) |
goto done; |
goto done; |
Line 1677 sudo_ldap_display_cmnd(struct sudo_nss *nss, struct pa
|
Line 1963 sudo_ldap_display_cmnd(struct sudo_nss *nss, struct pa
|
* The sudo_ldap_result_get() function returns all nodes that match |
* The sudo_ldap_result_get() function returns all nodes that match |
* the user and the host. |
* the user and the host. |
*/ |
*/ |
DPRINTF(("ldap search for command list"), 1); | DPRINTF1("ldap search for command list"); |
lres = sudo_ldap_result_get(nss, pw); |
lres = sudo_ldap_result_get(nss, pw); |
for (i = 0; i < lres->nentries; i++) { |
for (i = 0; i < lres->nentries; i++) { |
entry = lres->entries[i].entry; |
entry = lres->entries[i].entry; |
if (sudo_ldap_check_command(ld, entry, NULL) && |
if (sudo_ldap_check_command(ld, entry, NULL) && |
sudo_ldap_check_runas(ld, entry)) { |
sudo_ldap_check_runas(ld, entry)) { |
found = TRUE; | found = true; |
goto done; |
goto done; |
} |
} |
} |
} |
Line 1692 done:
|
Line 1978 done:
|
if (found) |
if (found) |
printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd, |
printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd, |
user_args ? " " : "", user_args ? user_args : ""); |
user_args ? " " : "", user_args ? user_args : ""); |
return !found; | debug_return_bool(!found); |
} |
} |
|
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
Line 1702 sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags,
|
Line 1988 sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags,
|
{ |
{ |
char *auth_id = (char *)_auth_id; |
char *auth_id = (char *)_auth_id; |
sasl_interact_t *interact = (sasl_interact_t *)_interact; |
sasl_interact_t *interact = (sasl_interact_t *)_interact; |
|
debug_decl(sudo_ldap_sasl_interact, SUDO_DEBUG_LDAP) |
|
|
for (; interact->id != SASL_CB_LIST_END; interact++) { |
for (; interact->id != SASL_CB_LIST_END; interact++) { |
if (interact->id != SASL_CB_USER) |
if (interact->id != SASL_CB_USER) |
return LDAP_PARAM_ERROR; | debug_return_int(LDAP_PARAM_ERROR); |
|
|
if (auth_id != NULL) |
if (auth_id != NULL) |
interact->result = auth_id; |
interact->result = auth_id; |
Line 1719 sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags,
|
Line 2006 sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags,
|
interact->result = estrdup(interact->result); |
interact->result = estrdup(interact->result); |
#endif /* SASL_VERSION_MAJOR < 2 */ |
#endif /* SASL_VERSION_MAJOR < 2 */ |
} |
} |
return LDAP_SUCCESS; | debug_return_int(LDAP_SUCCESS); |
} |
} |
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ |
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ |
|
|
|
|
/* |
/* |
* Set LDAP options based on the config table. | * Set LDAP options from the specified options table |
*/ |
*/ |
static int |
static int |
sudo_ldap_set_options(LDAP *ld) | sudo_ldap_set_options_table(LDAP *ld, struct ldap_config_table *table) |
{ |
{ |
struct ldap_config_table *cur; |
struct ldap_config_table *cur; |
int rc; | int ival, rc, errors = 0; |
| char *sval; |
| debug_decl(sudo_ldap_set_options_table, SUDO_DEBUG_LDAP) |
|
|
/* Set ber options */ | for (cur = table; cur->conf_str != NULL; cur++) { |
#ifdef LBER_OPT_DEBUG_LEVEL | |
if (ldap_conf.ldap_debug) | |
ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug); | |
#endif | |
| |
/* Set simple LDAP options */ | |
for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) { | |
LDAP *conn; | |
int ival; | |
char *sval; | |
| |
if (cur->opt_val == -1) |
if (cur->opt_val == -1) |
continue; |
continue; |
|
|
conn = cur->connected ? ld : NULL; |
|
switch (cur->type) { |
switch (cur->type) { |
case CONF_BOOL: |
case CONF_BOOL: |
case CONF_INT: |
case CONF_INT: |
ival = *(int *)(cur->valp); |
ival = *(int *)(cur->valp); |
if (ival >= 0) { |
if (ival >= 0) { |
rc = ldap_set_option(conn, cur->opt_val, &ival); | DPRINTF1("ldap_set_option: %s -> %d", cur->conf_str, ival); |
| rc = ldap_set_option(ld, cur->opt_val, &ival); |
if (rc != LDAP_OPT_SUCCESS) { |
if (rc != LDAP_OPT_SUCCESS) { |
warningx("ldap_set_option: %s -> %d: %s", |
warningx("ldap_set_option: %s -> %d: %s", |
cur->conf_str, ival, ldap_err2string(rc)); |
cur->conf_str, ival, ldap_err2string(rc)); |
return -1; | errors++; |
} |
} |
DPRINTF(("ldap_set_option: %s -> %d", cur->conf_str, ival), 1); |
|
} |
} |
break; |
break; |
case CONF_STR: |
case CONF_STR: |
sval = *(char **)(cur->valp); |
sval = *(char **)(cur->valp); |
if (sval != NULL) { |
if (sval != NULL) { |
rc = ldap_set_option(conn, cur->opt_val, sval); | DPRINTF1("ldap_set_option: %s -> %s", cur->conf_str, sval); |
| rc = ldap_set_option(ld, cur->opt_val, sval); |
if (rc != LDAP_OPT_SUCCESS) { |
if (rc != LDAP_OPT_SUCCESS) { |
warningx("ldap_set_option: %s -> %s: %s", |
warningx("ldap_set_option: %s -> %s: %s", |
cur->conf_str, sval, ldap_err2string(rc)); |
cur->conf_str, sval, ldap_err2string(rc)); |
return -1; | errors++; |
} |
} |
DPRINTF(("ldap_set_option: %s -> %s", cur->conf_str, sval), 1); |
|
} |
} |
break; |
break; |
} |
} |
} |
} |
|
debug_return_int(errors ? -1 : 0); |
|
} |
|
|
|
/* |
|
* Set LDAP options based on the global config table. |
|
*/ |
|
static int |
|
sudo_ldap_set_options_global(void) |
|
{ |
|
int rc; |
|
debug_decl(sudo_ldap_set_options_global, SUDO_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. */ |
|
rc = sudo_ldap_set_options_table(NULL, ldap_conf_global); |
|
if (rc == -1) |
|
debug_return_int(-1); |
|
debug_return_int(0); |
|
} |
|
|
|
/* |
|
* Set LDAP options based on the per-connection config table. |
|
*/ |
|
static int |
|
sudo_ldap_set_options_conn(LDAP *ld) |
|
{ |
|
int rc; |
|
debug_decl(sudo_ldap_set_options_conn, SUDO_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 |
#ifdef LDAP_OPT_TIMEOUT |
/* Convert timeout to a timeval */ |
/* Convert timeout to a timeval */ |
if (ldap_conf.timeout > 0) { |
if (ldap_conf.timeout > 0) { |
struct timeval tv; |
struct timeval tv; |
tv.tv_sec = ldap_conf.timeout; |
tv.tv_sec = ldap_conf.timeout; |
tv.tv_usec = 0; |
tv.tv_usec = 0; |
|
DPRINTF1("ldap_set_option(LDAP_OPT_TIMEOUT, %d)", ldap_conf.timeout); |
rc = ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv); |
rc = ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv); |
if (rc != LDAP_OPT_SUCCESS) { |
if (rc != LDAP_OPT_SUCCESS) { |
warningx("ldap_set_option(TIMEOUT, %ld): %s", | warningx("ldap_set_option(TIMEOUT, %d): %s", |
(long)tv.tv_sec, ldap_err2string(rc)); | ldap_conf.timeout, ldap_err2string(rc)); |
return -1; | |
} |
} |
DPRINTF(("ldap_set_option(LDAP_OPT_TIMEOUT, %ld)", |
|
(long)tv.tv_sec), 1); |
|
} |
} |
#endif |
#endif |
#ifdef LDAP_OPT_NETWORK_TIMEOUT |
#ifdef LDAP_OPT_NETWORK_TIMEOUT |
Line 1799 sudo_ldap_set_options(LDAP *ld)
|
Line 2113 sudo_ldap_set_options(LDAP *ld)
|
struct timeval tv; |
struct timeval tv; |
tv.tv_sec = ldap_conf.bind_timelimit / 1000; |
tv.tv_sec = ldap_conf.bind_timelimit / 1000; |
tv.tv_usec = 0; |
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); |
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) { |
if (rc != LDAP_OPT_SUCCESS) { |
warningx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s", | warningx("ldap_set_option(NETWORK_TIMEOUT, %d): %s", |
(long)tv.tv_sec, ldap_err2string(rc)); | ldap_conf.bind_timelimit / 1000, ldap_err2string(rc)); |
return -1; | |
} |
} |
DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)", | # endif |
(long)tv.tv_sec), 1); | |
} |
} |
#endif |
#endif |
|
|
#if defined(LDAP_OPT_X_TLS) && !defined(HAVE_LDAPSSL_INIT) |
#if defined(LDAP_OPT_X_TLS) && !defined(HAVE_LDAPSSL_INIT) |
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { |
if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) { |
int val = LDAP_OPT_X_TLS_HARD; |
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); |
rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s", |
warningx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s", |
ldap_err2string(rc)); |
ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)"), 1); |
|
} |
} |
#endif |
#endif |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 1832 static struct ldap_result *
|
Line 2148 static struct ldap_result *
|
sudo_ldap_result_alloc(void) |
sudo_ldap_result_alloc(void) |
{ |
{ |
struct ldap_result *result; |
struct ldap_result *result; |
|
debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP) |
|
|
result = emalloc(sizeof(*result)); | debug_return_ptr(ecalloc(1, sizeof(*result))); |
result->searches = NULL; | |
result->nentries = 0; | |
result->entries = NULL; | |
result->allocated_entries = 0; | |
result->user_matches = FALSE; | |
result->host_matches = FALSE; | |
return result; | |
} |
} |
|
|
/* |
/* |
Line 1850 static void
|
Line 2160 static void
|
sudo_ldap_result_free(struct ldap_result *lres) |
sudo_ldap_result_free(struct ldap_result *lres) |
{ |
{ |
struct ldap_search_list *s; |
struct ldap_search_list *s; |
|
debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP) |
|
|
if (lres != NULL) { |
if (lres != NULL) { |
if (lres->nentries) { |
if (lres->nentries) { |
Line 1865 sudo_ldap_result_free(struct ldap_result *lres)
|
Line 2176 sudo_ldap_result_free(struct ldap_result *lres)
|
} |
} |
efree(lres); |
efree(lres); |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 1875 sudo_ldap_result_add_search(struct ldap_result *lres,
|
Line 2187 sudo_ldap_result_add_search(struct ldap_result *lres,
|
LDAPMessage *searchresult) |
LDAPMessage *searchresult) |
{ |
{ |
struct ldap_search_list *s, *news; |
struct ldap_search_list *s, *news; |
|
debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP) |
|
|
news = emalloc(sizeof(struct ldap_search_list)); | news = ecalloc(1, sizeof(struct ldap_search_list)); |
news->next = NULL; | |
news->ldap = ldap; |
news->ldap = ldap; |
news->searchresult = searchresult; |
news->searchresult = searchresult; |
|
/* news->next = NULL; */ |
|
|
/* Add entry to the end of the chain (XXX - tailq instead?). */ |
/* Add entry to the end of the chain (XXX - tailq instead?). */ |
if (lres->searches) { |
if (lres->searches) { |
Line 1889 sudo_ldap_result_add_search(struct ldap_result *lres,
|
Line 2202 sudo_ldap_result_add_search(struct ldap_result *lres,
|
} else { |
} else { |
lres->searches = news; |
lres->searches = news; |
} |
} |
return news; | debug_return_ptr(news); |
} |
} |
|
|
/* |
/* |
Line 1905 sudo_ldap_bind_s(LDAP *ld)
|
Line 2218 sudo_ldap_bind_s(LDAP *ld)
|
unsigned int status; |
unsigned int status; |
# endif |
# endif |
#endif |
#endif |
|
debug_decl(sudo_ldap_bind_s, SUDO_DEBUG_LDAP) |
|
|
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S |
if (ldap_conf.rootuse_sasl == TRUE || | if (ldap_conf.rootuse_sasl == true || |
(ldap_conf.rootuse_sasl != FALSE && ldap_conf.use_sasl == TRUE)) { | (ldap_conf.rootuse_sasl != false && ldap_conf.use_sasl == true)) { |
void *auth_id = ldap_conf.rootsasl_auth_id ? |
void *auth_id = ldap_conf.rootsasl_auth_id ? |
ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id; |
ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id; |
|
|
Line 1917 sudo_ldap_bind_s(LDAP *ld)
|
Line 2231 sudo_ldap_bind_s(LDAP *ld)
|
if (gss_krb5_ccache_name(&status, ldap_conf.krb5_ccname, &old_ccname) |
if (gss_krb5_ccache_name(&status, ldap_conf.krb5_ccname, &old_ccname) |
!= GSS_S_COMPLETE) { |
!= GSS_S_COMPLETE) { |
old_ccname = NULL; |
old_ccname = NULL; |
DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); | sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO, |
| "gss_krb5_ccache_name() failed: %d", status); |
} |
} |
# else |
# else |
setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE); | sudo_setenv("KRB5CCNAME", ldap_conf.krb5_ccname, true); |
# endif |
# endif |
} |
} |
rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI", |
rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI", |
Line 1928 sudo_ldap_bind_s(LDAP *ld)
|
Line 2243 sudo_ldap_bind_s(LDAP *ld)
|
if (ldap_conf.krb5_ccname != NULL) { |
if (ldap_conf.krb5_ccname != NULL) { |
# ifdef HAVE_GSS_KRB5_CCACHE_NAME |
# ifdef HAVE_GSS_KRB5_CCACHE_NAME |
if (gss_krb5_ccache_name(&status, old_ccname, NULL) != GSS_S_COMPLETE) |
if (gss_krb5_ccache_name(&status, old_ccname, NULL) != GSS_S_COMPLETE) |
DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); | sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO, |
| "gss_krb5_ccache_name() failed: %d", status); |
# else |
# else |
if (old_ccname != NULL) |
if (old_ccname != NULL) |
setenv("KRB5CCNAME", old_ccname, TRUE); | sudo_setenv("KRB5CCNAME", old_ccname, true); |
else |
else |
unsetenv("KRB5CCNAME"); | sudo_unsetenv("KRB5CCNAME"); |
# endif |
# endif |
} |
} |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_sasl_interactive_bind_s(): %s", |
warningx("ldap_sasl_interactive_bind_s(): %s", |
ldap_err2string(rc)); |
ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1); | DPRINTF1("ldap_sasl_interactive_bind_s() ok"); |
} else |
} else |
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ |
#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ |
#ifdef HAVE_LDAP_SASL_BIND_S |
#ifdef HAVE_LDAP_SASL_BIND_S |
Line 1955 sudo_ldap_bind_s(LDAP *ld)
|
Line 2271 sudo_ldap_bind_s(LDAP *ld)
|
NULL, NULL, NULL); |
NULL, NULL, NULL); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_sasl_bind_s(): %s", ldap_err2string(rc)); |
warningx("ldap_sasl_bind_s(): %s", ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_sasl_bind_s() ok"), 1); | DPRINTF1("ldap_sasl_bind_s() ok"); |
} |
} |
#else |
#else |
{ |
{ |
rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw); |
rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc)); |
warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_simple_bind_s() ok"), 1); | DPRINTF1("ldap_simple_bind_s() ok"); |
} |
} |
#endif |
#endif |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 1980 static int
|
Line 2296 static int
|
sudo_ldap_open(struct sudo_nss *nss) |
sudo_ldap_open(struct sudo_nss *nss) |
{ |
{ |
LDAP *ld; |
LDAP *ld; |
int rc, ldapnoinit = FALSE; | int rc; |
struct sudo_ldap_handle *handle; | bool ldapnoinit = false; |
| struct sudo_ldap_handle *handle; |
| debug_decl(sudo_ldap_open, SUDO_DEBUG_LDAP) |
|
|
if (!sudo_ldap_read_config()) |
if (!sudo_ldap_read_config()) |
return -1; | debug_return_int(-1); |
|
|
/* Prevent reading of user ldaprc and system defaults. */ |
/* Prevent reading of user ldaprc and system defaults. */ |
if (getenv("LDAPNOINIT") == NULL) { | if (sudo_getenv("LDAPNOINIT") == NULL) { |
ldapnoinit = TRUE; | ldapnoinit = true; |
setenv("LDAPNOINIT", "1", TRUE); | sudo_setenv("LDAPNOINIT", "1", true); |
} |
} |
|
|
|
/* Set global LDAP options */ |
|
if (sudo_ldap_set_options_global() < 0) |
|
debug_return_int(-1); |
|
|
/* Connect to LDAP server */ |
/* Connect to LDAP server */ |
#ifdef HAVE_LDAP_INITIALIZE |
#ifdef HAVE_LDAP_INITIALIZE |
if (ldap_conf.uri != NULL) { |
if (ldap_conf.uri != NULL) { |
char *buf = sudo_ldap_join_uri(ldap_conf.uri); |
char *buf = sudo_ldap_join_uri(ldap_conf.uri); |
DPRINTF(("ldap_initialize(ld, %s)", buf), 2); | DPRINTF2("ldap_initialize(ld, %s)", buf); |
rc = ldap_initialize(&ld, buf); |
rc = ldap_initialize(&ld, buf); |
efree(buf); |
efree(buf); |
|
if (rc != LDAP_SUCCESS) |
|
warningx(_("unable to initialize LDAP: %s"), ldap_err2string(rc)); |
} else |
} else |
#endif |
#endif |
rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port); |
rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port); |
if (rc != LDAP_SUCCESS) { | if (rc != LDAP_SUCCESS) |
warningx(_("unable to initialize LDAP: %s"), ldap_err2string(rc)); | debug_return_int(-1); |
return -1; | |
} | |
|
|
|
/* Set LDAP per-connection options */ |
|
if (sudo_ldap_set_options_conn(ld) < 0) |
|
debug_return_int(-1); |
|
|
if (ldapnoinit) |
if (ldapnoinit) |
unsetenv("LDAPNOINIT"); | sudo_unsetenv("LDAPNOINIT"); |
|
|
/* Set LDAP options */ |
|
if (sudo_ldap_set_options(ld) < 0) |
|
return -1; |
|
|
|
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { |
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { |
#if defined(HAVE_LDAP_START_TLS_S) |
#if defined(HAVE_LDAP_START_TLS_S) |
rc = ldap_start_tls_s(ld, NULL, NULL); |
rc = ldap_start_tls_s(ld, NULL, NULL); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_start_tls_s(): %s", ldap_err2string(rc)); |
warningx("ldap_start_tls_s(): %s", ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_start_tls_s() ok"), 1); | DPRINTF1("ldap_start_tls_s() ok"); |
#elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP) |
#elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP) |
if (ldap_ssl_client_init(NULL, NULL, 0, &rc) != LDAP_SUCCESS) { | if (ldap_ssl_client_init(ldap_conf.tls_keyfile, ldap_conf.tls_keypw, 0, &rc) != LDAP_SUCCESS) { |
warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc)); |
warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
rc = ldap_start_tls_s_np(ld, NULL); |
rc = ldap_start_tls_s_np(ld, NULL); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
warningx("ldap_start_tls_s_np(): %s", ldap_err2string(rc)); |
warningx("ldap_start_tls_s_np(): %s", ldap_err2string(rc)); |
return -1; | debug_return_int(-1); |
} |
} |
DPRINTF(("ldap_start_tls_s_np() ok"), 1); | DPRINTF1("ldap_start_tls_s_np() ok"); |
#else |
#else |
warningx(_("start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()")); |
warningx(_("start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()")); |
#endif /* !HAVE_LDAP_START_TLS_S && !HAVE_LDAP_START_TLS_S_NP */ |
#endif /* !HAVE_LDAP_START_TLS_S && !HAVE_LDAP_START_TLS_S_NP */ |
Line 2040 sudo_ldap_open(struct sudo_nss *nss)
|
Line 2362 sudo_ldap_open(struct sudo_nss *nss)
|
|
|
/* Actually connect */ |
/* Actually connect */ |
if (sudo_ldap_bind_s(ld) != 0) |
if (sudo_ldap_bind_s(ld) != 0) |
return -1; | debug_return_int(-1); |
|
|
/* Create a handle container. */ |
/* Create a handle container. */ |
handle = emalloc(sizeof(struct sudo_ldap_handle)); | handle = ecalloc(1, sizeof(struct sudo_ldap_handle)); |
handle->ld = ld; |
handle->ld = ld; |
handle->result = NULL; | /* handle->result = NULL; */ |
handle->username = NULL; | /* handle->username = NULL; */ |
handle->grlist = NULL; | /* handle->grlist = NULL; */ |
nss->handle = handle; |
nss->handle = handle; |
|
|
return 0; | debug_return_int(0); |
} |
} |
|
|
static int |
static int |
Line 2063 sudo_ldap_setdefs(struct sudo_nss *nss)
|
Line 2385 sudo_ldap_setdefs(struct sudo_nss *nss)
|
LDAPMessage *entry, *result; |
LDAPMessage *entry, *result; |
char *filt; |
char *filt; |
int rc; |
int rc; |
|
debug_decl(sudo_ldap_setdefs, SUDO_DEBUG_LDAP) |
|
|
if (handle == NULL || handle->ld == NULL) |
if (handle == NULL || handle->ld == NULL) |
return -1; | debug_return_int(-1); |
ld = handle->ld; |
ld = handle->ld; |
|
|
filt = sudo_ldap_build_default_filter(); |
filt = sudo_ldap_build_default_filter(); |
DPRINTF(("Looking for cn=defaults: %s", filt), 1); | DPRINTF1("Looking for cn=defaults: %s", filt); |
|
|
for (base = ldap_conf.base; base != NULL; base = base->next) { |
for (base = ldap_conf.base; base != NULL; base = base->next) { |
if (ldap_conf.timeout > 0) { |
if (ldap_conf.timeout > 0) { |
Line 2081 sudo_ldap_setdefs(struct sudo_nss *nss)
|
Line 2404 sudo_ldap_setdefs(struct sudo_nss *nss)
|
rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, |
rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, |
filt, NULL, 0, NULL, NULL, tvp, 0, &result); |
filt, NULL, 0, NULL, NULL, tvp, 0, &result); |
if (rc == LDAP_SUCCESS && (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); | DPRINTF1("found:%s", ldap_get_dn(ld, entry)); |
sudo_ldap_parse_options(ld, entry); |
sudo_ldap_parse_options(ld, entry); |
} else | } else { |
DPRINTF(("no default options found in %s", base->val), 1); | DPRINTF1("no default options found in %s", base->val); |
| } |
if (result) |
if (result) |
ldap_msgfree(result); |
ldap_msgfree(result); |
} |
} |
efree(filt); |
efree(filt); |
|
|
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 2105 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2428 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
LDAPMessage *entry; |
LDAPMessage *entry; |
int i, rc, setenv_implied; |
int i, rc, setenv_implied; |
struct ldap_result *lres = NULL; |
struct ldap_result *lres = NULL; |
|
debug_decl(sudo_ldap_lookup, SUDO_DEBUG_LDAP) |
|
|
if (handle == NULL || handle->ld == NULL) |
if (handle == NULL || handle->ld == NULL) |
return ret; | debug_return_int(ret); |
ld = handle->ld; |
ld = handle->ld; |
|
|
/* Fetch list of sudoRole entries that match user and host. */ |
/* Fetch list of sudoRole entries that match user and host. */ |
Line 2123 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2447 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
enum def_tuple pwcheck = |
enum def_tuple pwcheck = |
(pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; |
(pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; |
|
|
DPRINTF(("perform search for pwflag %d", pwflag), 1); | DPRINTF1("perform search for pwflag %d", pwflag); |
for (i = 0; i < lres->nentries; i++) { |
for (i = 0; i < lres->nentries; i++) { |
entry = lres->entries[i].entry; |
entry = lres->entries[i].entry; |
if ((pwcheck == any && doauth != FALSE) || | if ((pwcheck == any && doauth != false) || |
(pwcheck == all && doauth == FALSE)) { | (pwcheck == all && doauth == false)) { |
doauth = sudo_ldap_check_bool(ld, entry, "authenticate"); |
doauth = sudo_ldap_check_bool(ld, entry, "authenticate"); |
} |
} |
/* Only check the command when listing another user. */ |
/* Only check the command when listing another user. */ |
if (user_uid == 0 || list_pw == NULL || |
if (user_uid == 0 || list_pw == NULL || |
user_uid == list_pw->pw_uid || |
user_uid == list_pw->pw_uid || |
sudo_ldap_check_command(ld, entry, NULL)) { |
sudo_ldap_check_command(ld, entry, NULL)) { |
matched = TRUE; | matched = true; |
break; |
break; |
} |
} |
} |
} |
Line 2148 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2472 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
break; |
break; |
case all: |
case all: |
case any: |
case any: |
if (doauth == FALSE) | if (doauth == false) |
def_authenticate = FALSE; | def_authenticate = false; |
break; |
break; |
case never: |
case never: |
def_authenticate = FALSE; | def_authenticate = false; |
break; |
break; |
default: |
default: |
break; |
break; |
Line 2162 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2486 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
goto done; |
goto done; |
} |
} |
|
|
DPRINTF(("searching LDAP for sudoers entries"), 1); | DPRINTF1("searching LDAP for sudoers entries"); |
|
|
setenv_implied = FALSE; | setenv_implied = false; |
for (i = 0; i < lres->nentries; i++) { |
for (i = 0; i < lres->nentries; i++) { |
entry = lres->entries[i].entry; |
entry = lres->entries[i].entry; |
if (!sudo_ldap_check_runas(ld, entry)) |
if (!sudo_ldap_check_runas(ld, entry)) |
Line 2172 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2496 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
rc = sudo_ldap_check_command(ld, entry, &setenv_implied); |
rc = sudo_ldap_check_command(ld, entry, &setenv_implied); |
if (rc != UNSPEC) { |
if (rc != UNSPEC) { |
/* We have a match. */ |
/* We have a match. */ |
DPRINTF(("Command %sallowed", rc == TRUE ? "" : "NOT "), 1); | DPRINTF1("Command %sallowed", rc == true ? "" : "NOT "); |
if (rc == TRUE) { | if (rc == true) { |
DPRINTF(("LDAP entry: %p", entry), 1); | DPRINTF1("LDAP entry: %p", entry); |
/* Apply entry-specific options. */ |
/* Apply entry-specific options. */ |
if (setenv_implied) |
if (setenv_implied) |
def_setenv = TRUE; | def_setenv = true; |
sudo_ldap_parse_options(ld, entry); |
sudo_ldap_parse_options(ld, entry); |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
/* Set role and type if not specified on command line. */ |
/* Set role and type if not specified on command line. */ |
Line 2197 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
Line 2521 sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pw
|
} |
} |
|
|
done: |
done: |
DPRINTF(("done with LDAP searches"), 1); | DPRINTF1("done with LDAP searches"); |
DPRINTF(("user_matches=%d", lres->user_matches), 1); | DPRINTF1("user_matches=%d", lres->user_matches); |
DPRINTF(("host_matches=%d", lres->host_matches), 1); | DPRINTF1("host_matches=%d", lres->host_matches); |
|
|
if (!ISSET(ret, VALIDATE_OK)) { |
if (!ISSET(ret, VALIDATE_OK)) { |
/* No matching entries. */ |
/* No matching entries. */ |
Line 2210 done:
|
Line 2534 done:
|
CLR(ret, FLAG_NO_USER); |
CLR(ret, FLAG_NO_USER); |
if (lres->host_matches) |
if (lres->host_matches) |
CLR(ret, FLAG_NO_HOST); |
CLR(ret, FLAG_NO_HOST); |
DPRINTF(("sudo_ldap_lookup(%d)=0x%02x", pwflag, ret), 1); | DPRINTF1("sudo_ldap_lookup(%d)=0x%02x", pwflag, ret); |
|
|
return ret; | debug_return_int(ret); |
} |
} |
|
|
/* |
/* |
Line 2223 ldap_entry_compare(const void *a, const void *b)
|
Line 2547 ldap_entry_compare(const void *a, const void *b)
|
{ |
{ |
const struct ldap_entry_wrapper *aw = a; |
const struct ldap_entry_wrapper *aw = a; |
const struct ldap_entry_wrapper *bw = b; |
const struct ldap_entry_wrapper *bw = b; |
|
debug_decl(ldap_entry_compare, SUDO_DEBUG_LDAP) |
|
|
return bw->order < aw->order ? -1 : | debug_return_int(bw->order < aw->order ? -1 : |
(bw->order > aw->order ? 1 : 0); | (bw->order > aw->order ? 1 : 0)); |
} |
} |
|
|
/* |
/* |
Line 2237 static struct ldap_search_list *
|
Line 2562 static struct ldap_search_list *
|
sudo_ldap_result_last_search(struct ldap_result *lres) |
sudo_ldap_result_last_search(struct ldap_result *lres) |
{ |
{ |
struct ldap_search_list *result = lres->searches; |
struct ldap_search_list *result = lres->searches; |
|
debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP) |
|
|
if (result) { |
if (result) { |
while (result->next) |
while (result->next) |
result = result->next; |
result = result->next; |
} |
} |
return result; | debug_return_ptr(result); |
} |
} |
|
|
/* |
/* |
Line 2255 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
Line 2581 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
struct berval **bv; |
struct berval **bv; |
double order = 0.0; |
double order = 0.0; |
char *ep; |
char *ep; |
|
debug_decl(sudo_ldap_result_add_entry, SUDO_DEBUG_LDAP) |
|
|
/* Determine whether the entry has the sudoOrder attribute. */ |
/* Determine whether the entry has the sudoOrder attribute. */ |
last = sudo_ldap_result_last_search(lres); |
last = sudo_ldap_result_last_search(lres); |
Line 2262 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
Line 2589 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
if (bv != NULL) { |
if (bv != NULL) { |
if (ldap_count_values_len(bv) > 0) { |
if (ldap_count_values_len(bv) > 0) { |
/* Get the value of this attribute, 0 if not present. */ |
/* Get the value of this attribute, 0 if not present. */ |
DPRINTF(("order attribute raw: %s", (*bv)->bv_val), 1); | DPRINTF2("order attribute raw: %s", (*bv)->bv_val); |
order = strtod((*bv)->bv_val, &ep); |
order = strtod((*bv)->bv_val, &ep); |
if (ep == (*bv)->bv_val || *ep != '\0') { |
if (ep == (*bv)->bv_val || *ep != '\0') { |
warningx(_("invalid sudoOrder attribute: %s"), (*bv)->bv_val); |
warningx(_("invalid sudoOrder attribute: %s"), (*bv)->bv_val); |
order = 0.0; |
order = 0.0; |
} |
} |
DPRINTF(("order attribute: %f", order), 1); | DPRINTF2("order attribute: %f", order); |
} |
} |
ldap_value_free_len(bv); |
ldap_value_free_len(bv); |
} |
} |
Line 2287 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
Line 2614 sudo_ldap_result_add_entry(struct ldap_result *lres, L
|
lres->entries[lres->nentries - 1].entry = entry; |
lres->entries[lres->nentries - 1].entry = entry; |
lres->entries[lres->nentries - 1].order = order; |
lres->entries[lres->nentries - 1].order = order; |
|
|
return &lres->entries[lres->nentries - 1]; | debug_return_ptr(&lres->entries[lres->nentries - 1]); |
} |
} |
|
|
/* |
/* |
Line 2297 static void
|
Line 2624 static void
|
sudo_ldap_result_free_nss(struct sudo_nss *nss) |
sudo_ldap_result_free_nss(struct sudo_nss *nss) |
{ |
{ |
struct sudo_ldap_handle *handle = nss->handle; |
struct sudo_ldap_handle *handle = nss->handle; |
|
debug_decl(sudo_ldap_result_free_nss, SUDO_DEBUG_LDAP) |
|
|
if (handle->result != NULL) { |
if (handle->result != NULL) { |
DPRINTF(("removing reusable search result"), 1); | DPRINTF1("removing reusable search result"); |
sudo_ldap_result_free(handle->result); |
sudo_ldap_result_free(handle->result); |
if (handle->username) { |
if (handle->username) { |
efree(handle->username); |
efree(handle->username); |
Line 2308 sudo_ldap_result_free_nss(struct sudo_nss *nss)
|
Line 2636 sudo_ldap_result_free_nss(struct sudo_nss *nss)
|
handle->grlist = NULL; |
handle->grlist = NULL; |
handle->result = NULL; |
handle->result = NULL; |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 2323 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
Line 2652 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
struct timeval tv, *tvp = NULL; |
struct timeval tv, *tvp = NULL; |
LDAPMessage *entry, *result; |
LDAPMessage *entry, *result; |
LDAP *ld = handle->ld; |
LDAP *ld = handle->ld; |
int do_netgr, rc; | int pass, rc; |
char *filt; |
char *filt; |
|
debug_decl(sudo_ldap_result_get, SUDO_DEBUG_LDAP) |
|
|
/* |
/* |
* If we already have a cached result, return it so we don't have to |
* If we already have a cached result, return it so we don't have to |
Line 2333 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
Line 2663 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
if (handle->result) { |
if (handle->result) { |
if (handle->grlist == user_group_list && |
if (handle->grlist == user_group_list && |
strcmp(pw->pw_name, handle->username) == 0) { |
strcmp(pw->pw_name, handle->username) == 0) { |
DPRINTF(("reusing previous result (user %s) with %d entries", | DPRINTF1("reusing previous result (user %s) with %d entries", |
handle->username, handle->result->nentries), 1); | handle->username, handle->result->nentries); |
return handle->result; | debug_return_ptr(handle->result); |
} |
} |
/* User mismatch, cached result cannot be used. */ |
/* User mismatch, cached result cannot be used. */ |
DPRINTF(("removing result (user %s), new search (user %s)", | DPRINTF1("removing result (user %s), new search (user %s)", |
handle->username, pw->pw_name), 1); | handle->username, pw->pw_name); |
sudo_ldap_result_free_nss(nss); |
sudo_ldap_result_free_nss(nss); |
} |
} |
|
|
Line 2353 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
Line 2683 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
* sudoUser in this pass since the LDAP server already scanned |
* sudoUser in this pass since the LDAP server already scanned |
* it for us. |
* it for us. |
* |
* |
* The second pass will return all the entries that contain | * The second pass will return all the entries that contain non- |
* user netgroups. Then we take the netgroups returned and | * Unix groups, including netgroups. Then we take the non-Unix |
* try to match them against the username. | * groups returned and try to match them against the username. |
* |
* |
* Since we have to sort the possible entries before we make a |
* Since we have to sort the possible entries before we make a |
* decision, we perform the queries and store all of the results in |
* decision, we perform the queries and store all of the results in |
* an ldap_result object. The results are then sorted by sudoOrder. |
* an ldap_result object. The results are then sorted by sudoOrder. |
*/ |
*/ |
lres = sudo_ldap_result_alloc(); |
lres = sudo_ldap_result_alloc(); |
for (do_netgr = 0; do_netgr < 2; do_netgr++) { | for (pass = 0; pass < 2; pass++) { |
filt = do_netgr ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw); | filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw); |
DPRINTF(("ldap search '%s'", filt), 1); | DPRINTF1("ldap search '%s'", filt); |
for (base = ldap_conf.base; base != NULL; base = base->next) { |
for (base = ldap_conf.base; base != NULL; base = base->next) { |
DPRINTF(("searching from base '%s'", base->val), 1); | DPRINTF1("searching from base '%s'", |
| base->val); |
if (ldap_conf.timeout > 0) { |
if (ldap_conf.timeout > 0) { |
tv.tv_sec = ldap_conf.timeout; |
tv.tv_sec = ldap_conf.timeout; |
tv.tv_usec = 0; |
tv.tv_usec = 0; |
Line 2376 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
Line 2707 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt, |
rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt, |
NULL, 0, NULL, NULL, tvp, 0, &result); |
NULL, 0, NULL, NULL, tvp, 0, &result); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
DPRINTF(("nothing found for '%s'", filt), 1); | DPRINTF1("nothing found for '%s'", filt); |
continue; |
continue; |
} |
} |
lres->user_matches = TRUE; | lres->user_matches = true; |
|
|
/* Add the seach result to list of search results. */ |
/* Add the seach result to list of search results. */ |
DPRINTF(("adding search result"), 1); | DPRINTF1("adding search result"); |
sudo_ldap_result_add_search(lres, ld, result); |
sudo_ldap_result_add_search(lres, ld, result); |
LDAP_FOREACH(entry, ld, result) { |
LDAP_FOREACH(entry, ld, result) { |
if ((!do_netgr || | if ((!pass || |
sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && | sudo_ldap_check_non_unix_group(ld, entry, pw)) && |
sudo_ldap_check_host(ld, entry)) { |
sudo_ldap_check_host(ld, entry)) { |
lres->host_matches = TRUE; | lres->host_matches = true; |
sudo_ldap_result_add_entry(lres, entry); |
sudo_ldap_result_add_entry(lres, entry); |
} |
} |
} |
} |
DPRINTF(("result now has %d entries", lres->nentries), 1); | DPRINTF1("result now has %d entries", lres->nentries); |
} |
} |
efree(filt); |
efree(filt); |
} |
} |
|
|
/* Sort the entries by the sudoOrder attribute. */ |
/* Sort the entries by the sudoOrder attribute. */ |
DPRINTF(("sorting remaining %d entries", lres->nentries), 1); | DPRINTF1("sorting remaining %d entries", lres->nentries); |
qsort(lres->entries, lres->nentries, sizeof(lres->entries[0]), |
qsort(lres->entries, lres->nentries, sizeof(lres->entries[0]), |
ldap_entry_compare); |
ldap_entry_compare); |
|
|
Line 2407 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
Line 2738 sudo_ldap_result_get(struct sudo_nss *nss, struct pass
|
handle->username = estrdup(pw->pw_name); |
handle->username = estrdup(pw->pw_name); |
handle->grlist = user_group_list; |
handle->grlist = user_group_list; |
|
|
return lres; | debug_return_ptr(lres); |
} |
} |
|
|
/* |
/* |
Line 2417 static int
|
Line 2748 static int
|
sudo_ldap_close(struct sudo_nss *nss) |
sudo_ldap_close(struct sudo_nss *nss) |
{ |
{ |
struct sudo_ldap_handle *handle = nss->handle; |
struct sudo_ldap_handle *handle = nss->handle; |
|
debug_decl(sudo_ldap_close, SUDO_DEBUG_LDAP) |
|
|
if (handle != NULL) { |
if (handle != NULL) { |
/* Free the result before unbinding; it may use the LDAP connection. */ |
/* Free the result before unbinding; it may use the LDAP connection. */ |
Line 2432 sudo_ldap_close(struct sudo_nss *nss)
|
Line 2764 sudo_ldap_close(struct sudo_nss *nss)
|
efree(nss->handle); |
efree(nss->handle); |
nss->handle = NULL; |
nss->handle = NULL; |
} |
} |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 2477 sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *
|
Line 2809 sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *
|
LDAP_FOREACH(entry, last->ldap, last->searchresult) { |
LDAP_FOREACH(entry, last->ldap, last->searchresult) { |
sudo_ldap_result_add_entry(result, entry); |
sudo_ldap_result_add_entry(result, entry); |
} |
} |
DPRINTF(("sudo_ldap_result_from_search: %d entries found", | DPRINTF1("sudo_ldap_result_from_search: %d entries found", result->nentries); |
result->nentries), 2); | |
return result; |
return result; |
} |
} |
#endif |
#endif |