diff options
author | Sam Hartman <hartmans@mit.edu> | 2009-01-03 23:19:42 +0000 |
---|---|---|
committer | Sam Hartman <hartmans@mit.edu> | 2009-01-03 23:19:42 +0000 |
commit | 0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d (patch) | |
tree | 2049c9c2cb135fe36b14c0a171711259258d18ec /src/lib/krb5/krb/mk_req_ext.c | |
parent | ff0a6514c9f4230938c29922d69cbd4e83691adf (diff) | |
download | krb5-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.c | 160 |
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; +} + |