summaryrefslogtreecommitdiffstats
path: root/src/lib/krb5/krb/mk_req_ext.c
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2009-01-03 23:19:42 +0000
committerSam Hartman <hartmans@mit.edu>2009-01-03 23:19:42 +0000
commit0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d (patch)
tree2049c9c2cb135fe36b14c0a171711259258d18ec /src/lib/krb5/krb/mk_req_ext.c
parentff0a6514c9f4230938c29922d69cbd4e83691adf (diff)
downloadkrb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.tar.gz
krb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.tar.xz
krb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.zip
Merge mskrb-integ onto trunk
The mskrb-integ branch includes support for the following projects: Projects/Aliases * Projects/PAC and principal APIs * Projects/AEAD encryption API * Projects/GSSAPI DCE * Projects/RFC 3244 In addition, it includes support for enctype negotiation, and a variety of GSS-API extensions. In the KDC it includes support for protocol transition, constrained delegation and a new authorization data interface. The old authorization data interface is also supported. This commit merges the mskrb-integ branch on to the trunk. Additional review and testing is required. Merge commit 'mskrb-integ' into trunk ticket: new status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21690 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5/krb/mk_req_ext.c')
-rw-r--r--src/lib/krb5/krb/mk_req_ext.c160
1 files changed, 150 insertions, 10 deletions
diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c
index 6d40e5de7a..4a9d03551f 100644
--- a/src/lib/krb5/krb/mk_req_ext.c
+++ b/src/lib/krb5/krb/mk_req_ext.c
@@ -64,16 +64,25 @@
returns system errors
*/
+static krb5_error_code
+make_etype_list(krb5_context context,
+ krb5_enctype *desired_etypes,
+ krb5_enctype tkt_enctype,
+ krb5_authdata ***authdata);
+
static krb5_error_code
krb5_generate_authenticator (krb5_context,
krb5_authenticator *, krb5_principal,
krb5_checksum *, krb5_keyblock *,
- krb5_ui_4, krb5_authdata ** );
+ krb5_ui_4, krb5_authdata **,
+ krb5_enctype *desired_etypes,
+ krb5_enctype tkt_enctype);
krb5_error_code
krb5int_generate_and_save_subkey (krb5_context context,
krb5_auth_context auth_context,
- krb5_keyblock *keyblock)
+ krb5_keyblock *keyblock,
+ krb5_enctype enctype)
{
/* Provide some more fodder for random number code.
This isn't strong cryptographically; the point here is not
@@ -92,7 +101,8 @@ krb5int_generate_and_save_subkey (krb5_context context,
if (auth_context->send_subkey)
krb5_free_keyblock(context, auth_context->send_subkey);
- if ((retval = krb5_generate_subkey(context, keyblock, &auth_context->send_subkey)))
+ if ((retval = krb5_generate_subkey_extended(context, keyblock, enctype,
+ &auth_context->send_subkey)))
return retval;
if (auth_context->recv_subkey)
@@ -116,18 +126,23 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
krb5_checksum checksum;
krb5_checksum *checksump = 0;
krb5_auth_context new_auth_context;
+ krb5_enctype *desired_etypes = NULL;
krb5_ap_req request;
krb5_data *scratch = 0;
krb5_data *toutbuf;
request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
- request.authenticator.ciphertext.data = 0;
+ request.authenticator.ciphertext.data = NULL;
request.ticket = 0;
if (!in_creds->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
+ if ((ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) &&
+ !(ap_req_options & AP_OPTS_MUTUAL_REQUIRED))
+ return(EINVAL);
+
/* we need a native ticket */
if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
return(retval);
@@ -174,7 +189,8 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->send_subkey)) {
retval = krb5int_generate_and_save_subkey (context, *auth_context,
- &in_creds->keyblock);
+ &in_creds->keyblock,
+ in_creds->keyblock.enctype);
if (retval)
goto cleanup;
}
@@ -205,12 +221,23 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
goto cleanup_cksum;
}
+ if (ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) {
+ if ((*auth_context)->permitted_etypes == NULL) {
+ retval = krb5_get_tgs_ktypes(context, in_creds->server, &desired_etypes);
+ if (retval)
+ goto cleanup_cksum;
+ } else
+ desired_etypes = (*auth_context)->permitted_etypes;
+ }
+
if ((retval = krb5_generate_authenticator(context,
(*auth_context)->authentp,
- (in_creds)->client, checksump,
+ in_creds->client, checksump,
(*auth_context)->send_subkey,
(*auth_context)->local_seq_number,
- (in_creds)->authdata)))
+ in_creds->authdata,
+ desired_etypes,
+ in_creds->keyblock.enctype)))
goto cleanup_cksum;
/* encode the authenticator */
@@ -223,7 +250,6 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
*/
(*auth_context)->authentp->client = NULL;
(*auth_context)->authentp->checksum = NULL;
- (*auth_context)->authentp->authorization_data = NULL;
/* call the encryption routine */
if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
@@ -242,6 +268,9 @@ cleanup_cksum:
free(checksump->contents);
cleanup:
+ if (desired_etypes &&
+ desired_etypes != (*auth_context)->permitted_etypes)
+ krb5_xfree(desired_etypes);
if (request.ticket)
krb5_free_ticket(context, request.ticket);
if (request.authenticator.ciphertext.data) {
@@ -261,7 +290,9 @@ static krb5_error_code
krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent,
krb5_principal client, krb5_checksum *cksum,
krb5_keyblock *key, krb5_ui_4 seq_number,
- krb5_authdata **authorization)
+ krb5_authdata **authorization,
+ krb5_enctype *desired_etypes,
+ krb5_enctype tkt_enctype)
{
krb5_error_code retval;
@@ -274,7 +305,116 @@ krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent,
} else
authent->subkey = 0;
authent->seq_number = seq_number;
- authent->authorization_data = authorization;
+ authent->authorization_data = NULL;
+
+ if (authorization != NULL) {
+ retval = krb5_copy_authdata(context, authorization,
+ &authent->authorization_data);
+ if (retval)
+ return retval;
+ }
+ /* Only send EtypeList if we prefer another enctype to tkt_enctype */
+ if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) {
+ retval = make_etype_list(context, desired_etypes, tkt_enctype,
+ &authent->authorization_data);
+ if (retval)
+ return retval;
+ }
return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));
}
+
+/* RFC 4537 */
+static krb5_error_code
+make_etype_list(krb5_context context,
+ krb5_enctype *desired_etypes,
+ krb5_enctype tkt_enctype,
+ krb5_authdata ***authdata)
+{
+ krb5_error_code code;
+ krb5_etype_list etypes;
+ krb5_data *enc_etype_list;
+ krb5_data *ad_if_relevant;
+ krb5_authdata *etype_adata[2], etype_adatum, **adata;
+ int i;
+
+ etypes.etypes = desired_etypes;
+
+ for (etypes.length = 0;
+ etypes.etypes[etypes.length] != ENCTYPE_NULL;
+ etypes.length++)
+ ;
+
+ /*
+ * RFC 4537:
+ *
+ * If the enctype of the ticket session key is included in the enctype
+ * list sent by the client, it SHOULD be the last on the list;
+ */
+ for (i = 0; i < etypes.length; i++) {
+ if (etypes.etypes[i] == tkt_enctype) {
+ krb5_enctype etype;
+
+ etype = etypes.etypes[etypes.length - 1];
+ etypes.etypes[etypes.length - 1] = tkt_enctype;
+ etypes.etypes[i] = etype;
+ break;
+ }
+ }
+
+ code = encode_krb5_etype_list(&etypes, &enc_etype_list);
+ if (code) {
+ return code;
+ }
+
+ etype_adatum.magic = KV5M_AUTHDATA;
+ etype_adatum.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION;
+ etype_adatum.length = enc_etype_list->length;
+ etype_adatum.contents = (krb5_octet *)enc_etype_list->data;
+
+ etype_adata[0] = &etype_adatum;
+ etype_adata[1] = NULL;
+
+ /* Wrap in AD-IF-RELEVANT container */
+ code = encode_krb5_authdata(etype_adata, &ad_if_relevant);
+ if (code) {
+ krb5_free_data(context, enc_etype_list);
+ return code;
+ }
+
+ krb5_free_data(context, enc_etype_list);
+
+ adata = *authdata;
+ if (adata == NULL) {
+ adata = (krb5_authdata **)calloc(2, sizeof(krb5_authdata *));
+ i = 0;
+ } else {
+ for (i = 0; adata[i] != NULL; i++)
+ ;
+
+ adata = (krb5_authdata **)realloc(*authdata,
+ (i + 2) * sizeof(krb5_authdata *));
+ }
+ if (adata == NULL) {
+ krb5_free_data(context, ad_if_relevant);
+ return ENOMEM;
+ }
+
+ adata[i] = (krb5_authdata *)malloc(sizeof(krb5_authdata));
+ if (adata[i] == NULL) {
+ krb5_free_data(context, ad_if_relevant);
+ return ENOMEM;
+ }
+ adata[i]->magic = KV5M_AUTHDATA;
+ adata[i]->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+ adata[i]->length = ad_if_relevant->length;
+ adata[i]->contents = (krb5_octet *)ad_if_relevant->data;
+ krb5_xfree(ad_if_relevant); /* contents owned by adata[i] */
+
+ adata[i + 1] = NULL;
+
+ *authdata = adata;
+
+ return 0;
+}
+