diff options
author | assar <assar@FreeBSD.org> | 2001-02-13 16:46:19 +0000 |
---|---|---|
committer | assar <assar@FreeBSD.org> | 2001-02-13 16:46:19 +0000 |
commit | ebfe6dc471c206300fd82c7c0fd145f683aa52f6 (patch) | |
tree | e66aa570ad1d12c43b32a7313b0f8e28971bf8a9 /crypto/heimdal/kdc/kerberos5.c | |
parent | e5f617598c2db0dd51906a38ecea9208123a8b70 (diff) | |
download | FreeBSD-src-ebfe6dc471c206300fd82c7c0fd145f683aa52f6.zip FreeBSD-src-ebfe6dc471c206300fd82c7c0fd145f683aa52f6.tar.gz |
import of heimdal 0.3e
Diffstat (limited to 'crypto/heimdal/kdc/kerberos5.c')
-rw-r--r-- | crypto/heimdal/kdc/kerberos5.c | 356 |
1 files changed, 203 insertions, 153 deletions
diff --git a/crypto/heimdal/kdc/kerberos5.c b/crypto/heimdal/kdc/kerberos5.c index 7100274..90cc49e 100644 --- a/crypto/heimdal/kdc/kerberos5.c +++ b/crypto/heimdal/kdc/kerberos5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-1999 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kerberos5.c,v 1.109 2000/01/18 03:13:00 assar Exp $"); +RCSID("$Id: kerberos5.c,v 1.123 2001/01/30 01:44:08 assar Exp $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) @@ -71,62 +71,34 @@ find_padata(KDC_REQ *req, int *start, int type) return NULL; } -#if 0 - -static krb5_error_code -find_keys(hdb_entry *client, - hdb_entry *server, - Key **ckey, - krb5_enctype *cetype, - Key **skey, - krb5_enctype *setype, - unsigned *etypes, - unsigned num_etypes) -{ - int i; - krb5_error_code ret; - for(i = 0; i < num_etypes; i++) { - if(client){ - ret = hdb_enctype2key(context, client, etypes[i], ckey); - if(ret) - continue; - } - if(server){ - ret = hdb_enctype2key(context, server, etypes[i], skey); - if(ret) - continue; - } - if(etype) - *cetype = *setype = etypes[i]; - return 0; - } - return KRB5KDC_ERR_ETYPE_NOSUPP; -} - -#else +/* + * return the first appropriate key of `princ' in `ret_key'. Look for + * all the etypes in (`etypes', `len'), stopping as soon as we find + * one, but preferring one that has default salt + */ static krb5_error_code find_etype(hdb_entry *princ, unsigned *etypes, unsigned len, - Key **key, int *index) + Key **ret_key, krb5_enctype *ret_etype) { int i; krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; - for(i = 0; i < len ; i++) { - krb5_error_code tmp; + for(i = 0; ret != 0 && i < len ; i++) { + Key *key = NULL; - tmp = hdb_enctype2key(context, princ, etypes[i], key); - if (tmp == 0) { - if ((*key)->key.keyvalue.length != 0) { - ret = 0; - break; - } else { + while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) { + if (key->key.keyvalue.length == 0) { ret = KRB5KDC_ERR_NULL_KEY; + continue; } + *ret_key = key; + *ret_etype = etypes[i]; + ret = 0; + if (key->salt == NULL) + return ret; } } - if(index) - *index = i; return ret; } @@ -140,30 +112,44 @@ find_keys(hdb_entry *client, int *etypes, unsigned num_etypes) { - int i; krb5_error_code ret; + if(client){ /* find client key */ - ret = find_etype(client, etypes, num_etypes, ckey, &i); + ret = find_etype(client, etypes, num_etypes, ckey, cetype); if (ret) { kdc_log(0, "Client has no support for etypes"); return ret; } - *cetype = etypes[i]; } if(server){ /* find server key */ - ret = find_etype(server, etypes, num_etypes, skey, NULL); + ret = find_etype(server, etypes, num_etypes, skey, setype); if (ret) { kdc_log(0, "Server has no support for etypes"); return ret; } - *setype = (*skey)->key.keytype; } return 0; } -#endif + +static krb5_error_code +make_anonymous_principalname (PrincipalName *pn) +{ + pn->name_type = KRB5_NT_PRINCIPAL; + pn->name_string.len = 1; + pn->name_string.val = malloc(sizeof(*pn->name_string.val)); + if (pn->name_string.val == NULL) + return ENOMEM; + pn->name_string.val[0] = strdup("anonymous"); + if (pn->name_string.val[0] == NULL) { + free(pn->name_string.val); + pn->name_string.val = NULL; + return ENOMEM; + } + return 0; +} static krb5_error_code encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, @@ -185,7 +171,12 @@ encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, } - krb5_crypto_init(context, skey, etype, &crypto); + ret = krb5_crypto_init(context, skey, etype, &crypto); + if (ret) { + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + return ret; + } krb5_encrypt_EncryptedData(context, crypto, @@ -208,7 +199,12 @@ encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, krb5_get_err_text(context, ret)); return ret; } - krb5_crypto_init(context, ckey, 0, &crypto); + ret = krb5_crypto_init(context, ckey, 0, &crypto); + if (ret) { + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + return ret; + } if(rep->msg_type == krb_as_rep) { krb5_encrypt_EncryptedData(context, crypto, @@ -266,8 +262,8 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client) return ENOMEM; for(i = 0; i < client->keys.len; i++) { pa.val[i].etype = client->keys.val[i].key.keytype; - ALLOC(pa.val[i].salttype); if(client->keys.val[i].salt){ + ALLOC(pa.val[i].salttype); #if 0 if(client->keys.val[i].salt->type == hdb_pw_salt) *pa.val[i].salttype = 0; /* or 1? or NULL? */ @@ -290,19 +286,20 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client) krb5_copy_data(context, &client->keys.val[i].salt->salt, &pa.val[i].salt); } else { -#if 0 - *pa.val[i].salttype = 1; /* or 0 with salt? */ -#else - *pa.val[i].salttype = pa_pw_salt; -#endif + /* we return no salt type at all, as that should indicate + * the default salt type and make everybody happy. some + * systems (like w2k) dislike being told the salt type + * here. */ + + pa.val[i].salttype = NULL; pa.val[i].salt = NULL; } } len = length_ETYPE_INFO(&pa); buf = malloc(len); - if (buf) { + if (buf == NULL) { free_ETYPE_INFO(&pa); - return ret; + return ENOMEM; } ret = encode_ETYPE_INFO(buf + len - 1, len, &pa, &len); free_ETYPE_INFO(&pa); @@ -315,13 +312,19 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client) free(buf); return ret; } - md->val[md->len - 1].padata_type = pa_etype_info; + md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; md->val[md->len - 1].padata_value.length = len; md->val[md->len - 1].padata_value.data = buf; return 0; } -static int +/* + * verify the flags on `client' and `server', returning 0 + * if they are OK and generating an error messages and returning + * and error code otherwise. + */ + +krb5_error_code check_flags(hdb_entry *client, const char *client_name, hdb_entry *server, const char *server_name, krb5_boolean is_as_req) @@ -393,11 +396,18 @@ check_flags(hdb_entry *client, const char *client_name, return 0; } +/* + * Return TRUE if `from' is part of `addresses' taking into consideration + * the configuration variables that tells us how strict we should be about + * these checks + */ + static krb5_boolean -check_addresses(HostAddresses *addresses, struct sockaddr *from) +check_addresses(HostAddresses *addresses, const struct sockaddr *from) { krb5_error_code ret; krb5_address addr; + krb5_boolean result; if(check_ticket_addresses == 0) return TRUE; @@ -409,7 +419,9 @@ check_addresses(HostAddresses *addresses, struct sockaddr *from) if(ret) return FALSE; - return krb5_address_search(context, &addr, addresses); + result = krb5_address_search(context, &addr, addresses); + krb5_free_address (context, &addr); + return result; } krb5_error_code @@ -430,9 +442,10 @@ as_rep(KDC_REQ *req, krb5_error_code ret = 0; const char *e_text = NULL; krb5_crypto crypto; - Key *ckey, *skey; + memset(&rep, 0, sizeof(rep)); + if(b->sname == NULL){ server_name = "<unknown server>"; ret = KRB5KRB_ERR_GENERIC; @@ -456,17 +469,18 @@ as_rep(KDC_REQ *req, if(ret) goto out; - client = db_fetch(client_princ); - if(client == NULL){ - kdc_log(0, "UNKNOWN -- %s", client_name); + ret = db_fetch(client_princ, &client); + if(ret){ + kdc_log(0, "UNKNOWN -- %s: %s", client_name, + krb5_get_err_text(context, ret)); ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; goto out; } - server = db_fetch(server_princ); - - if(server == NULL){ - kdc_log(0, "UNKNOWN -- %s", server_name); + ret = db_fetch(server_princ, &server); + if(ret){ + kdc_log(0, "UNKNOWN -- %s: %s", server_name, + krb5_get_err_text(context, ret)); ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } @@ -483,7 +497,7 @@ as_rep(KDC_REQ *req, PA_DATA *pa; int found_pa = 0; kdc_log(5, "Looking for pa-data -- %s", client_name); - while((pa = find_padata(req, &i, pa_enc_timestamp))){ + while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){ krb5_data ts_data; PA_ENC_TS_ENC p; time_t patime; @@ -523,7 +537,14 @@ as_rep(KDC_REQ *req, continue; } - krb5_crypto_init(context, &pa_key->key, 0, &crypto); + ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto); + if (ret) { + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + free_EncryptedData(&enc_data); + continue; + } + ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_PA_ENC_TIMESTAMP, @@ -586,7 +607,7 @@ as_rep(KDC_REQ *req, ret = realloc_method_data(&method_data); pa = &method_data.val[method_data.len-1]; - pa->padata_type = pa_enc_timestamp; + pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; pa->padata_value.length = 0; pa->padata_value.data = NULL; @@ -627,23 +648,19 @@ as_rep(KDC_REQ *req, { char *cet; char *set; - krb5_enctype_to_string(context, cetype, &cet); - krb5_enctype_to_string(context, setype, &set); - kdc_log(5, "Using %s/%s", cet, set); - free(cet); - free(set); + + ret = krb5_enctype_to_string(context, cetype, &cet); + if(ret == 0) { + ret = krb5_enctype_to_string(context, setype, &set); + if (ret == 0) { + kdc_log(5, "Using %s/%s", cet, set); + free(set); + } else + free(cet); + } else + kdc_log(5, "Using e-types %d/%d", cetype, setype); } - - memset(&rep, 0, sizeof(rep)); - rep.pvno = 5; - rep.msg_type = krb_as_rep; - copy_Realm(&b->realm, &rep.crealm); - copy_PrincipalName(b->cname, &rep.cname); - rep.ticket.tkt_vno = 5; - copy_Realm(&b->realm, &rep.ticket.realm); - copy_PrincipalName(b->sname, &rep.ticket.sname); - { char str[128]; unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str)); @@ -651,13 +668,25 @@ as_rep(KDC_REQ *req, kdc_log(2, "Requested flags: %s", str); } - if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey || - f.request_anonymous){ + + if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey + || (f.request_anonymous && !allow_anonymous)) { ret = KRB5KDC_ERR_BADOPTION; kdc_log(0, "Bad KDC options -- %s", client_name); goto out; } + rep.pvno = 5; + rep.msg_type = krb_as_rep; + copy_Realm(&b->realm, &rep.crealm); + if (f.request_anonymous) + make_anonymous_principalname (&rep.cname); + else + copy_PrincipalName(b->cname, &rep.cname); + rep.ticket.tkt_vno = 5; + copy_Realm(&b->realm, &rep.ticket.realm); + copy_PrincipalName(b->sname, &rep.ticket.sname); + et.flags.initial = 1; if(client->flags.forwardable && server->flags.forwardable) et.flags.forwardable = f.forwardable; @@ -689,7 +718,7 @@ as_rep(KDC_REQ *req, } krb5_generate_random_keyblock(context, setype, &et.key); - copy_PrincipalName(b->cname, &et.cname); + copy_PrincipalName(&rep.cname, &et.cname); copy_Realm(&b->realm, &et.crealm); { @@ -706,10 +735,13 @@ as_rep(KDC_REQ *req, } fix_time(&b->till); t = *b->till; + + /* be careful not overflowing */ + if(client->max_life) - t = min(t, start + *client->max_life); + t = start + min(t - start, *client->max_life); if(server->max_life) - t = min(t, start + *server->max_life); + t = start + min(t - start, *server->max_life); #if 0 t = min(t, start + realm->max_life); #endif @@ -728,9 +760,9 @@ as_rep(KDC_REQ *req, if(t == 0) t = MAX_TIME; if(client->max_renew) - t = min(t, start + *client->max_renew); + t = start + min(t - start, *client->max_renew); if(server->max_renew) - t = min(t, start + *server->max_renew); + t = start + min(t - start, *server->max_renew); #if 0 t = min(t, start + realm->max_renew); #endif @@ -739,6 +771,9 @@ as_rep(KDC_REQ *req, et.flags.renewable = 1; } } + + if (f.request_anonymous) + et.flags.anonymous = 1; if(b->addresses){ ALLOC(et.caddr); @@ -836,15 +871,10 @@ out2: free(client_name); krb5_free_principal(context, server_princ); free(server_name); - if(client){ - hdb_free_entry(context, client); - free(client); - } - if(server){ - hdb_free_entry(context, server); - free(server); - } - + if(client) + free_ent(client); + if(server) + free_ent(server); return ret; } @@ -948,11 +978,11 @@ check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et) old_life -= *tgt->starttime; else old_life -= tgt->authtime; - et->endtime = min(*b->till, *et->starttime + old_life); + et->endtime = min(*et->renew_till, *et->starttime + old_life); } /* checks for excess flags */ - if(f.request_anonymous){ + if(f.request_anonymous && !allow_anonymous){ kdc_log(0, "Request for anonymous ticket"); return KRB5KDC_ERR_BADOPTION; } @@ -1089,7 +1119,10 @@ tgs_make_reply(KDC_REQ_BODY *b, &rep.ticket.realm); krb5_principal2principalname(&rep.ticket.sname, server->principal); copy_Realm(&tgt->crealm, &rep.crealm); - copy_PrincipalName(&tgt->cname, &rep.cname); + if (f.request_anonymous) + make_anonymous_principalname (&tgt->cname); + else + copy_PrincipalName(&tgt->cname, &rep.cname); rep.ticket.tkt_vno = 5; ek.caddr = et.caddr; @@ -1140,7 +1173,8 @@ tgs_make_reply(KDC_REQ_BODY *b, } et.flags.pre_authent = tgt->flags.pre_authent; - et.flags.hw_authent = tgt->flags.hw_authent; + et.flags.hw_authent = tgt->flags.hw_authent; + et.flags.anonymous = tgt->flags.anonymous; /* XXX Check enc-authorization-data */ et.authorization_data = auth_data; @@ -1228,7 +1262,12 @@ tgs_check_authenticator(krb5_auth_context ac, krb5_get_err_text(context, ret)); goto out; } - krb5_crypto_init(context, key, 0, &crypto); + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out; + } ret = krb5_verify_checksum(context, crypto, KRB5_KU_TGS_REQ_AUTH_CKSUM, @@ -1312,12 +1351,13 @@ tgs_rep2(KDC_REQ_BODY *b, ap_req.ticket.sname, ap_req.ticket.realm); - krbtgt = db_fetch(princ); + ret = db_fetch(princ, &krbtgt); - if(krbtgt == NULL) { + if(ret) { char *p; krb5_unparse_name(context, princ, &p); - kdc_log(0, "Ticket-granting ticket not found in database: %s", p); + kdc_log(0, "Ticket-granting ticket not found in database: %s: %s", + p, krb5_get_err_text(context, ret)); free(p); ret = KRB5KRB_AP_ERR_NOT_US; goto out2; @@ -1352,14 +1392,15 @@ tgs_rep2(KDC_REQ_BODY *b, else verify_ap_req_flags = 0; - ret = krb5_verify_ap_req(context, - &ac, - &ap_req, - princ, - &tkey->key, - verify_ap_req_flags, - &ap_req_options, - &ticket); + ret = krb5_verify_ap_req2(context, + &ac, + &ap_req, + princ, + &tkey->key, + verify_ap_req_flags, + &ap_req_options, + &ticket, + KRB5_KU_TGS_REQ_AUTH); krb5_free_principal(context, princ); if(ret) { @@ -1381,6 +1422,7 @@ tgs_rep2(KDC_REQ_BODY *b, ac, &subkey); if(ret){ + krb5_auth_con_free(context, ac); kdc_log(0, "Failed to get remote subkey: %s", krb5_get_err_text(context, ret)); goto out2; @@ -1388,17 +1430,25 @@ tgs_rep2(KDC_REQ_BODY *b, if(subkey == NULL){ ret = krb5_auth_con_getkey(context, ac, &subkey); if(ret) { + krb5_auth_con_free(context, ac); kdc_log(0, "Failed to get session key: %s", krb5_get_err_text(context, ret)); goto out2; } } if(subkey == NULL){ + krb5_auth_con_free(context, ac); kdc_log(0, "Failed to get key for enc-authorization-data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out2; } - krb5_crypto_init(context, subkey, 0, &crypto); + ret = krb5_crypto_init(context, subkey, 0, &crypto); + if (ret) { + krb5_auth_con_free(context, ac); + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out2; + } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, @@ -1406,6 +1456,7 @@ tgs_rep2(KDC_REQ_BODY *b, &ad); krb5_crypto_destroy(context, crypto); if(ret){ + krb5_auth_con_free(context, ac); kdc_log(0, "Failed to decrypt enc-authorization-data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out2; @@ -1414,6 +1465,7 @@ tgs_rep2(KDC_REQ_BODY *b, ALLOC(auth_data); ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL); if(ret){ + krb5_auth_con_free(context, ac); free(auth_data); auth_data = NULL; kdc_log(0, "Failed to decode authorization data"); @@ -1460,10 +1512,11 @@ tgs_rep2(KDC_REQ_BODY *b, goto out2; } principalname2krb5_principal(&p, t->sname, t->realm); - uu = db_fetch(p); + ret = db_fetch(p, &uu); krb5_free_principal(context, p); - if(uu == NULL){ - ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + if(ret){ + if (ret == ENOENT) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey); @@ -1491,10 +1544,9 @@ tgs_rep2(KDC_REQ_BODY *b, else kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn); server_lookup: - server = db_fetch(sp); - + ret = db_fetch(sp, &server); - if(server == NULL){ + if(ret){ Realm req_rlm, new_rlm; if(loop++ < 2 && (req_rlm = is_krbtgt(&sp->name))){ new_rlm = find_rpath(req_rlm); @@ -1509,19 +1561,24 @@ tgs_rep2(KDC_REQ_BODY *b, goto server_lookup; } } - kdc_log(0, "Server not found in database: %s", spn); - ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + kdc_log(0, "Server not found in database: %s: %s", spn, + krb5_get_err_text(context, ret)); + if (ret == ENOENT) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } - client = db_fetch(cp); - if(client == NULL) - kdc_log(1, "Client not found in database: %s", cpn); + ret = db_fetch(cp, &client); + if(ret) + kdc_log(1, "Client not found in database: %s: %s", + cpn, krb5_get_err_text(context, ret)); #if 0 /* XXX check client only if same realm as krbtgt-instance */ - if(client == NULL){ - kdc_log(0, "Client not found in database: %s", cpn); - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + if(ret){ + kdc_log(0, "Client not found in database: %s: %s", + cpn, krb5_get_err_text(context, ret)); + if (ret == ENOENT) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; goto out; } #endif @@ -1561,15 +1618,10 @@ tgs_rep2(KDC_REQ_BODY *b, free(spn); free(cpn); - if(server){ - hdb_free_entry(context, server); - free(server); - } - if(client){ - hdb_free_entry(context, client); - free(client); - } - + if(server) + free_ent(server); + if(client) + free_ent(client); } out2: if(ret) @@ -1593,10 +1645,8 @@ out2: free(auth_data); } - if(krbtgt){ - hdb_free_entry(context, krbtgt); - free(krbtgt); - } + if(krbtgt) + free_ent(krbtgt); return ret; } @@ -1617,7 +1667,7 @@ tgs_rep(KDC_REQ *req, goto out; } - tgs_req = find_padata(req, &i, pa_tgs_req); + tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ); if(tgs_req == NULL){ ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; |