svn rev #21566: branches/mskrb-integ/src/ include/krb5/ kdc/
lhoward@MIT.EDU
lhoward at MIT.EDU
Mon Dec 22 21:55:04 EST 2008
http://src.mit.edu/fisheye/changelog/krb5/?cs=21566
Commit By: lhoward
Log Message:
Consolidate authorization data handling interface. Both AS-REQ and
TGS-REQ paths call handle_authdata(). There is a new V1 callback that
provides some additional arguments.
Copying TGT authorization data to new tickets as well as the existing
Novell DB sign_auth_data method are both implemented as static authdata
systems.
Both V0 and V1 plugins are supported.
Changed Files:
U branches/mskrb-integ/src/include/krb5/authdata_plugin.h
U branches/mskrb-integ/src/kdc/do_as_req.c
U branches/mskrb-integ/src/kdc/do_tgs_req.c
U branches/mskrb-integ/src/kdc/kdc_authdata.c
U branches/mskrb-integ/src/kdc/kdc_util.c
U branches/mskrb-integ/src/kdc/kdc_util.h
Modified: branches/mskrb-integ/src/include/krb5/authdata_plugin.h
===================================================================
--- branches/mskrb-integ/src/include/krb5/authdata_plugin.h 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/include/krb5/authdata_plugin.h 2008-12-23 02:55:02 UTC (rev 21566)
@@ -108,4 +108,53 @@
krb5_kdc_req *request,
krb5_enc_tkt_part *enc_tkt_reply);
} krb5plugin_authdata_ftable_v0;
+
+typedef struct krb5plugin_authdata_ftable_v1 {
+ /* Not-usually-visible name. */
+ char *name;
+
+ /*
+ * Per-plugin initialization/cleanup. The init function is called
+ * by the KDC when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded. Both are optional.
+ */
+ krb5_error_code (*init_proc)(krb5_context, void **);
+ void (*fini_proc)(krb5_context, void *);
+ /*
+ * Actual authorization data handling function. If this field
+ * holds a null pointer, this mechanism will be skipped, and the
+ * init/fini functions will not be run.
+ *
+ * This function should only modify the field
+ * enc_tkt_reply->authorization_data. All other values should be
+ * considered inputs only. And, it should *modify* the field, not
+ * overwrite it and assume that there are no other authdata
+ * plugins in use.
+ *
+ * Memory management: authorization_data is a malloc-allocated,
+ * null-terminated sequence of malloc-allocated pointers to
+ * authorization data structures. This plugin code currently
+ * assumes the libraries, KDC, and plugin all use the same malloc
+ * pool, which may be a problem if/when we get the KDC code
+ * running on Windows.
+ *
+ * If this function returns a non-zero error code, a message
+ * is logged, but no other action is taken. Other authdata
+ * plugins will be called, and a response will be sent to the
+ * client (barring other problems).
+ */
+ krb5_error_code (*authdata_proc)(krb5_context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ struct _krb5_db_entry_new *client,
+ struct _krb5_db_entry_new *server,
+ struct _krb5_db_entry_new *tgs,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
+} krb5plugin_authdata_ftable_v1;
+
#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
Modified: branches/mskrb-integ/src/kdc/do_as_req.c
===================================================================
--- branches/mskrb-integ/src/kdc/do_as_req.c 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/kdc/do_as_req.c 2008-12-23 02:55:02 UTC (rev 21566)
@@ -296,6 +296,8 @@
ticket_reply.server = &server_princ;
enc_tkt_reply.flags = 0;
+ enc_tkt_reply.times.authtime = authtime;
+
setflag(enc_tkt_reply.flags, TKT_FLG_INITIAL);
/* It should be noted that local policy may affect the */
@@ -323,8 +325,6 @@
enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */
- enc_tkt_reply.times.authtime = kdc_time;
-
if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
@@ -498,30 +498,21 @@
reply_encpart.times.authtime = authtime = kdc_time;
reply_encpart.caddrs = enc_tkt_reply.caddrs;
- errcode = sign_authorization_data(kdc_context,
- 0,
- reply.client,
- &client,
- &server,
- &server,
- &client_keyblock,
- &server_keyblock,
- authtime,
- NULL,
- &enc_tkt_reply.authorization_data,
- NULL,
- NULL);
+ reply_encpart.enc_padata = NULL;
+
+ /* Fetch the padata info to be returned (do this before
+ authdata to handle possible replacement of reply key */
+ errcode = return_padata(kdc_context, &client, req_pkt, request,
+ &reply, client_key, &client_keyblock, &pa_context);
if (errcode) {
- status = "SIGN_AUTH_DATA";
+ status = "KDC_RETURN_PADATA";
goto errout;
}
- /* Add any additional auth data - XXX need to consolidate plugin interfaces */
- errcode = handle_authdata(kdc_context, &client, req_pkt, request, &enc_tkt_reply);
- if (errcode) {
- krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode);
- }
- reply_encpart.enc_padata = NULL;
+#if APPLE_PKINIT
+ asReqDebug("process_as_req reply realm %s name %s\n",
+ reply.client->realm.data, reply.client->data->data);
+#endif /* APPLE_PKINIT */
errcode = return_svr_referral_data(kdc_context,
&server, &reply_encpart);
@@ -530,27 +521,31 @@
goto errout;
}
- /* moved here because we need authorization data in ticket_reply */
- errcode = krb5_encrypt_tkt_part(kdc_context, &server_keyblock, &ticket_reply);
+ errcode = handle_authdata(kdc_context,
+ c_flags,
+ reply.client,
+ &client,
+ &server,
+ &server,
+ &client_keyblock,
+ &server_keyblock,
+ req_pkt,
+ request,
+ NULL, /* enc_tkt_request */
+ &enc_tkt_reply);
if (errcode) {
- status = "ENCRYPTING_TICKET";
+ krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode);
+ status = "HANDLE_AUTHDATA";
goto errout;
}
- ticket_reply.enc_part.kvno = server_key->key_data_kvno;
- /* Fetch the padata info to be returned */
- errcode = return_padata(kdc_context, &client, req_pkt, request,
- &reply, client_key, &client_keyblock, &pa_context);
+ errcode = krb5_encrypt_tkt_part(kdc_context, &server_keyblock, &ticket_reply);
if (errcode) {
- status = "KDC_RETURN_PADATA";
+ status = "ENCRYPTING_TICKET";
goto errout;
}
+ ticket_reply.enc_part.kvno = server_key->key_data_kvno;
-#if APPLE_PKINIT
- asReqDebug("process_as_req reply realm %s name %s\n",
- reply.client->realm.data, reply.client->data->data);
-#endif /* APPLE_PKINIT */
-
/* now encode/encrypt the response */
reply.enc_part.enctype = client_keyblock.enctype;
Modified: branches/mskrb-integ/src/kdc/do_tgs_req.c
===================================================================
--- branches/mskrb-integ/src/kdc/do_tgs_req.c 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/kdc/do_tgs_req.c 2008-12-23 02:55:02 UTC (rev 21566)
@@ -614,58 +614,27 @@
c_nprincs = 0;
}
}
+ }
- /*
- * Check whether KDC issued authorization data should be included.
- * A server can explicitly disable the inclusion of authorization
- * data by setting the KRB5_KDB_NO_AUTH_DATA_REQUIRED flag on its
- * principal entry. Otherwise authorization data will be included
- * if it was present in the TGT, the client is from another realm
- * or protocol transition/constrained delegation was used.
- *
- * We permit sign_authorization_data() to return a krb5_db_entry
- * representing the principal associated with the authorization
- * data, in case that principal is not local to our realm and we
- * need to perform additional checks (such as disabling delegation
- * for cross-realm protocol transition below).
- */
- if (header_enc_tkt->authorization_data != NULL ||
- isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM) ||
- isflagset(c_flags, KRB5_KDB_FLAGS_S4U)) {
- krb5_db_entry ad_entry;
- int ad_nprincs = 0;
+ enc_tkt_reply.authorization_data = NULL;
- errcode = sign_authorization_data(kdc_context,
- c_flags,
- isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) ?
- for_user->user : header_enc_tkt->client,
- (c_nprincs != 0) ? &client : NULL,
- &server,
- &krbtgt,
- NULL, /* ticket reply key not relevant */
- &encrypting_key, /* U2U or server key */
- header_enc_tkt->times.authtime,
- header_enc_tkt->authorization_data,
- &kdc_issued_auth_data,
- &ad_entry,
- &ad_nprincs);
- if (errcode) {
- status = "SIGN_AUTH_DATA";
- goto cleanup;
- }
- if (ad_nprincs != 0) {
- if (isflagset(ad_entry.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))
- clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
-
- krb5_db_free_principal(kdc_context, &ad_entry, ad_nprincs);
-
- if (ad_nprincs != 1) {
- status = "NON_UNIQUE_AUTH_DATA_PRINCIPAL";
- errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
- goto cleanup;
- }
- }
- }
+ errcode = handle_authdata(kdc_context,
+ c_flags,
+ isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) ?
+ for_user->user : header_enc_tkt->client,
+ (c_nprincs != 0) ? &client : NULL,
+ &server,
+ &krbtgt,
+ NULL, /* ticket reply key not relevant here */
+ &encrypting_key, /* U2U or server key */
+ pkt,
+ request,
+ header_enc_tkt,
+ &enc_tkt_reply);
+ if (errcode) {
+ krb5_klog_syslog(LOG_INFO, "TGS_REQ : handle_authdata (%d)", errcode);
+ status = "HANDLE_AUTHDATA";
+ goto cleanup;
}
errcode = return_svr_referral_data(kdc_context,
@@ -675,46 +644,6 @@
goto cleanup;
}
- /* assemble any authorization data */
- if (request->authorization_data.ciphertext.data != NULL) {
- krb5_data scratch;
-
- scratch.length = request->authorization_data.ciphertext.length;
- if (!(scratch.data =
- malloc(request->authorization_data.ciphertext.length))) {
- status = "AUTH_NOMEM";
- errcode = ENOMEM;
- goto cleanup;
- }
-
- if ((errcode = krb5_c_decrypt(kdc_context,
- header_ticket->enc_part2->session,
- KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
- 0, &request->authorization_data,
- &scratch))) {
- status = "AUTH_ENCRYPT_FAIL";
- free(scratch.data);
- goto cleanup;
- }
-
- /* scratch now has the authorization data, so we decode it */
- errcode = decode_krb5_authdata(&scratch, &(request->unenc_authdata));
- free(scratch.data);
- if (errcode) {
- status = "AUTH_DECODE";
- goto cleanup;
- }
-
- if ((errcode =
- concat_authorization_data(kdc_issued_auth_data,
- request->unenc_authdata,
- &enc_tkt_reply.authorization_data))) {
- status = "CONCAT_AUTH";
- goto cleanup;
- }
- } else
- enc_tkt_reply.authorization_data = kdc_issued_auth_data;
-
enc_tkt_reply.session = &session_key;
if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) &&
is_local_principal(header_enc_tkt->client))
Modified: branches/mskrb-integ/src/kdc/kdc_authdata.c
===================================================================
--- branches/mskrb-integ/src/kdc/kdc_authdata.c 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/kdc/kdc_authdata.c 2008-12-23 02:55:02 UTC (rev 21566)
@@ -2,6 +2,7 @@
* kdc/kdc_authdata.c
*
* Copyright (C) 2007 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008 by the Massachusetts Institute of Technology.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
@@ -42,109 +43,95 @@
static const char *objdirs[] = { LIBDIR "/krb5/plugins/authdata", NULL };
#endif
-typedef krb5_error_code (*authdata_proc)
+/* MIT Kerberos 1.6 (V0) authdata plugin callback */
+typedef krb5_error_code (*authdata_proc_0)
(krb5_context, krb5_db_entry *client,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_enc_tkt_part * enc_tkt_reply);
-
+/* MIT Kerberos 1.7 (V1) authdata plugin callback */
+typedef krb5_error_code (*authdata_proc_1)
+ (krb5_context, unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
typedef krb5_error_code (*init_proc)
(krb5_context, void **);
typedef void (*fini_proc)
(krb5_context, void *);
+/* Internal authdata system for copying TGS-REQ authdata to ticket */
+static krb5_error_code handle_request_authdata
+ (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
+
+/* Internal authdata system for handling KDC-issued authdata */
+static krb5_error_code handle_tgt_authdata
+ (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
+
typedef struct _krb5_authdata_systems {
const char *name;
+#define AUTHDATA_SYSTEM_UNKNOWN -1
+#define AUTHDATA_SYSTEM_V0 0
+#define AUTHDATA_SYSTEM_V1 1
int type;
+#define AUTHDATA_FLAG_CRITICAL 0x1
int flags;
void *plugin_context;
init_proc init;
fini_proc fini;
- authdata_proc handle_authdata;
+ union {
+ authdata_proc_1 v1;
+ authdata_proc_0 v0;
+ } handle_authdata;
} krb5_authdata_systems;
-#undef GREET_PREAUTH
-
-#ifdef GREET_PREAUTH
-static krb5_error_code
-greet_init(krb5_context ctx, void **blob)
-{
- *blob = "hello";
- return 0;
-}
-
-static void
-greet_fini(krb5_context ctx, void *blob)
-{
-}
-
-static krb5_error_code
-greet_authdata(krb5_context ctx, krb5_db_entry *client,
- krb5_data *req_pkt,
- krb5_kdc_req *request,
- krb5_enc_tkt_part * enc_tkt_reply)
-{
-#define GREET_SIZE (20)
-
- char *p;
- krb5_authdata *a;
- size_t count;
- krb5_authdata **new_ad;
-
- krb5_klog_syslog (LOG_DEBUG, "in greet_authdata");
-
- p = calloc(1, GREET_SIZE);
- a = calloc(1, sizeof(*a));
-
- if (p == NULL || a == NULL) {
- free(p);
- free(a);
- return ENOMEM;
- }
- strlcpy(p, "hello", GREET_SIZE);
- a->magic = KV5M_AUTHDATA;
- a->ad_type = -42;
- a->length = GREET_SIZE;
- a->contents = p;
- if (enc_tkt_reply->authorization_data == 0) {
- count = 0;
- } else {
- for (count = 0; enc_tkt_reply->authorization_data[count] != 0; count++)
- ;
- }
- new_ad = realloc(enc_tkt_reply->authorization_data,
- (count+2) * sizeof(krb5_authdata *));
- if (new_ad == NULL) {
- free(p);
- free(a);
- return ENOMEM;
- }
- enc_tkt_reply->authorization_data = new_ad;
- new_ad[count] = a;
- new_ad[count+1] = NULL;
- return 0;
-}
-#endif
-
static krb5_authdata_systems static_authdata_systems[] = {
-#ifdef GREET_PREAUTH
- { "greeting", 0, 0, 0, greet_init, greet_fini, greet_authdata },
-#endif
- { "[end]", -1,}
+ { "tgs_req", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_request_authdata } },
+ { "tgt", AUTHDATA_SYSTEM_V1, AUTHDATA_FLAG_CRITICAL, NULL, NULL, NULL, { handle_tgt_authdata } },
};
static krb5_authdata_systems *authdata_systems;
static int n_authdata_systems;
static struct plugin_dir_handle authdata_plugins;
+/* Load both v0 and v1 authdata plugins */
krb5_error_code
load_authdata_plugins(krb5_context context)
{
- void **authdata_plugins_ftables = NULL;
- struct krb5plugin_authdata_ftable_v0 *ftable = NULL;
+ void **authdata_plugins_ftables_v0 = NULL;
+ void **authdata_plugins_ftables_v1 = NULL;
size_t module_count;
- int i, k;
+ size_t i, k;
init_proc server_init_proc = NULL;
+ krb5_error_code code;
/* Attempt to load all of the authdata plugins we can find. */
PLUGIN_DIR_INIT(&authdata_plugins);
@@ -156,40 +143,56 @@
}
/* Get the method tables provided by the loaded plugins. */
- authdata_plugins_ftables = NULL;
+ authdata_plugins_ftables_v0 = NULL;
+ authdata_plugins_ftables_v1 = NULL;
n_authdata_systems = 0;
+
if (krb5int_get_plugin_dir_data(&authdata_plugins,
+ "authdata_server_1",
+ &authdata_plugins_ftables_v1, &context->err) != 0 ||
+ krb5int_get_plugin_dir_data(&authdata_plugins,
"authdata_server_0",
- &authdata_plugins_ftables, &context->err) != 0) {
- return KRB5_PLUGIN_NO_HANDLE;
+ &authdata_plugins_ftables_v0, &context->err) != 0) {
+ code = KRB5_PLUGIN_NO_HANDLE;
+ goto cleanup;
}
/* Count the valid modules. */
module_count = sizeof(static_authdata_systems)
/ sizeof(static_authdata_systems[0]);
- if (authdata_plugins_ftables != NULL) {
- for (i = 0; authdata_plugins_ftables[i] != NULL; i++) {
- ftable = authdata_plugins_ftables[i];
- if ((ftable->authdata_proc != NULL)) {
+
+ if (authdata_plugins_ftables_v1 != NULL) {
+ struct krb5plugin_authdata_ftable_v1 *ftable;
+
+ for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) {
+ ftable = authdata_plugins_ftables_v1[i];
+ if (ftable->authdata_proc != NULL)
module_count++;
- }
}
}
+
+ if (authdata_plugins_ftables_v0 != NULL) {
+ struct krb5plugin_authdata_ftable_v0 *ftable;
+ for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
+ ftable = authdata_plugins_ftables_v0[i];
+ if (ftable->authdata_proc != NULL)
+ module_count++;
+ }
+ }
+
/* Build the complete list of supported authdata options, and
* leave room for a terminator entry. */
authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems));
if (authdata_systems == NULL) {
- krb5int_free_plugin_dir_data(authdata_plugins_ftables);
- return ENOMEM;
+ code = ENOMEM;
+ goto cleanup;
}
/* Add the locally-supplied mechanisms to the dynamic list first. */
for (i = 0, k = 0;
i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]);
i++) {
- if (static_authdata_systems[i].type == -1)
- break;
authdata_systems[k] = static_authdata_systems[i];
/* Try to initialize the authdata system. If it fails, we'll remove it
* from the list of systems we'll be using. */
@@ -202,13 +205,15 @@
k++;
}
- /* Now add the dynamically-loaded mechanisms to the list. */
- if (authdata_plugins_ftables != NULL) {
- for (i = 0; authdata_plugins_ftables[i] != NULL; i++) {
+ /* Add dynamically loaded V1 plugins */
+ if (authdata_plugins_ftables_v1 != NULL) {
+ struct krb5plugin_authdata_ftable_v1 *ftable;
+
+ for (i = 0; authdata_plugins_ftables_v1[i] != NULL; i++) {
krb5_error_code initerr;
void *pctx = NULL;
- ftable = authdata_plugins_ftables[i];
+ ftable = authdata_plugins_ftables_v1[i];
if ((ftable->authdata_proc == NULL)) {
continue;
}
@@ -229,19 +234,66 @@
}
authdata_systems[k].name = ftable->name;
+ authdata_systems[k].type = AUTHDATA_SYSTEM_V1;
authdata_systems[k].init = server_init_proc;
authdata_systems[k].fini = ftable->fini_proc;
- authdata_systems[k].handle_authdata = ftable->authdata_proc;
+ authdata_systems[k].handle_authdata.v1 = ftable->authdata_proc;
authdata_systems[k].plugin_context = pctx;
k++;
}
- krb5int_free_plugin_dir_data(authdata_plugins_ftables);
}
+
+ /* Add dynamically loaded V0 plugins */
+ if (authdata_plugins_ftables_v0 != NULL) {
+ struct krb5plugin_authdata_ftable_v0 *ftable;
+
+ for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
+ krb5_error_code initerr;
+ void *pctx = NULL;
+
+ ftable = authdata_plugins_ftables_v0[i];
+ if ((ftable->authdata_proc == NULL)) {
+ continue;
+ }
+ server_init_proc = ftable->init_proc;
+ if ((server_init_proc != NULL) &&
+ ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
+ const char *emsg;
+ emsg = krb5_get_error_message(context, initerr);
+ if (emsg) {
+ krb5_klog_syslog(LOG_ERR,
+ "authdata %s failed to initialize: %s",
+ ftable->name, emsg);
+ krb5_free_error_message(context, emsg);
+ }
+ memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
+
+ continue;
+ }
+
+ authdata_systems[k].name = ftable->name;
+ authdata_systems[k].type = AUTHDATA_SYSTEM_V0;
+ authdata_systems[k].init = server_init_proc;
+ authdata_systems[k].fini = ftable->fini_proc;
+ authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc;
+ authdata_systems[k].plugin_context = pctx;
+ k++;
+ }
+ }
+
n_authdata_systems = k;
/* Add the end-of-list marker. */
authdata_systems[k].name = "[end]";
- authdata_systems[k].type = -1;
- return 0;
+ authdata_systems[k].type = AUTHDATA_SYSTEM_UNKNOWN;
+ code = 0;
+
+cleanup:
+ if (authdata_plugins_ftables_v1 != NULL)
+ krb5int_free_plugin_dir_data(authdata_plugins_ftables_v1);
+ if (authdata_plugins_ftables_v0 != NULL)
+ krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0);
+
+ return code;
}
krb5_error_code
@@ -264,35 +316,277 @@
return 0;
}
+/* Merge authdata. If copy == 0, in_authdata is invalid on return */
+static krb5_error_code
+merge_authdata (krb5_context context,
+ krb5_authdata **in_authdata,
+ krb5_authdata ***out_authdata,
+ int copy)
+{
+ size_t i, nadata = 0;
+ krb5_authdata **authdata = *out_authdata;
+
+ if (in_authdata == NULL || in_authdata[0] == NULL)
+ return 0;
+
+ if (authdata != NULL) {
+ for (nadata = 0; authdata[nadata] != NULL; nadata++)
+ ;
+ }
+
+ for (i = 0; in_authdata[i] != NULL; i++)
+ ;
+
+ authdata = (krb5_authdata **)realloc(*out_authdata,
+ ((nadata + i + 1) * sizeof(krb5_authdata *)));
+ if (authdata == NULL)
+ return ENOMEM;
+
+ if (copy) {
+ krb5_error_code code;
+ krb5_authdata **tmp;
+
+ code = krb5_copy_authdata(context, in_authdata, &tmp);
+ if (code != 0)
+ return code;
+
+ in_authdata = tmp;
+ }
+
+ for (i = 0; in_authdata[i] != NULL; i++)
+ authdata[nadata + i] = in_authdata[i];
+
+ authdata[nadata + i] = NULL;
+
+ free(in_authdata);
+
+ *out_authdata = authdata;
+
+ return 0;
+}
+
+/* Handle copying TGS-REQ authorization data into reply */
+static krb5_error_code
+handle_request_authdata (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply)
+{
+ krb5_error_code code;
+ krb5_data scratch;
+
+ if (request->msg_type != KRB5_TGS_REQ ||
+ request->authorization_data.ciphertext.data == NULL)
+ return 0;
+
+ assert(enc_tkt_request != NULL);
+
+ scratch.length = request->authorization_data.ciphertext.length;
+ scratch.data = malloc(scratch.length);
+ if (scratch.data == NULL)
+ return ENOMEM;
+
+ code = krb5_c_decrypt(context,
+ enc_tkt_request->session,
+ KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
+ 0, &request->authorization_data,
+ &scratch);
+ if (code != 0) {
+ free(scratch.data);
+ return code;
+ }
+
+ /* scratch now has the authorization data, so we decode it, and make
+ * it available to subsequent authdata plugins */
+ code = decode_krb5_authdata(&scratch, &request->unenc_authdata);
+ if (code != 0) {
+ free(scratch.data);
+ return code;
+ }
+
+ free(scratch.data);
+
+ code = merge_authdata(context, request->unenc_authdata,
+ &enc_tkt_reply->authorization_data, TRUE /* copy */);
+
+ return code;
+}
+
+/* Handle backend-managed authorization data */
+static krb5_error_code
+handle_tgt_authdata (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply)
+{
+ krb5_error_code code;
+ krb5_authdata **db_authdata = NULL;
+ krb5_db_entry ad_entry;
+ int ad_nprincs = 0;
+ krb5_boolean tgs_req = (request->msg_type == KRB5_TGS_REQ);
+
+ /*
+ * Check whether KDC issued authorization data should be included.
+ * A server can explicitly disable the inclusion of authorization
+ * data by setting the KRB5_KDB_NO_AUTH_DATA_REQUIRED flag on its
+ * principal entry. Otherwise authorization data will be included
+ * if it was present in the TGT, the client is from another realm
+ * or protocol transition/constrained delegation was used, or, in
+ * the AS-REQ case, if the pre-auth data indicated the PAC should
+ * be absent.
+ *
+ * We permit sign_authorization_data() to return a krb5_db_entry
+ * representing the principal associated with the authorization
+ * data, in case that principal is not local to our realm and we
+ * need to perform additional checks (such as disabling delegation
+ * for cross-realm protocol transition below).
+ */
+ if (tgs_req) {
+ assert(enc_tkt_request != NULL);
+
+ if (isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED))
+ return 0;
+
+ if (enc_tkt_request->authorization_data == NULL &&
+ !isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM | KRB5_KDB_FLAGS_S4U))
+ return 0;
+
+ assert(enc_tkt_reply->times.authtime == enc_tkt_request->times.authtime);
+ } else {
+ if (!isflagset(flags, KRB5_KDB_FLAG_INCLUDE_PAC))
+ return 0;
+ }
+
+ /*
+ * If the backend does not implement the sign authdata method, then
+ * just copy the TGT authorization data into the reply, except for
+ * the constrained delegation case (which requires special handling
+ * because it will promote untrusted auth data to KDC issued auth
+ * data; this requires backend-specific code)
+ *
+ * Presently this interface does not support using request auth data
+ * to influence (eg. possibly restrict) the reply auth data.
+ */
+ code = sign_db_authdata(context,
+ flags,
+ reply_client,
+ client,
+ server,
+ krbtgt,
+ client_key,
+ server_key, /* U2U or server key */
+ enc_tkt_reply->times.authtime,
+ tgs_req ? enc_tkt_request->authorization_data : NULL,
+ &db_authdata,
+ &ad_entry,
+ &ad_nprincs);
+ if (code == KRB5_KDB_DBTYPE_NOSUP) {
+ assert(ad_nprincs == 0);
+ assert(db_authdata == NULL);
+
+ if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION))
+ return KRB5KDC_ERR_POLICY;
+
+ if (tgs_req)
+ return merge_authdata(context, enc_tkt_request->authorization_data,
+ &enc_tkt_reply->authorization_data, TRUE);
+ }
+
+ if (ad_nprincs != 0) {
+ if (tgs_req &&
+ isflagset(ad_entry.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))
+ clear(enc_tkt_reply->flags, TKT_FLG_FORWARDABLE);
+
+ krb5_db_free_principal(context, &ad_entry, ad_nprincs);
+
+ if (ad_nprincs != 1) {
+ if (db_authdata != NULL)
+ krb5_free_authdata(context, db_authdata);
+ return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
+ }
+ }
+
+ if (db_authdata != NULL) {
+ code = merge_authdata(context, db_authdata,
+ &enc_tkt_reply->authorization_data,
+ FALSE);
+ if (code != 0)
+ krb5_free_authdata(context, db_authdata);
+ }
+
+ return code;
+}
+
krb5_error_code
-handle_authdata (krb5_context context, krb5_db_entry *client,
- krb5_data *req_pkt, krb5_kdc_req *request,
+handle_authdata (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
krb5_enc_tkt_part *enc_tkt_reply)
{
- krb5_error_code retval = 0;
+ krb5_error_code code = 0;
int i;
- const char *emsg;
-#if 0
- krb5_klog_syslog (LOG_DEBUG, "handling authdata");
-#endif
-
+ assert(enc_tkt_reply->authorization_data == NULL);
for (i = 0; i < n_authdata_systems; i++) {
const krb5_authdata_systems *asys = &authdata_systems[i];
- if (asys->handle_authdata && asys->type != -1) {
- retval = asys->handle_authdata(context, client, req_pkt,
- request, enc_tkt_reply);
- if (retval) {
- emsg = krb5_get_error_message (context, retval);
- krb5_klog_syslog (LOG_INFO,
- "authdata (%s) handling failure: %s",
- asys->name, emsg);
- krb5_free_error_message (context, emsg);
- } else {
- krb5_klog_syslog (LOG_DEBUG, ".. .. ok");
- }
+
+ switch (asys->type) {
+ case AUTHDATA_SYSTEM_V0:
+ /* V0 was only in AS-REQ code path */
+ if (request->msg_type != KRB5_AS_REQ)
+ continue;
+
+ code = asys->handle_authdata.v0(context, client, req_pkt,
+ request, enc_tkt_reply);
+ break;
+ case AUTHDATA_SYSTEM_V1:
+ code = asys->handle_authdata.v1(context, flags, reply_client,
+ client, server, krbtgt,
+ client_key, server_key,
+ req_pkt, request, enc_tkt_request,
+ enc_tkt_reply);
+ default:
+ code = 0;
+ break;
}
+ if (code != 0) {
+ const char *emsg;
+
+ emsg = krb5_get_error_message (context, code);
+ krb5_klog_syslog (LOG_INFO,
+ "authdata (%s) handling failure: %s",
+ asys->name, emsg);
+ krb5_free_error_message (context, emsg);
+
+ if (asys->flags & AUTHDATA_FLAG_CRITICAL)
+ break;
+ }
}
- return 0;
+ return code;
}
+
Modified: branches/mskrb-integ/src/kdc/kdc_util.c
===================================================================
--- branches/mskrb-integ/src/kdc/kdc_util.c 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/kdc/kdc_util.c 2008-12-23 02:55:02 UTC (rev 21566)
@@ -1669,27 +1669,27 @@
}
krb5_error_code
-sign_authorization_data(krb5_context context,
- unsigned int flags,
- krb5_const_principal client_princ,
- krb5_db_entry *client,
- krb5_db_entry *server,
- krb5_db_entry *krbtgt,
- krb5_keyblock *client_key,
- krb5_keyblock *server_key,
- krb5_timestamp authtime,
- krb5_authdata **auth_data,
- krb5_authdata ***ret_auth_data,
- krb5_db_entry *ad_entry,
- int *ad_nprincs)
+sign_db_authdata (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal client_princ,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_timestamp authtime,
+ krb5_authdata **tgs_authdata,
+ krb5_authdata ***ret_authdata,
+ krb5_db_entry *ad_entry,
+ int *ad_nprincs)
{
- krb5_error_code code;
- kdb_sign_auth_data_req req;
- kdb_sign_auth_data_rep rep;
- krb5_data req_data;
- krb5_data rep_data;
+ krb5_error_code code;
+ kdb_sign_auth_data_req req;
+ kdb_sign_auth_data_rep rep;
+ krb5_data req_data;
+ krb5_data rep_data;
- *ret_auth_data = NULL;
+ *ret_authdata = NULL;
if (ad_entry != NULL) {
assert(ad_nprincs != NULL);
memset(ad_entry, 0, sizeof(*ad_entry));
@@ -1707,7 +1707,7 @@
req.client_key = client_key;
req.server_key = server_key;
req.authtime = authtime;
- req.auth_data = auth_data;
+ req.auth_data = tgs_authdata;
rep.entry = ad_entry;
rep.nprincs = 0;
@@ -1722,25 +1722,10 @@
KRB5_KDB_METHOD_SIGN_AUTH_DATA,
&req_data,
&rep_data);
- if (code == KRB5_KDB_DBTYPE_NOSUP) {
- /*
- * If the backend does not implement the sign auth data
- * method, then we just copy the authorization data into
- * the response, except for the constrained delegation
- * case (which requires special handling because it will
- * promote untrusted auth data to KDC issued auth data;
- * this requires backend specific code)
- */
- if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION))
- code = KRB5KDC_ERR_POLICY;
- else
- code = krb5_copy_authdata(context, auth_data, ret_auth_data);
- } else {
- *ret_auth_data = rep.auth_data;
- if (ad_nprincs != NULL)
- *ad_nprincs = rep.nprincs;
- }
+ *ret_authdata = rep.auth_data;
+ *ad_nprincs = rep.nprincs;
+
return code;
}
Modified: branches/mskrb-integ/src/kdc/kdc_util.h
===================================================================
--- branches/mskrb-integ/src/kdc/kdc_util.h 2008-12-23 02:39:51 UTC (rev 21565)
+++ branches/mskrb-integ/src/kdc/kdc_util.h 2008-12-23 02:55:02 UTC (rev 21566)
@@ -176,9 +176,19 @@
krb5_error_code load_authdata_plugins(krb5_context context);
krb5_error_code unload_authdata_plugins(krb5_context context);
-krb5_error_code handle_authdata (krb5_context context, krb5_db_entry *client,
- krb5_data *req_pkt, krb5_kdc_req *request,
- krb5_enc_tkt_part *enc_tkt_reply);
+krb5_error_code
+handle_authdata (krb5_context context,
+ unsigned int flags,
+ krb5_const_principal reply_client,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
/* replay.c */
krb5_boolean kdc_check_lookaside (krb5_data *, krb5_data **);
@@ -201,11 +211,11 @@
krb5_error_code return_svr_referral_data
(krb5_context context,
- krb5_db_entry *server,
- krb5_enc_kdc_rep_part *reply_encpart);
+ krb5_db_entry *server,
+ krb5_enc_kdc_rep_part *reply_encpart);
-krb5_error_code sign_authorization_data
- (krb5_context context,
+krb5_error_code sign_db_authdata
+ (krb5_context context,
unsigned int flags,
krb5_const_principal client_princ,
krb5_db_entry *client,
@@ -214,8 +224,8 @@
krb5_keyblock *client_key,
krb5_keyblock *server_key,
krb5_timestamp authtime,
- krb5_authdata **tgs_auth_data,
- krb5_authdata ***ret_auth_data,
+ krb5_authdata **tgs_authdata,
+ krb5_authdata ***ret_authdata,
krb5_db_entry *ad_entry,
int *ad_nprincs);
More information about the cvs-krb5
mailing list