From c7a37c2524a4cfa1e7c812c555f9c5c93d9be98e Mon Sep 17 00:00:00 2001 From: Mark Eichin Date: Tue, 9 Apr 1996 22:57:14 +0000 Subject: [PATCH] preauth.c: add SAM support str_conv.c: add AFS3 support init_ctx.c: add processing for default_tkt_enctypes, matching default_tgs_enctypes but client-side (so as not to hard code it, since hard coded values are usually wrong :-) git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7773 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/krb/init_ctx.c | 82 ++++++++++-- src/lib/krb5/krb/preauth.c | 252 +++++++++++++++++++++++++++++++++++- src/lib/krb5/krb/str_conv.c | 5 +- 3 files changed, 322 insertions(+), 17 deletions(-) diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index 14ca0a653..96c406535 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -136,16 +136,8 @@ krb5_set_default_in_tkt_ktypes(context, ktypes) return ENOMEM; } else { - i = 3; - - /* Should reset the list to the runtime defaults */ - if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) { - new_ktypes[0] = ENCTYPE_DES3_CBC_MD5; - new_ktypes[1] = ENCTYPE_DES_CBC_MD5; - new_ktypes[2] = ENCTYPE_DES_CBC_CRC; - } else { - return ENOMEM; - } + i = 0; + new_ktypes = 0; } if (context->in_tkt_ktypes) @@ -162,13 +154,75 @@ krb5_get_default_in_tkt_ktypes(context, ktypes) { krb5_enctype * old_ktypes; - if ((old_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * - (context->in_tkt_ktype_count + 1)))) { + if (context->in_tkt_ktype_count) { + /* application-set defaults */ + if ((old_ktypes = + (krb5_enctype *)malloc(sizeof(krb5_enctype) * + (context->in_tkt_ktype_count + 1)))) { memcpy(old_ktypes, context->in_tkt_ktypes, sizeof(krb5_enctype) * - context->in_tkt_ktype_count); + context->in_tkt_ktype_count); old_ktypes[context->in_tkt_ktype_count] = 0; - } else { + } else { return ENOMEM; + } + } else { + /* taken directly from krb5_get_tgs_ktypes... */ + /* + XXX - For now, we only support libdefaults + Perhaps this should be extended to allow for per-host / per-realm + session key types. + */ + + char *retval; + char *sp, *ep; + int i, j, count; + krb5_error_code code; + + code = profile_get_string(context->profile, + "libdefaults", "default_tkt_enctypes", NULL, + "des3-cbc-md5 des-cbc-md5 des-cbc-crc", + &retval); + if (code) + return code; + + count = 0; + sp = retval; + while (sp) { + for (ep = sp; *ep && (*ep != ',') && !isspace(*ep); ep++) + ; + if (*ep) { + *ep++ = '\0'; + while (isspace(*ep)) + ep++; + } else + ep = (char *) NULL; + + count++; + sp = ep; + } + + if ((old_ktypes = + (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) == + (krb5_enctype *) NULL) + return ENOMEM; + + sp = retval; + j = 0; + i = 1; + while (1) { + if (! krb5_string_to_enctype(sp, &old_ktypes[j])) + j++; + + if (i++ >= count) + break; + + /* skip to next token */ + while (*sp) sp++; + while (! *sp) sp++; + } + + old_ktypes[j] = (krb5_enctype) 0; + free(retval); } *ktypes = old_ktypes; diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c index e062f0606..a266d9bc9 100644 --- a/src/lib/krb5/krb/preauth.c +++ b/src/lib/krb5/krb/preauth.c @@ -26,7 +26,6 @@ * kerberos kdc request, with various hardware/software verification devices. */ - #include "k5-int.h" #include #include @@ -71,6 +70,21 @@ KRB5_NPROTOTYPE((krb5_context, krb5_int32 *, krb5_int32 *)); +static krb5_error_code obtain_sam_padata +KRB5_NPROTOTYPE((krb5_context, + krb5_pa_data *, + krb5_etype_info, + krb5_keyblock *, + krb5_error_code ( * )(krb5_context, + krb5_const krb5_enctype, + krb5_data *, + krb5_const_pointer, + krb5_keyblock **), + krb5_const_pointer, + krb5_creds *, + krb5_kdc_req *, + krb5_pa_data **)); + static krb5_preauth_ops preauth_systems[] = { { KV5M_PREAUTH_OPS, @@ -86,6 +100,20 @@ static krb5_preauth_ops preauth_systems[] = { 0, process_pw_salt, }, + { + KV5M_PREAUTH_OPS, + KRB5_PADATA_AFS3_SALT, + 0, + 0, + process_pw_salt, + }, + { + KV5M_PREAUTH_OPS, + KRB5_PADATA_SAM_CHALLENGE, + 0, + obtain_sam_padata, + 0, + }, { KV5M_PREAUTH_OPS, -1 } }; @@ -335,7 +363,8 @@ process_pw_salt(context, padata, request, as_reply, return 0; salt.data = (char *) padata->contents; - salt.length = padata->length; + salt.length = + (padata->pa_type == KRB5_PADATA_AFS3_SALT)?(-1):(padata->length); if ((retval = (*key_proc)(context, as_reply->enc_part.enctype, &salt, keyseed, decrypt_key))) { @@ -361,3 +390,222 @@ find_pa_system(type, preauth) return 0; } + +extern char *krb5_default_pwd_prompt1; + +static krb5_error_code +sam_get_pass_from_user(context, etype_info, key_proc, key_seed, request, + new_enc_key, prompt) + krb5_context context; + krb5_etype_info etype_info; + git_key_proc key_proc; + krb5_const_pointer key_seed; + krb5_kdc_req * request; + krb5_keyblock ** new_enc_key; + const char * prompt; +{ + krb5_enctype enctype; + krb5_error_code retval; + char *oldprompt; + + /* enctype = request->ktype[0]; */ + enctype = ENCTYPE_DES_CBC_MD5; +/* hack with this first! */ + oldprompt = krb5_default_pwd_prompt1; + krb5_default_pwd_prompt1 = prompt; + { + krb5_data newpw; + newpw.data = 0; newpw.length = 0; + /* we don't keep the new password, just the key... */ + retval = (*key_proc)(context, enctype, 0, + (krb5_const_pointer)&newpw, new_enc_key); + krb5_xfree(newpw.data); + } + krb5_default_pwd_prompt1 = oldprompt; + return retval; +} +static +char *handle_sam_labels(sc) + krb5_sam_challenge *sc; +{ + char *label = sc->sam_challenge_label.data; + int label_len = sc->sam_challenge_label.length; + char *prompt = sc->sam_response_prompt.data; + int prompt_len = sc->sam_response_prompt.length; + char *challenge = sc->sam_challenge.data; + int challenge_len = sc->sam_challenge.length; + char *prompt1, *p; + char *sep1 = ": ["; + char *sep2 = "]\n"; + char *sep3 = ": "; + + if (sc->sam_cksum.length == 0) { + /* or invalid -- but lets just handle presence now XXX */ + switch (sc->sam_type) { + case PA_SAM_TYPE_ENIGMA: /* Enigma Logic */ + label = "Challenge for Enigma Logic mechanism"; + break; + case PA_SAM_TYPE_DIGI_PATH: /* Digital Pathways */ + label = "Challenge for Digital Pathways mechanism"; + break; + case PA_SAM_TYPE_SKEY_K0: /* S/key where KDC has key 0 */ + label = "Challenge for Enhanced S/Key mechanism"; + break; + case PA_SAM_TYPE_SKEY: /* Traditional S/Key */ + label = "Challenge for Traditional S/Key mechanism"; + break; + case PA_SAM_TYPE_SECURID: /* Security Dynamics */ + label = "Challenge for Security Dynamics mechanism"; + break; + } + prompt = "Passcode"; + label_len = strlen(label); + prompt_len = strlen(prompt); + } + + /* example: + Challenge for Digital Pathways mechanism: [134591] + Passcode: + */ + p = prompt1 = malloc(label_len + strlen(sep1) + + challenge_len + strlen(sep2) + + prompt_len+ strlen(sep3) + 1); + strncpy(p, label, label_len); p += label_len; + strcpy(p, sep1); p += strlen(sep1); + strncpy(p, challenge, challenge_len); p += challenge_len; + strcpy(p, sep2); p += strlen(sep2); + strncpy(p, prompt, prompt_len); p += prompt_len; + strcpy(p, sep3); /* p += strlen(sep3); */ + return prompt1; +} + +/* + * This routine is the "obtain" function for the SAM_CHALLENGE + * preauthentication type. It presents the challenge... + */ +static krb5_error_code +obtain_sam_padata(context, in_padata, etype_info, def_enc_key, + key_proc, key_seed, creds, request, out_padata) + krb5_context context; + krb5_pa_data * in_padata; + krb5_etype_info etype_info; + krb5_keyblock * def_enc_key; + git_key_proc key_proc; + krb5_const_pointer key_seed; + krb5_creds * creds; + krb5_kdc_req * request; + krb5_pa_data ** out_padata; +{ + krb5_pa_enc_ts pa_enc; + krb5_error_code retval; + krb5_data * scratch; + krb5_data tmpsam; + krb5_pa_data * pa; + krb5_sam_challenge *sam_challenge = 0; + krb5_sam_response sam_response; + /* these two get encrypted and stuffed in to sam_response */ + krb5_enc_sam_response_enc enc_sam_response_enc; + krb5_keyblock * sam_use_key = 0; + char * prompt; + + tmpsam.length = in_padata->length; + tmpsam.data = in_padata->contents; + retval = decode_krb5_sam_challenge(&tmpsam, &sam_challenge); + if (retval) + return retval; + + if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) { + return KRB5_SAM_UNSUPPORTED; + } + + enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce; + if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) { + /* encrypt passcode in key by stuffing it here */ + int pcsize = 256; + char *passcode = malloc(pcsize+1); + prompt = handle_sam_labels(sam_challenge); + retval = krb5_read_password(context, prompt, 0, passcode, &pcsize); + free(prompt); + + if (retval) { + free(passcode); + return retval; + } + enc_sam_response_enc.sam_passcode.data = passcode; + enc_sam_response_enc.sam_passcode.length = pcsize; + } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) { + if (sam_challenge->sam_nonce) { + /* use nonce in the next AS request? */ + } else { + retval = krb5_us_timeofday(context, + &enc_sam_response_enc.sam_timestamp, + &enc_sam_response_enc.sam_usec); + sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp; + } + if (retval) + return retval; + prompt = handle_sam_labels(sam_challenge); + retval = sam_get_pass_from_user(context, etype_info, key_proc, + key_seed, request, &sam_use_key, + prompt); + free(prompt); + if (retval) + return retval; + enc_sam_response_enc.sam_passcode.length = 0; + } else { + /* what *was* it? */ + return KRB5_SAM_UNSUPPORTED; + } + + /* so at this point, either sam_use_key is generated from the passcode + * or enc_sam_response_enc.sam_passcode is set to it, and we use + * def_enc_key instead. */ + /* encode the encoded part of the response */ + if ((retval = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc, + &scratch)) != 0) + return retval; + + if ((retval = krb5_encrypt_data(context, + sam_use_key?sam_use_key:def_enc_key, + 0, scratch, + &sam_response.sam_enc_nonce_or_ts))) + goto cleanup; + + krb5_free_data(context, scratch); + scratch = 0; + + /* sam_enc_key is reserved for future use */ + sam_response.sam_enc_key.ciphertext.length = 0; + + /* copy things from the challenge */ + sam_response.sam_nonce = sam_challenge->sam_nonce; + sam_response.sam_flags = sam_challenge->sam_flags; + sam_response.sam_track_id = sam_challenge->sam_track_id; + sam_response.sam_type = sam_challenge->sam_type; + sam_response.magic = KV5M_SAM_RESPONSE; + + if ((retval = encode_krb5_sam_response(&sam_response, &scratch)) != 0) + return retval; + + if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + pa->magic = KV5M_PA_DATA; + pa->pa_type = KRB5_PADATA_SAM_RESPONSE; + pa->length = scratch->length; + pa->contents = scratch->data; + scratch = 0; /* so we don't free it! */ + + *out_padata = pa; + + retval = 0; + +cleanup: + if (scratch) + krb5_free_data(context, scratch); + if (sam_challenge) + krb5_xfree(sam_challenge); + return retval; +} diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c index fea6d6b2f..854ac9189 100644 --- a/src/lib/krb5/krb/str_conv.c +++ b/src/lib/krb5/krb/str_conv.c @@ -104,11 +104,13 @@ static const char stype_v4_in[] = "v4"; static const char stype_norealm_in[] = "norealm"; static const char stype_olrealm_in[] = "onlyrealm"; static const char stype_special_in[] = "special"; +static const char stype_afs3_in[] = "afs3"; static const char stype_v5_out[] = "Version 5"; static const char stype_v4_out[] = "Version 4"; static const char stype_norealm_out[] = "Version 5 - No Realm"; static const char stype_olrealm_out[] = "Version 5 - Realm Only"; static const char stype_special_out[] = "Special"; +static const char stype_afs3_out[] = "AFS version 3"; /* Checksum type strings */ static const char cstype_crc32_in[] = "crc32"; @@ -195,7 +197,8 @@ static const struct salttype_lookup_entry salttype_table[] = { { KRB5_KDB_SALTTYPE_V4, stype_v4_in, stype_v4_out }, { KRB5_KDB_SALTTYPE_NOREALM, stype_norealm_in, stype_norealm_out }, { KRB5_KDB_SALTTYPE_ONLYREALM, stype_olrealm_in, stype_olrealm_out }, -{ KRB5_KDB_SALTTYPE_SPECIAL, stype_special_in, stype_special_out } +{ KRB5_KDB_SALTTYPE_SPECIAL, stype_special_in, stype_special_out }, +{ KRB5_KDB_SALTTYPE_AFS3, stype_afs3_in, stype_afs3_out } }; static const int salttype_table_nents = sizeof(salttype_table)/ sizeof(salttype_table[0]); -- 2.26.2