Use the new Kerberos 4 functions in libkrb5 and so kaserver support is

always compiled in (still default disabled)


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@14912 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2005-04-24 13:45:18 +00:00
parent ea79507d4f
commit d1d73cd17f

View File

@@ -35,7 +35,7 @@
RCSID("$Id$"); RCSID("$Id$");
#include <krb5-v4compat.h>
#include <rx.h> #include <rx.h>
#define KA_AUTHENTICATION_SERVICE 731 #define KA_AUTHENTICATION_SERVICE 731
@@ -250,27 +250,35 @@ create_reply_ticket (struct rx_header *hdr,
const char *sname, const char *sinstance, const char *sname, const char *sinstance,
u_int32_t challenge, u_int32_t challenge,
const char *label, const char *label,
des_cblock *key, krb5_keyblock *key,
krb5_data *reply) krb5_data *reply)
{ {
KTEXT_ST ticket; krb5_data ticket;
des_cblock session; krb5_keyblock session;
krb5_storage *sp; krb5_storage *sp;
krb5_data enc_data; krb5_data enc_data;
des_key_schedule schedule;
struct rx_header reply_hdr; struct rx_header reply_hdr;
des_cblock zero; char zero[8];
size_t pad; size_t pad;
unsigned fyrtiosjuelva; unsigned fyrtiosjuelva;
/* create the ticket */ /* create the ticket */
des_new_random_key(&session); krb5_generate_random_keyblock(context, ETYPE_DES_PCBC_NONE, &session);
krb_create_ticket (&ticket, 0, name, instance, realm, _krb5_krb_create_ticket(context,
addr->sin_addr.s_addr, 0,
&session, life, kdc_time, name,
sname, sinstance, skey->key.keyvalue.data); instance,
realm,
addr->sin_addr.s_addr,
&session,
life,
kdc_time,
sname,
sinstance,
&skey->key,
&ticket);
/* create the encrypted part of the reply */ /* create the encrypted part of the reply */
sp = krb5_storage_emem (); sp = krb5_storage_emem ();
@@ -278,10 +286,10 @@ create_reply_ticket (struct rx_header *hdr,
fyrtiosjuelva &= 0xffffffff; fyrtiosjuelva &= 0xffffffff;
krb5_store_int32 (sp, fyrtiosjuelva); krb5_store_int32 (sp, fyrtiosjuelva);
krb5_store_int32 (sp, challenge); krb5_store_int32 (sp, challenge);
krb5_storage_write (sp, session, 8); krb5_storage_write (sp, session.keyvalue.data, 8);
memset (&session, 0, sizeof(session)); krb5_free_keyblock_contents(context, &session);
krb5_store_int32 (sp, kdc_time); krb5_store_int32 (sp, kdc_time);
krb5_store_int32 (sp, kdc_time + krb_life_to_time (0, life)); krb5_store_int32 (sp, kdc_time + _krb5_krb_life_to_time (0, life));
krb5_store_int32 (sp, kvno); krb5_store_int32 (sp, kvno);
krb5_store_int32 (sp, ticket.length); krb5_store_int32 (sp, ticket.length);
krb5_store_stringz (sp, name); krb5_store_stringz (sp, name);
@@ -293,7 +301,7 @@ create_reply_ticket (struct rx_header *hdr,
#endif #endif
krb5_store_stringz (sp, sname); krb5_store_stringz (sp, sname);
krb5_store_stringz (sp, sinstance); krb5_store_stringz (sp, sinstance);
krb5_storage_write (sp, ticket.dat, ticket.length); krb5_storage_write (sp, ticket.data, ticket.length);
krb5_storage_write (sp, label, strlen(label)); krb5_storage_write (sp, label, strlen(label));
/* pad to DES block */ /* pad to DES block */
@@ -311,14 +319,21 @@ create_reply_ticket (struct rx_header *hdr,
} }
/* encrypt it */ /* encrypt it */
des_set_key (key, schedule); {
des_pcbc_encrypt (enc_data.data, DES_key_schedule schedule;
enc_data.data, DES_cblock deskey;
enc_data.length,
schedule, memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
key, DES_set_key (&deskey, &schedule);
DES_ENCRYPT); DES_pcbc_encrypt (enc_data.data,
memset (&schedule, 0, sizeof(schedule)); enc_data.data,
enc_data.length,
&schedule,
&deskey,
DES_ENCRYPT);
memset (&schedule, 0, sizeof(schedule));
memset (&deskey, 0, sizeof(deskey));
}
/* create the reply packet */ /* create the reply packet */
init_reply_header (hdr, &reply_hdr, HT_DATA, HF_LAST); init_reply_header (hdr, &reply_hdr, HT_DATA, HF_LAST);
@@ -389,8 +404,6 @@ do_authenticate (struct rx_header *hdr,
hdb_entry *server_entry = NULL; hdb_entry *server_entry = NULL;
Key *ckey = NULL; Key *ckey = NULL;
Key *skey = NULL; Key *skey = NULL;
des_cblock key;
des_key_schedule schedule;
krb5_storage *reply_sp; krb5_storage *reply_sp;
time_t max_life; time_t max_life;
u_int8_t life; u_int8_t life;
@@ -453,19 +466,26 @@ do_authenticate (struct rx_header *hdr,
goto out; goto out;
} }
/* try to decode the `request' */ {
memcpy (&key, ckey->key.keyvalue.data, sizeof(key)); DES_cblock key;
des_set_key (&key, schedule); DES_key_schedule schedule;
des_pcbc_encrypt (request.data,
request.data, /* try to decode the `request' */
request.length, memcpy (&key, ckey->key.keyvalue.data, sizeof(key));
schedule, DES_set_key (&key, &schedule);
&key, DES_pcbc_encrypt (request.data,
DES_DECRYPT); request.data,
memset (&schedule, 0, sizeof(schedule)); request.length,
&schedule,
&key,
DES_DECRYPT);
memset (&schedule, 0, sizeof(schedule));
memset (&key, 0, sizeof(key));
}
/* check for the magic label */ /* check for the magic label */
if (memcmp ((char *)request.data + 4, "gTGS", 4) != 0) { if (memcmp ((char *)request.data + 4, "gTGS", 4) != 0) {
kdc_log(0, "preauth failed for %s", client_name);
make_error_reply (hdr, KABADREQUEST, reply); make_error_reply (hdr, KABADREQUEST, reply);
goto out; goto out;
} }
@@ -498,8 +518,7 @@ do_authenticate (struct rx_header *hdr,
max_seq_len, max_seq_len,
"krbtgt", v4_realm, "krbtgt", v4_realm,
chal + 1, "tgsT", chal + 1, "tgsT",
&key, reply); &ckey->key, reply);
memset (&key, 0, sizeof(key));
out: out:
if (request.length) { if (request.length) {
@@ -589,21 +608,21 @@ do_getticket (struct rx_header *hdr,
hdb_entry *krbtgt_entry = NULL; hdb_entry *krbtgt_entry = NULL;
Key *kkey = NULL; Key *kkey = NULL;
Key *skey = NULL; Key *skey = NULL;
des_cblock key; DES_cblock key;
des_key_schedule schedule; DES_key_schedule schedule;
des_cblock session; DES_cblock session;
time_t max_life; time_t max_life;
int8_t life; int8_t life;
time_t start_time, end_time; time_t start_time, end_time;
char pname[ANAME_SZ];
char pinst[INST_SZ];
char prealm[REALM_SZ];
char server_name[256]; char server_name[256];
char client_name[256]; char client_name[256];
struct _krb5_krb_auth_data ad;
krb5_data_zero (&aticket); krb5_data_zero (&aticket);
krb5_data_zero (&times); krb5_data_zero (&times);
memset(&ad, 0, sizeof(ad));
unparse_getticket_args (sp, &kvno, &auth_domain, &aticket, unparse_getticket_args (sp, &kvno, &auth_domain, &aticket,
&name, &instance, &times, &max_seq_len); &name, &instance, &times, &max_seq_len);
if (times.length < 8) { if (times.length < 8) {
@@ -652,59 +671,55 @@ do_getticket (struct rx_header *hdr,
/* unpack the ticket */ /* unpack the ticket */
{ {
KTEXT_ST ticket; char *sname = NULL;
u_char flags; char *sinstance = NULL;
int life;
u_int32_t time_sec;
char sname[ANAME_SZ];
char sinstance[SNAME_SZ];
u_int32_t paddress;
if (aticket.length > sizeof(ticket.dat)) { ret = _krb5_krb_decomp_ticket(context, &aticket, &kkey->key,
kdc_log(0, "ticket too long (%u > %u)", v4_realm, &sname, &sinstance, &ad);
(unsigned)aticket.length, if (ret) {
(unsigned)sizeof(ticket.dat)); kdc_log(0, "kaserver: decomp failed for %s.%s with %d",
sname, sinstance, ret);
make_error_reply (hdr, KABADTICKET, reply); make_error_reply (hdr, KABADTICKET, reply);
goto out; goto out;
} }
ticket.length = aticket.length;
memcpy (ticket.dat, aticket.data, ticket.length);
des_set_key (&key, schedule);
decomp_ticket (&ticket, &flags, pname, pinst, prealm,
&paddress, session, &life, &time_sec,
sname, sinstance,
&key, schedule);
if (strcmp (sname, "krbtgt") != 0 if (strcmp (sname, "krbtgt") != 0
|| strcmp (sinstance, v4_realm) != 0) { || strcmp (sinstance, v4_realm) != 0) {
kdc_log(0, "no TGT: %s.%s for %s.%s@%s", kdc_log(0, "no TGT: %s.%s for %s.%s@%s",
sname, sinstance, sname, sinstance,
pname, pinst, prealm); ad.pname, ad.pinst, ad.prealm);
make_error_reply (hdr, KABADTICKET, reply); make_error_reply (hdr, KABADTICKET, reply);
free(sname);
free(sinstance);
goto out; goto out;
} }
free(sname);
free(sinstance);
if (kdc_time > krb_life_to_time(time_sec, life)) { if (kdc_time > _krb5_krb_life_to_time(ad.time_sec, ad.life)) {
kdc_log(0, "TGT expired: %s.%s@%s", kdc_log(0, "TGT expired: %s.%s@%s",
pname, pinst, prealm); ad.pname, ad.pinst, ad.prealm);
make_error_reply (hdr, KABADTICKET, reply); make_error_reply (hdr, KABADTICKET, reply);
goto out; goto out;
} }
} }
snprintf (client_name, sizeof(client_name), snprintf (client_name, sizeof(client_name),
"%s.%s@%s", pname, pinst, prealm); "%s.%s@%s", ad.pname, ad.pinst, ad.prealm);
ret = db_fetch4 (pname, pinst, prealm, &client_entry); ret = db_fetch4 (ad.pname, ad.pinst, ad.prealm, &client_entry);
if(ret != HDB_ERR_NOENTRY || if(ret && ret != HDB_ERR_NOENTRY) {
(ret == HDB_ERR_NOENTRY && strcmp(prealm, v4_realm) == 0)) { kdc_log(0, "Client not found in database: (krb4) %s: %s",
kdc_log(0, "Client not found in database: %s: %s",
client_name, krb5_get_err_text(context, ret)); client_name, krb5_get_err_text(context, ret));
make_error_reply (hdr, KANOENT, reply); make_error_reply (hdr, KANOENT, reply);
goto out; goto out;
} }
if (client_entry == NULL && strcmp(ad.prealm, v4_realm) == 0) {
kdc_log(0, "Local client not found in database: (krb4) "
"%s", client_name);
make_error_reply (hdr, KANOENT, reply);
goto out;
}
ret = check_flags (client_entry, client_name, ret = check_flags (client_entry, client_name,
server_entry, server_name, server_entry, server_name,
@@ -715,12 +730,14 @@ do_getticket (struct rx_header *hdr,
} }
/* decrypt the times */ /* decrypt the times */
des_set_key (&session, schedule); memcpy(&session, ad.session.keyvalue.data, sizeof(session));
des_ecb_encrypt (times.data, DES_set_key (&session, &schedule);
DES_ecb_encrypt (times.data,
times.data, times.data,
schedule, &schedule,
DES_DECRYPT); DES_DECRYPT);
memset (&schedule, 0, sizeof(schedule)); memset (&schedule, 0, sizeof(schedule));
memset (&session, 0, sizeof(session));
/* and extract them */ /* and extract them */
{ {
@@ -750,18 +767,18 @@ do_getticket (struct rx_header *hdr,
if (client_entry && client_entry->max_life) if (client_entry && client_entry->max_life)
max_life = min(max_life, *client_entry->max_life); max_life = min(max_life, *client_entry->max_life);
life = krb_time_to_life(kdc_time, kdc_time + max_life); life = _krb5_krb_time_to_life(kdc_time, kdc_time + max_life);
create_reply_ticket (hdr, skey, create_reply_ticket (hdr, skey,
pname, pinst, prealm, ad.pname, ad.pinst, ad.prealm,
addr, life, server_entry->kvno, addr, life, server_entry->kvno,
max_seq_len, max_seq_len,
name, instance, name, instance,
0, "gtkt", 0, "gtkt",
&session, reply); &ad.session, reply);
memset (&session, 0, sizeof(session));
out: out:
_krb5_krb_free_auth_data(context, &ad);
if (aticket.length) { if (aticket.length) {
memset (aticket.data, 0, aticket.length); memset (aticket.data, 0, aticket.length);
krb5_data_free (&aticket); krb5_data_free (&aticket);