aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Coffman <kwc@citi.umich.edu>2007-03-06 15:31:40 +0000
committerKevin Coffman <kwc@citi.umich.edu>2007-03-06 15:31:40 +0000
commit188f315fa1861dc1bafc9f1d0e3662968753f893 (patch)
tree6f8ad80a5f1d12f3cfdeafb39c9af39a2382648a
parent6a47113c611c962b01d813ecaf0f2eb7e715cb54 (diff)
downloadkrb5-188f315fa1861dc1bafc9f1d0e3662968753f893.zip
krb5-188f315fa1861dc1bafc9f1d0e3662968753f893.tar.gz
krb5-188f315fa1861dc1bafc9f1d0e3662968753f893.tar.bz2
Allow pkinit to support multiple realms within a single KDC.
Allow per-realm pkinit configuration. - include/krb5/preauth_plugin.h Add NULL-terminated realm name list to preauth_server_init_proc interface. - kdc/kdc_preauth.c Construct realm name list and pass it to preauth_server_init_proc (and free it). - plugins/preauth/pkinit/pkinit.h Add realmname and name length to kdc (per-realm) plugin context. Change interface to config/profile routines to pass the realm name. - plugins/preauth/pkinit/pkinit_crypto_openssl.c Restructure the init/fini functions a bit. Make sure OBJ_cleanup() is only called once by using a refcount. - plugins/preauth/pkinit/pkinit_profile.c Change routines to pass in realm name rather than depending on default_realm being set in the context. - plugins/preauth/pkinit/pkinit_srv.c Create a plugin context for each realm that should be supported. Add function to find the correct realm context. Call it at the beginning of each major preauth function (get_edata, verify_padata, return_padata). git-svn-id: svn://anonsvn.mit.edu/krb5/users/coffman/pkinit@19209 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/include/krb5/preauth_plugin.h4
-rw-r--r--src/kdc/kdc_preauth.c18
-rw-r--r--src/plugins/preauth/pkinit/pkinit.h14
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto_openssl.c95
-rw-r--r--src/plugins/preauth/pkinit/pkinit_profile.c57
-rw-r--r--src/plugins/preauth/pkinit/pkinit_srv.c233
6 files changed, 296 insertions, 125 deletions
diff --git a/src/include/krb5/preauth_plugin.h b/src/include/krb5/preauth_plugin.h
index ef12840..f1106e4 100644
--- a/src/include/krb5/preauth_plugin.h
+++ b/src/include/krb5/preauth_plugin.h
@@ -337,7 +337,9 @@ typedef krb5_error_code
/* Preauth plugin initialization function */
typedef krb5_error_code
-(*preauth_server_init_proc)(krb5_context context, void **plugin_context);
+(*preauth_server_init_proc)(krb5_context context,
+ void **plugin_context,
+ const char** realmnames);
/* Preauth plugin cleanup function */
typedef void
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index e6c0e55..324b746 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -271,6 +271,7 @@ load_preauth_plugins(krb5_context context)
int module_count, i, j, k;
void *plugin_context;
preauth_server_init_proc server_init_proc = NULL;
+ char **kdc_realm_names = NULL;
memset(&err, 0, sizeof(err));
@@ -320,6 +321,18 @@ load_preauth_plugins(krb5_context context)
return ENOMEM;
}
+ /* Build a list of the names of the supported realms for this KDC.
+ * The list of names is terminated with a NULL. */
+ kdc_realm_names = malloc(sizeof(char *) * (kdc_numrealms + 1));
+ if (kdc_realm_names == NULL) {
+ krb5int_free_plugin_dir_data(preauth_plugins_ftables);
+ return ENOMEM;
+ }
+ for (i = 0; i < kdc_numrealms; i++) {
+ kdc_realm_names[i] = kdc_realmlist[i]->realm_name;
+ }
+ kdc_realm_names[i] = NULL;
+
/* Add the locally-supplied mechanisms to the dynamic list first. */
for (i = 0, k = 0;
i < sizeof(static_preauth_systems) / sizeof(static_preauth_systems[0]);
@@ -332,7 +345,7 @@ load_preauth_plugins(krb5_context context)
plugin_context = NULL;
server_init_proc = static_preauth_systems[i].init;
if ((server_init_proc != NULL) &&
- ((*server_init_proc)(context, &plugin_context) != 0)) {
+ ((*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names) != 0)) {
memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
continue;
}
@@ -361,7 +374,7 @@ load_preauth_plugins(krb5_context context)
server_init_proc = ftable->init_proc;
if (server_init_proc != NULL) {
krb5_error_code initerr;
- initerr = (*server_init_proc)(context, &plugin_context);
+ initerr = (*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names);
if (initerr) {
const char *emsg;
emsg = krb5_get_error_message(context, initerr);
@@ -400,6 +413,7 @@ load_preauth_plugins(krb5_context context)
}
krb5int_free_plugin_dir_data(preauth_plugins_ftables);
}
+ free(kdc_realm_names);
n_preauth_systems = k;
/* Add the end-of-list marker. */
preauth_systems[k].name = "[end]";
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index 19dbb53..f8048ba 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -177,7 +177,7 @@ struct _pkinit_req_context {
};
/*
- * KDC's plugin context
+ * KDC's (per-realm) plugin context
*/
struct _pkinit_kdc_context {
int magic;
@@ -185,6 +185,8 @@ struct _pkinit_kdc_context {
pkinit_plg_opts *opts;
pkinit_identity_crypto_context idctx;
pkinit_identity_opts *idopts;
+ char *realmname;
+ unsigned int realmname_len;
};
/*
@@ -675,14 +677,16 @@ void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
* Functions in pkinit_profile.c
*/
krb5_error_code pkinit_kdcdefault_strings
- (krb5_context context, const char *option, char ***ret_value);
+ (krb5_context context, const char *realmname, const char *option,
+ char ***ret_value);
krb5_error_code pkinit_kdcdefault_string
- (krb5_context context, const char *option, char **ret_value);
+ (krb5_context context, const char *realmname, const char *option,
+ char **ret_value);
krb5_error_code pkinit_kdcdefault_boolean
- (krb5_context context, const char *option,
+ (krb5_context context, const char *realmname, const char *option,
int default_value, int *ret_value);
krb5_error_code pkinit_kdcdefault_integer
- (krb5_context context, const char *option,
+ (krb5_context context, const char *realmname, const char *option,
int default_value, int *ret_value);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index e9b2669..7922b00 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -162,24 +162,30 @@ unsigned char pkinit_4096_dhprime[4096/8] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+static int pkinit_oids_refs = 0;
+
const krb5_octet_data dh_oid = { 0, 7, "\x2A\x86\x48\xce\x3e\x02\x01" };
-static krb5_error_code create_identifiers_from_stack(STACK_OF(X509) *sk, krb5_external_principal_identifier *** ids);
+static krb5_error_code
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+ krb5_external_principal_identifier *** ids);
krb5_error_code
pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
krb5_error_code retval = ENOMEM;
- struct _pkinit_plg_crypto_context *ctx = NULL;
+ pkinit_plg_crypto_context ctx = NULL;
/* initialize openssl routines */
openssl_init();
- ctx = (struct _pkinit_plg_crypto_context *)malloc(sizeof(*ctx));
+ ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
if (ctx == NULL)
goto out;
memset(ctx, 0, sizeof(*ctx));
+ pkiDebug("%s: initializing openssl crypto context at %p\n",
+ __FUNCTION__, ctx);
retval = pkinit_init_pkinit_oids(ctx);
if (retval)
goto out;
@@ -191,10 +197,8 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
*cryptoctx = ctx;
out:
- if (retval) {
- free(ctx);
- OBJ_cleanup();
- }
+ if (retval && ctx != NULL)
+ pkinit_fini_plg_crypto(ctx);
return retval;
}
@@ -202,22 +206,22 @@ out:
void
pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
{
- struct _pkinit_plg_crypto_context *ctx = cryptoctx;
+ pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
- if (ctx == NULL)
+ if (cryptoctx == NULL)
return;
- pkinit_fini_pkinit_oids(ctx);
- pkinit_fini_dh_params(ctx);
- free(ctx);
+ pkinit_fini_pkinit_oids(cryptoctx);
+ pkinit_fini_dh_params(cryptoctx);
+ free(cryptoctx);
}
krb5_error_code
pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
{
krb5_error_code retval = ENOMEM;
- struct _pkinit_identity_crypto_context *ctx = NULL;
+ pkinit_identity_crypto_context ctx = NULL;
- ctx = (struct _pkinit_identity_crypto_context *)malloc(sizeof(*ctx));
+ ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx));
if (ctx == NULL)
goto out;
memset(ctx, 0, sizeof(*ctx));
@@ -230,13 +234,13 @@ pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
if (retval)
goto out;
- pkiDebug("pkinit_init_identity_crypto: returning ctx at %p\n", ctx);
+ pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
*idctx = ctx;
out:
if (retval) {
- free(ctx);
- OBJ_cleanup();
+ if (ctx)
+ pkinit_fini_identity_crypto(ctx);
}
return retval;
@@ -245,15 +249,13 @@ out:
void
pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
{
- struct _pkinit_identity_crypto_context *ctx = idctx;
-
- if (ctx == NULL)
+ if (idctx == NULL)
return;
- pkiDebug("pkinit_fini_identity_crypto: freeing ctx at %p\n", ctx);
- pkinit_fini_certs(ctx);
- pkinit_fini_pkcs11(ctx);
- free(ctx);
+ pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx);
+ pkinit_fini_certs(idctx);
+ pkinit_fini_pkcs11(idctx);
+ free(idctx);
}
krb5_error_code
@@ -261,9 +263,9 @@ pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
{
krb5_error_code retval = ENOMEM;
- struct _pkinit_req_crypto_context *ctx = NULL;
+ pkinit_req_crypto_context ctx = NULL;
- ctx = (struct _pkinit_req_crypto_context *)malloc(sizeof(*ctx));
+ ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx));
if (ctx == NULL)
goto out;
memset(ctx, 0, sizeof(*ctx));
@@ -273,7 +275,7 @@ pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
*cryptoctx = ctx;
- pkiDebug("pkinit_init_req_crypto: returning ctx at %p\n", ctx);
+ pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
retval = 0;
out:
if (retval)
@@ -283,20 +285,18 @@ out:
}
void
-pkinit_fini_req_crypto(pkinit_req_crypto_context cryptoctx)
+pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
{
- struct _pkinit_req_crypto_context *ctx = cryptoctx;
-
- if (ctx == NULL)
+ if (req_cryptoctx == NULL)
return;
- pkiDebug("pkinit_fini_req_crypto: freeing ctx at %p\n", ctx);
- if (ctx->dh != NULL)
- DH_free(ctx->dh);
- if (ctx->received_cert != NULL)
- X509_free(ctx->received_cert);
+ pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
+ if (req_cryptoctx->dh != NULL)
+ DH_free(req_cryptoctx->dh);
+ if (req_cryptoctx->received_cert != NULL)
+ X509_free(req_cryptoctx->received_cert);
- free(ctx);
+ free(req_cryptoctx);
}
static krb5_error_code
@@ -359,7 +359,9 @@ pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
goto out;
ctx->id_kp_serverAuth = (ASN1_OBJECT *)OBJ_nid2obj(tmp);
+ /* Success */
retval = 0;
+ pkinit_oids_refs++;
out:
return retval;
@@ -368,7 +370,12 @@ out:
static void
pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
{
- OBJ_cleanup();
+ if (ctx == NULL)
+ return;
+
+ /* Only call OBJ_cleanup once! */
+ if (--pkinit_oids_refs == 0)
+ OBJ_cleanup();
}
static krb5_error_code
@@ -450,6 +457,9 @@ pkinit_init_certs(pkinit_identity_crypto_context ctx)
static void
pkinit_fini_certs(pkinit_identity_crypto_context ctx)
{
+ if (ctx == NULL)
+ return;
+
if (ctx->my_certs != NULL)
sk_X509_pop_free(ctx->my_certs, X509_free);
@@ -492,6 +502,9 @@ static void
pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
{
#ifndef WITHOUT_PKCS11
+ if (ctx == NULL)
+ return;
+
if (ctx->p11 != NULL) {
if (ctx->session) {
ctx->p11->C_CloseSession(ctx->session);
@@ -1947,7 +1960,7 @@ server_process_dh(krb5_context context,
static void
openssl_init()
{
- static int did_init;
+ static int did_init = 0;
if (!did_init) {
/* initialize openssl routines */
@@ -2557,7 +2570,6 @@ openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
static ASN1_OBJECT *
pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
{
-
switch (pkcs7_type) {
case CMS_SIGN_CLIENT:
return cryptoctx->id_pkinit_authData;
@@ -3735,7 +3747,8 @@ load_trusted_certifiers(STACK_OF(X509) **trusted_CAs,
}
static krb5_error_code
-create_identifiers_from_stack(STACK_OF(X509) *sk, krb5_external_principal_identifier *** ids)
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+ krb5_external_principal_identifier *** ids)
{
krb5_error_code retval = ENOMEM;
int i = 0, sk_size = sk_X509_num(sk);
diff --git a/src/plugins/preauth/pkinit/pkinit_profile.c b/src/plugins/preauth/pkinit/pkinit_profile.c
index 0159d63..0cbdf23 100644
--- a/src/plugins/preauth/pkinit/pkinit_profile.c
+++ b/src/plugins/preauth/pkinit/pkinit_profile.c
@@ -91,8 +91,8 @@ _krb5_conf_boolean(const char *s)
* already been established.
*/
krb5_error_code
-pkinit_kdcdefault_strings(krb5_context context, const char *option,
- char ***ret_value)
+pkinit_kdcdefault_strings(krb5_context context, const char *realmname,
+ const char *option, char ***ret_value)
{
profile_t profile = NULL;
const char *names[5];
@@ -102,27 +102,26 @@ pkinit_kdcdefault_strings(krb5_context context, const char *option,
if (context == NULL)
return KV5M_CONTEXT;
- if (context->default_realm == NULL)
- return EINVAL;
-
profile = context->profile;
- /*
- * Try number one:
- *
- * [realms]
- * REALM = {
- * option = <value>
- * }
- */
+ if (realmname != NULL) {
+ /*
+ * Try number one:
+ *
+ * [realms]
+ * REALM = {
+ * option = <value>
+ * }
+ */
- names[0] = "realms";
- names[1] = context->default_realm;
- names[2] = option;
- names[3] = 0;
- retval = profile_get_values(profile, names, &values);
- if (retval == 0 && values != NULL)
- goto goodbye;
+ names[0] = "realms";
+ names[1] = realmname;
+ names[2] = option;
+ names[3] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL)
+ goto goodbye;
+ }
/*
* Try number two:
@@ -149,13 +148,13 @@ goodbye:
}
krb5_error_code
-pkinit_kdcdefault_string(krb5_context context, const char *option,
- char **ret_value)
+pkinit_kdcdefault_string(krb5_context context, const char *realmname,
+ const char *option, char **ret_value)
{
krb5_error_code retval;
char **values = NULL;
- retval = pkinit_kdcdefault_strings(context, option, &values);
+ retval = pkinit_kdcdefault_strings(context, realmname, option, &values);
if (retval)
return retval;
@@ -174,13 +173,13 @@ pkinit_kdcdefault_string(krb5_context context, const char *option,
}
krb5_error_code
-pkinit_kdcdefault_boolean(krb5_context context, const char *option,
- int default_value, int *ret_value)
+pkinit_kdcdefault_boolean(krb5_context context, const char *realmname,
+ const char *option, int default_value, int *ret_value)
{
char *string = NULL;
krb5_error_code retval;
- retval = pkinit_kdcdefault_string(context, option, &string);
+ retval = pkinit_kdcdefault_string(context, realmname, option, &string);
if (retval == 0) {
*ret_value = _krb5_conf_boolean(string);
@@ -192,13 +191,13 @@ pkinit_kdcdefault_boolean(krb5_context context, const char *option,
}
krb5_error_code
-pkinit_kdcdefault_integer(krb5_context context, const char *option,
- int default_value, int *ret_value)
+pkinit_kdcdefault_integer(krb5_context context, const char *realmname,
+ const char *option, int default_value, int *ret_value)
{
char *string = NULL;
krb5_error_code retval;
- retval = pkinit_kdcdefault_string(context, option, &string);
+ retval = pkinit_kdcdefault_string(context, realmname, option, &string);
if (retval == 0) {
char *endptr;
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 56c7e27..4305ac4 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -76,13 +76,26 @@ static int pkinit_server_get_flags
static krb5_error_code pkinit_init_kdc_req_context
(krb5_context, void **blob);
+
static void pkinit_fini_kdc_req_context
(krb5_context context, void *blob);
+
+static int pkinit_server_plugin_init_realm
+ (krb5_context context, const char *realmname,
+ pkinit_kdc_context *pplgctx);
+
+static void pkinit_server_plugin_fini_realm
+ (krb5_context context, pkinit_kdc_context plgctx);
+
static int pkinit_server_plugin_init
- (krb5_context context, void **blob);
+ (krb5_context context, void **blob, const char **realmnames);
+
static void pkinit_server_plugin_fini
(krb5_context context, void *blob);
+static pkinit_kdc_context pkinit_find_realm_context
+ (krb5_context context, void *pa_plugin_context, krb5_principal princ);
+
static krb5_error_code
pkinit_create_edata(krb5_context context,
pkinit_plg_crypto_context plg_cryptoctx,
@@ -132,7 +145,19 @@ pkinit_server_get_edata(krb5_context context,
krb5_pa_data * data)
{
krb5_error_code retval = 0;
+ pkinit_kdc_context plgctx = NULL;
+
pkiDebug("pkinit_get_edata: entered!\n");
+
+ /*
+ * If we don't have a realm context for the given realm,
+ * don't tell the client that we support pkinit!
+ */
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL)
+ retval = EINVAL;
+
return retval;
}
@@ -155,7 +180,7 @@ pkinit_server_verify_padata(krb5_context context,
krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
krb5_auth_pack *auth_pack = NULL;
krb5_auth_pack_draft9 *auth_pack9 = NULL;
- pkinit_kdc_context plgctx = (pkinit_kdc_context)pa_plugin_context;
+ pkinit_kdc_context plgctx = NULL;
pkinit_kdc_req_context reqctx;
krb5_preauthtype pa_type;
krb5_principal tmp_client;
@@ -171,7 +196,12 @@ pkinit_server_verify_padata(krb5_context context,
return 0;
if (pa_plugin_context == NULL || e_data == NULL)
- return -1;
+ return EINVAL;
+
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL)
+ return 0;
scratch.data = data->contents;
scratch.length = data->length;
@@ -227,7 +257,7 @@ pkinit_server_verify_padata(krb5_context context,
pkiDebug("unrecognized pa_type = %d\n", data->pa_type);
scratch.data = NULL;
scratch.length = 0;
- retval = -1;
+ retval = EINVAL;
goto cleanup;
}
if (retval) {
@@ -245,7 +275,6 @@ pkinit_server_verify_padata(krb5_context context,
retval = KRB5KDC_ERR_CLIENT_NOT_TRUSTED;
goto cleanup;
} else {
-#if 0
if (tmp_client != NULL) {
retval = krb5_principal_compare(context, request->client,
tmp_client);
@@ -261,7 +290,6 @@ pkinit_server_verify_padata(krb5_context context,
retval = KRB5KDC_ERR_CLIENT_NOT_TRUSTED;
goto cleanup;
}
-#endif
}
retval = verify_id_pkinit_eku(context, plgctx->cryptoctx, reqctx->cryptoctx,
@@ -491,7 +519,7 @@ pkinit_server_return_padata(krb5_context context,
int num_types;
krb5_cksumtype *cksum_types = NULL;
- pkinit_kdc_context plgctx = (pkinit_kdc_context)pa_plugin_context;
+ pkinit_kdc_context plgctx;
pkinit_kdc_req_context reqctx;
*send_pa = NULL;
@@ -500,8 +528,16 @@ pkinit_server_return_padata(krb5_context context,
if (pa_request_context == NULL || *pa_request_context == NULL) {
pkiDebug("missing request context \n");
- return -1;
+ return EINVAL;
}
+
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL) {
+ pkiDebug("Unable to locate correct realm context\n");
+ return ENOENT;
+ }
+
pkiDebug("pkinit_return_padata: entered!\n");
reqctx = (pkinit_kdc_req_context)*pa_request_context;
@@ -602,7 +638,8 @@ pkinit_server_return_padata(krb5_context context,
goto cleanup;
}
#ifdef DEBUG_ASN1
- print_buffer_bin(encoded_dhkey_info->data, encoded_dhkey_info->length, "/tmp/kdc_dh_key_info");
+ print_buffer_bin(encoded_dhkey_info->data, encoded_dhkey_info->length,
+ "/tmp/kdc_dh_key_info");
#endif
switch ((int)padata->pa_type) {
@@ -849,43 +886,55 @@ pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
{
krb5_error_code retval;
- retval = pkinit_kdcdefault_string(context, "pkinit_identity",
+ pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
+ retval = pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_identity",
&plgctx->idopts->identity);
if (retval != 0 || NULL == plgctx->idopts->identity) {
retval = EINVAL;
krb5_set_error_message(context, retval,
- "No pkinit_identity supplied for the KDC");
+ "No pkinit_identity supplied for realm %s",
+ plgctx->realmname);
goto errout;
}
- retval = pkinit_kdcdefault_strings(context, "pkinit_anchors",
+ retval = pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_anchors",
&plgctx->idopts->anchors);
if (retval != 0 || NULL == plgctx->idopts->anchors) {
retval = EINVAL;
krb5_set_error_message(context, retval,
- "No pkinit_anchors supplied for the KDC");
+ "No pkinit_anchors supplied for realm %s",
+ plgctx->realmname);
goto errout;
}
- pkinit_kdcdefault_strings(context, "pkinit_pool",
+ pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_pool",
&plgctx->idopts->intermediates);
- pkinit_kdcdefault_strings(context, "pkinit_revoke",
+ pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_revoke",
&plgctx->idopts->crls);
- pkinit_kdcdefault_string(context, "pkinit_kdc_ocsp",
+ pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_kdc_ocsp",
&plgctx->idopts->ocsp);
- pkinit_kdcdefault_string(context, "pkinit_mappings_file",
+ pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_mappings_file",
&plgctx->idopts->dn_mapping_file);
- pkinit_kdcdefault_boolean(context, "pkinit_principal_in_certificate",
+ pkinit_kdcdefault_boolean(context, plgctx->realmname,
+ "pkinit_principal_in_certificate",
1, &plgctx->opts->princ_in_cert);
- pkinit_kdcdefault_boolean(context, "pkinit_allow_proxy_certificate",
+ pkinit_kdcdefault_boolean(context, plgctx->realmname,
+ "pkinit_allow_proxy_certificate",
0, &plgctx->opts->allow_proxy_certs);
- pkinit_kdcdefault_integer(context, "pkinit_dh_min_bits",
+ pkinit_kdcdefault_integer(context, plgctx->realmname,
+ "pkinit_dh_min_bits",
0, &plgctx->opts->dh_min_bits);
return 0;
@@ -894,33 +943,65 @@ errout:
return retval;
}
+static pkinit_kdc_context
+pkinit_find_realm_context(krb5_context context, void *pa_plugin_context,
+ krb5_principal princ)
+{
+ int i;
+ pkinit_kdc_context *realm_contexts = pa_plugin_context;
+
+ if (pa_plugin_context == NULL)
+ return NULL;
+
+ for (i = 0; realm_contexts[i] != NULL; i++) {
+ pkinit_kdc_context p = realm_contexts[i];
+
+ if ((p->realmname_len == princ->realm.length) &&
+ (strncmp(p->realmname, princ->realm.data, p->realmname_len) == 0)) {
+ pkiDebug("%s: returning context at %p for realm '%s'\n",
+ __FUNCTION__, p, p->realmname);
+ return p;
+ }
+ }
+ pkiDebug("%s: unable to find realm context for realm '%.*s'\n",
+ __FUNCTION__, princ->realm.length, princ->realm.data);
+ return NULL;
+}
+
static int
-pkinit_server_plugin_init(krb5_context context, void **blob)
+pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
+ pkinit_kdc_context *pplgctx)
{
krb5_error_code retval = ENOMEM;
- struct _pkinit_kdc_context *plgctx = NULL;
+ pkinit_kdc_context plgctx = NULL;
+
+ *pplgctx = NULL;
- plgctx = (struct _pkinit_kdc_context *)calloc(1, sizeof(*plgctx));
+ plgctx = (pkinit_kdc_context) calloc(1, sizeof(*plgctx));
if (plgctx == NULL)
- return ENOMEM;
+ goto errout;
+
+ pkiDebug("%s: initializing context at %p for realm '%s'\n",
+ __FUNCTION__, plgctx, realmname);
memset(plgctx, 0, sizeof(*plgctx));
plgctx->magic = PKINIT_CTX_MAGIC;
- retval = pkinit_accessor_init();
- if (retval)
- goto errout;
+ plgctx->realmname = strdup(realmname);
+ if (plgctx->realmname == NULL)
+ goto errout;
+ plgctx->realmname_len = strlen(plgctx->realmname);
- retval = pkinit_init_plg_opts(&plgctx->opts);
+ retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
if (retval)
- goto errout;
+ goto errout;
- retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
+ retval = pkinit_init_plg_opts(&plgctx->opts);
if (retval)
- goto errout;
+ goto errout;
retval = pkinit_init_identity_crypto(&plgctx->idctx);
if (retval)
- goto errout;
+ goto errout;
retval = pkinit_init_identity_opts(&plgctx->idopts);
if (retval)
@@ -932,45 +1013,104 @@ pkinit_server_plugin_init(krb5_context context, void **blob)
retval = pkinit_initialize_identity(context, plgctx->idopts, plgctx->idctx);
if (retval)
- goto errout;
+ goto errout;
+
+ pkiDebug("%s: returning context at %p for realm '%s'\n",
+ __FUNCTION__, plgctx, realmname);
+ *pplgctx = plgctx;
+ retval = 0;
- *blob = plgctx;
+errout:
+ if (retval)
+ pkinit_server_plugin_fini_realm(context, plgctx);
- pkiDebug("%s: returning plgctx at %p\n", __FUNCTION__, plgctx);
+ return retval;
+}
+
+static int
+pkinit_server_plugin_init(krb5_context context, void **blob,
+ const char **realmnames)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_kdc_context plgctx, *realm_contexts = NULL;
+ int i, j, numrealms;
+
+ retval = pkinit_accessor_init();
+ if (retval)
+ return retval;
+
+ /* Determine how many realms we may need to support */
+ for (i = 0; realmnames[i] != NULL; i++) {};
+ numrealms = i;
+
+ realm_contexts = (pkinit_kdc_context *)
+ calloc(numrealms+1, sizeof(pkinit_kdc_context));
+ if (realm_contexts == NULL)
+ return ENOMEM;
+
+ for (i = 0, j = 0; i < numrealms; i++) {
+ pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
+ retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
+ if (retval == 0 && plgctx != NULL)
+ realm_contexts[j++] = plgctx;
+ }
+
+ if (j == 0) {
+ retval = EINVAL;
+ krb5_set_error_message(context, retval, "No realms configured "
+ "correctly for pkinit support");
+ goto errout;
+ }
+
+ *blob = realm_contexts;
+ retval = 0;
+ pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
errout:
if (retval)
- pkinit_server_plugin_fini(context, plgctx);
+ pkinit_server_plugin_fini(context, realm_contexts);
return retval;
}
static void
-pkinit_server_plugin_fini(krb5_context context, void *blob)
+pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx)
{
- struct _pkinit_kdc_context *plgctx = (struct _pkinit_kdc_context *) blob;
-
- if (plgctx == NULL || plgctx->magic != PKINIT_CTX_MAGIC) {
- pkiDebug("pkinit_lib_fini: got bad plgctx (%p)!\n", plgctx);
+ if (plgctx == NULL)
return;
- }
- pkiDebug("%s: freeing plgctx at %p\n", __FUNCTION__, plgctx);
pkinit_fini_kdc_profile(context, plgctx);
pkinit_fini_identity_opts(plgctx->idopts);
pkinit_fini_identity_crypto(plgctx->idctx);
pkinit_fini_plg_crypto(plgctx->cryptoctx);
pkinit_fini_plg_opts(plgctx->opts);
+ free(plgctx->realmname);
free(plgctx);
}
+static void
+pkinit_server_plugin_fini(krb5_context context, void *blob)
+{
+ pkinit_kdc_context *realm_contexts = blob;
+ int i;
+
+ if (realm_contexts == NULL)
+ return;
+
+ for (i = 0; realm_contexts[i] != NULL; i++) {
+ pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
+ }
+ pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
+ free(realm_contexts);
+}
+
static krb5_error_code pkinit_init_kdc_req_context(krb5_context context,
void **ctx)
{
krb5_error_code retval = ENOMEM;
- struct _pkinit_kdc_req_context *reqctx = NULL;
+ pkinit_kdc_req_context reqctx = NULL;
- reqctx = (struct _pkinit_kdc_req_context *)malloc(sizeof(*reqctx));
+ reqctx = (pkinit_kdc_req_context)malloc(sizeof(*reqctx));
if (reqctx == NULL)
return retval;
memset(reqctx, 0, sizeof(*reqctx));
@@ -994,8 +1134,7 @@ cleanup:
static void pkinit_fini_kdc_req_context(krb5_context context, void *ctx)
{
- struct _pkinit_kdc_req_context *reqctx =
- (struct _pkinit_kdc_req_context *)ctx;
+ pkinit_kdc_req_context reqctx = (pkinit_kdc_req_context)ctx;
if (reqctx == NULL || reqctx->magic != PKINIT_CTX_MAGIC) {
pkiDebug("pkinit_fini_kdc_req_context: got bad reqctx (%p)!\n", reqctx);