summaryrefslogtreecommitdiffstats
path: root/src/kdc
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
committerMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
commit1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch)
tree9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/kdc
parent61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (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/ChangeLog53
-rw-r--r--src/kdc/do_as_req.c27
-rw-r--r--src/kdc/do_tgs_req.c59
-rw-r--r--src/kdc/extern.h2
-rw-r--r--src/kdc/kdc_preauth.c256
-rw-r--r--src/kdc/kdc_util.c115
-rw-r--r--src/kdc/kerberos_v4.c240
-rw-r--r--src/kdc/main.c84
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: