From b39330c4873d4c3923a577e89690fc0e43b0c61a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Aug 2007 06:46:34 +0000 Subject: r24614: Merge with current lorikeet-heimdal. This brings us one step closer to an alpha release. Andrew Bartlett (This used to be commit 30e02747d511630659c59eafec8d28f58605943b) --- source4/heimdal/kdc/default_config.c | 2 +- source4/heimdal/kdc/digest.c | 25 +++++-- source4/heimdal/kdc/kaserver.c | 17 ++++- source4/heimdal/kdc/kerberos4.c | 53 +++++++------ source4/heimdal/kdc/kerberos5.c | 140 +++++++++++++++++++++++------------ source4/heimdal/kdc/kx509.c | 6 +- 6 files changed, 154 insertions(+), 89 deletions(-) (limited to 'source4/heimdal/kdc') diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c index e06366f214..5f336e3275 100644 --- a/source4/heimdal/kdc/default_config.c +++ b/source4/heimdal/kdc/default_config.c @@ -36,7 +36,7 @@ #include #include -RCSID("$Id: default_config.c 21296 2007-06-25 14:49:11Z lha $"); +RCSID("$Id: default_config.c 21405 2007-07-04 10:35:45Z lha $"); krb5_error_code krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c index 801449fe5e..358ca5ad56 100644 --- a/source4/heimdal/kdc/digest.c +++ b/source4/heimdal/kdc/digest.c @@ -34,7 +34,7 @@ #include "kdc_locl.h" #include -RCSID("$Id: digest.c 21241 2007-06-20 11:30:19Z lha $"); +RCSID("$Id: digest.c 21606 2007-07-17 07:03:25Z lha $"); #define MS_CHAP_V2 0x20 #define CHAP_MD5 0x10 @@ -975,7 +975,7 @@ _kdc_do_digest(krb5_context context, } kdc_log(context, config, 0, "Digest %s request successful %s", - ireq.u.digestRequest.type, from); + ireq.u.digestRequest.type, ireq.u.digestRequest.username); break; } @@ -1227,7 +1227,7 @@ _kdc_do_digest(krb5_context context, version = 1; if (flags & NTLM_NEG_NTLM2_SESSION) { - char sessionhash[MD5_DIGEST_LENGTH]; + unsigned char sessionhash[MD5_DIGEST_LENGTH]; MD5_CTX md5ctx; if ((config->digests_allowed & NTLM_V1_SESSION) == 0) { @@ -1331,10 +1331,24 @@ _kdc_do_digest(krb5_context context, version, ireq.u.ntlmRequest.username); break; } - default: + default: { + char *s; + krb5_set_error_string(context, "unknown operation to digest"); + ret = EINVAL; + failed: + + s = krb5_get_error_message(context, ret); + if (s == NULL) { + krb5_clear_error_string(context); + goto out; + } + + kdc_log(context, config, 0, "Digest failed with: %s", s); + r.element = choice_DigestRepInner_error; - r.u.error.reason = strdup("unknown/failed operation"); + r.u.error.reason = strdup("unknown error"); + krb5_free_error_string(context, s); if (r.u.error.reason == NULL) { krb5_set_error_string(context, "out of memory"); ret = ENOMEM; @@ -1343,6 +1357,7 @@ _kdc_do_digest(krb5_context context, r.u.error.code = EINVAL; break; } + } ASN1_MALLOC_ENCODE(DigestRepInner, buf.data, buf.length, &r, &size, ret); if (ret) { diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c index deb32e1019..15624e8e76 100644 --- a/source4/heimdal/kdc/kaserver.c +++ b/source4/heimdal/kdc/kaserver.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kaserver.c 17904 2006-08-23 11:45:16Z lha $"); +RCSID("$Id: kaserver.c 21661 2007-07-22 01:57:17Z lha $"); #include #include @@ -191,19 +191,28 @@ init_reply_header (struct rx_header *hdr, reply_hdr->serviceid = hdr->serviceid; } +/* + * Create an error `reply´ using for the packet `hdr' with the error + * `error´ code. + */ static void make_error_reply (struct rx_header *hdr, - uint32_t ret, + uint32_t error, krb5_data *reply) { - krb5_storage *sp; struct rx_header reply_hdr; + krb5_error_code ret; + krb5_storage *sp; init_reply_header (hdr, &reply_hdr, HT_ABORT, HF_LAST); sp = krb5_storage_emem(); + if (sp == NULL) + return; ret = encode_rx_header (&reply_hdr, sp); - krb5_store_int32(sp, ret); + if (ret) + return; + krb5_store_int32(sp, error); krb5_storage_to_data (sp, reply); krb5_storage_free (sp); } diff --git a/source4/heimdal/kdc/kerberos4.c b/source4/heimdal/kdc/kerberos4.c index 3c76bb99b2..cbba64945b 100644 --- a/source4/heimdal/kdc/kerberos4.c +++ b/source4/heimdal/kdc/kerberos4.c @@ -35,7 +35,7 @@ #include -RCSID("$Id: kerberos4.c 18349 2006-10-08 13:43:52Z lha $"); +RCSID("$Id: kerberos4.c 21577 2007-07-16 08:14:06Z lha $"); #ifndef swap32 static uint32_t @@ -151,7 +151,8 @@ _kdc_do_version4(krb5_context context, if(!config->enable_v4) { kdc_log(context, config, 0, "Rejected version 4 request from %s", from); - make_err_reply(context, reply, KDC_GEN_ERR, "function not enabled"); + make_err_reply(context, reply, KRB4ET_KDC_GEN_ERR, + "Function not enabled"); return 0; } @@ -160,7 +161,7 @@ _kdc_do_version4(krb5_context context, if(pvno != 4){ kdc_log(context, config, 0, "Protocol version mismatch (krb4) (%d)", pvno); - make_err_reply(context, reply, KDC_PKT_VER, "protocol mismatch"); + make_err_reply(context, reply, KRB4ET_KDC_PKT_VER, "protocol mismatch"); goto out; } RCHECK(krb5_ret_int8(sp, &msg_type), out); @@ -196,7 +197,7 @@ _kdc_do_version4(krb5_context context, if(ret) { kdc_log(context, config, 0, "Client not found in database: %s: %s", client_name, krb5_get_err_text(context, ret)); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, "principal unknown"); goto out1; } @@ -205,7 +206,7 @@ _kdc_do_version4(krb5_context context, if(ret){ kdc_log(context, config, 0, "Server not found in database: %s: %s", server_name, krb5_get_err_text(context, ret)); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, "principal unknown"); goto out1; } @@ -216,7 +217,7 @@ _kdc_do_version4(krb5_context context, TRUE); if (ret) { /* good error code? */ - make_err_reply(context, reply, KERB_ERR_NAME_EXP, + make_err_reply(context, reply, KRB4ET_KDC_NAME_EXP, "operation not allowed"); goto out1; } @@ -227,7 +228,7 @@ _kdc_do_version4(krb5_context context, kdc_log(context, config, 0, "Per principal Kerberos 4 flag not turned on for %s", client_name); - make_err_reply(context, reply, KERB_ERR_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "allow kerberos4 flag required"); goto out1; } @@ -244,7 +245,7 @@ _kdc_do_version4(krb5_context context, "Pre-authentication required for v4-request: " "%s for %s", client_name, server_name); - make_err_reply(context, reply, KERB_ERR_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "preauth required"); goto out1; } @@ -252,7 +253,7 @@ _kdc_do_version4(krb5_context context, ret = _kdc_get_des_key(context, client, FALSE, FALSE, &ckey); if(ret){ kdc_log(context, config, 0, "no suitable DES key for client"); - make_err_reply(context, reply, KDC_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "no suitable DES key for client"); goto out1; } @@ -265,7 +266,7 @@ _kdc_do_version4(krb5_context context, if(ret){ kdc_log(context, config, 0, "No version-4 salted key in database -- %s.%s@%s", name, inst, realm); - make_err_reply(context, reply, KDC_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "No version-4 salted key in database"); goto out1; } @@ -274,8 +275,7 @@ _kdc_do_version4(krb5_context context, ret = _kdc_get_des_key(context, server, TRUE, FALSE, &skey); if(ret){ kdc_log(context, config, 0, "no suitable DES key for server"); - /* XXX */ - make_err_reply(context, reply, KDC_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "no suitable DES key for server"); goto out1; } @@ -400,7 +400,7 @@ _kdc_do_version4(krb5_context context, "tgs-req (krb4) with old kvno %d (current %d) for " "krbtgt.%s@%s", kvno, tgt->entry.kvno % 256, realm, config->v4_realm); - make_err_reply(context, reply, KDC_AUTH_EXP, + make_err_reply(context, reply, KRB4ET_KDC_AUTH_EXP, "old krbtgt kvno used"); goto out2; } @@ -409,8 +409,7 @@ _kdc_do_version4(krb5_context context, if(ret){ kdc_log(context, config, 0, "no suitable DES key for krbtgt (krb4)"); - /* XXX */ - make_err_reply(context, reply, KDC_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "no suitable DES key for krbtgt"); goto out2; } @@ -456,7 +455,7 @@ _kdc_do_version4(krb5_context context, if(strcmp(ad.prealm, realm)){ kdc_log(context, config, 0, "Can't hop realms (krb4) %s -> %s", realm, ad.prealm); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, "Can't hop realms"); goto out2; } @@ -465,7 +464,7 @@ _kdc_do_version4(krb5_context context, kdc_log(context, config, 0, "krb4 Cross-realm %s -> %s disabled", realm, config->v4_realm); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, "Can't hop realms"); goto out2; } @@ -473,7 +472,7 @@ _kdc_do_version4(krb5_context context, if(strcmp(sname, "changepw") == 0){ kdc_log(context, config, 0, "Bad request for changepw ticket (krb4)"); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, "Can't authorize password change based on TGT"); goto out2; } @@ -485,7 +484,7 @@ _kdc_do_version4(krb5_context context, s = kdc_log_msg(context, config, 0, "Client not found in database: (krb4) %s: %s", client_name, krb5_get_err_text(context, ret)); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s); + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s); free(s); goto out2; } @@ -494,7 +493,7 @@ _kdc_do_version4(krb5_context context, s = kdc_log_msg(context, config, 0, "Local client not found in database: (krb4) " "%s", client_name); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s); + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s); free(s); goto out2; } @@ -506,7 +505,7 @@ _kdc_do_version4(krb5_context context, s = kdc_log_msg(context, config, 0, "Server not found in database (krb4): %s: %s", server_name, krb5_get_err_text(context, ret)); - make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s); + make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s); free(s); goto out2; } @@ -516,8 +515,7 @@ _kdc_do_version4(krb5_context context, server, server_name, FALSE); if (ret) { - /* good error code? */ - make_err_reply(context, reply, KERB_ERR_NAME_EXP, + make_err_reply(context, reply, KRB4ET_KDC_NAME_EXP, "operation not allowed"); goto out2; } @@ -526,8 +524,7 @@ _kdc_do_version4(krb5_context context, if(ret){ kdc_log(context, config, 0, "no suitable DES key for server (krb4)"); - /* XXX */ - make_err_reply(context, reply, KDC_NULL_KEY, + make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY, "no suitable DES key for server"); goto out2; } @@ -787,7 +784,7 @@ _kdc_get_des_key(krb5_context context, else if(is_server && server_key) *ret_key = server_key; else - return KERB_ERR_NULL_KEY; + return KRB4ET_KDC_NULL_KEY; } else { if(v4_key) *ret_key = v4_key; @@ -798,11 +795,11 @@ _kdc_get_des_key(krb5_context context, else if(is_server && server_key) *ret_key = server_key; else - return KERB_ERR_NULL_KEY; + return KRB4ET_KDC_NULL_KEY; } if((*ret_key)->key.keyvalue.length == 0) - return KERB_ERR_NULL_KEY; + return KRB4ET_KDC_NULL_KEY; return 0; } diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index e34938447a..40a9c9c972 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kerberos5.c 21040 2007-06-10 06:20:59Z lha $"); +RCSID("$Id: kerberos5.c 21529 2007-07-13 12:37:14Z lha $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) @@ -84,6 +84,22 @@ _kdc_find_padata(const KDC_REQ *req, int *start, int type) return NULL; } +/* + * Detect if `key' is the using the the precomputed `default_salt'. + */ + +static krb5_boolean +is_default_salt_p(const krb5_salt *default_salt, const Key *key) +{ + if (key->salt == NULL) + return TRUE; + if (default_salt->salttype != key->salt->type) + return FALSE; + if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt)) + return FALSE; + return TRUE; +} + /* * return the first appropriate key of `princ' in `ret_key'. Look for * all the etypes in (`etypes', `len'), stopping as soon as we find @@ -97,6 +113,9 @@ _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, { int i; krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; + krb5_salt def_salt; + + krb5_get_pw_salt (context, princ->entry.principal, &def_salt); for(i = 0; ret != 0 && i < len ; i++) { Key *key = NULL; @@ -112,10 +131,13 @@ _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, *ret_key = key; *ret_etype = etypes[i]; ret = 0; - if (key->salt == NULL) + if (is_default_salt_p(&def_salt, key)) { + krb5_free_salt (context, def_salt); return ret; + } } } + krb5_free_salt (context, def_salt); return ret; } @@ -325,6 +347,43 @@ _kdc_encode_reply(krb5_context context, return 0; } +/* + * Return 1 if the client have only older enctypes, this is for + * determining if the server should send ETYPE_INFO2 or not. + */ + +static int +older_enctype(krb5_enctype enctype) +{ + switch (enctype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + return 1; + default: + return 0; + } +} + +static int +only_older_enctype_p(const KDC_REQ *req) +{ + int i; + + for(i = 0; i < req->req_body.etype.len; i++) { + if (!older_enctype(req->req_body.etype.val[i])) + return 0; + } + return 1; +} + +/* + * + */ + static krb5_error_code make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key) { @@ -395,14 +454,18 @@ get_pa_etype_info(krb5_context context, return ENOMEM; memset(pa.val, 0, pa.len * sizeof(*pa.val)); - for(j = 0; j < etypes_len; j++) { - for (i = 0; i < n; i++) - if (pa.val[i].etype == etypes[j]) + for(i = 0; i < client->keys.len; i++) { + for (j = 0; j < n; j++) + if (pa.val[j].etype == client->keys.val[i].key.keytype) goto skip1; - for(i = 0; i < client->keys.len; i++) { + for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) { if (krb5_enctype_valid(context, etypes[j]) != 0) continue; + if (!older_enctype(etypes[j])) + continue; + if (n >= pa.len) + krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info_entry(context, &pa.val[n++], &client->keys.val[i])) != 0) { @@ -420,6 +483,10 @@ get_pa_etype_info(krb5_context context, } if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; + if (!older_enctype(etypes[j])) + continue; + if (n >= pa.len) + krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info_entry(context, &pa.val[n++], &client->keys.val[i])) != 0) { @@ -429,16 +496,8 @@ get_pa_etype_info(krb5_context context, skip2:; } - if(n != pa.len) { - char *name; - ret = krb5_unparse_name(context, client->principal, &name); - if (ret) - name = rk_UNCONST(""); - kdc_log(context, config, 0, - "internal error in get_pa_etype_info(%s): %d != %d", - name, n, pa.len); - if (ret == 0) - free(name); + if(n < pa.len) { + /* stripped out newer enctypes */ pa.len = n; } @@ -528,33 +587,9 @@ make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key) } /* - * Return 1 if the client have only older enctypes, this is for - * determining if the server should send ETYPE_INFO2 or not. - */ - -static int -only_older_enctype_p(const KDC_REQ *req) -{ - int i; - - for(i = 0; i < req->req_body.etype.len; i++) { - switch (req->req_body.etype.val[i]) { - case ETYPE_DES_CBC_CRC: - case ETYPE_DES_CBC_MD4: - case ETYPE_DES_CBC_MD5: - case ETYPE_DES3_CBC_SHA1: - case ETYPE_ARCFOUR_HMAC_MD5: - case ETYPE_ARCFOUR_HMAC_MD5_56: - break; - default: - return 0; - } - } - return 1; -} - -/* - * + * Return an ETYPE-INFO2. Enctypes are storted the same way as in the + * database (client supported enctypes first, then the unsupported + * enctypes). */ static krb5_error_code @@ -578,11 +613,11 @@ get_pa_etype_info2(krb5_context context, return ENOMEM; memset(pa.val, 0, pa.len * sizeof(*pa.val)); - for(j = 0; j < etypes_len; j++) { - for (i = 0; i < n; i++) - if (pa.val[i].etype == etypes[j]) + for(i = 0; i < client->keys.len; i++) { + for (j = 0; j < n; j++) + if (pa.val[j].etype == client->keys.val[i].key.keytype) goto skip1; - for(i = 0; i < client->keys.len; i++) { + for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) { if (krb5_enctype_valid(context, etypes[j]) != 0) continue; @@ -595,6 +630,7 @@ get_pa_etype_info2(krb5_context context, } skip1:; } + /* send enctypes that the cliene doesn't know about too */ for(i = 0; i < client->keys.len; i++) { for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) @@ -959,7 +995,9 @@ _kdc_as_rep(krb5_context context, if (b->cname->name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { if (b->cname->name_string.len != 1) { kdc_log(context, config, 0, - "AS-REQ malformed canon request from %s", from); + "AS-REQ malformed canon request from %s, " + "enterprise name with %d name components", + from, b->cname->name_string.len); ret = KRB5_PARSE_MALFORMED; goto out; } @@ -1395,6 +1433,12 @@ _kdc_as_rep(krb5_context context, copy_Realm(&server->entry.principal->realm, &rep.ticket.realm); _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal); + /* java 1.6 expects the name to be the same type, lets allow that + * uncomplicated name-types. */ +#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t) + if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST)) + rep.ticket.sname.name_type = b->sname->name_type; +#undef CNT et.flags.initial = 1; if(client->entry.flags.forwardable && server->entry.flags.forwardable) diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c index 8414ecb4b2..b1b861efef 100644 --- a/source4/heimdal/kdc/kx509.c +++ b/source4/heimdal/kdc/kx509.c @@ -36,7 +36,7 @@ #include #include -RCSID("$Id: kx509.c 19992 2007-01-20 09:06:18Z lha $"); +RCSID("$Id: kx509.c 21607 2007-07-17 07:04:52Z lha $"); /* * @@ -56,7 +56,7 @@ _kdc_try_kx509_request(void *ptr, size_t len, Kx509Request *req, size_t *size) * */ -static const char version_2_0[4] = {0 , 0, 2, 0}; +static const unsigned char version_2_0[4] = {0 , 0, 2, 0}; static krb5_error_code verify_req_hash(krb5_context context, @@ -122,7 +122,7 @@ calculate_reply_hash(krb5_context context, if (rep->certificate) HMAC_Update(&ctx, rep->certificate->data, rep->certificate->length); if (rep->e_text) - HMAC_Update(&ctx, *rep->e_text, strlen(*rep->e_text)); + HMAC_Update(&ctx, (unsigned char *)*rep->e_text, strlen(*rep->e_text)); HMAC_Final(&ctx, rep->hash->data, 0); HMAC_CTX_cleanup(&ctx); -- cgit