From: Thomas Reim <reimth@xxxxxxxxx> automounter only provides very limited debug information when binding using OpenLDAP. LDAP based directory services currently all increase communication security, which makes it difficult for system administrators to find the root cause of failed authentication binds. Allow users to switch on and configure debug logging for OpenLDAP client used by automount. Signed-off-by: Thomas Reim <reimth@xxxxxxxxx> --- daemon/automount.c | 31 ++++++++++++++++++++++++++----- include/log.h | 4 +++- lib/log.c | 9 ++++++++- man/automount.8 | 9 +++++++-- modules/lookup_ldap.c | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 9 deletions(-) diff --git a/daemon/automount.c b/daemon/automount.c index 32f95a5..ce79078 100644 --- a/daemon/automount.c +++ b/daemon/automount.c @@ -1413,6 +1413,21 @@ static unsigned long getnumopt(char *str, char option) return val; } +static long getsnumopt(char *str, char option) +{ + long val; + char *end; + + val = strtol(str, &end, 0); + if (!*str || *end) { + fprintf(stderr, + "%s: option -%c requires a numeric argument, got %s\n", + program, option, str); + exit(1); + } + return val; +} + static void do_master_cleanup_unlock(void *arg) { int status; @@ -2017,7 +2032,9 @@ static void usage(void) " maximum wait time (seconds) for master\n" " map to become available\n" " -v --verbose be verbose\n" - " -d --debug log debuging info\n" + " -d[level]\n" + " --debug[=level]\n" + " log debugging info\n" " -Dvariable=value, --define variable=value\n" " define global macro variable\n" " -S --systemd-service\n" @@ -2282,18 +2299,19 @@ int main(int argc, char *argv[]) int logpri = -1; unsigned int flags; unsigned int logging; + int debug_level = 0; unsigned master_read; int master_wait; time_t timeout; time_t age = monotonic_time(NULL); struct rlimit rlim; - const char *options = "+hp:t:vmdD:SfVrO:l:n:CFUM:"; + const char *options = "+hp:t:vmd::D:SfVrO:l:n:CFUM:"; static const struct option long_options[] = { {"help", 0, 0, 'h'}, {"pid-file", 1, 0, 'p'}, {"timeout", 1, 0, 't'}, {"verbose", 0, 0, 'v'}, - {"debug", 0, 0, 'd'}, + {"debug", 2, 0, 'd'}, {"define", 1, 0, 'D'}, {"systemd-service", 0, 0, 'S'}, {"foreground", 0, 0, 'f'}, @@ -2363,6 +2381,8 @@ int main(int argc, char *argv[]) case 'd': logging |= LOGOPT_DEBUG; + if (optarg) + debug_level = getsnumopt(optarg, opt); break; case 'D': @@ -2439,7 +2459,8 @@ int main(int argc, char *argv[]) case '?': case ':': - printf("%s: Ambiguous or unknown options\n", program); + fprintf(stderr, "%s: Ambiguous or unknown options\n", program); + fprintf(stderr, "Try `%s --help` for more information\n", program); exit(1); } } @@ -2448,7 +2469,7 @@ int main(int argc, char *argv[]) set_log_verbose(); if (logging & LOGOPT_DEBUG) - set_log_debug(); + set_log_debug(debug_level); if (geteuid() != 0) { fprintf(stderr, "%s: this program must be run by root.\n", diff --git a/include/log.h b/include/log.h index a7b09f9..3ec8f0c 100644 --- a/include/log.h +++ b/include/log.h @@ -31,12 +31,14 @@ struct autofs_point; extern void set_log_norm(void); extern void set_log_verbose(void); -extern void set_log_debug(void); +extern void set_log_debug(int level); extern void set_log_norm_ap(struct autofs_point *ap); extern void set_log_verbose_ap(struct autofs_point *ap); extern void set_log_debug_ap(struct autofs_point *ap); extern void set_mnt_logging(unsigned global_logopt); +extern int get_log_debug_level(void); + extern void open_log(void); extern void log_to_stderr(void); diff --git a/lib/log.c b/lib/log.c index 43eccc0..9567460 100644 --- a/lib/log.c +++ b/lib/log.c @@ -31,6 +31,7 @@ static unsigned int logging_to_syslog = 0; /* log notification level */ static unsigned int do_verbose = 0; /* Verbose feedback option */ static unsigned int do_debug = 0; /* Full debug output */ +static unsigned int debug_level = 0; /* Level for libldap debug output */ static char *prepare_attempt_prefix(const char *msg) { @@ -57,6 +58,11 @@ static char *prepare_attempt_prefix(const char *msg) return prefixed_msg; } +int get_log_debug_level(void) +{ + return debug_level; +} + void set_log_norm(void) { do_verbose = 0; @@ -70,9 +76,10 @@ void set_log_verbose(void) return; } -void set_log_debug(void) +void set_log_debug(int level) { do_debug = 1; + debug_level = level; return; } diff --git a/man/automount.8 b/man/automount.8 index 1061c9d..2d2b56f 100644 --- a/man/automount.8 +++ b/man/automount.8 @@ -48,9 +48,14 @@ Set the default timeout for caching failed key lookups. The default is 60 second Enables logging of general status and progress messages for all autofs managed mounts. .TP -.I "\-d, \-\-debug" +\fB\-d\fR[\fILEVEL\fR], \fB\-\-debug\fR[=\fILEVEL\fR] Enables logging of general status and progress messages as well as -debugging messages for all autofs managed mounts. +debugging messages for all autofs managed mounts. The default \fILEVEL\fR is 0. +automounter must perform OpenLDAP authenticated binds for optional argument +\fILEVEL\fR to have any effect. OpenLDAP uses a bitmap to enable debugging for +specific components. Debug \fILEVEL\fR=0 disables libldap deugging. +For further details see +.BR slapd (8). .TP .I "\-Dvariable=value, --define variable=value" Define a global macro substitution variable. Global definitions diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c index 3e43fc0..c174426 100644 --- a/modules/lookup_ldap.c +++ b/modules/lookup_ldap.c @@ -155,6 +155,18 @@ int ldap_parse_page_control(LDAP *ldap, LDAPControl **controls, } #endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */ +static void autofs_ldap_debug(const char *buf) +{ + char *msg; + + if (buf) { + msg = strdup(buf); + msg[strcspn(msg, "\n")] = '\0'; + log_debug(LOGOPT_DEBUG, "libldap: %s", msg); + free(msg); + } +} + static void ldapinit_mutex_lock(void) { int status = pthread_mutex_lock(&ldapinit_mutex); @@ -257,11 +269,36 @@ LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_conte LDAP *ldap = NULL; struct timeval timeout = { ctxt->timeout, 0 }; struct timeval net_timeout = { ctxt->network_timeout, 0 }; + int ldap_library_debug_level; int rv; ctxt->version = 3; + ldap_library_debug_level = get_log_debug_level(); + if (ldap_library_debug_level == -1 || ldap_library_debug_level > 0) { + rv = ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, + &ldap_library_debug_level); + if (rv != LBER_OPT_SUCCESS) + info(logopt, MODPREFIX + "failed to set LBER debug level to %d, ignored", + ldap_library_debug_level); + rv = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, + autofs_ldap_debug); + if (rv != LBER_OPT_SUCCESS) + info(logopt, MODPREFIX + "Failed to set LBER_OPT_LOG_PRINT_FN, ignored"); + rv = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, + &ldap_library_debug_level); + if (rv != LDAP_OPT_SUCCESS) + info(logopt, MODPREFIX + "failed to set LDAP debug level to %d, ignored", + ldap_library_debug_level); + } + /* Initialize the LDAP context. */ + debug(logopt, MODPREFIX + "ldap_initialize( %s )", + uri ? uri : "default"); rv = ldap_initialize(&ldap, uri); if (rv != LDAP_OPT_SUCCESS) { info(logopt, MODPREFIX -- 2.37.1