1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*
* Heimdal shared module API.
*
* This is the glue required to connect a Heimdal kadmin hook module to the
* API for the krb5-sync module. It is based on a preliminary proposal for
* the Heimdal hook API, so the interface exposed here may change in the
* future.
*
* Written by Russ Allbery <eagle@eyrie.org>
* Copyright 2010, 2013
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
#include <config.h>
#include <portable/kadmin.h>
#include <portable/krb5.h>
#include <portable/system.h>
#include <errno.h>
#include <plugin/internal.h>
#include <util/macros.h>
#define KADM5_HOOK_VERSION_V0 0
enum kadm5_hook_stage {
KADM5_HOOK_STAGE_PRECOMMIT,
KADM5_HOOK_STAGE_POSTCOMMIT
};
typedef struct kadm5_hook {
const char *name;
int version;
const char *vendor;
krb5_error_code (*init)(krb5_context, void **);
void (*fini)(krb5_context, void *);
krb5_error_code (*chpass)(krb5_context, void *, enum kadm5_hook_stage,
krb5_principal, const char *);
krb5_error_code (*create)(krb5_context, void *, enum kadm5_hook_stage,
kadm5_principal_ent_t, uint32_t mask,
const char *password);
krb5_error_code (*modify)(krb5_context, void *, enum kadm5_hook_stage,
kadm5_principal_ent_t, uint32_t mask);
} kadm5_hook;
/*
* Initialize the plugin. Calls the pwupdate_init() function and returns the
* resulting data object.
*/
static krb5_error_code
init(krb5_context ctx, void **data)
{
return sync_init(ctx, (kadm5_hook_modinfo **) data);
}
/*
* Shut down the object, freeing any internal resources.
*/
static void
fini(krb5_context ctx, void *data)
{
sync_close(ctx, data);
}
/*
* Handle a password change.
*/
static krb5_error_code
chpass(krb5_context ctx, void *data, enum kadm5_hook_stage stage,
krb5_principal princ, const char *password)
{
/*
* If password is NULL, we have a new key set but no password (meaning
* this is an operation such as add -r). We can't do anything without a
* password, so ignore these cases.
*/
if (password == NULL)
return 0;
/* Dispatch to the appropriate function. */
if (stage == KADM5_HOOK_STAGE_PRECOMMIT)
return sync_chpass(data, ctx, princ, password);
else
return 0;
}
/*
* Handle a principal creation.
*
* We only care about synchronizing the password, so we just call the same
* hooks as we did for a password change.
*/
static krb5_error_code
create(krb5_context ctx, void *data, enum kadm5_hook_stage stage,
kadm5_principal_ent_t entry, uint32_t mask UNUSED,
const char *password)
{
return chpass(ctx, data, stage, entry->principal, password);
}
/*
* Handle a principal modification.
*
* We only care about changes to the DISALLOW_ALL_TIX flag, and we only
* support status postcommit. Check whether that's what's being changed and
* call the appropriate hook.
*/
static krb5_error_code
modify(krb5_context ctx, void *data, enum kadm5_hook_stage stage,
kadm5_principal_ent_t entry, uint32_t mask)
{
bool enabled;
if (mask & KADM5_ATTRIBUTES && stage == KADM5_HOOK_STAGE_POSTCOMMIT) {
enabled = !(entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX);
return sync_status(data, ctx, entry->principal, enabled);
}
return 0;
}
/* The public symbol that Heimdal looks for. */
struct kadm5_hook kadm5_hook_v0 = {
"krb5-sync",
KADM5_HOOK_VERSION_V0,
"Russ Allbery",
init,
fini,
chpass,
create,
modify
};
|