diff options
Diffstat (limited to 'src/kdc/kdc_preauth.c')
| -rw-r--r-- | src/kdc/kdc_preauth.c | 211 |
1 files changed, 202 insertions, 9 deletions
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index c7655ab0d..51c16739d 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -51,6 +51,33 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The copyright holder's name is not used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #include "k5-int.h" #include "kdc_util.h" @@ -311,6 +338,27 @@ static krb5_preauth_systems static_preauth_systems[] = { 0, 0 }, + { + "pac-request", + KRB5_PADATA_PAC_REQUEST, + PA_PSEUDO, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, +#if 0 + { + "server-referral", + KRB5_PADATA_SERVER_REFERRAL, + PA_PSEUDO, + 0, + 0, + return_server_referral + }, +#endif { "[end]", -1,} }; @@ -323,7 +371,7 @@ load_preauth_plugins(krb5_context context) { void **preauth_plugins_ftables; struct krb5plugin_preauth_server_ftable_v1 *ftable; - int module_count, i, j, k; + size_t module_count, i, j, k; void *plugin_context; preauth_server_init_proc server_init_proc = NULL; char **kdc_realm_names = NULL; @@ -381,7 +429,7 @@ load_preauth_plugins(krb5_context context) krb5int_free_plugin_dir_data(preauth_plugins_ftables); return ENOMEM; } - for (i = 0; i < kdc_numrealms; i++) { + for (i = 0; i < (size_t)kdc_numrealms; i++) { kdc_realm_names[i] = kdc_realmlist[i]->realm_name; } kdc_realm_names[i] = NULL; @@ -1102,11 +1150,12 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, krb5_klog_syslog (LOG_INFO, "no valid preauth type found: %s", emsg); krb5_free_error_message(context, emsg); } + /* The following switch statement allows us * to return some preauth system errors back to the client. */ switch(retval) { - case KRB5KRB_AP_ERR_BAD_INTEGRITY: + case 0: /* in case of PA-PAC-REQUEST with no PA-ENC-TIMESTAMP */ case KRB5KRB_AP_ERR_SKEW: case KRB5KDC_ERR_ETYPE_NOSUPP: /* rfc 4556 */ @@ -1130,6 +1179,7 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ return retval; + case KRB5KRB_AP_ERR_BAD_INTEGRITY: default: return KRB5KDC_ERR_PREAUTH_FAILED; } @@ -1293,7 +1343,7 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client, krb5_timestamp timenow; krb5_error_code decrypt_err = 0; - scratch.data = pa->contents; + scratch.data = (char *)pa->contents; scratch.length = pa->length; enc_ts_data.data = 0; @@ -1599,7 +1649,7 @@ etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, if (retval) goto cleanup; - tmp_padata->contents = scratch->data; + tmp_padata->contents = (krb5_octet *)scratch->data; tmp_padata->length = scratch->length; *send_pa = tmp_padata; @@ -1769,7 +1819,7 @@ return_sam_data(krb5_context context, krb5_pa_data *in_padata, * all this once. */ - scratch.data = in_padata->contents; + scratch.data = (char *)in_padata->contents; scratch.length = in_padata->length; if ((retval = decode_krb5_sam_response(&scratch, &sr))) { @@ -2079,7 +2129,7 @@ get_sam_edata(krb5_context context, krb5_kdc_req *request, if (retval) goto cleanup; pa_data->magic = KV5M_PA_DATA; pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; - pa_data->contents = scratch->data; + pa_data->contents = (krb5_octet *)scratch->data; pa_data->length = scratch->length; retval = 0; @@ -2247,7 +2297,7 @@ sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); if (retval) goto cleanup; pa_data->magic = KV5M_PA_DATA; pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; - pa_data->contents = scratch->data; + pa_data->contents = (krb5_octet *)scratch->data; pa_data->length = scratch->length; retval = 0; @@ -2278,7 +2328,7 @@ verify_sam_response(krb5_context context, krb5_db_entry *client, krb5_timestamp timenow; char *princ_req = 0, *princ_psr = 0; - scratch.data = pa->contents; + scratch.data = (char *)pa->contents; scratch.length = pa->length; if ((retval = decode_krb5_sam_response(&scratch, &sr))) { @@ -2847,3 +2897,146 @@ cleanup: } #endif /* APPLE_PKINIT */ + +/* + * Returns TRUE if the PAC should be included + */ +krb5_boolean +include_pac_p(krb5_context context, krb5_kdc_req *request) +{ + krb5_error_code code; + krb5_pa_data **padata; + krb5_boolean retval = TRUE; /* default is to return PAC */ + krb5_data data; + krb5_pa_pac_req *req = NULL; + + if (request->padata == NULL) { + return retval; + } + + for (padata = request->padata; *padata != NULL; padata++) { + if ((*padata)->pa_type == KRB5_PADATA_PAC_REQUEST) { + data.data = (char *)(*padata)->contents; + data.length = (*padata)->length; + + code = decode_krb5_pa_pac_req(&data, &req); + if (code == 0) { + retval = req->include_pac; + krb5_free_pa_pac_req(context, req); + req = NULL; + } + break; + } + } + + return retval; +} + +krb5_error_code +return_svr_referral_data(krb5_context context, + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart) +{ + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; + + /* This should be initialized and only used for Win2K compat */ + assert(reply_encpart->enc_padata == NULL); + + tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA; + + code = krb5_dbe_lookup_tl_data(context, server, &tl_data); + if (code || tl_data.tl_data_length == 0) + return 0; /* no server referrals to return */ + + pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); + if (pa_data == NULL) + return ENOMEM; + + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; + pa_data->length = tl_data.tl_data_length; + pa_data->contents = malloc(pa_data->length); + if (pa_data->contents == NULL) { + free(pa_data); + return ENOMEM; + } + memcpy(pa_data->contents, tl_data.tl_data_contents, tl_data.tl_data_length); + + reply_encpart->enc_padata = (krb5_pa_data **)calloc(2, sizeof(krb5_pa_data *)); + if (reply_encpart->enc_padata == NULL) { + free(pa_data->contents); + free(pa_data); + return ENOMEM; + } + + reply_encpart->enc_padata[0] = pa_data; + reply_encpart->enc_padata[1] = NULL; + + return 0; +} + +#if 0 +static krb5_error_code return_server_referral(krb5_context context, + krb5_pa_data * padata, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa) +{ + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; + krb5_enc_data enc_data; + krb5_data plain; + krb5_data *enc_pa_data; + + *send_pa = NULL; + + tl_data.tl_data_type = KRB5_TL_SERVER_REFERRAL; + + code = krb5_dbe_lookup_tl_data(context, server, &tl_data); + if (code || tl_data.tl_data_length == 0) + return 0; /* no server referrals to return */ + + plain.length = tl_data.tl_data_length; + plain.data = tl_data.tl_data_contents; + + /* Encrypt ServerReferralData */ + code = krb5_encrypt_helper(context, encrypting_key, + KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA, + &plain, &enc_data); + if (code) + return code; + + /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */ + code = encode_krb5_enc_data(&enc_data, &enc_pa_data); + if (code) { + krb5_free_data_contents(context, &enc_data.ciphertext); + return code; + } + + krb5_free_data_contents(context, &enc_data.ciphertext); + + /* Return PA-SERVER-REFERRAL-DATA */ + pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); + if (pa_data == NULL) { + krb5_free_data(context, enc_pa_data); + return ENOMEM; + } + + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; + pa_data->length = enc_pa_data->length; + pa_data->contents = enc_pa_data->data; + + free(enc_pa_data); /* don't free contents */ + + *send_pa = pa_data; + + return 0; +} +#endif |
