module_LTLIBRARIES = plugin/krb5_sync.la
plugin_krb5_sync_la_SOURCES = plugin/ad.c plugin/api.c plugin/config.c \
plugin/error.c plugin/internal.h plugin/heimdal.c plugin/instance.c \
- plugin/mit.c plugin/queue.c plugin/vector.c
+ plugin/logging.c plugin/mit.c plugin/queue.c plugin/vector.c
plugin_krb5_sync_la_CPPFLAGS = $(KADM5SRV_CPPFLAGS) $(LDAP_CPPFLAGS) \
$(AM_CPPFLAGS)
plugin_krb5_sync_la_LDFLAGS = -module -avoid-version $(KADM5SRV_LDFLAGS) \
Directory cause performance issues in kadmind or kpasswdd. kpasswd
clients in particular are often intolerant of delays.
+ Add a new boolean krb5.conf option, syslog, which can be set to false
+ to suppress syslog logging of the actions taken by the plugin and
+ error messages leading to queuing the change. Always log the error
+ that leads to queuing a status change.
+
Any time an Active Directory password change fails, queue the change
instead of failing it, rather than trying to distinguish between local
errors that should fail the change and errors that should be queued.
ad_queue_only = false
queue_dir = /var/spool/krb5-sync
+ syslog = true
}
It is possible to add realm-specific configuration here following the
you'll want to either change the path in that script or always use
the -d option.
+ syslog
+
+ Whether or not to log errors, warnings, and informational messages
+ from the plugin to syslog. By default, this is enabled. Set this
+ configuration option to false to suppress this logging, in which
+ case the only logging will be for errors returned to the kadmind or
+ kpasswdd servers.
+
With MIT Kerberos 1.9 or later, support for kadmind plugins is built in.
To load this plugin, add the following to the kdc.conf or krb5.conf file
used by kadmind:
#include <errno.h>
#include <lber.h>
#include <ldap.h>
-#include <syslog.h>
#include <plugin/internal.h>
#include <util/macros.h>
}
free(result_string.data);
free(result_code_string.data);
- syslog(LOG_INFO, "krb5-sync: %s password changed", target);
+ sync_syslog_info(config, "krb5-sync: %s password changed", target);
done:
krb5_cc_destroy(ctx, ccache);
/* Success. */
code = 0;
- syslog(LOG_INFO, "successfully %s account %s",
- enabled ? "enabled" : "disabled", target);
+ sync_syslog_info(config, "successfully %s account %s",
+ enabled ? "enabled" : "disabled", target);
done:
free(ldapuri);
#include <portable/system.h>
#include <errno.h>
-#include <syslog.h>
#include <plugin/internal.h>
#include <util/macros.h>
/* Get the directory for queued changes from krb5.conf. */
sync_config_string(ctx, "queue_dir", &config->queue_dir);
+ /* Whether to log informational and warning messages to syslog. */
+ config->syslog = true;
+ sync_config_boolean(ctx, "syslog", &config->syslog);
+
/* Initialized. Set data and return. */
*result = config;
return 0;
if (exists) {
code = krb5_unparse_name(ctx, principal, &display);
if (code != 0)
- display = NULL;
- syslog(LOG_DEBUG, "account synchronization skipping principal"
- " \"%s\" for Active Directory because %s instance exists",
- display != NULL ? display : "???",
- config->ad_base_instance);
- if (display != NULL)
- krb5_free_unparsed_name(ctx, display);
+ return code;
+ sync_syslog_debug(config, "krb5-sync: ignoring principal \"%s\""
+ " because %s instance exists", display,
+ config->ad_base_instance);
+ krb5_free_unparsed_name(ctx, display);
*allowed = false;
}
} else if (ncomp > 1) {
if (!instance_allowed(config, instance)) {
code = krb5_unparse_name(ctx, principal, &display);
if (code != 0)
- display = NULL;
- syslog(LOG_DEBUG, "account synchronization skipping principal"
- " \"%s\" with non-null instance for Active Directory",
- display != NULL ? display : "???");
- if (display != NULL)
- krb5_free_unparsed_name(ctx, display);
+ return code;
+ sync_syslog_debug(config, "krb5-sync: ignoring principal \"%s\""
+ " with non-null instance", display);
+ krb5_free_unparsed_name(ctx, display);
*allowed = false;
}
}
if (password == NULL)
return 0;
code = principal_allowed(config, ctx, principal, true, &allowed);
- if (code != 0) {
- message = krb5_get_error_message(ctx, code);
- syslog(LOG_WARNING, "krb5-sync: cannot check if password change"
- " should be propagated: %s", message);
- krb5_free_error_message(ctx, message);
+ if (code != 0)
return code;
- }
if (!allowed)
return 0;
code = sync_queue_conflict(config, ctx, principal, "enable", &conflict);
- if (code != 0) {
- message = krb5_get_error_message(ctx, code);
- syslog(LOG_WARNING, "krb5-sync: cannot check for queue conflicts: %s",
- message);
- krb5_free_error_message(ctx, message);
+ if (code != 0)
return code;
- }
if (conflict)
goto queue;
if (config->ad_queue_only)
code = sync_ad_chpass(config, ctx, principal, password);
if (code != 0) {
message = krb5_get_error_message(ctx, code);
- syslog(LOG_INFO, "krb5-sync: AD password change failed, queuing: %s",
- message);
+ sync_syslog_notice(config, "krb5-sync: AD password change failed,"
+ " queuing: %s", message);
krb5_free_error_message(ctx, message);
goto queue;
}
|| config->ad_realm == NULL)
return 0;
code = principal_allowed(config, ctx, principal, true, &allowed);
- if (code != 0) {
- message = krb5_get_error_message(ctx, code);
- syslog(LOG_WARNING, "krb5-sync: cannot check if password change"
- " should be propagated: %s", message);
- krb5_free_error_message(ctx, message);
+ if (code != 0)
return code;
- }
if (!allowed)
return 0;
code = sync_queue_conflict(config, ctx, principal, "enable", &conflict);
- if (code != 0) {
- message = krb5_get_error_message(ctx, code);
- syslog(LOG_WARNING, "krb5-sync: cannot check for queue conflicts: %s",
- message);
- krb5_free_error_message(ctx, message);
+ if (code != 0)
return code;
- }
if (conflict)
goto queue;
if (config->ad_queue_only)
goto queue;
code = sync_ad_status(config, ctx, principal, enabled);
- if (code != 0)
+ if (code != 0) {
+ message = krb5_get_error_message(ctx, code);
+ sync_syslog_notice(config, "krb5-sync: AD status change failed,"
+ " queuing: %s", message);
+ krb5_free_error_message(ctx, message);
goto queue;
+ }
return 0;
queue:
bool ad_queue_only;
char *ad_realm;
char *queue_dir;
+ bool syslog;
};
BEGIN_DECLS
krb5_error_code sync_error_system(krb5_context, const char *format, ...)
__attribute__((__nonnull__, __format__(printf, 2, 3)));
+/* Log messages to syslog if configured to do so. */
+void sync_syslog_debug(kadm5_hook_modinfo *, const char *format, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+void sync_syslog_info(kadm5_hook_modinfo *, const char *format, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+void sync_syslog_notice(kadm5_hook_modinfo *, const char *format, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+void sync_syslog_warning(kadm5_hook_modinfo *, const char *format, ...)
+ __attribute__((__nonnull__, __format__(printf, 2, 3)));
+
/* Undo default visibility change. */
#pragma GCC visibility pop
--- /dev/null
+/*
+ * Syslog logging.
+ *
+ * Functions to log informational and warning messages through syslog. There
+ * are cases, such as when we queue changes, where we want to log the reason
+ * but return success to kadmind or kpasswdd, which means that they won't log
+ * anything. In those cases, we log directly to syslog unless the syslog
+ * configuration option is set to false.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2013
+ * The Board of Trustees of the Leland Stanford Junior University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <syslog.h>
+
+#include <plugin/internal.h>
+
+
+/*
+ * Log a message to syslog. This is a helper function used to implement all
+ * of the syslog logging functions. If we can't allocate memory for the
+ * message to log, we just do nothing, since these functions are only used for
+ * supplemental logging.
+ */
+static void
+log_syslog(kadm5_hook_modinfo *config, int priority, const char *fmt,
+ va_list args)
+{
+ char *message;
+ int status;
+
+ /* If configured not to log, do nothing. */
+ if (!config->syslog)
+ return;
+
+ /* Log the message. */
+ status = vasprintf(&message, fmt, args);
+ if (status < 0)
+ return;
+ syslog(priority, "%s", message);
+ free(message);
+}
+
+
+/*
+ * Generate the functions for the various priority levels we use.
+ */
+#define SYSLOG_FUNCTION(name, type) \
+ void \
+ sync_syslog_ ## name(kadm5_hook_modinfo *c, const char *f, ...) \
+ { \
+ va_list args; \
+ va_start(args, f); \
+ log_syslog(c, LOG_ ## type, f, args); \
+ va_end(args); \
+ }
+SYSLOG_FUNCTION(debug, DEBUG)
+SYSLOG_FUNCTION(info, INFO)
+SYSLOG_FUNCTION(notice, NOTICE)
+SYSLOG_FUNCTION(warning, WARNING)
ad_instances = exclude
queue_dir = queue
+ syslog = false
}
[libdefaults]
ad_queue_only = true
queue_dir = queue
+ syslog = false
}
[libdefaults]