* Kerberos error code on failure.
*/
static krb5_error_code
-get_ad_principal(krb5_context ctx, struct plugin_config *config,
+get_ad_principal(struct plugin_config *config, krb5_context ctx,
krb5_const_principal principal, krb5_principal *ad_principal)
{
krb5_error_code ret;
return 1;
/* Get the corresponding Active Directory principal. */
- ret = get_ad_principal(ctx, config, principal, &ad_principal);
+ ret = get_ad_principal(config, ctx, principal, &ad_principal);
if (ret != 0) {
pwupdate_set_error(errstr, errstrlen, ctx, ret,
"unable to get AD principal");
* the AD principal and then query Active Directory via LDAP to get back
* the CN for the user to construct the full DN.
*/
- ret = get_ad_principal(ctx, config, principal, &ad_principal);
+ ret = get_ad_principal(config, ctx, principal, &ad_principal);
if (ret != 0) {
pwupdate_set_error(errstr, errstrlen, ctx, ret,
"unable to get AD principal");
* This function returns failure only if it could not allocate memory.
*/
int
-pwupdate_init(krb5_context ctx, void **data)
+pwupdate_init(struct plugin_config **result, krb5_context ctx)
{
struct plugin_config *config;
sync_config_string(ctx, "queue_dir", &config->queue_dir);
/* Initialized. Set data and return. */
- *data = config;
+ *result = config;
return 0;
}
* since we don't store any other local state.
*/
void
-pwupdate_close(void *data)
+pwupdate_close(struct plugin_config *config)
{
- struct plugin_config *config = data;
-
if (config->ad_keytab != NULL)
free(config->ad_keytab);
if (config->ad_principal != NULL)
}
-/*
- * Create a local Kerberos context and set the error appropriately if this
- * fails. Return true on success, false otherwise. Puts the error message in
- * errstr on failure.
- */
-static int
-create_context(krb5_context *ctx, char *errstr, int errstrlen)
-{
- krb5_error_code ret;
-
- ret = krb5_init_context(ctx);
- if (ret != 0) {
- pwupdate_set_error(errstr, errstrlen, *ctx, ret,
- "failure initializing Kerberos library");
- return 0;
- }
- return 1;
-}
-
-
/*
* Given the list of allowed principals as a space-delimited string and the
* instance of a principal, returns true if that instance is allowed and false
* Otherwise, if the principal is multi-part, check the instance.
*/
if (pwchange && ncomp == 1 && config->ad_base_instance != NULL) {
- okay = !pwupdate_instance_exists(principal, config->ad_base_instance);
+ okay = !pwupdate_instance_exists(config, ctx, principal,
+ config->ad_base_instance);
if (!okay) {
code = krb5_unparse_name(ctx, principal, &display);
if (code != 0)
* Currently, we can't do anything in that case, so just skip it.
*/
int
-pwupdate_precommit_password(void *data, krb5_principal principal,
+pwupdate_precommit_password(struct plugin_config *config, krb5_context ctx,
+ krb5_principal principal,
const char *password, int pwlen,
char *errstr, int errstrlen)
{
- struct plugin_config *config = data;
- krb5_context ctx;
int status;
if (config->ad_realm == NULL)
return 0;
if (password == NULL)
return 0;
- if (!create_context(&ctx, errstr, errstrlen))
- return 1;
if (!principal_allowed(config, ctx, principal, 1))
return 0;
if (pwupdate_queue_conflict(config, ctx, principal, "ad", "password"))
errstr);
goto queue;
}
- krb5_free_context(ctx);
return status;
queue:
status = pwupdate_queue_write(config, ctx, principal, "ad", "password",
password);
- krb5_free_context(ctx);
if (status)
return 0;
else {
* Currently, there are none.
*/
int
-pwupdate_postcommit_password(void *data UNUSED,
+pwupdate_postcommit_password(struct plugin_config *config UNUSED,
+ krb5_context ctx UNUSED,
krb5_principal principal UNUSED,
const char *password UNUSED, int pwlen UNUSED,
char *errstr UNUSED, int errstrlen UNUSED)
* queue it for later processing.
*/
int
-pwupdate_postcommit_status(void *data, krb5_principal principal, int enabled,
+pwupdate_postcommit_status(struct plugin_config *config, krb5_context ctx,
+ krb5_principal principal, int enabled,
char *errstr, int errstrlen)
{
- struct plugin_config *config = data;
- krb5_context ctx;
int status;
if (config->ad_admin_server == NULL
|| config->ad_principal == NULL
|| config->ad_realm == NULL)
return 0;
- if (!create_context(&ctx, errstr, errstrlen))
- return 1;
if (!principal_allowed(config, ctx, principal, 0))
return 0;
if (pwupdate_queue_conflict(config, ctx, principal, "ad", "enable"))
errstrlen);
if (status != 0)
goto queue;
- krb5_free_context(ctx);
return status;
queue:
status = pwupdate_queue_write(config, ctx, principal, "ad",
enabled ? "enable" : "disable", NULL);
- krb5_free_context(ctx);
if (status)
return 0;
else {
{
krb5_error_code code = 0;
- if (pwupdate_init(ctx, data) != 0)
+ if (pwupdate_init((struct plugin_config **) data, ctx) != 0)
code = errno;
return code;
}
/* Dispatch to the appropriate function. */
if (stage == KADM5_HOOK_STAGE_PRECOMMIT)
- status = pwupdate_precommit_password(data, princ, password, length,
- error, sizeof(error));
+ status = pwupdate_precommit_password(data, ctx, princ, password,
+ length, error, sizeof(error));
else if (stage == KADM5_HOOK_STAGE_POSTCOMMIT)
- status = pwupdate_postcommit_password(data, princ, password, length,
- error, sizeof(error));
+ status = pwupdate_postcommit_password(data, ctx, princ, password,
+ length, error, sizeof(error));
if (status == 0)
return 0;
else {
if (mask & KADM5_ATTRIBUTES && stage == KADM5_HOOK_STAGE_POSTCOMMIT) {
enabled = !(entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX);
- status = pwupdate_postcommit_status(data, entry->principal, enabled,
- error, sizeof(error));
+ status = pwupdate_postcommit_status(data, ctx, entry->principal,
+ enabled, error, sizeof(error));
if (status == 0)
return 0;
else {
* or on any other error.
*/
int
-pwupdate_instance_exists(krb5_principal base, const char *instance)
+pwupdate_instance_exists(struct plugin_config *config UNUSED,
+ krb5_context ctx, krb5_principal base,
+ const char *instance)
{
- krb5_context ctx;
krb5_principal princ = NULL;
krb5_error_code code;
const char *realm;
int mask;
kadm5_principal_ent_rec ent;
- /* Get a Kerberos context. Eventually, this will be passed in. */
- code = krb5_init_context(&ctx);
- if (code != 0)
- return 0;
-
/* Principals must have exactly one component. */
if (krb5_principal_get_num_comp(ctx, base) != 1)
return 0;
kadm5_destroy(handle);
krb5_free_principal(ctx, princ);
princ = NULL;
- krb5_free_context(ctx);
return (code == 0);
fail:
krb5_free_principal(ctx, princ);
- krb5_free_context(ctx);
return 0;
}
#pragma GCC visibility push(hidden)
/* General public API. */
-int pwupdate_init(krb5_context ctx, void **data);
-void pwupdate_close(void *data);
-int pwupdate_precommit_password(void *data, krb5_principal principal,
- const char *password, int pwlen,
- char *errstr, int errstrlen);
-int pwupdate_postcommit_password(void *data, krb5_principal principal,
- const char *password, int pwlen,
- char *errstr, int errstrlen);
-int pwupdate_postcommit_status(void *data, krb5_principal principal,
- int enabled, char *errstr, int errstrlen);
+int pwupdate_init(struct plugin_config **, krb5_context);
+void pwupdate_close(struct plugin_config *);
+int pwupdate_precommit_password(struct plugin_config *, krb5_context,
+ krb5_principal, const char *password,
+ int pwlen, char *errstr, int errstrlen);
+int pwupdate_postcommit_password(struct plugin_config *, krb5_context,
+ krb5_principal, const char *password,
+ int pwlen, char *errstr, int errstrlen);
+int pwupdate_postcommit_status(struct plugin_config *, krb5_context,
+ krb5_principal, int enabled, char *errstr,
+ int errstrlen);
/* Password changing. */
-int pwupdate_ad_change(struct plugin_config *config, krb5_context ctx,
- krb5_principal principal, const char *password,
- int pwlen, char *errstr, int errstrlen);
+int pwupdate_ad_change(struct plugin_config *, krb5_context, krb5_principal,
+ const char *password, int pwlen, char *errstr,
+ int errstrlen);
/* Account status update. */
-int pwupdate_ad_status(struct plugin_config *config, krb5_context ctx,
- krb5_principal principal, int enabled, char *errstr,
- int errstrlen);
+int pwupdate_ad_status(struct plugin_config *, krb5_context, krb5_principal,
+ int enabled, char *errstr, int errstrlen);
/* Instance lookups. */
-int pwupdate_instance_exists(krb5_principal principal, const char *instance);
+int pwupdate_instance_exists(struct plugin_config *, krb5_context,
+ krb5_principal, const char *instance);
/* Queuing. */
-int pwupdate_queue_conflict(struct plugin_config *config, krb5_context ctx,
- krb5_principal principal, const char *domain,
+int pwupdate_queue_conflict(struct plugin_config *, krb5_context,
+ krb5_principal, const char *domain,
const char *operation);
-int pwupdate_queue_write(struct plugin_config *config, krb5_context ctx,
- krb5_principal principal, const char *domain,
- const char *operation, const char *password);
+int pwupdate_queue_write(struct plugin_config *, krb5_context, krb5_principal,
+ const char *domain, const char *operation,
+ const char *password);
/* Error handling. */
void pwupdate_set_error(char *, size_t, krb5_context, krb5_error_code,
{
krb5_error_code code = 0;
- if (pwupdate_init(ctx, (void **) data) != 0)
+ if (pwupdate_init((struct plugin_config **) data, ctx) != 0)
code = errno;
return code;
}
static void
fini(krb5_context ctx UNUSED, kadm5_hook_modinfo *data)
{
- pwupdate_close(data);
+ pwupdate_close((struct plugin_config *) data);
}
/* Dispatch to the appropriate function. */
length = strlen(password);
if (stage == KADM5_HOOK_STAGE_PRECOMMIT)
- status = pwupdate_precommit_password(data, princ, password, length,
- error, sizeof(error));
+ status = pwupdate_precommit_password((struct plugin_config *) data,
+ ctx, princ, password,
+ length, error, sizeof(error));
else if (stage == KADM5_HOOK_STAGE_POSTCOMMIT)
- status = pwupdate_postcommit_password(data, princ, password, length,
- error, sizeof(error));
+ status = pwupdate_postcommit_password((struct plugin_config *) data,
+ ctx, princ, password,
+ length, error, sizeof(error));
if (status == 0)
return 0;
else {
if (mask & KADM5_ATTRIBUTES && stage == KADM5_HOOK_STAGE_POSTCOMMIT) {
enabled = !(entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX);
- status = pwupdate_postcommit_status(data, entry->principal, enabled,
- error, sizeof(error));
+ status = pwupdate_postcommit_status((struct plugin_config *) data,
+ ctx, entry->principal,
+ enabled, error, sizeof(error));
if (status == 0)
return 0;
else {
krb5_context ctx;
krb5_principal princ;
krb5_error_code code;
- void *data;
+ struct plugin_config *config;
char errstr[BUFSIZ], buffer[BUFSIZ];
time_t now, try;
struct tm *date;
plan(27);
/* Test init. */
- is_int(0, pwupdate_init(ctx, &data), "pwupdate_init succeeds");
- ok(data != NULL, "...and data is non-NULL");
+ is_int(0, pwupdate_init(&config, ctx), "pwupdate_init succeeds");
+ ok(config != NULL, "...and config is non-NULL");
/* Create a password change and be sure it's queued. */
errstr[0] = '\0';
- code = pwupdate_precommit_password(data, princ, "foobar", strlen("foobar"),
- errstr, sizeof(errstr));
+ code = pwupdate_precommit_password(config, ctx, princ, "foobar",
+ strlen("foobar"), errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_precommit_password succeeds");
is_string("", errstr, "...and there is no error string");
queue = NULL;
/* Test queuing of enable. */
errstr[0] = '\0';
- code = pwupdate_postcommit_status(data, princ, 1, errstr, sizeof(errstr));
+ code = pwupdate_postcommit_status(config, ctx, princ, 1, errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_status enable succeeds");
is_string("", errstr, "...and there is no error");
queue = NULL;
ok(unlink(queue) == 0, "Remove queued enable");
/* Test queuing of disable. */
- errstr[0] = '\0';
- code = pwupdate_postcommit_status(data, princ, 0, errstr, sizeof(errstr));
+ errstr[0] = '\0';
+ code = pwupdate_postcommit_status(config, ctx, princ, 0, errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_status disable succeeds");
is_string("", errstr, "...and there is no error");
queue = NULL;
ok(rmdir("queue") == 0, "No other files in queue directory");
/* Shut down the plugin. */
- pwupdate_close(data);
+ pwupdate_close(config);
/* Clean up. */
krb5_free_principal(ctx, princ);
* to queue.
*
* Written by Russ Allbery <eagle@eyrie.org>
- * Copyright 2012
+ * Copyright 2012, 2013
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
krb5_context ctx;
krb5_principal princ;
krb5_error_code code;
- void *data;
+ struct plugin_config *data;
int fd;
char errstr[BUFSIZ], buffer[BUFSIZ];
time_t now, try;
plan(42);
/* Test init. */
- is_int(0, pwupdate_init(ctx, &data), "pwupdate_init succeeds");
+ is_int(0, pwupdate_init(&data, ctx), "pwupdate_init succeeds");
ok(data != NULL, "...and data is non-NULL");
/* Block processing for our test user and then test password change. */
sysbail("cannot create fake queue file");
close(fd);
errstr[0] = '\0';
- code = pwupdate_precommit_password(data, princ, "foobar", strlen("foobar"),
- errstr, sizeof(errstr));
+ code = pwupdate_precommit_password(data, ctx, princ, "foobar",
+ strlen("foobar"), errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_precommit_password succeeds");
ok(access("queue/.lock", F_OK) == 0, "...lock file now exists");
is_string("", errstr, "...and there is no error");
/* pwupdate_postcommit_password should do nothing, silently. */
errstr[0] = '\0';
- code = pwupdate_postcommit_password(data, princ, "foobar",
+ code = pwupdate_postcommit_password(data, ctx, princ, "foobar",
strlen("foobar"), errstr,
sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_password succeeds");
sysbail("cannot create fake queue file");
close(fd);
errstr[0] = '\0';
- code = pwupdate_postcommit_status(data, princ, 1, errstr, sizeof(errstr));
+ code = pwupdate_postcommit_status(data, ctx, princ, 1, errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_status enable succeeds");
is_string("", errstr, "...and there is no error");
queue = NULL;
* same marker.
*/
errstr[0] = '\0';
- code = pwupdate_postcommit_status(data, princ, 0, errstr, sizeof(errstr));
+ code = pwupdate_postcommit_status(data, ctx, princ, 0, errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_status disable succeeds");
is_string("", errstr, "...and there is no error");
queue = NULL;
/* Check failure when there's no queue directory. */
errstr[0] = '\0';
- code = pwupdate_precommit_password(data, princ, "foobar", strlen("foobar"),
- errstr, sizeof(errstr));
+ code = pwupdate_precommit_password(data, ctx, princ, "foobar",
+ strlen("foobar"), errstr,
+ sizeof(errstr));
is_int(1, code, "pwupdate_precommit_password fails with no queue");
is_string("queueing AD password change failed", errstr,
"...with correct error");
- code = pwupdate_postcommit_status(data, princ, 0, errstr, sizeof(errstr));
+ code = pwupdate_postcommit_status(data, ctx, princ, 0, errstr,
+ sizeof(errstr));
is_int(1, code, "pwupdate_postcommit_status disable fails with no queue");
is_string("queueing AD status change failed", errstr,
"...with correct error");
code = krb5_parse_name(ctx, "test@EXAMPLE.COM", &princ);
if (code != 0)
bail("cannot parse principal: %s", krb5_get_error_message(ctx, code));
- is_int(0, pwupdate_init(ctx, &data), "pwupdate_init succeeds");
+ is_int(0, pwupdate_init(&data, ctx), "pwupdate_init succeeds");
ok(data != NULL, "...and data is non-NULL");
errstr[0] = '\0';
- code = pwupdate_precommit_password(data, princ, "foobar", strlen("foobar"),
- errstr, sizeof(errstr));
+ code = pwupdate_precommit_password(data, ctx, princ, "foobar",
+ strlen("foobar"), errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_precommit_password succeeds");
is_string("", errstr, "...and there is no error");
errstr[0] = '\0';
- code = pwupdate_postcommit_status(data, princ, 0, errstr, sizeof(errstr));
+ code = pwupdate_postcommit_status(data, ctx, princ, 0, errstr,
+ sizeof(errstr));
is_int(0, code, "pwupdate_postcommit_status disable succeeds");
is_string("", errstr, "...and there is no error");
* Written by Russ Allbery <eagle@eyrie.org>
* Based on code developed by Derrick Brashear and Ken Hornstein of Sine
* Nomine Associates, on behalf of Stanford University
- * Copyright 2006, 2007, 2010, 2012
+ * Copyright 2006, 2007, 2010, 2012, 2013
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
* successful, and exit with an error message if we weren't.
*/
static void
-ad_password(void *data, krb5_context ctx, krb5_principal principal,
- char *password, const char *user)
+ad_password(struct plugin_config *data, krb5_context ctx,
+ krb5_principal principal, char *password, const char *user)
{
char errbuf[BUFSIZ];
int status;
* we were successful, and exit with an error message if we weren't.
*/
static void
-ad_status(void *data, krb5_context ctx, krb5_principal principal, bool enable,
- const char *user)
+ad_status(struct plugin_config *data, krb5_context ctx,
+ krb5_principal principal, bool enable, const char *user)
{
char errbuf[BUFSIZ];
int status;
* supported for AFS.
*/
static void
-process_queue_file(void *data, krb5_context ctx, const char *filename)
+process_queue_file(struct plugin_config *data, krb5_context ctx,
+ const char *filename)
{
FILE *queue;
char buffer[BUFSIZ];
char *password = NULL;
char *filename = NULL;
char *user;
- void *data;
+ struct plugin_config *config;
krb5_context ctx;
krb5_error_code ret;
krb5_principal principal;
die_krb5(ctx, ret, "cannot initialize Kerberos context");
/* Initialize the plugin. */
- if (pwupdate_init(ctx, &data))
+ if (pwupdate_init(&config, ctx))
die("plugin initialization failed");
/* Now, do whatever we were supposed to do. */
if (filename != NULL)
- process_queue_file(data, ctx, filename);
+ process_queue_file(config, ctx, filename);
else {
ret = krb5_parse_name(ctx, user, &principal);
if (ret != 0)
die_krb5(ctx, ret, "cannot parse user %s into principal", user);
if (password != NULL)
- ad_password(data, ctx, principal, password, user);
+ ad_password(config, ctx, principal, password, user);
if (enable || disable)
- ad_status(data, ctx, principal, enable, user);
+ ad_status(config, ctx, principal, enable, user);
}
exit(0);