From a925f039ee382df0f3be434108416bab0d17e8c0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 Aug 2008 07:08:51 +0200 Subject: heimdal: update to lorikeet-heimdal rev 801 metze (This used to be commit d6c54a66fb23c784ef221a3c1cf766b72bdb5a0b) --- source4/heimdal/kdc/default_config.c | 4 +- source4/heimdal/kdc/digest.c | 200 +++++------ source4/heimdal/kdc/kaserver.c | 8 +- source4/heimdal/kdc/kerberos5.c | 14 +- source4/heimdal/kdc/krb5tgs.c | 639 ++++++++++++++++++++++------------- source4/heimdal/kdc/kx509.c | 36 +- source4/heimdal/kdc/misc.c | 11 +- source4/heimdal/kdc/pkinit.c | 146 ++++---- source4/heimdal/kdc/process.c | 9 +- source4/heimdal/kdc/windc.c | 6 +- source4/heimdal/kdc/windc_plugin.h | 4 +- 11 files changed, 617 insertions(+), 460 deletions(-) (limited to 'source4/heimdal/kdc') diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c index 5f336e3275..33a2c297fa 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 21405 2007-07-04 10:35:45Z lha $"); +RCSID("$Id: default_config.c 23316 2008-06-23 04:32:32Z lha $"); krb5_error_code krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) @@ -45,7 +45,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) c = calloc(1, sizeof(*c)); if (c == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c index b845b0f9a8..bf1e45b328 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 22374 2007-12-28 18:36:52Z lha $"); +RCSID("$Id: digest.c 23316 2008-06-23 04:32:32Z lha $"); #define MS_CHAP_V2 0x20 #define CHAP_MD5 0x10 @@ -44,13 +44,13 @@ RCSID("$Id: digest.c 22374 2007-12-28 18:36:52Z lha $"); #define NTLM_V1 0x01 const struct units _kdc_digestunits[] = { - {"ms-chap-v2", 1U << 5}, - {"chap-md5", 1U << 4}, - {"digest-md5", 1U << 3}, - {"ntlm-v2", 1U << 2}, - {"ntlm-v1-session", 1U << 1}, - {"ntlm-v1", 1U << 0}, - {NULL, 0} + {"ms-chap-v2", 1U << 5}, + {"chap-md5", 1U << 4}, + {"digest-md5", 1U << 3}, + {"ntlm-v2", 1U << 2}, + {"ntlm-v1-session", 1U << 1}, + {"ntlm-v1", 1U << 0}, + {NULL, 0} }; @@ -121,10 +121,10 @@ fill_targetinfo(krb5_context context, strcmp("imap", str) == 0 || strcmp("pop", str) == 0 || strcmp("smtp", str))) - { - str = krb5_principal_get_comp_string(context, p, 1); - ti.dnsservername = rk_UNCONST(str); - } + { + str = krb5_principal_get_comp_string(context, p, 1); + ti.dnsservername = rk_UNCONST(str); + } ret = heim_ntlm_encode_targetinfo(&ti, 1, &d); if (ret) @@ -186,7 +186,7 @@ get_password_entry(krb5_context context, if (ret || password == NULL) { if (ret == 0) { ret = EINVAL; - krb5_set_error_string(context, "password missing"); + krb5_set_error_message(context, ret, "password missing"); } memset(user, 0, sizeof(*user)); } @@ -263,7 +263,7 @@ _kdc_do_digest(krb5_context context, goto out; ret = EINVAL; - krb5_set_error_string(context, "Wrong digest server principal used"); + krb5_set_error_message(context, ret, "Wrong digest server principal used"); p = krb5_principal_get_comp_string(context, principal, 0); if (p == NULL) { krb5_free_principal(context, principal); @@ -323,9 +323,9 @@ _kdc_do_digest(krb5_context context, "Client %s tried to use digest " "but is not allowed to", client_name); - krb5_set_error_string(context, - "Client is not permitted to use digest"); ret = KRB5KDC_ERR_POLICY; + krb5_set_error_message(context, ret, + "Client is not permitted to use digest"); goto out; } } @@ -338,8 +338,8 @@ _kdc_do_digest(krb5_context context, if (ret) goto out; if (key == NULL) { - krb5_set_error_string(context, "digest: remote subkey not found"); ret = EINVAL; + krb5_set_error_message(context, ret, "digest: remote subkey not found"); goto out; } @@ -359,7 +359,7 @@ _kdc_do_digest(krb5_context context, ret = decode_DigestReqInner(buf.data, buf.length, &ireq, NULL); krb5_data_free(&buf); if (ret) { - krb5_set_error_string(context, "Failed to decode digest inner request"); + krb5_set_error_message(context, ret, "Failed to decode digest inner request"); goto out; } @@ -386,15 +386,15 @@ _kdc_do_digest(krb5_context context, hex_encode(server_nonce, sizeof(server_nonce), &r.u.initReply.nonce); if (r.u.initReply.nonce == NULL) { - krb5_set_error_string(context, "Failed to decode server nonce"); ret = ENOMEM; + krb5_set_error_message(context, ret, "Failed to decode server nonce"); goto out; } sp = krb5_storage_emem(); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_store_stringz(sp, ireq.u.init.type); @@ -410,9 +410,9 @@ _kdc_do_digest(krb5_context context, ireq.u.init.channel->cb_type, ireq.u.init.channel->cb_binding); if (s == NULL) { - krb5_set_error_string(context, "Failed to allocate " - "channel binding"); ret = ENOMEM; + krb5_set_error_message(context, ret, + "Failed to allocate channel binding"); goto out; } free(r.u.initReply.nonce); @@ -429,15 +429,15 @@ _kdc_do_digest(krb5_context context, r.u.initReply.identifier = malloc(sizeof(*r.u.initReply.identifier)); if (r.u.initReply.identifier == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } asprintf(r.u.initReply.identifier, "%02X", identifier & 0xff); if (*r.u.initReply.identifier == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -478,8 +478,8 @@ _kdc_do_digest(krb5_context context, ASN1_MALLOC_ENCODE(Checksum, buf.data, buf.length, &res, &size, ret); free_Checksum(&res); if (ret) { - krb5_set_error_string(context, "Failed to encode " - "checksum in digest request"); + krb5_set_error_message(context, ret, "Failed to encode " + "checksum in digest request"); goto out; } if (size != buf.length) @@ -502,7 +502,7 @@ _kdc_do_digest(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_store_stringz(sp, ireq.u.digestRequest.type); @@ -524,15 +524,15 @@ _kdc_do_digest(krb5_context context, buf.length = strlen(ireq.u.digestRequest.opaque); buf.data = malloc(buf.length); if (buf.data == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = hex_decode(ireq.u.digestRequest.opaque, buf.data, buf.length); if (ret <= 0) { - krb5_set_error_string(context, "Failed to decode opaque"); ret = ENOMEM; + krb5_set_error_message(context, ret, "Failed to decode opaque"); goto out; } buf.length = ret; @@ -540,7 +540,7 @@ _kdc_do_digest(krb5_context context, ret = decode_Checksum(buf.data, buf.length, &res, NULL); free(buf.data); if (ret) { - krb5_set_error_string(context, "Failed to decode digest Checksum"); + krb5_set_error_message(context, ret, "Failed to decode digest Checksum"); goto out; } @@ -553,8 +553,8 @@ _kdc_do_digest(krb5_context context, serverNonce.length = strlen(ireq.u.digestRequest.serverNonce); serverNonce.data = malloc(serverNonce.length); if (serverNonce.data == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -568,8 +568,8 @@ _kdc_do_digest(krb5_context context, ssize = hex_decode(ireq.u.digestRequest.serverNonce, serverNonce.data, serverNonce.length); if (ssize <= 0) { - krb5_set_error_string(context, "Failed to decode serverNonce"); ret = ENOMEM; + krb5_set_error_message(context, ret, "Failed to decode serverNonce"); goto out; } serverNonce.length = ssize; @@ -593,15 +593,15 @@ _kdc_do_digest(krb5_context context, uint32_t t; if (serverNonce.length < 4) { - krb5_set_error_string(context, "server nonce too short"); ret = EINVAL; + krb5_set_error_message(context, ret, "server nonce too short"); goto out; } t = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); if (abs((kdc_time & 0xffffffff) - t) > context->max_skew) { - krb5_set_error_string(context, "time screw in server nonce "); ret = EINVAL; + krb5_set_error_message(context, ret, "time screw in server nonce "); goto out; } } @@ -618,15 +618,15 @@ _kdc_do_digest(krb5_context context, } if (ireq.u.digestRequest.identifier == NULL) { - krb5_set_error_string(context, "Identifier missing " - "from CHAP request"); ret = EINVAL; + krb5_set_error_message(context, ret, "Identifier missing " + "from CHAP request"); goto out; } if (hex_decode(*ireq.u.digestRequest.identifier, &id, 1) != 1) { - krb5_set_error_string(context, "failed to decode identifier"); ret = EINVAL; + krb5_set_error_message(context, ret, "failed to decode identifier"); goto out; } @@ -714,8 +714,8 @@ _kdc_do_digest(krb5_context context, MD5_Final(md, &ctx); hex_encode(md, sizeof(md), &A1); if (A1 == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto failed; } @@ -733,8 +733,8 @@ _kdc_do_digest(krb5_context context, MD5_Final(md, &ctx); hex_encode(md, sizeof(md), &A2); if (A2 == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); free(A1); goto failed; } @@ -795,15 +795,15 @@ _kdc_do_digest(krb5_context context, } if (ireq.u.digestRequest.clientNonce == NULL) { - krb5_set_error_string(context, - "MS-CHAP-V2 clientNonce missing"); ret = EINVAL; + krb5_set_error_message(context, ret, + "MS-CHAP-V2 clientNonce missing"); goto failed; } if (serverNonce.length != 16) { - krb5_set_error_string(context, - "MS-CHAP-V2 serverNonce wrong length"); ret = EINVAL; + krb5_set_error_message(context, ret, + "MS-CHAP-V2 serverNonce wrong length"); goto failed; } @@ -824,16 +824,16 @@ _kdc_do_digest(krb5_context context, clientNonce.data = malloc(clientNonce.length); if (clientNonce.data == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ssize = hex_decode(*ireq.u.digestRequest.clientNonce, clientNonce.data, clientNonce.length); if (ssize != 16) { - krb5_set_error_string(context, - "Failed to decode clientNonce"); ret = ENOMEM; + krb5_set_error_message(context, ret, + "Failed to decode clientNonce"); goto out; } SHA1_Update(&ctx, clientNonce.data, ssize); @@ -852,18 +852,18 @@ _kdc_do_digest(krb5_context context, HDB_F_GET_CLIENT, NULL, &user); krb5_free_principal(context, clientprincipal); if (ret) { - krb5_set_error_string(context, - "MS-CHAP-V2 user %s not in database", - username); + krb5_set_error_message(context, ret, + "MS-CHAP-V2 user %s not in database", + username); goto failed; } ret = hdb_enctype2key(context, &user->entry, ETYPE_ARCFOUR_HMAC_MD5, &key); if (ret) { - krb5_set_error_string(context, - "MS-CHAP-V2 missing arcfour key %s", - username); + krb5_set_error_message(context, ret, + "MS-CHAP-V2 missing arcfour key %s", + username); goto failed; } @@ -872,7 +872,7 @@ _kdc_do_digest(krb5_context context, key->key.keyvalue.length, challange, &answer); if (ret) { - krb5_set_error_string(context, "NTLM missing arcfour key"); + krb5_set_error_message(context, ret, "NTLM missing arcfour key"); goto failed; } @@ -967,8 +967,8 @@ _kdc_do_digest(krb5_context context, asprintf(&r.u.error.reason, "Unsupported digest type %s", ireq.u.digestRequest.type); if (r.u.error.reason == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } r.u.error.code = EINVAL; @@ -1021,29 +1021,29 @@ _kdc_do_digest(krb5_context context, r.u.ntlmInitReply.targetname = get_ntlm_targetname(context, client); if (r.u.ntlmInitReply.targetname == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } r.u.ntlmInitReply.challange.data = malloc(8); if (r.u.ntlmInitReply.challange.data == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } r.u.ntlmInitReply.challange.length = 8; if (RAND_bytes(r.u.ntlmInitReply.challange.data, r.u.ntlmInitReply.challange.length) != 1) - { - krb5_set_error_string(context, "out of random error"); - ret = ENOMEM; - goto out; - } + { + ret = ENOMEM; + krb5_set_error_message(context, ret, "out of random error"); + goto out; + } /* XXX fix targetinfo */ ALLOC(r.u.ntlmInitReply.targetinfo); if (r.u.ntlmInitReply.targetinfo == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -1052,8 +1052,8 @@ _kdc_do_digest(krb5_context context, client, r.u.ntlmInitReply.targetinfo); if (ret) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -1064,14 +1064,14 @@ _kdc_do_digest(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_storage_write(sp, r.u.ntlmInitReply.challange.data, 8); if (ret != 8) { ret = ENOMEM; - krb5_set_error_string(context, "storage write challange"); + krb5_set_error_message(context, ret, "storage write challange"); goto out; } ret = krb5_store_uint32(sp, r.u.ntlmInitReply.flags); @@ -1127,8 +1127,8 @@ _kdc_do_digest(krb5_context context, HDB_F_GET_CLIENT, NULL, &user); krb5_free_principal(context, clientprincipal); if (ret) { - krb5_set_error_string(context, "NTLM user %s not in database", - ireq.u.ntlmRequest.username); + krb5_set_error_message(context, ret, "NTLM user %s not in database", + ireq.u.ntlmRequest.username); goto failed; } @@ -1150,33 +1150,33 @@ _kdc_do_digest(krb5_context context, sp = krb5_storage_from_data(&buf); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_storage_read(sp, challange, sizeof(challange)); if (ret != sizeof(challange)) { - krb5_set_error_string(context, "NTLM storage read challange"); ret = ENOMEM; + krb5_set_error_message(context, ret, "NTLM storage read challange"); goto out; } ret = krb5_ret_uint32(sp, &flags); if (ret) { - krb5_set_error_string(context, "NTLM storage read flags"); + krb5_set_error_message(context, ret, "NTLM storage read flags"); goto out; } krb5_data_free(&buf); if ((flags & NTLM_NEG_NTLM) == 0) { ret = EINVAL; - krb5_set_error_string(context, "NTLM not negotiated"); + krb5_set_error_message(context, ret, "NTLM not negotiated"); goto out; } ret = hdb_enctype2key(context, &user->entry, ETYPE_ARCFOUR_HMAC_MD5, &key); if (ret) { - krb5_set_error_string(context, "NTLM missing arcfour key"); + krb5_set_error_message(context, ret, "NTLM missing arcfour key"); goto out; } @@ -1194,8 +1194,8 @@ _kdc_do_digest(krb5_context context, targetname = get_ntlm_targetname(context, client); if (targetname == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -1213,7 +1213,7 @@ _kdc_do_digest(krb5_context context, sessionkey); free(targetname); if (ret) { - krb5_set_error_string(context, "NTLM v2 verify failed"); + krb5_set_error_message(context, ret, "NTLM v2 verify failed"); goto failed; } @@ -1238,9 +1238,9 @@ _kdc_do_digest(krb5_context context, } if (ireq.u.ntlmRequest.lm.length != 24) { - krb5_set_error_string(context, "LM hash have wrong length " - "for NTLM session key"); ret = EINVAL; + krb5_set_error_message(context, ret, "LM hash have wrong length " + "for NTLM session key"); goto failed; } @@ -1260,18 +1260,18 @@ _kdc_do_digest(krb5_context context, key->key.keyvalue.length, challange, &answer); if (ret) { - krb5_set_error_string(context, "NTLM missing arcfour key"); + krb5_set_error_message(context, ret, "NTLM missing arcfour key"); goto failed; } if (ireq.u.ntlmRequest.ntlm.length != answer.length || memcmp(ireq.u.ntlmRequest.ntlm.data, answer.data, answer.length) != 0) - { - free(answer.data); - ret = EINVAL; - krb5_set_error_string(context, "NTLM hash mismatch"); - goto failed; - } + { + free(answer.data); + ret = EINVAL; + krb5_set_error_message(context, ret, "NTLM hash mismatch"); + goto failed; + } free(answer.data); { @@ -1290,18 +1290,19 @@ _kdc_do_digest(krb5_context context, size_t len; if ((flags & NTLM_NEG_KEYEX) == 0) { - krb5_set_error_string(context, - "NTLM client failed to neg key " - "exchange but still sent key"); ret = EINVAL; + krb5_set_error_message(context, ret, + "NTLM client failed to neg key " + "exchange but still sent key"); goto failed; } len = ireq.u.ntlmRequest.sessionkey->length; if (len != sizeof(masterkey)){ - krb5_set_error_string(context, - "NTLM master key wrong length: %lu", - (unsigned long)len); + ret = EINVAL; + krb5_set_error_message(context, ret, + "NTLM master key wrong length: %lu", + (unsigned long)len); goto failed; } @@ -1315,14 +1316,15 @@ _kdc_do_digest(krb5_context context, r.u.ntlmResponse.sessionkey = malloc(sizeof(*r.u.ntlmResponse.sessionkey)); if (r.u.ntlmResponse.sessionkey == NULL) { - krb5_set_error_string(context, "out of memory"); + ret = EINVAL; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_data_copy(r.u.ntlmResponse.sessionkey, masterkey, sizeof(masterkey)); if (ret) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } } @@ -1354,11 +1356,11 @@ _kdc_do_digest(krb5_context context, break; default: { - char *s; - krb5_set_error_string(context, "unknown operation to digest"); + const char *s; ret = EINVAL; + krb5_set_error_message(context, ret, "unknown operation to digest"); - failed: + failed: s = krb5_get_error_message(context, ret); if (s == NULL) { @@ -1370,10 +1372,10 @@ _kdc_do_digest(krb5_context context, r.element = choice_DigestRepInner_error; r.u.error.reason = strdup("unknown error"); - krb5_free_error_string(context, s); + krb5_free_error_message(context, s); if (r.u.error.reason == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } r.u.error.code = EINVAL; @@ -1383,7 +1385,7 @@ _kdc_do_digest(krb5_context context, ASN1_MALLOC_ENCODE(DigestRepInner, buf.data, buf.length, &r, &size, ret); if (ret) { - krb5_set_error_string(context, "Failed to encode inner digest reply"); + krb5_set_error_message(context, ret, "Failed to encode inner digest reply"); goto out; } if (size != buf.length) @@ -1414,14 +1416,14 @@ _kdc_do_digest(krb5_context context, ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret); if (ret) { - krb5_set_error_string(context, "Failed to encode digest reply"); + krb5_set_error_message(context, ret, "Failed to encode digest reply"); goto out; } if (size != reply->length) krb5_abortx(context, "ASN1 internal error"); -out: + out: if (ac) krb5_auth_con_free(context, ac); if (ret) diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c index 27f497ea66..4f257d717e 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 21654 2007-07-21 17:30:18Z lha $"); +RCSID("$Id: kaserver.c 23110 2008-04-27 18:51:17Z lha $"); #include #include @@ -366,7 +366,7 @@ create_reply_ticket (krb5_context context, DES_cblock deskey; memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - DES_set_key (&deskey, &schedule); + DES_set_key_unchecked (&deskey, &schedule); DES_pcbc_encrypt (enc_data.data, enc_data.data, enc_data.length, @@ -524,7 +524,7 @@ do_authenticate (krb5_context context, /* try to decode the `request' */ memcpy (&key, ckey->key.keyvalue.data, sizeof(key)); - DES_set_key (&key, &schedule); + DES_set_key_unchecked (&key, &schedule); DES_pcbc_encrypt (request.data, request.data, request.length, @@ -801,7 +801,7 @@ do_getticket (krb5_context context, /* decrypt the times */ memcpy(&session, ad.session.keyvalue.data, sizeof(session)); - DES_set_key (&session, &schedule); + DES_set_key_unchecked (&session, &schedule); DES_ecb_encrypt (times.data, times.data, &schedule, diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index f1dea6499d..2a2c48c233 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 22071 2007-11-14 20:04:50Z lha $"); +RCSID("$Id: kerberos5.c 23316 2008-06-23 04:32:32Z lha $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) @@ -1648,7 +1648,7 @@ _kdc_as_rep(krb5_context context, memset(&canon, 0, sizeof(canon)); canon.names.requested_name = *b->cname; - canon.names.real_name = client->entry.principal->name; + canon.names.mapped_name = client->entry.principal->name; ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, &canon.names, &len, ret); @@ -1807,7 +1807,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, if (tkt->authorization_data == NULL) { tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); if (tkt->authorization_data == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "out of memory"); return ENOMEM; } } @@ -1822,7 +1822,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, ret = add_AuthorizationData(&ad, &ade); if (ret) { - krb5_set_error_string(context, "add AuthorizationData failed"); + krb5_set_error_message(context, ret, "add AuthorizationData failed"); return ret; } @@ -1833,8 +1833,8 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, &ad, &size, ret); free_AuthorizationData(&ad); if (ret) { - krb5_set_error_string(context, "ASN.1 encode of " - "AuthorizationData failed"); + krb5_set_error_message(context, ret, "ASN.1 encode of " + "AuthorizationData failed"); return ret; } if (ade.ad_data.length != size) @@ -1843,7 +1843,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, ret = add_AuthorizationData(tkt->authorization_data, &ade); der_free_octet_string(&ade.ad_data); if (ret) { - krb5_set_error_string(context, "add AuthorizationData failed"); + krb5_set_error_message(context, ret, "add AuthorizationData failed"); return ret; } } diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 32bdee9799..071a30d5a7 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1,45 +1,45 @@ /* - * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. + * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include "kdc_locl.h" -RCSID("$Id: krb5tgs.c 22071 2007-11-14 20:04:50Z lha $"); +RCSID("$Id: krb5tgs.c 23316 2008-06-23 04:32:32Z lha $"); /* * return the realm of a krbtgt-ticket or NULL */ -static Realm +static Realm get_krbtgt_realm(const PrincipalName *p) { if(p->name_string.len == 2 @@ -80,8 +80,8 @@ find_KRB5SignedPath(krb5_context context, &child, NULL); if (ret) { - krb5_set_error_string(context, "Failed to decode " - "IF_RELEVANT with %d", ret); + krb5_set_error_message(context, ret, "Failed to decode " + "IF_RELEVANT with %d", ret); return ret; } @@ -168,7 +168,7 @@ _kdc_add_KRB5SignedPath(krb5_context context, if (data.length != size) krb5_abortx(context, "internal asn.1 encoder error"); - + /* * Add IF-RELEVANT(KRB5SignedPath) to the last slot in * authorization data field. @@ -187,13 +187,14 @@ check_KRB5SignedPath(krb5_context context, hdb_entry_ex *krbtgt, EncTicketPart *tkt, KRB5SignedPathPrincipals **delegated, - int require_signedpath) + int *signedpath) { krb5_error_code ret; krb5_data data; krb5_crypto crypto = NULL; - *delegated = NULL; + if (delegated) + *delegated = NULL; ret = find_KRB5SignedPath(context, tkt->authorization_data, &data); if (ret == 0) { @@ -236,8 +237,8 @@ check_KRB5SignedPath(krb5_context context, return ret; } } - ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, - data.data, data.length, + ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, + data.data, data.length, &sp.cksum); krb5_crypto_destroy(context, crypto); free(data.data); @@ -246,7 +247,7 @@ check_KRB5SignedPath(krb5_context context, return ret; } - if (sp.delegated) { + if (delegated && sp.delegated) { *delegated = malloc(sizeof(*sp.delegated)); if (*delegated == NULL) { @@ -263,10 +264,8 @@ check_KRB5SignedPath(krb5_context context, } } free_KRB5SignedPath(&sp); - - } else { - if (require_signedpath) - return KRB5KDC_ERR_BADOPTION; + + *signedpath = 1; } return 0; @@ -286,7 +285,7 @@ check_PAC(krb5_context context, const EncryptionKey *krbtgt_key, EncTicketPart *tkt, krb5_data *rspac, - int *require_signedpath) + int *signedpath) { AuthorizationData *ad = tkt->authorization_data; unsigned i, j; @@ -306,8 +305,8 @@ check_PAC(krb5_context context, &child, NULL); if (ret) { - krb5_set_error_string(context, "Failed to decode " - "IF_RELEVANT with %d", ret); + krb5_set_error_message(context, ret, "Failed to decode " + "IF_RELEVANT with %d", ret); return ret; } for (j = 0; j < child.len; j++) { @@ -324,7 +323,7 @@ check_PAC(krb5_context context, if (ret) return ret; - ret = krb5_pac_verify(context, pac, tkt->authtime, + ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal, krbtgt_key, NULL); if (ret) { @@ -332,13 +331,13 @@ check_PAC(krb5_context context, return ret; } - ret = _kdc_pac_verify(context, client_principal, + ret = _kdc_pac_verify(context, client_principal, client, server, &pac); if (ret) { krb5_pac_free(context, pac); return ret; } - *require_signedpath = 0; + *signedpath = 1; ret = _krb5_pac_sign(context, pac, tkt->authtime, client_principal, @@ -359,7 +358,7 @@ check_PAC(krb5_context context, */ static krb5_error_code -check_tgs_flags(krb5_context context, +check_tgs_flags(krb5_context context, krb5_kdc_configuration *config, KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et) { @@ -379,7 +378,7 @@ check_tgs_flags(krb5_context context, /* XXX tkt = tgt */ et->flags.invalid = 0; }else if(tgt->flags.invalid){ - kdc_log(context, config, 0, + kdc_log(context, config, 0, "Ticket-granting ticket has INVALID flag set"); return KRB5KRB_AP_ERR_TKT_INVALID; } @@ -473,8 +472,8 @@ check_tgs_flags(krb5_context context, et->endtime = *et->starttime + old_life; if (et->renew_till != NULL) et->endtime = min(*et->renew_till, et->endtime); - } - + } + #if 0 /* checks for excess flags */ if(f.request_anonymous && !config->allow_anonymous){ @@ -491,7 +490,7 @@ check_tgs_flags(krb5_context context, */ static krb5_error_code -check_constrained_delegation(krb5_context context, +check_constrained_delegation(krb5_context context, krb5_kdc_configuration *config, hdb_entry_ex *client, krb5_const_principal server) @@ -522,7 +521,7 @@ check_constrained_delegation(krb5_context context, */ static krb5_error_code -verify_flags (krb5_context context, +verify_flags (krb5_context context, krb5_kdc_configuration *config, const EncTicketPart *et, const char *pstr) @@ -543,18 +542,18 @@ verify_flags (krb5_context context, */ static krb5_error_code -fix_transited_encoding(krb5_context context, +fix_transited_encoding(krb5_context context, krb5_kdc_configuration *config, krb5_boolean check_policy, - const TransitedEncoding *tr, - EncTicketPart *et, - const char *client_realm, - const char *server_realm, + const TransitedEncoding *tr, + EncTicketPart *et, + const char *client_realm, + const char *server_realm, const char *tgt_realm) { krb5_error_code ret = 0; char **realms, **tmp; - int num_realms; + unsigned int num_realms; int i; switch (tr->tr_type) { @@ -576,9 +575,9 @@ fix_transited_encoding(krb5_context context, return KRB5KDC_ERR_TRTYPE_NOSUPP; } - ret = krb5_domain_x500_decode(context, + ret = krb5_domain_x500_decode(context, tr->contents, - &realms, + &realms, &num_realms, client_realm, server_realm); @@ -589,7 +588,7 @@ fix_transited_encoding(krb5_context context, } if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { /* not us, so add the previous realm to transited set */ - if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { + if (num_realms + 1 > UINT_MAX/sizeof(*realms)) { ret = ERANGE; goto free_realms; } @@ -607,7 +606,7 @@ fix_transited_encoding(krb5_context context, num_realms++; } if(num_realms == 0) { - if(strcmp(client_realm, server_realm)) + if(strcmp(client_realm, server_realm)) kdc_log(context, config, 0, "cross-realm %s -> %s", client_realm, server_realm); } else { @@ -630,11 +629,11 @@ fix_transited_encoding(krb5_context context, } } if(check_policy) { - ret = krb5_check_transited(context, client_realm, - server_realm, + ret = krb5_check_transited(context, client_realm, + server_realm, realms, num_realms, NULL); if(ret) { - krb5_warn(context, ret, "cross-realm %s -> %s", + krb5_warn(context, ret, "cross-realm %s -> %s", client_realm, server_realm); goto free_realms; } @@ -653,23 +652,24 @@ fix_transited_encoding(krb5_context context, static krb5_error_code -tgs_make_reply(krb5_context context, +tgs_make_reply(krb5_context context, krb5_kdc_configuration *config, - KDC_REQ_BODY *b, + KDC_REQ_BODY *b, krb5_const_principal tgt_name, - const EncTicketPart *tgt, + const EncTicketPart *tgt, const EncryptionKey *serverkey, const krb5_keyblock *sessionkey, krb5_kvno kvno, AuthorizationData *auth_data, - hdb_entry_ex *server, - const char *server_name, - hdb_entry_ex *client, - krb5_principal client_principal, + hdb_entry_ex *server, + const char *server_name, + hdb_entry_ex *client, + krb5_principal client_principal, hdb_entry_ex *krbtgt, krb5_enctype krbtgt_etype, KRB5SignedPathPrincipals *spp, const krb5_data *rspac, + const METHOD_DATA *enc_pa_data, const char **e_text, krb5_data *reply) { @@ -678,11 +678,11 @@ tgs_make_reply(krb5_context context, EncTicketPart et; KDCOptions f = b->kdc_options; krb5_error_code ret; - + memset(&rep, 0, sizeof(rep)); memset(&et, 0, sizeof(et)); memset(&ek, 0, sizeof(ek)); - + rep.pvno = 5; rep.msg_type = krb_tgs_rep; @@ -691,7 +691,7 @@ tgs_make_reply(krb5_context context, et.endtime = min(tgt->endtime, *b->till); ALLOC(et.starttime); *et.starttime = kdc_time; - + ret = check_tgs_flags(context, config, b, tgt, &et); if(ret) goto out; @@ -715,11 +715,11 @@ tgs_make_reply(krb5_context context, #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 - ret = fix_transited_encoding(context, config, + ret = fix_transited_encoding(context, config, !f.disable_transited_check || GLOBAL_FORCE_TRANSITED_CHECK || PRINCIPAL_FORCE_TRANSITED_CHECK(server) || - !((GLOBAL_ALLOW_PER_PRINCIPAL && + !((GLOBAL_ALLOW_PER_PRINCIPAL && PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), &tgt->transited, &et, @@ -729,7 +729,7 @@ tgs_make_reply(krb5_context context, if(ret) goto out; - copy_Realm(krb5_princ_realm(context, server->entry.principal), + copy_Realm(krb5_princ_realm(context, server->entry.principal), &rep.ticket.realm); _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal); copy_Realm(&tgt_name->realm, &rep.crealm); @@ -754,7 +754,7 @@ tgs_make_reply(krb5_context context, life = min(life, *server->entry.max_life); et.endtime = *et.starttime + life; } - if(f.renewable_ok && tgt->flags.renewable && + if(f.renewable_ok && tgt->flags.renewable && et.renew_till == NULL && et.endtime < *b->till){ et.flags.renewable = 1; ALLOC(et.renew_till); @@ -769,13 +769,13 @@ tgs_make_reply(krb5_context context, renew = min(renew, *server->entry.max_renew); *et.renew_till = et.authtime + renew; } - + if(et.renew_till){ *et.renew_till = min(*et.renew_till, *tgt->renew_till); *et.starttime = min(*et.starttime, *et.renew_till); et.endtime = min(et.endtime, *et.renew_till); } - + *et.starttime = min(*et.starttime, et.endtime); if(*et.starttime == et.endtime){ @@ -787,12 +787,12 @@ tgs_make_reply(krb5_context context, et.renew_till = NULL; et.flags.renewable = 0; } - + et.flags.pre_authent = tgt->flags.pre_authent; et.flags.hw_authent = tgt->flags.hw_authent; et.flags.anonymous = tgt->flags.anonymous; et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate; - + if (auth_data) { /* XXX Check enc-authorization-data */ et.authorization_data = calloc(1, sizeof(*et.authorization_data)); @@ -836,7 +836,7 @@ tgs_make_reply(krb5_context context, goto out; et.crealm = tgt->crealm; et.cname = tgt_name->name; - + ek.key = et.key; /* MIT must have at least one last_req */ ek.last_req.len = 1; @@ -853,8 +853,8 @@ tgs_make_reply(krb5_context context, ek.renew_till = et.renew_till; ek.srealm = rep.ticket.realm; ek.sname = rep.ticket.sname; - - _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, + + _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, et.endtime, et.renew_till); /* Don't sign cross realm tickets, they can't be checked anyway */ @@ -874,6 +874,17 @@ tgs_make_reply(krb5_context context, } } + if (enc_pa_data->len) { + rep.padata = calloc(1, sizeof(*rep.padata)); + if (rep.padata == NULL) { + ret = ENOMEM; + goto out; + } + ret = copy_METHOD_DATA(enc_pa_data, rep.padata); + if (ret) + goto out; + } + /* It is somewhat unclear where the etype in the following encryption should come from. What we have is a session key in the passed tgt, and a list of preferred etypes @@ -884,9 +895,9 @@ tgs_make_reply(krb5_context context, CAST session key. Should the DES3 etype be added to the etype list, even if we don't want a session key with DES3? */ - ret = _kdc_encode_reply(context, config, + ret = _kdc_encode_reply(context, config, &rep, &et, &ek, et.key.keytype, - kvno, + kvno, serverkey, 0, &tgt->key, e_text, reply); out: free_TGS_REP(&rep); @@ -906,10 +917,10 @@ out: } static krb5_error_code -tgs_check_authenticator(krb5_context context, +tgs_check_authenticator(krb5_context context, krb5_kdc_configuration *config, krb5_auth_context ac, - KDC_REQ_BODY *b, + KDC_REQ_BODY *b, const char **e_text, krb5_keyblock *key) { @@ -919,7 +930,7 @@ tgs_check_authenticator(krb5_context context, size_t buf_size; krb5_error_code ret; krb5_crypto crypto; - + krb5_auth_con_getauthenticator(context, ac, &auth); if(auth->cksum == NULL){ kdc_log(context, config, 0, "No authenticator in request"); @@ -936,7 +947,7 @@ tgs_check_authenticator(krb5_context context, || #endif !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) { - kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", + kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", auth->cksum->cksumtype); ret = KRB5KRB_AP_ERR_INAPP_CKSUM; goto out; @@ -945,7 +956,7 @@ tgs_check_authenticator(krb5_context context, /* XXX should not re-encode this */ ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); if(ret){ - kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", + kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", krb5_get_err_text(context, ret)); goto out; } @@ -966,14 +977,14 @@ tgs_check_authenticator(krb5_context context, ret = krb5_verify_checksum(context, crypto, KRB5_KU_TGS_REQ_AUTH_CKSUM, - buf, + buf, len, auth->cksum); free(buf); krb5_crypto_destroy(context, crypto); if(ret){ kdc_log(context, config, 0, - "Failed to verify authenticator checksum: %s", + "Failed to verify authenticator checksum: %s", krb5_get_err_text(context, ret)); } out: @@ -991,27 +1002,38 @@ find_rpath(krb5_context context, Realm crealm, Realm srealm) { const char *new_realm = krb5_config_get_string(context, NULL, - "capaths", + "capaths", crealm, srealm, NULL); return new_realm; } - + static krb5_boolean -need_referral(krb5_context context, krb5_principal server, krb5_realm **realms) +need_referral(krb5_context context, krb5_kdc_configuration *config, + const KDCOptions * const options, krb5_principal server, + krb5_realm **realms) { - if(server->name.name_type != KRB5_NT_SRV_INST || - server->name.name_string.len != 2) + const char *name; + + if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST) + return FALSE; + + if (server->name.name_string.len == 1) + name = server->name.name_string.val[0]; + if (server->name.name_string.len > 1) + name = server->name.name_string.val[1]; + else return FALSE; - - return _krb5_get_host_realm_int(context, server->name.name_string.val[1], - FALSE, realms) == 0; + + kdc_log(context, config, 0, "Searching referral for %s", name); + + return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0; } static krb5_error_code -tgs_parse_request(krb5_context context, +tgs_parse_request(krb5_context context, krb5_kdc_configuration *config, KDC_REQ_BODY *b, const PA_DATA *tgs_req, @@ -1041,7 +1063,7 @@ tgs_parse_request(krb5_context context, memset(&ap_req, 0, sizeof(ap_req)); ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); if(ret){ - kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", + kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", krb5_get_err_text(context, ret)); goto out; } @@ -1052,12 +1074,12 @@ tgs_parse_request(krb5_context context, ret = KRB5KDC_ERR_POLICY; /* ? */ goto out; } - + _krb5_principalname2krb5_principal(context, &princ, ap_req.ticket.sname, ap_req.ticket.realm); - + ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt); if(ret) { @@ -1074,8 +1096,8 @@ tgs_parse_request(krb5_context context, ret = KRB5KRB_AP_ERR_NOT_US; goto out; } - - if(ap_req.ticket.enc_part.kvno && + + if(ap_req.ticket.enc_part.kvno && *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){ char *p; @@ -1084,7 +1106,7 @@ tgs_parse_request(krb5_context context, if (ret != 0) p = ""; kdc_log(context, config, 0, - "Ticket kvno = %d, DB kvno = %d (%s)", + "Ticket kvno = %d, DB kvno = %d (%s)", *ap_req.ticket.enc_part.kvno, (*krbtgt)->entry.kvno, p); @@ -1096,7 +1118,7 @@ tgs_parse_request(krb5_context context, *krbtgt_etype = ap_req.ticket.enc_part.etype; - ret = hdb_enctype2key(context, &(*krbtgt)->entry, + ret = hdb_enctype2key(context, &(*krbtgt)->entry, ap_req.ticket.enc_part.etype, &tkey); if(ret){ char *str = NULL, *p = NULL; @@ -1112,7 +1134,7 @@ tgs_parse_request(krb5_context context, ret = KRB5KRB_AP_ERR_BADKEYVER; goto out; } - + if (b->kdc_options.validate) verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; else @@ -1127,10 +1149,10 @@ tgs_parse_request(krb5_context context, &ap_req_options, ticket, KRB5_KU_TGS_REQ_AUTH); - + krb5_free_principal(context, princ); if(ret) { - kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", + kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", krb5_get_err_text(context, ret)); goto out; } @@ -1158,7 +1180,7 @@ tgs_parse_request(krb5_context context, } } - ret = tgs_check_authenticator(context, config, + ret = tgs_check_authenticator(context, config, ac, b, e_text, &(*ticket)->ticket.key); if (ret) { krb5_auth_con_free(context, ac); @@ -1175,7 +1197,7 @@ tgs_parse_request(krb5_context context, &subkey); if(ret){ krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "Failed to get remote subkey: %s", + kdc_log(context, config, 0, "Failed to get remote subkey: %s", krb5_get_err_text(context, ret)); goto out; } @@ -1184,7 +1206,7 @@ tgs_parse_request(krb5_context context, ret = krb5_auth_con_getkey(context, ac, &subkey); if(ret) { krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "Failed to get session key: %s", + kdc_log(context, config, 0, "Failed to get session key: %s", krb5_get_err_text(context, ret)); goto out; } @@ -1211,7 +1233,7 @@ tgs_parse_request(krb5_context context, krb5_crypto_destroy(context, crypto); if(ret){ krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, + kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out; @@ -1235,17 +1257,95 @@ tgs_parse_request(krb5_context context, } krb5_auth_con_free(context, ac); - + out: free_AP_REQ(&ap_req); - + return ret; } static krb5_error_code -tgs_build_reply(krb5_context context, +build_server_referral(krb5_context context, + krb5_kdc_configuration *config, + krb5_crypto session, + krb5_const_realm referred_realm, + const PrincipalName *true_principal_name, + const PrincipalName *requested_principal, + krb5_data *outdata) +{ + PA_ServerReferralData ref; + krb5_error_code ret; + EncryptedData ed; + krb5_data data; + size_t size; + + memset(&ref, 0, sizeof(ref)); + + if (referred_realm) { + ref.referred_realm = malloc(sizeof(ref.referred_realm)); + if (ref.referred_realm == NULL) + goto eout; + *ref.referred_realm = strdup(referred_realm); + if (*ref.referred_realm == NULL) + goto eout; + } + if (true_principal_name) { + ref.true_principal_name = + malloc(sizeof(ref.true_principal_name)); + if (ref.true_principal_name == NULL) + goto eout; + ret = copy_PrincipalName(true_principal_name, ref.true_principal_name); + if (ret) + goto eout; + } + if (requested_principal) { + ref.requested_principal_name = + malloc(sizeof(ref.requested_principal_name)); + if (ref.requested_principal_name == NULL) + goto eout; + ret = copy_PrincipalName(requested_principal, + ref.requested_principal_name); + if (ret) + goto eout; + } + + ASN1_MALLOC_ENCODE(PA_ServerReferralData, + data.data, data.length, + &ref, &size, ret); + free_PA_ServerReferralData(&ref); + if (ret) + return ret; + if (data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + ret = krb5_encrypt_EncryptedData(context, session, + KRB5_KU_PA_SERVER_REFERRAL, + data.data, data.length, + 0 /* kvno */, &ed); + free(data.data); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EncryptedData, + outdata->data, outdata->length, + &ed, &size, ret); + free_EncryptedData(&ed); + if (ret) + return ret; + if (outdata->length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + return 0; +eout: + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; +} + +static krb5_error_code +tgs_build_reply(krb5_context context, krb5_kdc_configuration *config, - KDC_REQ *req, + KDC_REQ *req, KDC_REQ_BODY *b, hdb_entry_ex *krbtgt, krb5_enctype krbtgt_etype, @@ -1253,7 +1353,7 @@ tgs_build_reply(krb5_context context, krb5_data *reply, const char *from, const char **e_text, - AuthorizationData *auth_data, + AuthorizationData **auth_data, const struct sockaddr *from_addr, int datagram_reply) { @@ -1262,6 +1362,7 @@ tgs_build_reply(krb5_context context, krb5_principal client_principal = NULL; char *spn = NULL, *cpn = NULL; hdb_entry_ex *server = NULL, *client = NULL; + krb5_realm ref_realm = NULL; EncTicketPart *tgt = &ticket->ticket; KRB5SignedPathPrincipals *spp = NULL; const EncryptionKey *ekey; @@ -1270,16 +1371,19 @@ tgs_build_reply(krb5_context context, krb5_data rspac; int cross_realm = 0; + METHOD_DATA enc_pa_data; + PrincipalName *s; Realm r; int nloop = 0; EncTicketPart adtkt; char opt_str[128]; - int require_signedpath = 0; + int signedpath = 0; memset(&sessionkey, 0, sizeof(sessionkey)); memset(&adtkt, 0, sizeof(adtkt)); krb5_data_zero(&rspac); + memset(&enc_pa_data, 0, sizeof(enc_pa_data)); s = b->sname; r = b->realm; @@ -1289,8 +1393,8 @@ tgs_build_reply(krb5_context context, hdb_entry_ex *uu; krb5_principal p; Key *uukey; - - if(b->additional_tickets == NULL || + + if(b->additional_tickets == NULL || b->additional_tickets->len == 0){ ret = KRB5KDC_ERR_BADOPTION; /* ? */ kdc_log(context, config, 0, @@ -1305,8 +1409,8 @@ tgs_build_reply(krb5_context context, goto out; } _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); - ret = _kdc_db_fetch(context, config, p, - HDB_F_GET_CLIENT|HDB_F_GET_SERVER, + ret = _kdc_db_fetch(context, config, p, + HDB_F_GET_CLIENT|HDB_F_GET_SERVER, NULL, &uu); krb5_free_principal(context, p); if(ret){ @@ -1314,7 +1418,7 @@ tgs_build_reply(krb5_context context, ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } - ret = hdb_enctype2key(context, &uu->entry, + ret = hdb_enctype2key(context, &uu->entry, t->enc_part.etype, &uukey); if(ret){ _kdc_free_ent(context, uu); @@ -1347,7 +1451,7 @@ tgs_build_reply(krb5_context context, opt_str, sizeof(opt_str)); if(*opt_str) kdc_log(context, config, 0, - "TGS-REQ %s from %s for %s [%s]", + "TGS-REQ %s from %s for %s [%s]", cpn, from, spn, opt_str); else kdc_log(context, config, 0, @@ -1370,20 +1474,23 @@ server_lookup: new_rlm = find_rpath(context, tgt->crealm, req_rlm); if(new_rlm) { kdc_log(context, config, 5, "krbtgt for realm %s " - "not found, trying %s", + "not found, trying %s", req_rlm, new_rlm); krb5_free_principal(context, sp); free(spn); - krb5_make_principal(context, &sp, r, + krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, new_rlm, NULL); ret = krb5_unparse_name(context, sp, &spn); if (ret) goto out; - auth_data = NULL; /* ms don't handle AD in referals */ + + if (ref_realm) + free(ref_realm); + ref_realm = strdup(new_rlm); goto server_lookup; } } - } else if(need_referral(context, sp, &realms)) { + } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) { if (strcmp(realms[0], sp->realm) != 0) { kdc_log(context, config, 5, "Returning a referral to realm %s for " @@ -1396,8 +1503,12 @@ server_lookup: ret = krb5_unparse_name(context, sp, &spn); if (ret) goto out; + + if (ref_realm) + free(ref_realm); + ref_realm = strdup(realms[0]); + krb5_free_host_realm(context, realms); - auth_data = NULL; /* ms don't handle AD in referals */ goto server_lookup; } krb5_free_host_realm(context, realms); @@ -1412,7 +1523,7 @@ server_lookup: ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT, NULL, &client); if(ret) { - const char *krbtgt_realm; + const char *krbtgt_realm; /* * If the client belongs to the same realm as our krbtgt, it @@ -1420,8 +1531,8 @@ server_lookup: * */ - krbtgt_realm = - krb5_principal_get_comp_string(context, + krbtgt_realm = + krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1); if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) { @@ -1437,16 +1548,60 @@ server_lookup: cross_realm = 1; } - + + /* + * Select enctype, return key and kvno. + */ + + { + krb5_enctype etype; + + if(b->kdc_options.enc_tkt_in_skey) { + int i; + ekey = &adtkt.key; + for(i = 0; i < b->etype.len; i++) + if (b->etype.val[i] == adtkt.key.keytype) + break; + if(i == b->etype.len) { + kdc_log(context, config, 0, + "Addition ticket have not matching etypes", spp); + krb5_clear_error_string(context); + return KRB5KDC_ERR_ETYPE_NOSUPP; + } + etype = b->etype.val[i]; + kvno = 0; + } else { + Key *skey; + + ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len, + &skey, &etype); + if(ret) { + kdc_log(context, config, 0, + "Server (%s) has no support for etypes", spn); + return ret; + } + ekey = &skey->key; + kvno = server->entry.kvno; + } + + ret = krb5_generate_random_keyblock(context, etype, &sessionkey); + if (ret) + goto out; + } + + /* + * Validate authoriation data + */ + /* * Check that service is in the same realm as the krbtgt. If it's * not the same, it's someone that is using a uni-directional trust * backward. */ - + if (strcmp(krb5_principal_get_realm(context, sp), - krb5_principal_get_comp_string(context, - krbtgt->entry.principal, + krb5_principal_get_comp_string(context, + krbtgt->entry.principal, 1)) != 0) { char *tpn; ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn); @@ -1459,8 +1614,45 @@ server_lookup: goto out; } + /* check PAC if not cross realm and if there is one */ + if (!cross_realm) { + Key *tkey; + + ret = hdb_enctype2key(context, &krbtgt->entry, + krbtgt_etype, &tkey); + if(ret) { + kdc_log(context, config, 0, + "Failed to find key for krbtgt PAC check"); + goto out; + } + + ret = check_PAC(context, config, cp, + client, server, ekey, &tkey->key, + tgt, &rspac, &signedpath); + if (ret) { + kdc_log(context, config, 0, + "Verify PAC failed for %s (%s) from %s with %s", + spn, cpn, from, krb5_get_err_text(context, ret)); + goto out; + } + } + + /* also check the krbtgt for signature */ + ret = check_KRB5SignedPath(context, + config, + krbtgt, + tgt, + &spp, + &signedpath); + if (ret) { + kdc_log(context, config, 0, + "KRB5SignedPath check failed for %s (%s) from %s with %s", + spn, cpn, from, krb5_get_err_text(context, ret)); + goto out; + } + /* - * + * Process request */ client_principal = cp; @@ -1477,7 +1669,7 @@ server_lookup: char *selfcpn = NULL; const char *str; - ret = decode_PA_S4U2Self(sdata->padata_value.data, + ret = decode_PA_S4U2Self(sdata->padata_value.data, sdata->padata_value.length, &self, NULL); if (ret) { @@ -1501,14 +1693,14 @@ server_lookup: ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, - datack.data, - datack.length, + datack.data, + datack.length, &self.cksum); krb5_data_free(&datack); krb5_crypto_destroy(context, crypto); if (ret) { free_PA_S4U2Self(&self); - kdc_log(context, config, 0, + kdc_log(context, config, 0, "krb5_verify_checksum failed for S4U2Self: %s", krb5_get_err_text(context, ret)); goto out; @@ -1566,13 +1758,26 @@ server_lookup: && b->additional_tickets->len != 0 && b->kdc_options.enc_tkt_in_skey == 0) { + int ad_signedpath = 0; Key *clientkey; Ticket *t; char *str; + /* + * Require that the KDC have issued the service's krbtgt (not + * self-issued ticket with kimpersonate(1). + */ + if (!signedpath) { + ret = KRB5KDC_ERR_BADOPTION; + kdc_log(context, config, 0, + "Constrained delegation done on service ticket %s/%s", + cpn, spn); + goto out; + } + t = &b->additional_tickets->val[0]; - ret = hdb_enctype2key(context, &client->entry, + ret = hdb_enctype2key(context, &client->entry, t->enc_part.etype, &clientkey); if(ret){ ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ @@ -1588,19 +1793,18 @@ server_lookup: } /* check that ticket is valid */ - if (adtkt.flags.forwardable == 0) { kdc_log(context, config, 0, "Missing forwardable flag on ticket for " "constrained delegation from %s to %s ", spn, cpn); - ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ + ret = KRB5KDC_ERR_BADOPTION; goto out; } ret = check_constrained_delegation(context, config, client, sp); if (ret) { kdc_log(context, config, 0, - "constrained delegation from %s to %s not allowed", + "constrained delegation from %s to %s not allowed", spn, cpn); goto out; } @@ -1623,16 +1827,16 @@ server_lookup: } /* - * Check KRB5SignedPath in authorization data and add new entry to - * make sure servers can't fake a ticket to us. + * Check that the KDC issued the user's ticket. */ - ret = check_KRB5SignedPath(context, config, krbtgt, &adtkt, - &spp, - 1); + NULL, + &ad_signedpath); + if (ret == 0 && !ad_signedpath) + ret = KRB5KDC_ERR_BADOPTION; if (ret) { kdc_log(context, config, 0, "KRB5SignedPath check from service %s failed " @@ -1646,27 +1850,21 @@ server_lookup: kdc_log(context, config, 0, "constrained delegation for %s " "from %s to %s", str, cpn, spn); free(str); - - /* - * Also require that the KDC have issue the service's krbtgt - * used to do the request. - */ - require_signedpath = 1; } /* * Check flags */ - ret = _kdc_check_flags(context, config, + ret = _kdc_check_flags(context, config, client, cpn, server, spn, FALSE); if(ret) goto out; - if((b->kdc_options.validate || b->kdc_options.renew) && - !krb5_principal_compare(context, + if((b->kdc_options.validate || b->kdc_options.renew) && + !krb5_principal_compare(context, krbtgt->entry.principal, server->entry.principal)){ kdc_log(context, config, 0, "Inconsistent request."); @@ -1682,108 +1880,68 @@ server_lookup: } /* - * Select enctype, return key and kvno. + * If this is an referral, add server referral data to the + * auth_data reply . */ + if (ref_realm) { + PA_DATA pa; + krb5_crypto crypto; - { - krb5_enctype etype; + kdc_log(context, config, 0, + "Adding server referral to %s", ref_realm); - if(b->kdc_options.enc_tkt_in_skey) { - int i; - ekey = &adtkt.key; - for(i = 0; i < b->etype.len; i++) - if (b->etype.val[i] == adtkt.key.keytype) - break; - if(i == b->etype.len) { - krb5_clear_error_string(context); - return KRB5KDC_ERR_ETYPE_NOSUPP; - } - etype = b->etype.val[i]; - kvno = 0; - } else { - Key *skey; - - ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len, - &skey, &etype); - if(ret) { - kdc_log(context, config, 0, - "Server (%s) has no support for etypes", spp); - return ret; - } - ekey = &skey->key; - kvno = server->entry.kvno; - } - - ret = krb5_generate_random_keyblock(context, etype, &sessionkey); + ret = krb5_crypto_init(context, &sessionkey, 0, &crypto); if (ret) goto out; - } - - /* check PAC if not cross realm and if there is one */ - if (!cross_realm) { - Key *tkey; - ret = hdb_enctype2key(context, &krbtgt->entry, - krbtgt_etype, &tkey); - if(ret) { + ret = build_server_referral(context, config, crypto, ref_realm, + NULL, s, &pa.padata_value); + krb5_crypto_destroy(context, crypto); + if (ret) { kdc_log(context, config, 0, - "Failed to find key for krbtgt PAC check"); + "Failed building server referral"); goto out; } + pa.padata_type = KRB5_PADATA_SERVER_REFERRAL; - ret = check_PAC(context, config, client_principal, - client, server, ekey, &tkey->key, - tgt, &rspac, &require_signedpath); + ret = add_METHOD_DATA(&enc_pa_data, &pa); + krb5_data_free(&pa.padata_value); if (ret) { kdc_log(context, config, 0, - "Verify PAC failed for %s (%s) from %s with %s", - spn, cpn, from, krb5_get_err_text(context, ret)); + "Add server referral METHOD-DATA failed"); goto out; } } - /* also check the krbtgt for signature */ - ret = check_KRB5SignedPath(context, - config, - krbtgt, - tgt, - &spp, - require_signedpath); - if (ret) { - kdc_log(context, config, 0, - "KRB5SignedPath check failed for %s (%s) from %s with %s", - spn, cpn, from, krb5_get_err_text(context, ret)); - goto out; - } - /* * */ ret = tgs_make_reply(context, - config, - b, + config, + b, client_principal, - tgt, + tgt, ekey, &sessionkey, kvno, - auth_data, - server, + *auth_data, + server, spn, - client, - cp, - krbtgt, + client, + cp, + krbtgt, krbtgt_etype, spp, &rspac, + &enc_pa_data, e_text, reply); out: free(spn); free(cpn); - + krb5_data_free(&rspac); krb5_free_keyblock_contents(context, &sessionkey); if(server) @@ -1797,6 +1955,9 @@ out: krb5_free_principal(context, cp); if (sp) krb5_free_principal(context, sp); + if (ref_realm) + free(ref_realm); + free_METHOD_DATA(&enc_pa_data); free_EncTicketPart(&adtkt); @@ -1808,9 +1969,9 @@ out: */ krb5_error_code -_kdc_tgs_rep(krb5_context context, +_kdc_tgs_rep(krb5_context context, krb5_kdc_configuration *config, - KDC_REQ *req, + KDC_REQ *req, krb5_data *data, const char *from, struct sockaddr *from_addr, @@ -1835,17 +1996,17 @@ _kdc_tgs_rep(krb5_context context, "TGS-REQ from %s without PA-DATA", from); goto out; } - + tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ); if(tgs_req == NULL){ ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - kdc_log(context, config, 0, + kdc_log(context, config, 0, "TGS-REQ from %s without PA-TGS-REQ", from); goto out; } - ret = tgs_parse_request(context, config, + ret = tgs_parse_request(context, config, &req->req_body, tgs_req, &krbtgt, &krbtgt_etype, @@ -1855,7 +2016,7 @@ _kdc_tgs_rep(krb5_context context, &csec, &cusec, &auth_data); if (ret) { - kdc_log(context, config, 0, + kdc_log(context, config, 0, "Failed parsing TGS-REQ from %s", from); goto out; } @@ -1870,11 +2031,11 @@ _kdc_tgs_rep(krb5_context context, data, from, &e_text, - auth_data, + &auth_data, from_addr, datagram_reply); if (ret) { - kdc_log(context, config, 0, + kdc_log(context, config, 0, "Failed building TGS-REP to %s", from); goto out; } diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c index b1b861efef..8f117cebc0 100644 --- a/source4/heimdal/kdc/kx509.c +++ b/source4/heimdal/kdc/kx509.c @@ -36,7 +36,7 @@ #include #include -RCSID("$Id: kx509.c 21607 2007-07-17 07:04:52Z lha $"); +RCSID("$Id: kx509.c 23316 2008-06-23 04:32:32Z lha $"); /* * @@ -67,8 +67,9 @@ verify_req_hash(krb5_context context, HMAC_CTX ctx; if (req->pk_hash.length != sizeof(digest)) { - krb5_set_error_string(context, "pk-hash have wrong length: %lu", - (unsigned long)req->pk_hash.length); + krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, + "pk-hash have wrong length: %lu", + (unsigned long)req->pk_hash.length); return KRB5KDC_ERR_PREAUTH_FAILED; } @@ -84,7 +85,8 @@ verify_req_hash(krb5_context context, HMAC_CTX_cleanup(&ctx); if (memcmp(req->pk_hash.data, digest, sizeof(digest)) != 0) { - krb5_set_error_string(context, "pk-hash is not correct"); + krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, + "pk-hash is not correct"); return KRB5KDC_ERR_PREAUTH_FAILED; } return 0; @@ -106,7 +108,7 @@ calculate_reply_hash(krb5_context context, rep->hash->data = malloc(rep->hash->length); if (rep->hash->data == NULL) { HMAC_CTX_cleanup(&ctx); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -157,12 +159,8 @@ build_certificate(krb5_context context, ret = hx509_context_init(&hxctx); if (ret) goto out; - - ret = hx509_env_init(hxctx, &env); - if (ret) - goto out; - - ret = hx509_env_add(hxctx, env, "principal-name", + + ret = hx509_env_add(hxctx, &env, "principal-name", krb5_principal_get_comp_string(context, principal, 0)); if (ret) goto out; @@ -280,7 +278,7 @@ out: hx509_cert_free(signer); if (hxctx) hx509_context_free(&hxctx); - krb5_set_error_string(context, "cert creation failed"); + krb5_set_error_message(context, ret, "cert creation failed"); return ret; } @@ -358,16 +356,18 @@ _kdc_do_kx509(krb5_context context, krb5_free_principal(context, principal); if (ret != TRUE) { ret = KRB5KDC_ERR_SERVER_NOMATCH; - krb5_set_error_string(context, - "User %s used wrong Kx509 service principal", - cname); + krb5_set_error_message(context, ret, + "User %s used wrong Kx509 service principal", + cname); goto out; } } ret = krb5_auth_con_getkey(context, ac, &key); - if (ret || key == NULL) { - krb5_set_error_string(context, "Kx509 can't get session key"); + if (ret == 0 && key == NULL) + ret = KRB5KDC_ERR_NULL_KEY; + if (ret) { + krb5_set_error_message(context, ret, "Kx509 can't get session key"); goto out; } @@ -418,7 +418,7 @@ _kdc_do_kx509(krb5_context context, ASN1_MALLOC_ENCODE(Kx509Response, data.data, data.length, &rep, &size, ret); if (ret) { - krb5_set_error_string(context, "Failed to encode kx509 reply"); + krb5_set_error_message(context, ret, "Failed to encode kx509 reply"); goto out; } if (size != data.length) diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index 072df44042..528b9e6a3b 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: misc.c 21106 2007-06-18 10:18:11Z lha $"); +RCSID("$Id: misc.c 23316 2008-06-23 04:32:32Z lha $"); struct timeval _kdc_now; @@ -51,7 +51,7 @@ _kdc_db_fetch(krb5_context context, ent = calloc (1, sizeof (*ent)); if (ent == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -76,8 +76,8 @@ _kdc_db_fetch(krb5_context context, } } free(ent); - krb5_set_error_string(context, "no such entry found in hdb"); - return HDB_ERR_NOENTRY; + krb5_set_error_message(context, HDB_ERR_NOENTRY, "no such entry found in hdb"); + return HDB_ERR_NOENTRY; } void @@ -116,7 +116,8 @@ _kdc_get_preferred_key(krb5_context context, } } - krb5_set_error_string(context, "No valid kerberos key found for %s", name); + krb5_set_error_message(context, EINVAL, + "No valid kerberos key found for %s", name); return EINVAL; } diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c index bf248af588..9f6d57f588 100755 --- a/source4/heimdal/kdc/pkinit.c +++ b/source4/heimdal/kdc/pkinit.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: pkinit.c 22243 2007-12-08 23:39:30Z lha $"); +RCSID("$Id: pkinit.c 23316 2008-06-23 04:32:32Z lha $"); #ifdef PKINIT @@ -45,23 +45,8 @@ RCSID("$Id: pkinit.c 22243 2007-12-08 23:39:30Z lha $"); #include #include "crypto-headers.h" -/* XXX copied from lib/krb5/pkinit.c */ -struct krb5_pk_identity { - hx509_context hx509ctx; - hx509_verify_ctx verify_ctx; - hx509_certs certs; - hx509_certs anchors; - hx509_certs certpool; - hx509_revoke_ctx revoke; -}; - -enum pkinit_type { - PKINIT_COMPAT_WIN2K = 1, - PKINIT_COMPAT_27 = 3 -}; - struct pk_client_params { - enum pkinit_type type; + enum krb5_pk_type type; BIGNUM *dh_public_key; hx509_cert cert; unsigned nonce; @@ -202,13 +187,13 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params, memset(&key, 0, sizeof(key)); if (!DH_generate_key(client_params->dh)) { - krb5_set_error_string(context, "Can't generate Diffie-Hellman keys"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "Can't generate Diffie-Hellman keys"); goto out; } if (client_params->dh_public_key == NULL) { - krb5_set_error_string(context, "dh_public_key"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "dh_public_key"); goto out; } @@ -219,8 +204,8 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params, dh_gen_key = malloc(size); if (dh_gen_key == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } memset(dh_gen_key, 0, size - dh_gen_keylen); @@ -229,8 +214,8 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params, client_params->dh_public_key, client_params->dh); if (dh_gen_keylen == -1) { - krb5_set_error_string(context, "Can't compute Diffie-Hellman key"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "Can't compute Diffie-Hellman key"); goto out; } @@ -256,7 +241,8 @@ integer_to_BN(krb5_context context, const char *field, heim_integer *f) bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); if (bn == NULL) { - krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); + krb5_set_error_message(context, KRB5_BADMSGTYPE, + "PKINIT: parsing BN failed %s", field); return NULL; } BN_set_negative(bn, f->negative); @@ -276,13 +262,14 @@ get_dh_param(krb5_context context, memset(&dhparam, 0, sizeof(dhparam)); if (der_heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) { - krb5_set_error_string(context, - "PKINIT invalid oid in clientPublicValue"); + krb5_set_error_message(context, KRB5_BADMSGTYPE, + "PKINIT invalid oid in clientPublicValue"); return KRB5_BADMSGTYPE; } if (dh_key_info->algorithm.parameters == NULL) { - krb5_set_error_string(context, "PKINIT missing algorithm parameter " + krb5_set_error_message(context, KRB5_BADMSGTYPE, + "PKINIT missing algorithm parameter " "in clientPublicValue"); return KRB5_BADMSGTYPE; } @@ -292,15 +279,16 @@ get_dh_param(krb5_context context, &dhparam, NULL); if (ret) { - krb5_set_error_string(context, "Can't decode algorithm " - "parameters in clientPublicValue"); + krb5_set_error_message(context, ret, "Can't decode algorithm " + "parameters in clientPublicValue"); goto out; } if ((dh_key_info->subjectPublicKey.length % 8) != 0) { ret = KRB5_BADMSGTYPE; - krb5_set_error_string(context, "PKINIT: subjectPublicKey not aligned " - "to 8 bit boundary"); + krb5_set_error_message(context, ret, + "PKINIT: subjectPublicKey not aligned " + "to 8 bit boundary"); goto out; } @@ -315,8 +303,8 @@ get_dh_param(krb5_context context, dh = DH_new(); if (dh == NULL) { - krb5_set_error_string(context, "Cannot create DH structure"); ret = ENOMEM; + krb5_set_error_message(context, ret, "Cannot create DH structure"); goto out; } ret = KRB5_BADMSGTYPE; @@ -347,8 +335,10 @@ get_dh_param(krb5_context context, "subjectPublicKey", &glue); der_free_heim_integer(&glue); - if (client_params->dh_public_key == NULL) + if (client_params->dh_public_key == NULL) { + ret = KRB5_BADMSGTYPE; goto out; + } } client_params->dh = dh; @@ -385,7 +375,7 @@ _kdc_pk_rd_padata(krb5_context context, return 0; } - hx509_verify_set_time(kdc_identity->verify_ctx, _kdc_now.tv_sec); + hx509_verify_set_time(kdc_identity->verify_ctx, kdc_time); client_params = calloc(1, sizeof(*client_params)); if (client_params == NULL) { @@ -404,8 +394,8 @@ _kdc_pk_rd_padata(krb5_context context, &r, NULL); if (ret) { - krb5_set_error_string(context, "Can't decode " - "PK-AS-REQ-Win2k: %d", ret); + krb5_set_error_message(context, ret, "Can't decode " + "PK-AS-REQ-Win2k: %d", ret); goto out; } @@ -415,7 +405,8 @@ _kdc_pk_rd_padata(krb5_context context, &have_data); free_PA_PK_AS_REQ_Win2k(&r); if (ret) { - krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); + krb5_set_error_message(context, ret, + "Can't decode PK-AS-REQ: %d", ret); goto out; } @@ -429,7 +420,7 @@ _kdc_pk_rd_padata(krb5_context context, &r, NULL); if (ret) { - krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); + krb5_set_error_message(context, ret, "Can't decode PK-AS-REQ: %d", ret); goto out; } @@ -443,7 +434,7 @@ _kdc_pk_rd_padata(krb5_context context, 0, NULL, &client_params->client_anchors); if (ret) { - krb5_set_error_string(context, "Can't allocate client anchors: %d", ret); + krb5_set_error_message(context, ret, "Can't allocate client anchors: %d", ret); goto out; } @@ -458,7 +449,7 @@ _kdc_pk_rd_padata(krb5_context context, ret = hx509_query_alloc(kdc_identity->hx509ctx, &q); if (ret) { - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "Failed to allocate hx509_query"); goto out; } @@ -495,7 +486,8 @@ _kdc_pk_rd_padata(krb5_context context, &have_data); free_PA_PK_AS_REQ(&r); if (ret) { - krb5_set_error_string(context, "Can't unwrap ContentInfo: %d", ret); + krb5_set_error_message(context, ret, + "Can't unwrap ContentInfo: %d", ret); goto out; } @@ -507,16 +499,16 @@ _kdc_pk_rd_padata(krb5_context context, ret = der_heim_oid_cmp(&contentInfoOid, oid_id_pkcs7_signedData()); if (ret != 0) { - krb5_set_error_string(context, "PK-AS-REQ-Win2k invalid content " - "type oid"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, + "PK-AS-REQ-Win2k invalid content type oid"); goto out; } if (!have_data) { - krb5_set_error_string(context, - "PK-AS-REQ-Win2k no signed auth pack"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, + "PK-AS-REQ-Win2k no signed auth pack"); goto out; } @@ -551,8 +543,8 @@ _kdc_pk_rd_padata(krb5_context context, if (der_heim_oid_cmp(&eContentType, oid_id_pkcs7_data()) != 0 && der_heim_oid_cmp(&eContentType, oid_id_pkauthdata()) != 0) { - krb5_set_error_string(context, "got wrong oid for pkauthdata"); ret = KRB5_BADMSGTYPE; + krb5_set_error_message(context, ret, "got wrong oid for pkauthdata"); goto out; } @@ -564,7 +556,7 @@ _kdc_pk_rd_padata(krb5_context context, &ap, NULL); if (ret) { - krb5_set_error_string(context, "can't decode AuthPack: %d", ret); + krb5_set_error_message(context, ret, "can't decode AuthPack: %d", ret); goto out; } @@ -576,12 +568,12 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - client_params->type = PKINIT_COMPAT_WIN2K; + client_params->type = PKINIT_WIN2K; client_params->nonce = ap.pkAuthenticator.nonce; if (ap.clientPublicValue) { - krb5_set_error_string(context, "DH not supported for windows"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "DH not supported for windows"); goto out; } free_AuthPack_Win2k(&ap); @@ -594,7 +586,7 @@ _kdc_pk_rd_padata(krb5_context context, &ap, NULL); if (ret) { - krb5_set_error_string(context, "can't decode AuthPack: %d", ret); + krb5_set_error_message(context, ret, "can't decode AuthPack: %d", ret); free_AuthPack(&ap); goto out; } @@ -607,7 +599,7 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - client_params->type = PKINIT_COMPAT_27; + client_params->type = PKINIT_27; client_params->nonce = ap.pkAuthenticator.nonce; if (ap.clientPublicValue) { @@ -700,7 +692,7 @@ pk_mk_pa_reply_enckey(krb5_context context, */ switch (client_params->type) { - case PKINIT_COMPAT_WIN2K: { + case PKINIT_WIN2K: { int i = 0; if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL && config->pkinit_require_binding == 0) @@ -709,7 +701,7 @@ pk_mk_pa_reply_enckey(krb5_context context, } break; } - case PKINIT_COMPAT_27: + case PKINIT_27: break; default: krb5_abortx(context, "internal pkinit error"); @@ -769,8 +761,8 @@ pk_mk_pa_reply_enckey(krb5_context context, free_ReplyKeyPack(&kp); } if (ret) { - krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack " - "failed (%d)", ret); + krb5_set_error_message(context, ret, "ASN.1 encoding of ReplyKeyPack " + "failed (%d)", ret); goto out; } if (buf.length != size) @@ -813,7 +805,7 @@ pk_mk_pa_reply_enckey(krb5_context context, if (ret) goto out; - if (client_params->type == PKINIT_COMPAT_WIN2K) { + if (client_params->type == PKINIT_WIN2K) { ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &signed_data, &buf); @@ -874,9 +866,8 @@ pk_mk_pa_reply_dh(krb5_context context, ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret); if (ret) { - krb5_set_error_string(context, "ASN.1 encoding of " - "DHPublicKey failed (%d)", ret); - krb5_clear_error_string(context); + krb5_set_error_message(context, ret, "ASN.1 encoding of " + "DHPublicKey failed (%d)", ret); return ret; } if (buf.length != size) @@ -890,8 +881,8 @@ pk_mk_pa_reply_dh(krb5_context context, ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size, ret); if (ret) { - krb5_set_error_string(context, "ASN.1 encoding of " - "KdcDHKeyInfo failed (%d)", ret); + krb5_set_error_message(context, ret, "ASN.1 encoding of " + "KdcDHKeyInfo failed (%d)", ret); goto out; } if (buf.length != size) @@ -990,15 +981,15 @@ _kdc_pk_mk_pa_reply(krb5_context context, break; if (req->req_body.etype.len <= i) { ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_string(context, - "No valid enctype available from client"); + krb5_set_error_message(context, ret, + "No valid enctype available from client"); goto out; } enctype = req->req_body.etype.val[i]; } else enctype = ETYPE_DES3_CBC_SHA1; - if (client_params->type == PKINIT_COMPAT_27) { + if (client_params->type == PKINIT_27) { PA_PK_AS_REP rep; const char *type, *other = ""; @@ -1035,8 +1026,8 @@ _kdc_pk_mk_pa_reply(krb5_context context, ret); free_ContentInfo(&info); if (ret) { - krb5_set_error_string(context, "encoding of Key ContentInfo " - "failed %d", ret); + krb5_set_error_message(context, ret, "encoding of Key ContentInfo " + "failed %d", ret); free_PA_PK_AS_REP(&rep); goto out; } @@ -1068,8 +1059,8 @@ _kdc_pk_mk_pa_reply(krb5_context context, ret); free_ContentInfo(&info); if (ret) { - krb5_set_error_string(context, "encoding of Key ContentInfo " - "failed %d", ret); + krb5_set_error_message(context, ret, "encoding of Key ContentInfo " + "failed %d", ret); free_PA_PK_AS_REP(&rep); goto out; } @@ -1085,8 +1076,8 @@ _kdc_pk_mk_pa_reply(krb5_context context, ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret); free_PA_PK_AS_REP(&rep); if (ret) { - krb5_set_error_string(context, "encode PA-PK-AS-REP failed %d", - ret); + krb5_set_error_message(context, ret, "encode PA-PK-AS-REP failed %d", + ret); goto out; } if (len != size) @@ -1094,13 +1085,13 @@ _kdc_pk_mk_pa_reply(krb5_context context, kdc_log(context, config, 0, "PK-INIT using %s %s", type, other); - } else if (client_params->type == PKINIT_COMPAT_WIN2K) { + } else if (client_params->type == PKINIT_WIN2K) { PA_PK_AS_REP_Win2k rep; ContentInfo info; if (client_params->dh) { - krb5_set_error_string(context, "Windows PK-INIT doesn't support DH"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "Windows PK-INIT doesn't support DH"); goto out; } @@ -1131,7 +1122,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, ret); free_ContentInfo(&info); if (ret) { - krb5_set_error_string(context, "encoding of Key ContentInfo " + krb5_set_error_message(context, ret, "encoding of Key ContentInfo " "failed %d", ret); free_PA_PK_AS_REP_Win2k(&rep); goto out; @@ -1142,7 +1133,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, ASN1_MALLOC_ENCODE(PA_PK_AS_REP_Win2k, buf, len, &rep, &size, ret); free_PA_PK_AS_REP_Win2k(&rep); if (ret) { - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "encode PA-PK-AS-REP-Win2k failed %d", ret); goto out; } @@ -1155,7 +1146,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, ret = krb5_padata_add(context, md, pa_type, buf, len); if (ret) { - krb5_set_error_string(context, "failed adding PA-PK-AS-REP %d", ret); + krb5_set_error_message(context, ret, "failed adding PA-PK-AS-REP %d", ret); free(buf); goto out; } @@ -1229,8 +1220,8 @@ _kdc_pk_mk_pa_reply(krb5_context context, KRB5_PADATA_PA_PK_OCSP_RESPONSE, ocsp.data.data, ocsp.data.length); if (ret) { - krb5_set_error_string(context, - "Failed adding OCSP response %d", ret); + krb5_set_error_message(context, ret, + "Failed adding OCSP response %d", ret); goto out; } } @@ -1453,7 +1444,8 @@ _kdc_pk_check_client(krb5_context context, return 0; } - krb5_set_error_string(context, + ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; + krb5_set_error_message(context, ret, "PKINIT no matching principals for %s", *subject_name); @@ -1464,7 +1456,7 @@ _kdc_pk_check_client(krb5_context context, free(*subject_name); *subject_name = NULL; - return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; + return ret; } static krb5_error_code diff --git a/source4/heimdal/kdc/process.c b/source4/heimdal/kdc/process.c index 1d0a01a215..550bfb04b2 100644 --- a/source4/heimdal/kdc/process.c +++ b/source4/heimdal/kdc/process.c @@ -34,7 +34,7 @@ #include "kdc_locl.h" -RCSID("$Id: process.c 20959 2007-06-07 04:46:06Z lha $"); +RCSID("$Id: process.c 23316 2008-06-23 04:32:32Z lha $"); /* * @@ -177,14 +177,15 @@ krb5_kdc_save_request(krb5_context context, fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); if (fd < 0) { - krb5_set_error_string(context, "Failed to open: %s", fn); - return errno; + int saved_errno = errno; + krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn); + return saved_errno; } sp = krb5_storage_from_fd(fd); close(fd); if (sp == NULL) { - krb5_set_error_string(context, "Storage failed to open fd"); + krb5_set_error_message(context, ENOMEM, "Storage failed to open fd"); return ENOMEM; } diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index 85e4d7f725..621757f6dc 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: windc.c 20559 2007-04-24 16:00:07Z lha $"); +RCSID("$Id: windc.c 23316 2008-06-23 04:32:32Z lha $"); static krb5plugin_windc_ftable *windcft; static void *windcctx; @@ -63,7 +63,7 @@ krb5_kdc_windc_init(krb5_context context) } if (e == NULL) { _krb5_plugin_free(list); - krb5_set_error_string(context, "Did not find any WINDC plugin"); + krb5_set_error_message(context, ENOENT, "Did not find any WINDC plugin"); windcft = NULL; return ENOENT; } @@ -91,7 +91,7 @@ _kdc_pac_verify(krb5_context context, krb5_pac *pac) { if (windcft == NULL) { - krb5_set_error_string(context, "Can't verify PAC, no function"); + krb5_set_error_message(context, EINVAL, "Can't verify PAC, no function"); return EINVAL; } return (windcft->pac_verify)(windcctx, context, diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index 3ae0c94681..44aab9e22b 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: windc_plugin.h 19798 2007-01-10 15:24:51Z lha $ */ +/* $Id: windc_plugin.h 22693 2008-03-19 08:57:49Z lha $ */ #ifndef HEIMDAL_KRB5_PAC_PLUGIN_H #define HEIMDAL_KRB5_PAC_PLUGIN_H 1 @@ -67,7 +67,7 @@ typedef krb5_error_code void *, krb5_context, struct hdb_entry_ex *, KDC_REQ *, krb5_data *); -#define KRB5_WINDC_PLUGING_MINOR 2 +#define KRB5_WINDC_PLUGING_MINOR 3 typedef struct krb5plugin_windc_ftable { int minor_version; -- cgit