diff options
| author | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
|---|---|---|
| committer | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
| commit | 1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch) | |
| tree | 9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/kdc | |
| parent | 61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (diff) | |
pull up 3des implementation from the marc-3des branch
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kdc')
| -rw-r--r-- | src/kdc/ChangeLog | 53 | ||||
| -rw-r--r-- | src/kdc/do_as_req.c | 27 | ||||
| -rw-r--r-- | src/kdc/do_tgs_req.c | 59 | ||||
| -rw-r--r-- | src/kdc/extern.h | 2 | ||||
| -rw-r--r-- | src/kdc/kdc_preauth.c | 256 | ||||
| -rw-r--r-- | src/kdc/kdc_util.c | 115 | ||||
| -rw-r--r-- | src/kdc/kerberos_v4.c | 240 | ||||
| -rw-r--r-- | src/kdc/main.c | 84 |
8 files changed, 511 insertions, 325 deletions
diff --git a/src/kdc/ChangeLog b/src/kdc/ChangeLog index 30cf89bdd..757ac7dc5 100644 --- a/src/kdc/ChangeLog +++ b/src/kdc/ChangeLog @@ -1,3 +1,56 @@ +1998-10-27 Marc Horowitz <marc@mit.edu> + + * do_as_req.c, do_tgs_req.c, extern.h, kdc_preauth.c, kdc_util.c, + kerberos_v4.c, main.c: conver to new crypto api. + +Fri Sep 25 19:47:26 1998 Tom Yu <tlyu@mit.edu> + + * kerberos_v4.c (check_princ): Re-order if statements that check + for null keys to make Purify shut up. + +Thu Sep 17 18:21:51 1998 Tom Yu <tlyu@mit.edu> + + * kdc_util.c (kdc_get_server_key): Fix to not use cached tgs key + to prevent lossage when it might be out of date by always fetching + the correct kvno for the ticket out of the database. + +Tue Sep 1 19:34:30 1998 Tom Yu <tlyu@mit.edu> + + * kerberos_v4.c (compat_decrypt_key): Add + ENCTYPE_LOCAL_DES3_HMAC_SHA1 to the list of keytypes to bash. + (kerb_get_principal): Add ENCTYPE_LOCAL_DES3_HMAC_SHA1 to the list + of searched enctypes. + +Wed Aug 19 13:37:00 1998 Tom Yu <tlyu@mit.edu> + + * kerberos_v4.c (set_tgtkey): Add kvno arg to fetch an explicit + kvno. Also compare kvno as well as realm when caching the TGT + key. Declare as static. + (kerb_get_principal): Add kvno argument to permit searching for + an explicit kvno. + (kerberos_v4): Extract the kvno directly out of the krb_req, since + we know what the format is. + +Wed Aug 12 18:40:08 1998 Tom Yu <tlyu@mit.edu> + + * kerberos_v4.c: Add macro K4KDC_ENCTYPE_OK to determine whether a + given enctype is compatible with single-DES krb4. + (compat_decrypt_key): Declare as static. Change call signature to + include an output krb5_keyblock as well as an input to determine + whether the principal should be treated as a service principal. + Bash the enctype of the keyblock to raw des3 if it's full-blown + des3. + (kerb_get_principal): Add k5key and issrv arguments as in + compat_decrypt_key, mostly to pass them on there. Hardcode a + search order that includes des3 for looking up service keys. + (kerberos_v4): Call krb_create_ticket or krb_cr_tkt_krb5 as + appropriate to the key type. While we're at it, s/ktbtgt/krbtgt/ + just to avoid confusing people. + (check_princ): Add k5key and issrv args for as in + compat_decrypt_key. Fix up null key detection to only operate if + it's a single-des key. + (set_tgtkey): Call krb_set_key_krb5 if appropriate. + Tue Jul 21 20:29:38 1998 Tom Yu <tlyu@mit.edu> * replay.c (kdc_check_lookaside): diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 22d5b1b56..b6fa39d3d 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -65,10 +65,9 @@ krb5_data **response; /* filled in with a response packet */ int c_nprincs = 0, s_nprincs = 0; krb5_boolean more; krb5_timestamp kdc_time, authtime; - krb5_keyblock *session_key = 0; + krb5_keyblock session_key; krb5_keyblock encrypting_key; const char *status; - krb5_encrypt_block eblock; krb5_key_data *server_key, *client_key; krb5_enctype useenctype; #ifdef KRBCONF_KDC_MODIFIES_KDB @@ -82,6 +81,7 @@ krb5_data **response; /* filled in with a response packet */ ticket_reply.enc_part.ciphertext.data = 0; e_data.data = 0; encrypting_key.contents = 0; + session_key.contents = 0; #ifdef HAVE_NETINET_IN_H if (from->address->addrtype == ADDRTYPE_INET) @@ -172,12 +172,9 @@ krb5_data **response; /* filled in with a response packet */ errcode = KRB5KDC_ERR_ETYPE_NOSUPP; goto errout; } - krb5_use_enctype(kdc_context, &eblock, useenctype); - - if ((errcode = krb5_random_key(kdc_context, &eblock, - krb5_enctype_array[useenctype]->random_sequence, - &session_key))) { - /* random key failed */ + + if ((errcode = krb5_c_make_random_key(kdc_context, useenctype, + &session_key))) { status = "RANDOM_KEY_FAILED"; goto errout; } @@ -200,7 +197,7 @@ krb5_data **response; /* filled in with a response packet */ if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE)) setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE); - enc_tkt_reply.session = session_key; + enc_tkt_reply.session = &session_key; enc_tkt_reply.client = request->client; enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */ @@ -312,7 +309,7 @@ krb5_data **response; /* filled in with a response packet */ /* convert server.key into a real key (it may be encrypted in the database) */ - if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, server_key, &encrypting_key, NULL))) { status = "DECRYPT_SERVER_KEY"; @@ -353,7 +350,7 @@ krb5_data **response; /* filled in with a response packet */ } /* convert client.key_data into a real key */ - if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, client_key, &encrypting_key, NULL))) { status = "DECRYPT_CLIENT_KEY"; @@ -366,7 +363,7 @@ krb5_data **response; /* filled in with a response packet */ reply.padata = 0; reply.client = request->client; reply.ticket = &ticket_reply; - reply_encpart.session = session_key; + reply_encpart.session = &session_key; if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) { status = "FETCH_LAST_REQ"; goto errout; @@ -397,7 +394,7 @@ krb5_data **response; /* filled in with a response packet */ reply.enc_part.enctype = encrypting_key.enctype; errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, - &encrypting_key, &reply, response); + 0, &encrypting_key, &reply, response); krb5_free_keyblock_contents(kdc_context, &encrypting_key); encrypting_key.contents = 0; @@ -465,8 +462,8 @@ errout: } if (s_nprincs) krb5_db_free_principal(kdc_context, &server, s_nprincs); - if (session_key) - krb5_free_keyblock(kdc_context, session_key); + if (session_key.contents) + krb5_free_keyblock_contents(kdc_context, &session_key); if (ticket_reply.enc_part.ciphertext.data) { memset(ticket_reply.enc_part.ciphertext.data , 0, ticket_reply.enc_part.ciphertext.length); diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index ff6f214d3..7faf748da 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -62,7 +62,6 @@ int portnum; krb5_data **response; /* filled in with a response packet */ { krb5_keyblock * subkey; - krb5_encrypt_block eblock; krb5_kdc_req *request = 0; krb5_db_entry server; krb5_kdc_rep reply; @@ -76,7 +75,7 @@ krb5_data **response; /* filled in with a response packet */ int nprincs = 0; krb5_boolean more; krb5_timestamp kdc_time, authtime=0; - krb5_keyblock *session_key = 0; + krb5_keyblock session_key; krb5_timestamp until, rtime; krb5_keyblock encrypting_key; krb5_key_data *server_key; @@ -88,6 +87,8 @@ krb5_data **response; /* filled in with a response packet */ register int i; int firstpass = 1; const char *status = 0; + + session_key.contents = 0; retval = decode_krb5_tgs_req(pkt, &request); if (retval) @@ -258,10 +259,8 @@ tgt_again: goto cleanup; } - krb5_use_enctype(kdc_context, &eblock, useenctype); - errcode = krb5_random_key(kdc_context, &eblock, - krb5_enctype_array[useenctype]->random_sequence, - &session_key); + errcode = krb5_c_make_random_key(kdc_context, useenctype, &session_key); + if (errcode) { /* random key failed */ status = "RANDOM_KEY_FAILED"; @@ -404,20 +403,8 @@ tgt_again: /* assemble any authorization data */ if (request->authorization_data.ciphertext.data) { - krb5_encrypt_block eblock; krb5_data scratch; - /* decrypt the authdata in the request */ - if (!valid_enctype(request->authorization_data.enctype)) { - status = "BAD_AUTH_ETYPE"; - errcode = KRB5KDC_ERR_ETYPE_NOSUPP; - goto cleanup; - } - /* put together an eblock for this encryption */ - - krb5_use_enctype(kdc_context, &eblock, - request->authorization_data.enctype); - scratch.length = request->authorization_data.ciphertext.length; if (!(scratch.data = malloc(request->authorization_data.ciphertext.length))) { @@ -425,28 +412,17 @@ tgt_again: errcode = ENOMEM; goto cleanup; } - /* do any necessary key pre-processing */ - if ((errcode = krb5_process_key(kdc_context, &eblock, - header_ticket->enc_part2->session))) { - status = "AUTH_PROCESS_KEY"; - free(scratch.data); - goto cleanup; - } - /* call the encryption routine */ - if ((errcode = krb5_decrypt(kdc_context, (krb5_pointer) request->authorization_data.ciphertext.data, - (krb5_pointer) scratch.data, - scratch.length, &eblock, 0))) { + 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"; - (void) krb5_finish_key(kdc_context, &eblock); - free(scratch.data); - goto cleanup; - } - if ((errcode = krb5_finish_key(kdc_context, &eblock))) { - status = "AUTH_FINISH_KEY"; 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); @@ -466,7 +442,7 @@ tgt_again: enc_tkt_reply.authorization_data = header_ticket->enc_part2->authorization_data; - enc_tkt_reply.session = session_key; + enc_tkt_reply.session = &session_key; enc_tkt_reply.client = header_ticket->enc_part2->client; enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */ @@ -562,7 +538,7 @@ tgt_again: /* convert server.key into a real key (it may be encrypted * in the database) */ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, - &master_encblock, + &master_keyblock, server_key, &encrypting_key, NULL))) { status = "DECRYPT_SERVER_KEY"; @@ -571,7 +547,6 @@ tgt_again: if ((encrypting_key.enctype == ENCTYPE_DES_CBC_CRC) && (isflagset(server.attributes, KRB5_KDB_SUPPORT_DESMD5))) encrypting_key.enctype = ENCTYPE_DES_CBC_MD5; - ticket_reply.enc_part.kvno = server_key->key_data_kvno; errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, &ticket_reply); krb5_free_keyblock_contents(kdc_context, &encrypting_key); @@ -579,6 +554,7 @@ tgt_again: status = "TKT_ENCRYPT"; goto cleanup; } + ticket_reply.enc_part.kvno = server_key->key_data_kvno; } /* Start assembling the response */ @@ -588,7 +564,7 @@ tgt_again: reply.enc_part.kvno = 0; /* We are using the session key */ reply.ticket = &ticket_reply; - reply_encpart.session = session_key; + reply_encpart.session = &session_key; reply_encpart.nonce = request->nonce; /* copy the time fields EXCEPT for authtime; its location @@ -616,6 +592,7 @@ tgt_again: reply.enc_part.enctype = subkey ? subkey->enctype : header_ticket->enc_part2->session->enctype; errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, + subkey ? 1 : 0, subkey ? subkey : header_ticket->enc_part2->session, &reply, response); @@ -661,8 +638,8 @@ cleanup: free(sname); if (nprincs) krb5_db_free_principal(kdc_context, &server, 1); - if (session_key) - krb5_free_keyblock(kdc_context, session_key); + if (session_key.contents) + krb5_free_keyblock_contents(kdc_context, &session_key); if (newtransited) free(enc_tkt_reply.transited.tr_contents.data); diff --git a/src/kdc/extern.h b/src/kdc/extern.h index e8de8a7e3..c31e5c70e 100644 --- a/src/kdc/extern.h +++ b/src/kdc/extern.h @@ -56,7 +56,6 @@ typedef struct __kdc_realm_data { /* * Other per-realm data. */ - krb5_encrypt_block realm_encblock; /* Per-realm master encryption block*/ char *realm_ports; /* Per-realm KDC port */ /* * Per-realm parameters. @@ -79,7 +78,6 @@ extern kdc_realm_t *kdc_active_realm; #define kdc_context kdc_active_realm->realm_context #define max_life_for_realm kdc_active_realm->realm_maxlife #define max_renewable_life_for_realm kdc_active_realm->realm_maxrlife -#define master_encblock kdc_active_realm->realm_encblock #define master_keyblock kdc_active_realm->realm_mkey #define master_princ kdc_active_realm->realm_mprinc #define tgs_key kdc_active_realm->realm_tgskey diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index b88c77283..0324694a2 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -23,6 +23,32 @@ * Preauthentication routines for the KDC. */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + #include "k5-int.h" #include "kdc_util.h" #include "extern.h" @@ -365,13 +391,18 @@ verify_enc_timestamp(context, client, request, enc_tkt_reply, pa) krb5_int32 start; krb5_timestamp timenow; - enc_ts_data.data = 0; scratch.data = pa->contents; scratch.length = pa->length; + + enc_ts_data.data = 0; if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0) goto cleanup; + enc_ts_data.length = enc_data->ciphertext.length; + if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL) + goto cleanup; + start = 0; while (1) { if ((retval = krb5_dbe_search_enctype(context, client, @@ -379,12 +410,14 @@ verify_enc_timestamp(context, client, request, enc_tkt_reply, pa) -1, 0, &client_key))) goto cleanup; - if ((retval = krb5_dbekd_decrypt_key_data(context, &master_encblock, + if ((retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock, client_key, &key, NULL))) goto cleanup; + key.enctype = enc_data->enctype; - retval = krb5_decrypt_data(context, &key, 0, enc_data, &enc_ts_data); + retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + 0, enc_data, &enc_ts_data); krb5_free_keyblock_contents(context, &key); if (retval == 0) break; @@ -492,6 +525,7 @@ get_etype_info(context, request, client, server, pa_data) goto cleanup; pa_data->contents = scratch->data; pa_data->length = scratch->length; + free(scratch); retval = 0; @@ -615,7 +649,6 @@ get_sam_edata(context, request, client, server, pa_data) krb5_predicted_sam_response psr; krb5_data * scratch; int i = 0; - krb5_encrypt_block eblock; krb5_keyblock encrypting_key; char response[9]; char inputblock[8]; @@ -666,6 +699,13 @@ get_sam_edata(context, request, client, server, pa_data) break; } } + + krb5_princ_component(kdc_context,newp,probeslot)->data = 0; + krb5_princ_component(kdc_context,newp,probeslot)->length = 0; + krb5_princ_size(context, newp)--; + + krb5_free_principal(kdc_context, newp); + /* if sc.sam_type is set, it worked */ if (sc.sam_type) { /* so use assoc to get the key out! */ @@ -678,14 +718,15 @@ get_sam_edata(context, request, client, server, pa_data) &assoc_key); if (retval) { char *sname; - krb5_unparse_name(kdc_context, newp, &sname); + krb5_unparse_name(kdc_context, request->client, &sname); com_err("krb5kdc", retval, "snk4 finding the enctype and key <%s>", sname); + free(sname); return retval; } /* convert server.key into a real key */ retval = krb5_dbekd_decrypt_key_data(kdc_context, - &master_encblock, + &master_keyblock, assoc_key, &encrypting_key, NULL); if (retval) { @@ -695,14 +736,10 @@ get_sam_edata(context, request, client, server, pa_data) } /* now we can use encrypting_key... */ } - } else + } else { /* SAM is not an option - so don't return as hint */ return KRB5_PREAUTH_BAD_TYPE; - - krb5_princ_component(kdc_context,newp,probeslot)->data = 0; - krb5_princ_component(kdc_context,newp,probeslot)->length = 0; - krb5_princ_size(context, newp)--; - krb5_free_principal(kdc_context, newp); + } } sc.magic = KV5M_SAM_CHALLENGE; sc.sam_flags = KRB5_SAM_USE_SAD_AS_KEY; @@ -721,21 +758,35 @@ get_sam_edata(context, request, client, server, pa_data) /* eblock is just to set the enctype */ { const krb5_enctype type = ENCTYPE_DES_CBC_MD5; - if (!valid_enctype(type)) return KRB5_PROG_ETYPE_NOSUPP; - krb5_use_enctype(context, &eblock, type); - retval = krb5_string_to_key(context, &eblock, - &psr.sam_key, &sc.sam_challenge, - 0 /* salt */); - retval = encode_krb5_predicted_sam_response(&psr, &scratch); - if (retval) goto cleanup; + + if ((retval = krb5_c_string_to_key(context, type, &sc.sam_challenge, + 0 /* salt */, &psr.sam_key))) + goto cleanup; + + if ((retval = encode_krb5_predicted_sam_response(&psr, &scratch))) + goto cleanup; { - krb5_enc_data tmpdata; - retval = krb5_encrypt_data(context, master_encblock.key, 0, - scratch, &tmpdata); - sc.sam_track_id = tmpdata.ciphertext; + size_t enclen; + krb5_enc_data tmpdata; + + if ((retval = krb5_c_encrypt_length(context, + master_keyblock.enctype, + scratch->length, &enclen))) + goto cleanup; + + if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + tmpdata.ciphertext.length = enclen; + + if ((retval = krb5_c_encrypt(context, &master_keyblock, + /* XXX */ 0, 0, scratch, &tmpdata))) + goto cleanup; + + sc.sam_track_id = tmpdata.ciphertext; } - if (retval) goto cleanup; } sc.sam_response_prompt.data = "response prompt"; @@ -779,15 +830,17 @@ get_sam_edata(context, request, client, server, pa_data) /* generate digit string, take it mod 1000000 (six digits.) */ { int j; - krb5_encrypt_block eblock; - krb5_keyblock *session_key = 0; + krb5_keyblock session_key; char outputblock[8]; int i; + + session_key.contents = 0; + memset(inputblock, 0, 8); - krb5_use_enctype(kdc_context, &eblock, ENCTYPE_DES_CBC_CRC); - retval = krb5_random_key(kdc_context, &eblock, - krb5_enctype_array[ENCTYPE_DES_CBC_CRC]->random_sequence, - &session_key); + + retval = krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_CRC, + &session_key); + if (retval) { /* random key failed */ com_err("krb5kdc", retval,"generating random challenge for preauth"); @@ -795,41 +848,48 @@ get_sam_edata(context, request, client, server, pa_data) } /* now session_key has a key which we can pick bits out of */ /* we need six decimal digits. Grab 6 bytes, div 2, mod 10 each. */ - if (session_key->length != 8) { + if (session_key.length != 8) { com_err("krb5kdc", retval = KRB5KDC_ERR_ETYPE_NOSUPP, "keytype didn't match code expectations"); return retval; } for(i = 0; i<6; i++) { - inputblock[i] = '0' + ((session_key->contents[i]/2) % 10); + inputblock[i] = '0' + ((session_key.contents[i]/2) % 10); } - if (session_key) - krb5_free_keyblock(kdc_context, session_key); + if (session_key.contents) + krb5_free_keyblock_contents(kdc_context, &session_key); /* retval = krb5_finish_key(kdc_context, &eblock); */ /* now we have inputblock containing the 8 byte input to DES... */ sc.sam_challenge.data = inputblock; sc.sam_challenge.length = 6; - krb5_use_enctype(kdc_context, &eblock, ENCTYPE_DES_CBC_RAW); encrypting_key.enctype = ENCTYPE_DES_CBC_RAW; - /* do any necessary key pre-processing */ - retval= krb5_process_key(kdc_context, &eblock, &encrypting_key); if (retval) { com_err("krb5kdc", retval, "snk4 processing key"); } { - char ivec[8]; - memset(ivec,0,8); - retval = krb5_encrypt(kdc_context, inputblock, outputblock, 8, - &eblock, ivec); - } - if (retval) { - com_err("krb5kdc", retval, "snk4 response generation failed"); - return retval; + krb5_data plain; + krb5_enc_data cipher; + + plain.length = 8; + plain.data = inputblock; + + /* XXX I know this is enough because of the fixed raw enctype. + if it's not, the underlying code will return a reasonable + error, which should never happen */ + cipher.ciphertext.length = 8; + cipher.ciphertext.data = outputblock; + + if ((retval = krb5_c_encrypt(kdc_context, &encrypting_key, + /* XXX */ 0, 0, &plain, &cipher))) { + com_err("krb5kdc", retval, "snk4 response generation failed"); + return retval; + } } + /* now output block is the raw bits of the response; convert it to display form */ for (j=0; j<4; j++) { @@ -863,20 +923,34 @@ sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); /* string2key on sc.sam_challenge goes in here */ /* eblock is just to set the enctype */ { - const krb5_enctype type = ENCTYPE_DES_CBC_MD5; - if (!valid_enctype(type)) return KRB5_PROG_ETYPE_NOSUPP; - krb5_use_enctype(context, &eblock, type); - retval = krb5_string_to_key(context, &eblock, - &psr.sam_key, &predict_response, - 0 /* salt */); + retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5, + &predict_response, 0 /* salt */, + &psr.sam_key); + if (retval) goto cleanup; + retval = encode_krb5_predicted_sam_response(&psr, &scratch); if (retval) goto cleanup; { - krb5_enc_data tmpdata; - retval = krb5_encrypt_data(context, master_encblock.key, 0, - scratch, &tmpdata); - sc.sam_track_id = tmpdata.ciphertext; + size_t enclen; + krb5_enc_data tmpdata; + + if ((retval = krb5_c_encrypt_length(context, + master_keyblock.enctype, + scratch->length, &enclen))) + goto cleanup; + + if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + tmpdata.ciphertext.length = enclen; + + if ((retval = krb5_c_encrypt(context, &master_keyblock, + /* XXX */ 0, 0, scratch, &tmpdata))) + goto cleanup; + + sc.sam_track_id = tmpdata.ciphertext; } if (retval) goto cleanup; } @@ -937,37 +1011,64 @@ verify_sam_response(context, client, request, enc_tkt_reply, pa) scratch.data = pa->contents; scratch.length = pa->length; - retval = decode_krb5_sam_response(&scratch, &sr); - if (retval) com_err("krb5kdc", retval, "decode_krb5_sam_response failed"); - if (retval) goto cleanup; + if ((retval = decode_krb5_sam_response(&scratch, &sr))) { + scratch.data = 0; + com_err("krb5kdc", retval, "decode_krb5_sam_response failed"); + goto cleanup; + } { krb5_enc_data tmpdata; + + tmpdata.enctype = ENCTYPE_UNKNOWN; tmpdata.ciphertext = sr->sam_track_id; - retval = krb5_decrypt_data(context, master_encblock.key, 0, - &tmpdata, &scratch); - if (retval) com_err("krb5kdc", retval, "decrypt track_id failed"); + + scratch.length = tmpdata.ciphertext.length; + if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + if ((retval = krb5_c_decrypt(context, &master_keyblock, /* XXX */ 0, 0, + &tmpdata, &scratch))) { + com_err("krb5kdc", retval, "decrypt track_id failed"); + goto cleanup; + } } - if (retval) goto cleanup; - retval = decode_krb5_predicted_sam_response(&scratch, &psr); - if (retval) com_err("krb5kdc", retval, "decode_krb5_predicted_sam_response failed"); - if (retval) goto cleanup; + + if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) { + com_err("krb5kdc", retval, + "decode_krb5_predicted_sam_response failed"); + goto cleanup; + } + { - /* now psr.sam_key is what we said to use... */ - retval = krb5_decrypt_data(context, &psr->sam_key, 0, - &sr->sam_enc_nonce_or_ts, &scratch); - if (retval) com_err("krb5kdc", retval, "decrypt nonce_or_ts failed"); + free(scratch.data); + scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length; + if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + if ((retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0, + 0, &sr->sam_enc_nonce_or_ts, &scratch))) { + com_err("krb5kdc", retval, "decrypt nonce_or_ts failed"); + goto cleanup; + } + } + + if ((retval = decode_krb5_enc_sam_response_enc(&scratch, &esre))) { + com_err("krb5kdc", retval, "decode_krb5_enc_sam_response_enc failed"); + goto cleanup; } - if (retval) goto cleanup; - retval = decode_krb5_enc_sam_response_enc(&scratch, &esre); - if (retval) com_err("krb5kdc", retval, "decode_krb5_enc_sam_response_enc failed"); - if (retval) goto cleanup; + if (esre->sam_timestamp != sr->sam_patimestamp) { retval = KRB5KDC_ERR_PREAUTH_FAILED; goto cleanup; } - retval = krb5_timeofday(context, &timenow); - if (retval) goto cleanup; + + if ((retval = krb5_timeofday(context, &timenow))) + goto cleanup; if (labs(timenow - sr->sam_patimestamp) > context->clockskew) { retval = KRB5KRB_AP_ERR_SKEW; @@ -975,8 +1076,11 @@ verify_sam_response(context, client, request, enc_tkt_reply, pa) } setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH); + cleanup: - if (retval) com_err("krb5kdc", retval, "sam verify failure"); + if (retval) + com_err("krb5kdc", retval, "sam verify failure"); + if (scratch.data) free(scratch.data); if (sr) free(sr); if (psr) free(psr); if (esre) free(esre); diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 863ffd19c..51d4d7807 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -124,6 +124,7 @@ comp_cksum(kcontext, source, ticket, his_cksum) krb5_checksum * his_cksum; { krb5_error_code retval; + krb5_boolean valid; if (!valid_cksumtype(his_cksum->checksum_type)) return KRB5KDC_ERR_SUMTYPE_NOSUPP; @@ -133,14 +134,15 @@ comp_cksum(kcontext, source, ticket, his_cksum) return KRB5KRB_AP_ERR_INAPP_CKSUM; /* verify checksum */ - if ((retval = krb5_verify_checksum(kcontext, his_cksum->checksum_type, - his_cksum, - source->data, source->length, - ticket->enc_part2->session->contents, - ticket->enc_part2->session->length))) { - retval = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - return retval; + if ((retval = krb5_c_verify_checksum(kcontext, ticket->enc_part2->session, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + source, his_cksum, &valid))) + return(retval); + + if (!valid) + return(KRB5KRB_AP_ERR_BAD_INTEGRITY); + + return(0); } krb5_error_code @@ -333,12 +335,15 @@ cleanup: /* XXX This function should no longer be necessary. * The KDC should take the keytab associated with the realm and pass that to * the krb5_rd_req_decode(). --proven + * + * It's actually still used by do_tgs_req() for u2u auth, and not too + * much else. -- tlyu */ krb5_error_code kdc_get_server_key(ticket, key, kvno) krb5_ticket * ticket; krb5_keyblock ** key; - krb5_kvno * kvno; + krb5_kvno * kvno; /* XXX nothing uses this */ { krb5_error_code retval; krb5_db_entry server; @@ -347,64 +352,46 @@ kdc_get_server_key(ticket, key, kvno) krb5_key_data * server_key; int i; - if (krb5_principal_compare(kdc_context, tgs_server, ticket->server)) { - retval = krb5_copy_keyblock(kdc_context, &tgs_key, key); - *kvno = tgs_kvno; - return retval; - } else { - nprincs = 1; + nprincs = 1; - if ((retval = krb5_db_get_principal(kdc_context, ticket->server, - &server, &nprincs, - &more))) { - return(retval); - } - if (more) { - krb5_db_free_principal(kdc_context, &server, nprincs); - return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); - } else if (nprincs != 1) { - char *sname; - - krb5_db_free_principal(kdc_context, &server, nprincs); - if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) { - krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'", - sname); - free(sname); - } - return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); - } - /* - * Get the latest version of the server key_data and - * convert the key into a real key (it may be encrypted in the database) - * - * Search the key list in the order specified by the key/salt list. - */ - server_key = (krb5_key_data *) NULL; - for (i=0; i<kdc_active_realm->realm_nkstypes; i++) { - krb5_key_salt_tuple *kslist; - - kslist = (krb5_key_salt_tuple *) kdc_active_realm->realm_kstypes; - if (!krb5_dbe_find_enctype(kdc_context, - &server, - kslist[i].ks_enctype, - -1, - -1, - &server_key)) - break; - } - if (!server_key) - return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); - - *kvno = server_key->key_data_kvno; - if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { - retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, - server_key, - *key, NULL); - } else - retval = ENOMEM; + if ((retval = krb5_db_get_principal(kdc_context, ticket->server, + &server, &nprincs, + &more))) { + return(retval); + } + if (more) { krb5_db_free_principal(kdc_context, &server, nprincs); - return retval; + return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + } else if (nprincs != 1) { + char *sname; + + krb5_db_free_principal(kdc_context, &server, nprincs); + if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) { + krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'", + sname); + free(sname); + } + return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); } + retval = krb5_dbe_find_enctype(kdc_context, &server, + ticket->enc_part.enctype, -1, + ticket->enc_part.kvno, &server_key); + if (retval) + goto errout; + if (!server_key) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } + *kvno = server_key->key_data_kvno; + if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { + retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, + server_key, + *key, NULL); + } else + retval = ENOMEM; +errout: + krb5_db_free_principal(kdc_context, &server, nprincs); + return retval; } /* This probably wants to be updated if you support last_req stuff */ diff --git a/src/kdc/kerberos_v4.c b/src/kdc/kerberos_v4.c index f5a3a7789..a1efd8b37 100644 --- a/src/kdc/kerberos_v4.c +++ b/src/kdc/kerberos_v4.c @@ -65,10 +65,12 @@ extern int errno; -int compat_decrypt_key PROTOTYPE((krb5_key_data *, C_Block)); -int kerb_get_principal PROTOTYPE((char *, char *, Principal *, int, - int *)); -int check_princ PROTOTYPE((char *, char *, unsigned, Principal *)); +static int compat_decrypt_key PROTOTYPE((krb5_key_data *, C_Block, + krb5_keyblock *, int)); +static int kerb_get_principal PROTOTYPE((char *, char *, Principal *, int, + int *, krb5_keyblock *, krb5_kvno, int)); +static int check_princ PROTOTYPE((char *, char *, unsigned, Principal *, + krb5_keyblock *, int)); #ifdef HAVE_STDARG_H char * v4_klog KRB5_PROTOTYPE((int, const char *, ...)); @@ -144,8 +146,8 @@ static krb5_data *response; void kerberos_v4 PROTOTYPE((struct sockaddr_in *, KTEXT)); void kerb_err_reply PROTOTYPE((struct sockaddr_in *, KTEXT, long, char *)); -int set_tgtkey PROTOTYPE((char *)); - +static int set_tgtkey PROTOTYPE((char *, krb5_kvno)); + /* Attributes converted from V5 to V4 - internal representation */ #define V4_KDB_REQUIRES_PREAUTH 0x1 #define V4_KDB_DISALLOW_ALL_TIX 0x2 @@ -334,36 +336,59 @@ hang() } #define kdb_encrypt_key( in, out, mk, mks, e_d_flag) #define LONGLEN 4 +#define K4KDC_ENCTYPE_OK(e) \ +((e) == ENCTYPE_DES_CBC_CRC \ + || (e) == ENCTYPE_DES_CBC_MD4 \ + || (e) == ENCTYPE_DES_CBC_MD5 \ + || (e) == ENCTYPE_DES_CBC_RAW) /* take a v5 keyblock, masquerading as a v4 key, * decrypt it, and convert the resulting v5 keyblock * to a real v4 key. * this is ugly, but it saves changing more v4 code. + * + * Also, keep old krb5_keyblock around in case we want to use it later. */ -int compat_decrypt_key (in5, out4) - krb5_key_data *in5; - C_Block out4; +static int +compat_decrypt_key (in5, out4, out5, issrv) + krb5_key_data *in5; + C_Block out4; + krb5_keyblock *out5; + int issrv; /* whether it's a server key */ { - krb5_keyblock out5; - int retval = -1; + krb5_error_code retval; - out5.contents = NULL; - if (krb5_dbekd_decrypt_key_data(kdc_context,&master_encblock,in5,&out5,NULL)){ + out5->contents = NULL; + memset(out4, 0, sizeof(out4)); + retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, + in5, out5, NULL); + if (retval) { lt = klog(L_DEATH_REQ, "KDC can't decrypt principal's key."); + out5->contents = NULL; return(retval); } - if (out5.length != KRB5_MIT_DES_KEYSIZE) - lt = klog(L_DEATH_REQ, "internal keysize error in kdc"); - else if ((out5.enctype != ENCTYPE_DES_CBC_CRC) && - (out5.enctype != ENCTYPE_DES_CBC_MD4) && - (out5.enctype != ENCTYPE_DES_CBC_MD5) && - (out5.enctype != ENCTYPE_DES_CBC_RAW)) - lt = klog(L_DEATH_REQ, "incompatible principal key type."); - else { - memcpy(out4, out5.contents, out5.length); - retval = 0; + if (K4KDC_ENCTYPE_OK(out5->enctype)) { + if (out5->length == KRB5_MIT_DES_KEYSIZE) + memcpy(out4, out5->contents, out5->length); + else { + lt = klog(L_DEATH_REQ, "internal keysize error in kdc"); + krb5_free_keyblock_contents(kdc_context, out5); + out5->contents = NULL; + retval = -1; + } + } else { + if (!issrv) { + lt = klog(L_DEATH_REQ, "incompatible principal key type."); + krb5_free_keyblock_contents(kdc_context, out5); + out5->contents = NULL; + retval = -1; + } else { + /* KLUDGE! If it's a non-raw des3 key, bash its enctype */ + if (out5->enctype == ENCTYPE_DES3_HMAC_SHA1 || + out5->enctype == ENCTYPE_LOCAL_DES3_HMAC_SHA1) + out5->enctype = ENCTYPE_DES3_CBC_RAW; + } } - krb5_free_keyblock_contents(kdc_context, &out5); return(retval); } @@ -372,13 +397,16 @@ int compat_decrypt_key (in5, out4) #define MIN5 300 #define HR21 255 -int -kerb_get_principal(name, inst, principal, maxn, more) +static int +kerb_get_principal(name, inst, principal, maxn, more, k5key, kvno, issrv) char *name; /* could have wild card */ char *inst; /* could have wild card */ Principal *principal; int maxn; /* max number of name structs to return */ int *more; /* more tuples than room for */ + krb5_keyblock *k5key; + krb5_kvno kvno; + int issrv; /* true if retrieving a service key */ { /* Note that this structure should not be passed to the krb5_free* functions, because the pointers within it point @@ -430,27 +458,52 @@ kerb_get_principal(name, inst, principal, maxn, more) return(nprinc); } - if (krb5_dbe_find_enctype(kdc_context, - &entries, - ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_V4, - -1, - &pkey) && - krb5_dbe_find_enctype(kdc_context, - &entries, - ENCTYPE_DES_CBC_CRC, - -1, - -1, - &pkey)) - { - lt = klog(L_KRB_PERR, "KDC V4: principal %s.%s isn't V4 compatible", - name, inst); - krb5_db_free_principal(kdc_context, &entries, nprinc); - return(0); + if (!issrv) { + if (krb5_dbe_find_enctype(kdc_context, + &entries, + ENCTYPE_DES_CBC_CRC, + KRB5_KDB_SALTTYPE_V4, + kvno, + &pkey) && + krb5_dbe_find_enctype(kdc_context, + &entries, + ENCTYPE_DES_CBC_CRC, + -1, + kvno, + &pkey)) { + lt = klog(L_KRB_PERR, + "KDC V4: principal %s.%s isn't V4 compatible", + name, inst); + krb5_db_free_principal(kdc_context, &entries, nprinc); + return(0); + } + } else { + /* XXX yes I know this is a hardcoded search order */ + if (krb5_dbe_find_enctype(kdc_context, &entries, + ENCTYPE_DES3_CBC_RAW, + -1, kvno, &pkey) && + krb5_dbe_find_enctype(kdc_context, &entries, + ENCTYPE_LOCAL_DES3_HMAC_SHA1, + -1, kvno, &pkey) && + krb5_dbe_find_enctype(kdc_context, &entries, + ENCTYPE_DES3_HMAC_SHA1, + -1, kvno, &pkey) && + krb5_dbe_find_enctype(kdc_context, &entries, + ENCTYPE_DES_CBC_CRC, + KRB5_KDB_SALTTYPE_V4, kvno, &pkey) && + krb5_dbe_find_enctype(kdc_context, &entries, + ENCTYPE_DES_CBC_CRC, + -1, kvno, &pkey)) { + lt = klog(L_KRB_PERR, + "KDC V4: failed to find key for %s.%s", + name, inst); + krb5_db_free_principal(kdc_context, &entries, nprinc); + return(0); + } } - if (! compat_decrypt_key( pkey, k)) { - memcpy( &principal->key_low, k, LONGLEN); + if (!compat_decrypt_key(pkey, k, k5key, issrv)) { + memcpy( &principal->key_low, k, LONGLEN); memcpy( &principal->key_high, (krb5_ui_4 *) k + 1, LONGLEN); } /* convert v5's entries struct to v4's Principal struct: @@ -550,7 +603,11 @@ kerberos_v4(client, pkt) Key_schedule key_s; char *ptr; + krb5_keyblock k5key; + krb5_kvno kvno; + + k5key.contents = NULL; /* in case we have to free it */ ciph->length = 0; @@ -639,11 +696,14 @@ kerberos_v4(client, pkt) inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0); if ((i = check_princ(req_name_ptr, req_inst_ptr, 0, - &a_name_data))) { + &a_name_data, &k5key, 0))) { kerb_err_reply(client, pkt, i, lt); a_name_data.key_low = a_name_data.key_high = 0; + krb5_free_keyblock_contents(kdc_context, &k5key); return; } + /* don't use k5key for client */ + krb5_free_keyblock_contents(kdc_context, &k5key); tk->length = 0; /* init */ if (strcmp(service, "krbtgt")) klog(L_NTGT_INTK, @@ -651,10 +711,11 @@ kerberos_v4(client, pkt) req_inst_ptr, service, instance, 0); /* this does all the checking */ if ((i = check_princ(service, instance, lifetime, - &s_name_data))) { + &s_name_data, &k5key, 1))) { kerb_err_reply(client, pkt, i, lt); a_name_data.key_high = a_name_data.key_low = 0; s_name_data.key_high = s_name_data.key_low = 0; + krb5_free_keyblock_contents(kdc_context, &k5key); return; } /* Bound requested lifetime with service and user */ @@ -675,10 +736,22 @@ kerberos_v4(client, pkt) kdb_encrypt_key(key, key, master_key, master_key_schedule, DECRYPT); /* construct and seal the ticket */ - krb_create_ticket(tk, k_flags, a_name_data.name, - a_name_data.instance, local_realm, - client_host.s_addr, (char *) session_key, lifetime, kerb_time.tv_sec, - s_name_data.name, s_name_data.instance, key); + if (K4KDC_ENCTYPE_OK(k5key.enctype)) { + krb_create_ticket(tk, k_flags, a_name_data.name, + a_name_data.instance, local_realm, + client_host.s_addr, (char *) session_key, + lifetime, kerb_time.tv_sec, + s_name_data.name, s_name_data.instance, + key); + } else { + krb_cr_tkt_krb5(tk, k_flags, a_name_data.name, + a_name_data.instance, local_realm, + client_host.s_addr, (char *) session_key, + lifetime, kerb_time.tv_sec, + s_name_data.name, s_name_data.instance, + &k5key); + } + krb5_free_keyblock_contents(kdc_context, &k5key); memset(key, 0, sizeof(key)); memset(key_s, 0, sizeof(key_s)); @@ -737,14 +810,15 @@ kerberos_v4(client, pkt) memcpy(auth->dat, pkt->dat, auth->length); strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ); - if (set_tgtkey(tktrlm)) { + kvno = (krb5_kvno)auth->dat[2]; + if (set_tgtkey(tktrlm, kvno)) { lt = klog(L_ERR_UNK, - "FAILED realm %s unknown. Host: %s ", - tktrlm, inet_ntoa(client_host)); + "FAILED set_tgtkey realm %s, kvno %d. Host: %s ", + tktrlm, kvno, inet_ntoa(client_host)); kerb_err_reply(client, pkt, kerno, lt); return; } - kerno = krb_rd_req(auth, "ktbtgt", tktrlm, client_host.s_addr, + kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr, ad, 0); if (kerno) { @@ -784,9 +858,11 @@ kerberos_v4(client, pkt) return; } kerno = check_princ(service, instance, req_life, - &s_name_data); + &s_name_data, &k5key, 1); if (kerno) { kerb_err_reply(client, pkt, kerno, lt); + s_name_data.key_high = s_name_data.key_low = 0; + krb5_free_keyblock_contents(kdc_context, &k5key); return; } /* Bound requested lifetime with service and user */ @@ -910,18 +986,21 @@ static char *krb4_stime(t) return st; } -int check_princ(p_name, instance, lifetime, p) +static int +check_princ(p_name, instance, lifetime, p, k5key, issrv) char *p_name; char *instance; unsigned lifetime; Principal *p; + krb5_keyblock *k5key; + int issrv; /* whether this is a server key */ { static int n; static int more; /* long trans; */ - n = kerb_get_principal(p_name, instance, p, 1, &more); + n = kerb_get_principal(p_name, instance, p, 1, &more, k5key, 0, issrv); klog(L_ALL_REQ, "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d", p_name, instance, lifetime, n, 0); @@ -986,11 +1065,13 @@ int check_princ(p_name, instance, lifetime, p) } /* If the user's key is null, we want to return an error */ - if ((p->key_low == 0) && (p->key_high == 0)) { - /* User has a null key */ - lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name, - instance, 0); - return KERB_ERR_NULL_KEY; + if (k5key->contents != NULL && K4KDC_ENCTYPE_OK(k5key->enctype)) { + if ((p->key_low == 0) && (p->key_high == 0)) { + /* User has a null key */ + lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name, + instance, 0); + return KERB_ERR_NULL_KEY; + } } /* make sure the service hasn't expired */ if (((u_long) p->exp_date != 0)&& @@ -1007,31 +1088,44 @@ int check_princ(p_name, instance, lifetime, p) /* Set the key for krb_rd_req so we can check tgt */ -int set_tgtkey(r) +static int +set_tgtkey(r, kvno) char *r; /* Realm for desired key */ + krb5_kvno kvno; { int n; static char lastrealm[REALM_SZ] = ""; + static int last_kvno = 0; Principal p_st; Principal *p = &p_st; C_Block key; + krb5_keyblock k5key; - if (!strcmp(lastrealm, r)) + k5key.contents = NULL; + if (!strcmp(lastrealm, r) && last_kvno == kvno) return (KSUCCESS); /* log("Getting key for %s", r); */ - n = kerb_get_principal("krbtgt", r, p, 1, &more); + n = kerb_get_principal("krbtgt", r, p, 1, &more, &k5key, kvno, 1); if (n == 0) return (KFAILURE); - /* unseal tgt key from master key */ - memcpy(key, &p->key_low, 4); - memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4); - kdb_encrypt_key(key, key, master_key, - master_key_schedule, DECRYPT); - krb_set_key((char *) key, 0); - strcpy(lastrealm, r); + if (!K4KDC_ENCTYPE_OK(k5key.enctype)) { + krb_set_key_krb5(kdc_context, &k5key); + strcpy(lastrealm, r); + last_kvno = kvno; + } else { + /* unseal tgt key from master key */ + memcpy(key, &p->key_low, 4); + memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4); + kdb_encrypt_key(key, key, master_key, + master_key_schedule, DECRYPT); + krb_set_key((char *) key, 0); + strcpy(lastrealm, r); + last_kvno = kvno; + } + krb5_free_keyblock_contents(kdc_context, &k5key); return (KSUCCESS); } diff --git a/src/kdc/main.c b/src/kdc/main.c index 4524c00f4..a8f4233be 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -166,8 +166,6 @@ finish_realm(rdp) memset(rdp->realm_tgskey.contents, 0, rdp->realm_tgskey.length); free(rdp->realm_tgskey.contents); } - if (rdp->realm_encblock.crypto_entry) - krb5_finish_key(rdp->realm_context, &rdp->realm_encblock); krb5_db_fini(rdp->realm_context); if (rdp->realm_tgsprinc) krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); @@ -326,17 +324,11 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname, goto whoops; } - /* Select the specified encryption type */ - /* krb5_db_fetch_mkey will setup the encblock for stashed keys */ - if (manual) - krb5_use_enctype(rdp->realm_context, &rdp->realm_encblock, - rdp->realm_mkey.enctype); - /* * Get the master key. */ if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, - &rdp->realm_encblock, manual, + rdp->realm_mkey.enctype, manual, FALSE, rdp->realm_stash, 0, &rdp->realm_mkey))) { com_err(progname, kret, @@ -363,8 +355,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname, /* Verify the master key */ if ((kret = krb5_db_verify_master_key(rdp->realm_context, rdp->realm_mprinc, - &rdp->realm_mkey, - &rdp->realm_encblock))) { + &rdp->realm_mkey))) { com_err(progname, kret, "while verifying master key for realm %s", realm); goto whoops; @@ -415,17 +406,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname, rdp->realm_mkvno = kdata->key_data_kvno; krb5_db_free_principal(rdp->realm_context, &db_entry, num2get); - /* Now preprocess the master key */ - if ((kret = krb5_process_key(rdp->realm_context, - &rdp->realm_encblock, - &rdp->realm_mkey))) { - com_err(progname, kret, - "while processing master key for realm %s", realm); - goto whoops; - } - - if ((kret = krb5_db_set_mkey(rdp->realm_context, - &rdp->realm_encblock))) { + if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { com_err(progname, kret, "while setting master key for realm %s", realm); goto whoops; @@ -491,7 +472,7 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname, goto whoops; } if (!(kret = krb5_dbekd_decrypt_key_data(rdp->realm_context, - &rdp->realm_encblock, + &rdp->realm_mkey, kdata, &rdp->realm_tgskey, NULL))){ rdp->realm_tgskvno = kdata->key_data_kvno; @@ -506,45 +487,40 @@ init_realm(progname, rdp, realm, def_dbname, def_mpname, } if (!rkey_init_done) { - krb5_enctype enctype; - krb5_encrypt_block temp_eblock; + krb5_timestamp now; + krb5_data seed; #ifdef KRB5_KRB4_COMPAT - krb5_keyblock *temp_key; + krb5_keyblock temp_key; #endif /* * If all that worked, then initialize the random key * generators. */ - for (enctype = 0; enctype <= krb5_max_enctype; enctype++) { - if (krb5_enctype_array[enctype] && - !krb5_enctype_array[enctype]->random_sequence) { - krb5_use_enctype(rdp->realm_context, &temp_eblock, enctype); - if ((kret = krb5_init_random_key( - rdp->realm_context, &temp_eblock, - &rdp->realm_mkey, - &krb5_enctype_array[enctype]->random_sequence))) { - com_err(progname, kret, - "while setting up random key generator for enctype %d--enctype disabled", - enctype); - krb5_enctype_array[enctype] = 0; - } else { + + if ((kret = krb5_timeofday(rdp->realm_context, &now))) + goto whoops; + seed.length = sizeof(now); + seed.data = (char *) &now; + if ((kret = krb5_c_random_seed(rdp->realm_context, &seed))) + goto whoops; + + seed.length = rdp->realm_mkey.length; + seed.data = rdp->realm_mkey.contents; + + if ((kret = krb5_c_random_seed(rdp->realm_context, &seed))) + goto whoops; + #ifdef KRB5_KRB4_COMPAT - if (enctype == ENCTYPE_DES_CBC_CRC) { - if ((kret = krb5_random_key( - rdp->realm_context, &temp_eblock, - krb5_enctype_array[enctype]->random_sequence, - &temp_key))) - com_err(progname, kret, - "while initializing V4 random key generator"); - else { - (void) des_init_random_number_generator(temp_key->contents); - krb5_free_keyblock(rdp->realm_context, temp_key); - } - } -#endif - } - } + if ((kret = krb5_c_make_random_key(rdp->realm_context, + ENCTYPE_DES_CBC_CRC, &temp_key))) { + com_err(progname, kret, + "while initializing V4 random key generator"); + goto whoops; } + + (void) des_init_random_number_generator(temp_key.contents); + krb5_free_keyblock_contents(rdp->realm_context, &temp_key); +#endif rkey_init_done = 1; } whoops: |
