From 255e3e18e00f717d99f3bc57c8a8895ff624f3c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Jul 2011 09:10:30 +0200 Subject: s4:heimdal: import lorikeet-heimdal-201107150856 (commit 48936803fae4a2fb362c79365d31f420c917b85b) --- source4/heimdal/kdc/default_config.c | 74 +++++------ source4/heimdal/kdc/digest.c | 142 ++++++++++----------- source4/heimdal/kdc/kdc.h | 16 +-- source4/heimdal/kdc/kerberos5.c | 236 ++++++++++++++++++++--------------- source4/heimdal/kdc/krb5tgs.c | 104 ++++++++------- source4/heimdal/kdc/kx509.c | 4 +- source4/heimdal/kdc/log.c | 10 +- source4/heimdal/kdc/misc.c | 39 ++++-- source4/heimdal/kdc/pkinit.c | 115 ++++++++--------- source4/heimdal/kdc/process.c | 18 +-- source4/heimdal/kdc/windc.c | 10 +- source4/heimdal/kdc/windc_plugin.h | 6 +- 12 files changed, 414 insertions(+), 360 deletions(-) (limited to 'source4/heimdal/kdc') diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c index 1441c3161e..fe977ded5a 100644 --- a/source4/heimdal/kdc/default_config.c +++ b/source4/heimdal/kdc/default_config.c @@ -51,14 +51,14 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) c->require_preauth = TRUE; c->kdc_warn_pwexpire = 0; c->encode_as_rep_as_tgs_rep = FALSE; + c->as_use_strongest_session_key = FALSE; + c->preauth_use_strongest_session_key = FALSE; + c->tgs_use_strongest_session_key = FALSE; + c->use_strongest_server_key = FALSE; c->check_ticket_addresses = TRUE; c->allow_null_ticket_addresses = TRUE; c->allow_anonymous = FALSE; c->trpolicy = TRPOLICY_ALWAYS_CHECK; - c->enable_v4 = FALSE; - c->enable_kaserver = FALSE; - c->enable_524 = FALSE; - c->enable_v4_cross_realm = FALSE; c->enable_pkinit = FALSE; c->pkinit_princ_in_cert = TRUE; c->pkinit_require_binding = TRUE; @@ -70,19 +70,6 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) krb5_config_get_bool_default(context, NULL, c->require_preauth, "kdc", "require-preauth", NULL); - c->enable_v4 = - krb5_config_get_bool_default(context, NULL, - c->enable_v4, - "kdc", "enable-kerberos4", NULL); - c->enable_v4_cross_realm = - krb5_config_get_bool_default(context, NULL, - c->enable_v4_cross_realm, - "kdc", - "enable-kerberos4-cross-realm", NULL); - c->enable_524 = - krb5_config_get_bool_default(context, NULL, - c->enable_v4, - "kdc", "enable-524", NULL); #ifdef DIGEST c->enable_digest = krb5_config_get_bool_default(context, NULL, @@ -133,6 +120,27 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) } #endif + c->as_use_strongest_session_key = + krb5_config_get_bool_default(context, NULL, + c->as_use_strongest_session_key, + "kdc", + "as-use-strongest-session-key", NULL); + c->preauth_use_strongest_session_key = + krb5_config_get_bool_default(context, NULL, + c->preauth_use_strongest_session_key, + "kdc", + "preauth-use-strongest-session-key", NULL); + c->tgs_use_strongest_session_key = + krb5_config_get_bool_default(context, NULL, + c->tgs_use_strongest_session_key, + "kdc", + "tgs-use-strongest-session-key", NULL); + c->use_strongest_server_key = + krb5_config_get_bool_default(context, NULL, + c->use_strongest_server_key, + "kdc", + "use-strongest-server-key", NULL); + c->check_ticket_addresses = krb5_config_get_bool_default(context, NULL, c->check_ticket_addresses, @@ -180,28 +188,6 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) } } - { - const char *p; - p = krb5_config_get_string (context, NULL, - "kdc", - "v4-realm", - NULL); - if(p != NULL) { - c->v4_realm = strdup(p); - if (c->v4_realm == NULL) - krb5_errx(context, 1, "out of memory"); - } else { - c->v4_realm = NULL; - } - } - - c->enable_kaserver = - krb5_config_get_bool_default(context, - NULL, - c->enable_kaserver, - "kdc", "enable-kaserver", NULL); - - c->encode_as_rep_as_tgs_rep = krb5_config_get_bool_default(context, NULL, c->encode_as_rep_as_tgs_rep, @@ -223,7 +209,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) NULL); - c->pkinit_kdc_identity = + c->pkinit_kdc_identity = krb5_config_get_string(context, NULL, "kdc", "pkinit_identity", NULL); c->pkinit_kdc_anchors = @@ -235,7 +221,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) c->pkinit_kdc_revoke = krb5_config_get_strings(context, NULL, "kdc", "pkinit_revoke", NULL); - c->pkinit_kdc_ocsp_file = + c->pkinit_kdc_ocsp_file = krb5_config_get_string(context, NULL, "kdc", "pkinit_kdc_ocsp", NULL); c->pkinit_kdc_friendly_name = @@ -272,7 +258,7 @@ krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config) if (config->pkinit_kdc_identity == NULL) { if (config->pkinit_kdc_friendly_name == NULL) - config->pkinit_kdc_friendly_name = + config->pkinit_kdc_friendly_name = strdup("O=System Identity,CN=com.apple.kerberos.kdc"); config->pkinit_kdc_identity = strdup("KEYCHAIN:"); } @@ -284,7 +270,7 @@ krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config) if (config->enable_pkinit) { if (config->pkinit_kdc_identity == NULL) krb5_errx(context, 1, "pkinit enabled but no identity"); - + if (config->pkinit_kdc_anchors == NULL) krb5_errx(context, 1, "pkinit enabled but no X509 anchors"); @@ -298,4 +284,4 @@ krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config) return 0; #endif /* PKINIT */ -} +} diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c index 70b45c2af6..5f0d27441a 100644 --- a/source4/heimdal/kdc/digest.c +++ b/source4/heimdal/kdc/digest.c @@ -257,7 +257,7 @@ _kdc_do_digest(krb5_context context, /* check the server principal in the ticket matches digest/R@R */ { krb5_principal principal = NULL; - const char *p, *r; + const char *p, *rr; ret = krb5_ticket_get_server(context, ticket, &principal); if (ret) @@ -280,12 +280,12 @@ _kdc_do_digest(krb5_context context, krb5_free_principal(context, principal); goto out; } - r = krb5_principal_get_realm(context, principal); - if (r == NULL) { + rr = krb5_principal_get_realm(context, principal); + if (rr == NULL) { krb5_free_principal(context, principal); goto out; } - if (strcmp(p, r) != 0) { + if (strcmp(p, rr) != 0) { krb5_free_principal(context, principal); goto out; } @@ -356,7 +356,7 @@ _kdc_do_digest(krb5_context context, crypto = NULL; if (ret) goto out; - + ret = decode_DigestReqInner(buf.data, buf.length, &ireq, NULL); krb5_data_free(&buf); if (ret) { @@ -419,7 +419,7 @@ _kdc_do_digest(krb5_context context, free(r.u.initReply.nonce); r.u.initReply.nonce = s; } - + ret = krb5_store_stringz(sp, r.u.initReply.nonce); if (ret) { krb5_clear_error_message(context); @@ -475,7 +475,7 @@ _kdc_do_digest(krb5_context context, krb5_data_free(&buf); if (ret) goto out; - + ASN1_MALLOC_ENCODE(Checksum, buf.data, buf.length, &res, &size, ret); free_Checksum(&res); if (ret) { @@ -547,7 +547,7 @@ _kdc_do_digest(krb5_context context, "Failed to decode digest Checksum"); goto out; } - + ret = krb5_storage_to_data(sp, &buf); if (ret) { krb5_clear_error_message(context); @@ -561,14 +561,14 @@ _kdc_do_digest(krb5_context context, krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } - + /* * CHAP does the checksum of the raw nonce, but do it for all * types, since we need to check the timestamp. */ { ssize_t ssize; - + ssize = hex_decode(ireq.u.digestRequest.serverNonce, serverNonce.data, serverNonce.length); if (ssize <= 0) { @@ -597,7 +597,7 @@ _kdc_do_digest(krb5_context context, { unsigned char *p = serverNonce.data; uint32_t t; - + if (serverNonce.length < 4) { ret = EINVAL; krb5_set_error_message(context, ret, "server nonce too short"); @@ -616,7 +616,7 @@ _kdc_do_digest(krb5_context context, EVP_MD_CTX *ctx; unsigned char md[MD5_DIGEST_LENGTH]; char *mdx; - char id; + char idx; if ((config->digests_allowed & CHAP_MD5) == 0) { kdc_log(context, config, 0, "Digest CHAP MD5 not allowed"); @@ -629,13 +629,13 @@ _kdc_do_digest(krb5_context context, "from CHAP request"); goto out; } - - if (hex_decode(*ireq.u.digestRequest.identifier, &id, 1) != 1) { + + if (hex_decode(*ireq.u.digestRequest.identifier, &idx, 1) != 1) { ret = EINVAL; krb5_set_error_message(context, ret, "failed to decode identifier"); goto out; } - + ret = get_password_entry(context, config, ireq.u.digestRequest.username, &password); @@ -645,7 +645,7 @@ _kdc_do_digest(krb5_context context, ctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, &id, 1); + EVP_DigestUpdate(ctx, &idx, 1); EVP_DigestUpdate(ctx, password, strlen(password)); EVP_DigestUpdate(ctx, serverNonce.data, serverNonce.length); EVP_DigestFinal_ex(ctx, md, NULL); @@ -691,7 +691,7 @@ _kdc_do_digest(krb5_context context, goto out; if (ireq.u.digestRequest.realm == NULL) goto out; - + ret = get_password_entry(context, config, ireq.u.digestRequest.username, &password); @@ -709,7 +709,7 @@ _kdc_do_digest(krb5_context context, EVP_DigestUpdate(ctx, ":", 1); EVP_DigestUpdate(ctx, password, strlen(password)); EVP_DigestFinal_ex(ctx, md, NULL); - + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); EVP_DigestUpdate(ctx, md, sizeof(md)); EVP_DigestUpdate(ctx, ":", 1); @@ -731,19 +731,19 @@ _kdc_do_digest(krb5_context context, EVP_MD_CTX_destroy(ctx); goto failed; } - + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); EVP_DigestUpdate(ctx, "AUTHENTICATE:", sizeof("AUTHENTICATE:") - 1); EVP_DigestUpdate(ctx, *ireq.u.digestRequest.uri, strlen(*ireq.u.digestRequest.uri)); - + /* conf|int */ if (strcmp(ireq.u.digestRequest.digest, "clear") != 0) { static char conf_zeros[] = ":00000000000000000000000000000000"; EVP_DigestUpdate(ctx, conf_zeros, sizeof(conf_zeros) - 1); } - + EVP_DigestFinal_ex(ctx, md, NULL); hex_encode(md, sizeof(md), &A2); @@ -804,7 +804,7 @@ _kdc_do_digest(krb5_context context, const char *username; struct ntlm_buf answer; Key *key = NULL; - EVP_MD_CTX *ctx; + EVP_MD_CTX *ctp; if ((config->digests_allowed & MS_CHAP_V2) == 0) { kdc_log(context, config, 0, "MS-CHAP-V2 not allowed"); @@ -816,7 +816,7 @@ _kdc_do_digest(krb5_context context, krb5_set_error_message(context, ret, "MS-CHAP-V2 clientNonce missing"); goto failed; - } + } if (serverNonce.length != 16) { ret = EINVAL; krb5_set_error_message(context, ret, @@ -831,21 +831,21 @@ _kdc_do_digest(krb5_context context, else username++; - ctx = EVP_MD_CTX_create(); + ctp = EVP_MD_CTX_create(); /* ChallangeHash */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); + EVP_DigestInit_ex(ctp, EVP_sha1(), NULL); { ssize_t ssize; krb5_data clientNonce; - + clientNonce.length = strlen(*ireq.u.digestRequest.clientNonce); clientNonce.data = malloc(clientNonce.length); if (clientNonce.data == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, "malloc: out of memory"); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctp); goto out; } @@ -855,24 +855,24 @@ _kdc_do_digest(krb5_context context, ret = ENOMEM; krb5_set_error_message(context, ret, "Failed to decode clientNonce"); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctp); goto out; } - EVP_DigestUpdate(ctx, clientNonce.data, ssize); + EVP_DigestUpdate(ctp, clientNonce.data, ssize); free(clientNonce.data); } - EVP_DigestUpdate(ctx, serverNonce.data, serverNonce.length); - EVP_DigestUpdate(ctx, username, strlen(username)); + EVP_DigestUpdate(ctp, serverNonce.data, serverNonce.length); + EVP_DigestUpdate(ctp, username, strlen(username)); - EVP_DigestFinal_ex(ctx, challange, NULL); + EVP_DigestFinal_ex(ctp, challange, NULL); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctp); /* NtPasswordHash */ ret = krb5_parse_name(context, username, &clientprincipal); if (ret) goto failed; - + ret = _kdc_db_fetch(context, config, clientprincipal, HDB_F_GET_CLIENT, NULL, NULL, &user); krb5_free_principal(context, clientprincipal); @@ -900,7 +900,7 @@ _kdc_do_digest(krb5_context context, krb5_set_error_message(context, ret, "NTLM missing arcfour key"); goto failed; } - + hex_encode(answer.data, answer.length, &mdx); if (mdx == NULL) { free(answer.data); @@ -923,39 +923,39 @@ _kdc_do_digest(krb5_context context, if (r.u.response.success) { unsigned char hashhash[MD4_DIGEST_LENGTH]; - EVP_MD_CTX *ctx; + EVP_MD_CTX *ctxp; - ctx = EVP_MD_CTX_create(); + ctxp = EVP_MD_CTX_create(); /* hashhash */ { - EVP_DigestInit_ex(ctx, EVP_md4(), NULL); - EVP_DigestUpdate(ctx, + EVP_DigestInit_ex(ctxp, EVP_md4(), NULL); + EVP_DigestUpdate(ctxp, key->key.keyvalue.data, key->key.keyvalue.length); - EVP_DigestFinal_ex(ctx, hashhash, NULL); + EVP_DigestFinal_ex(ctxp, hashhash, NULL); } /* GenerateAuthenticatorResponse */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, hashhash, sizeof(hashhash)); - EVP_DigestUpdate(ctx, answer.data, answer.length); - EVP_DigestUpdate(ctx, ms_chap_v2_magic1, + EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); + EVP_DigestUpdate(ctxp, hashhash, sizeof(hashhash)); + EVP_DigestUpdate(ctxp, answer.data, answer.length); + EVP_DigestUpdate(ctxp, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1)); - EVP_DigestFinal_ex(ctx, md, NULL); + EVP_DigestFinal_ex(ctxp, md, NULL); - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, md, sizeof(md)); - EVP_DigestUpdate(ctx, challange, 8); - EVP_DigestUpdate(ctx, ms_chap_v2_magic2, + EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); + EVP_DigestUpdate(ctxp, md, sizeof(md)); + EVP_DigestUpdate(ctxp, challange, 8); + EVP_DigestUpdate(ctxp, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2)); - EVP_DigestFinal_ex(ctx, md, NULL); + EVP_DigestFinal_ex(ctxp, md, NULL); r.u.response.rsp = calloc(1, sizeof(*r.u.response.rsp)); if (r.u.response.rsp == NULL) { free(answer.data); krb5_clear_error_message(context); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctxp); ret = ENOMEM; goto out; } @@ -964,22 +964,22 @@ _kdc_do_digest(krb5_context context, if (r.u.response.rsp == NULL) { free(answer.data); krb5_clear_error_message(context); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctxp); ret = ENOMEM; goto out; } /* get_master, rfc 3079 3.4 */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, hashhash, 16); - EVP_DigestUpdate(ctx, answer.data, answer.length); - EVP_DigestUpdate(ctx, ms_rfc3079_magic1, + EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); + EVP_DigestUpdate(ctxp, hashhash, 16); + EVP_DigestUpdate(ctxp, answer.data, answer.length); + EVP_DigestUpdate(ctxp, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1)); - EVP_DigestFinal_ex(ctx, md, NULL); + EVP_DigestFinal_ex(ctxp, md, NULL); free(answer.data); - EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctxp); r.u.response.session_key = calloc(1, sizeof(*r.u.response.session_key)); @@ -1101,7 +1101,7 @@ _kdc_do_digest(krb5_context context, 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; @@ -1143,7 +1143,7 @@ _kdc_do_digest(krb5_context context, uint32_t flags; Key *key = NULL; int version; - + r.element = choice_DigestRepInner_ntlmResponse; r.u.ntlmResponse.success = 0; r.u.ntlmResponse.flags = 0; @@ -1187,7 +1187,7 @@ _kdc_do_digest(krb5_context context, krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } - + ret = krb5_storage_read(sp, challange, sizeof(challange)); if (ret != sizeof(challange)) { ret = ENOMEM; @@ -1266,7 +1266,7 @@ _kdc_do_digest(krb5_context context, if (flags & NTLM_NEG_NTLM2_SESSION) { unsigned char sessionhash[MD5_DIGEST_LENGTH]; EVP_MD_CTX *ctx; - + if ((config->digests_allowed & NTLM_V1_SESSION) == 0) { kdc_log(context, config, 0, "NTLM v1-session not allowed"); ret = EINVAL; @@ -1279,7 +1279,7 @@ _kdc_do_digest(krb5_context context, "for NTLM session key"); goto failed; } - + ctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(ctx, EVP_md5(), NULL); @@ -1297,7 +1297,7 @@ _kdc_do_digest(krb5_context context, goto failed; } } - + ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data, key->key.keyvalue.length, challange, &answer); @@ -1305,7 +1305,7 @@ _kdc_do_digest(krb5_context context, 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) { @@ -1335,7 +1335,7 @@ _kdc_do_digest(krb5_context context, unsigned char masterkey[MD4_DIGEST_LENGTH]; EVP_CIPHER_CTX rc4; size_t len; - + if ((flags & NTLM_NEG_KEYEX) == 0) { ret = EINVAL; krb5_set_error_message(context, ret, @@ -1343,7 +1343,7 @@ _kdc_do_digest(krb5_context context, "exchange but still sent key"); goto failed; } - + len = ireq.u.ntlmRequest.sessionkey->length; if (len != sizeof(masterkey)){ ret = EINVAL; @@ -1352,7 +1352,7 @@ _kdc_do_digest(krb5_context context, (unsigned long)len); goto failed; } - + EVP_CIPHER_CTX_init(&rc4); EVP_CipherInit_ex(&rc4, EVP_rc4(), NULL, sessionkey, NULL, 1); @@ -1360,7 +1360,7 @@ _kdc_do_digest(krb5_context context, masterkey, ireq.u.ntlmRequest.sessionkey->data, sizeof(masterkey)); EVP_CIPHER_CTX_cleanup(&rc4); - + r.u.ntlmResponse.sessionkey = malloc(sizeof(*r.u.ntlmResponse.sessionkey)); if (r.u.ntlmResponse.sessionkey == NULL) { @@ -1368,7 +1368,7 @@ _kdc_do_digest(krb5_context context, 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) { @@ -1415,7 +1415,7 @@ _kdc_do_digest(krb5_context context, krb5_clear_error_message(context); goto out; } - + kdc_log(context, config, 0, "Digest failed with: %s", s); r.element = choice_DigestRepInner_error; diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h index 139b5e7087..9d52fd4c2e 100644 --- a/source4/heimdal/kdc/kdc.h +++ b/source4/heimdal/kdc/kdc.h @@ -58,21 +58,17 @@ typedef struct krb5_kdc_configuration { int num_db; krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */ - + + krb5_boolean as_use_strongest_session_key; + krb5_boolean preauth_use_strongest_session_key; + krb5_boolean tgs_use_strongest_session_key; + krb5_boolean use_strongest_server_key; + krb5_boolean check_ticket_addresses; krb5_boolean allow_null_ticket_addresses; krb5_boolean allow_anonymous; enum krb5_kdc_trpolicy trpolicy; - char *v4_realm; - krb5_boolean enable_v4; - krb5_boolean enable_v4_cross_realm; - krb5_boolean enable_v4_per_principal; - - krb5_boolean enable_kaserver; - - krb5_boolean enable_524; - krb5_boolean enable_pkinit; krb5_boolean pkinit_princ_in_cert; const char *pkinit_kdc_identity; diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index a437b9dbd9..4bc1619170 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -74,9 +74,9 @@ _kdc_find_padata(const KDC_REQ *req, int *start, int type) if (req->padata == NULL) return NULL; - while(*start < req->padata->len){ + while((size_t)*start < req->padata->len){ (*start)++; - if(req->padata->val[*start - 1].padata_type == type) + if(req->padata->val[*start - 1].padata_type == (unsigned)type) return &req->padata->val[*start - 1]; } return NULL; @@ -123,36 +123,103 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key) */ krb5_error_code -_kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, +_kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key, + krb5_boolean is_preauth, hdb_entry_ex *princ, krb5_enctype *etypes, unsigned len, - Key **ret_key) + krb5_enctype *ret_enctype, Key **ret_key) { - int i; - krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; + krb5_error_code ret; krb5_salt def_salt; + krb5_enctype enctype = ETYPE_NULL; + Key *key; + int i; - krb5_get_pw_salt (context, princ->entry.principal, &def_salt); + /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */ + ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt); + if (ret) + return ret; - for(i = 0; ret != 0 && i < len ; i++) { - Key *key = NULL; + ret = KRB5KDC_ERR_ETYPE_NOSUPP; - if (krb5_enctype_valid(context, etypes[i]) != 0 && - !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) - continue; + if (use_strongest_session_key) { + const krb5_enctype *p; + krb5_enctype clientbest = ETYPE_NULL; + int j; - while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { - if (key->key.keyvalue.length == 0) { - ret = KRB5KDC_ERR_NULL_KEY; + /* + * Pick the strongest key that the KDC, target service, and + * client all support, using the local cryptosystem enctype + * list in strongest-to-weakest order to drive the search. + * + * This is not what RFC4120 says to do, but it encourages + * adoption of stronger enctypes. This doesn't play well with + * clients that have multiple Kerberos client implementations + * available with different supported enctype lists. + */ + + /* drive the search with local supported enctypes list */ + p = krb5_kerberos_enctypes(context); + for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) continue; + + /* check that the client supports it too */ + for (j = 0; j < len && enctype == ETYPE_NULL; j++) { + if (p[i] != etypes[j]) + continue; + /* save best of union of { client, crypto system } */ + if (clientbest == ETYPE_NULL) + clientbest = p[i]; + /* check target princ support */ + ret = hdb_enctype2key(context, &princ->entry, p[i], &key); + if (ret) + continue; + if (is_preauth && !is_default_salt_p(&def_salt, key)) + continue; + enctype = p[i]; } - *ret_key = key; - ret = 0; - if (is_default_salt_p(&def_salt, key)) { - krb5_free_salt (context, def_salt); - return ret; + } + if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL) + enctype = clientbest; + else if (enctype == ETYPE_NULL) + ret = KRB5KDC_ERR_ETYPE_NOSUPP; + if (ret == 0 && ret_enctype != NULL) + *ret_enctype = enctype; + if (ret == 0 && ret_key != NULL) + *ret_key = key; + } else { + /* + * Pick the first key from the client's enctype list that is + * supported by the cryptosystem and by the given principal. + * + * RFC4120 says we SHOULD pick the first _strong_ key from the + * client's list... not the first key... If the admin disallows + * weak enctypes in krb5.conf and selects this key selection + * algorithm, then we get exactly what RFC4120 says. + */ + for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) { + + if (krb5_enctype_valid(context, etypes[i]) != 0 && + !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) + continue; + + while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { + if (key->key.keyvalue.length == 0) { + ret = KRB5KDC_ERR_NULL_KEY; + continue; + } + if (ret_key != NULL) + *ret_key = key; + if (ret_enctype != NULL) + *ret_enctype = etypes[i]; + ret = 0; + if (is_preauth && is_default_salt_p(&def_salt, key)) + goto out; } } } + +out: krb5_free_salt (context, def_salt); return ret; } @@ -211,8 +278,8 @@ log_patypes(krb5_context context, { struct rk_strpool *p = NULL; char *str; - int i; - + size_t i; + for (i = 0; i < padata->len; i++) { switch(padata->val[i].padata_type) { case KRB5_PADATA_PK_AS_REQ: @@ -240,7 +307,7 @@ log_patypes(krb5_context context, } if (p == NULL) p = rk_strpoolprintf(p, "none"); - + str = rk_strpoolcollect(p); kdc_log(context, config, 0, "Client sent patypes: %s", str); free(str); @@ -264,7 +331,7 @@ _kdc_encode_reply(krb5_context context, { unsigned char *buf; size_t buf_size; - size_t len; + size_t len = 0; krb5_error_code ret; krb5_crypto crypto; @@ -614,7 +681,7 @@ log_as_req(krb5_context context, krb5_error_code ret; struct rk_strpool *p; char *str; - int i; + size_t i; p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: "); @@ -694,13 +761,13 @@ kdc_check_flags(krb5_context context, "Client (%s) has invalid bit set", client_name); return KRB5KDC_ERR_POLICY; } - + if(!client->flags.client){ kdc_log(context, config, 0, "Principal may not act as client -- %s", client_name); return KRB5KDC_ERR_POLICY; } - + if (client->valid_start && *client->valid_start > kdc_time) { char starttime_str[100]; krb5_format_time(context, *client->valid_start, @@ -710,7 +777,7 @@ kdc_check_flags(krb5_context context, starttime_str, client_name); return KRB5KDC_ERR_CLIENT_NOTYET; } - + if (client->valid_end && *client->valid_end < kdc_time) { char endtime_str[100]; krb5_format_time(context, *client->valid_end, @@ -720,7 +787,7 @@ kdc_check_flags(krb5_context context, endtime_str, client_name); return KRB5KDC_ERR_NAME_EXP; } - + if (client->pw_end && *client->pw_end < kdc_time && (server_ex == NULL || !server_ex->entry.flags.change_pw)) { char pwend_str[100]; @@ -809,7 +876,7 @@ _kdc_check_addresses(krb5_context context, krb5_address addr; krb5_boolean result; krb5_boolean only_netbios = TRUE; - int i; + size_t i; if(config->check_ticket_addresses == 0) return TRUE; @@ -976,7 +1043,7 @@ _kdc_as_rep(krb5_context context, goto out; } } else if (b->kdc_options.request_anonymous) { - kdc_log(context, config, 0, + kdc_log(context, config, 0, "Request for a anonymous ticket with non " "anonymous client name: %s", client_name); ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; @@ -1018,59 +1085,31 @@ _kdc_as_rep(krb5_context context, memset(&ek, 0, sizeof(ek)); /* - * Select a session enctype from the list of the crypto systems - * supported enctype, is supported by the client and is one of the - * enctype of the enctype of the krbtgt. + * Select a session enctype from the list of the crypto system + * supported enctypes that is supported by the client and is one of + * the enctype of the enctype of the service (likely krbtgt). * - * The later is used as a hint what enctype all KDC are supporting - * to make sure a newer version of KDC wont generate a session - * enctype that and older version of a KDC in the same realm can't + * The latter is used as a hint of what enctypes all KDC support, + * to make sure a newer version of KDC won't generate a session + * enctype that an older version of a KDC in the same realm can't * decrypt. - * - * But if the KDC admin is paranoid and doesn't want to have "no + */ + ret = _kdc_find_etype(context, config->as_use_strongest_session_key, FALSE, + client, b->etype.val, b->etype.len, &sessionetype, + NULL); + if (ret) { + kdc_log(context, config, 0, + "Client (%s) from %s has no common enctypes with KDC " + "to use for the session key", + client_name, from); + goto out; + } + /* + * But if the KDC admin is paranoid and doesn't want to have "not * the best" enctypes on the krbtgt, lets save the best pick from * the client list and hope that that will work for any other * KDCs. */ - { - const krb5_enctype *p; - krb5_enctype clientbest = ETYPE_NULL; - int i, j; - - p = krb5_kerberos_enctypes(context); - - sessionetype = ETYPE_NULL; - - for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) { - if (krb5_enctype_valid(context, p[i]) != 0) - continue; - - for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) { - Key *dummy; - /* check with client */ - if (p[i] != b->etype.val[j]) - continue; - /* save best of union of { client, crypto system } */ - if (clientbest == ETYPE_NULL) - clientbest = p[i]; - /* check with krbtgt */ - ret = hdb_enctype2key(context, &server->entry, p[i], &dummy); - if (ret) - continue; - sessionetype = p[i]; - } - } - /* if krbtgt had no shared keys with client, pick clients best */ - if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) { - sessionetype = clientbest; - } else if (sessionetype == ETYPE_NULL) { - kdc_log(context, config, 0, - "Client (%s) from %s has no common enctypes with KDC" - "to use for the session key", - client_name, from); - goto out; - } - } /* * Pre-auth processing @@ -1111,7 +1150,7 @@ _kdc_as_rep(krb5_context context, ret = _kdc_pk_check_client(context, config, - clientdb, + clientdb, client, pkp, &client_cert); @@ -1119,7 +1158,7 @@ _kdc_as_rep(krb5_context context, e_text = "PKINIT certificate not allowed to " "impersonate principal"; _kdc_pk_free_client_param(context, pkp); - + kdc_log(context, config, 0, "%s", e_text); pkp = NULL; goto out; @@ -1148,9 +1187,9 @@ _kdc_as_rep(krb5_context context, EncryptedData enc_data; Key *pa_key; char *str; - + found_pa = 1; - + if (b->kdc_options.request_anonymous) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; kdc_log(context, config, 0, "ENC-TS doesn't support anon"); @@ -1167,7 +1206,7 @@ _kdc_as_rep(krb5_context context, client_name); goto out; } - + ret = hdb_enctype2key(context, &client->entry, enc_data.etype, &pa_key); if(ret){ @@ -1256,7 +1295,7 @@ _kdc_as_rep(krb5_context context, free_PA_ENC_TS_ENC(&p); if (abs(kdc_time - p.patimestamp) > context->max_skew) { char client_time[100]; - + krb5_format_time(context, p.patimestamp, client_time, sizeof(client_time), TRUE); @@ -1353,8 +1392,9 @@ _kdc_as_rep(krb5_context context, /* * If there is a client key, send ETYPE_INFO{,2} */ - ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, - &ckey); + ret = _kdc_find_etype(context, + config->preauth_use_strongest_session_key, TRUE, + client, b->etype.val, b->etype.len, NULL, &ckey); if (ret == 0) { /* @@ -1384,7 +1424,7 @@ _kdc_as_rep(krb5_context context, goto out; } } - + ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret); free_METHOD_DATA(&method_data); @@ -1401,7 +1441,7 @@ _kdc_as_rep(krb5_context context, } if (clientdb->hdb_auth_status) - (clientdb->hdb_auth_status)(context, clientdb, client, + (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_SUCCESS); /* @@ -1503,7 +1543,7 @@ _kdc_as_rep(krb5_context context, { time_t start; time_t t; - + start = et.authtime = kdc_time; if(f.postdated && req->req_body.from){ @@ -1663,8 +1703,8 @@ _kdc_as_rep(krb5_context context, PA_ClientCanonicalized canon; krb5_data data; PA_DATA pa; - krb5_crypto crypto; - size_t len; + krb5_crypto cryptox; + size_t len = 0; memset(&canon, 0, sizeof(canon)); @@ -1679,21 +1719,21 @@ _kdc_as_rep(krb5_context context, krb5_abortx(context, "internal asn.1 error"); /* sign using "returned session key" */ - ret = krb5_crypto_init(context, &et.key, 0, &crypto); + ret = krb5_crypto_init(context, &et.key, 0, &cryptox); if (ret) { free(data.data); goto out; } - ret = krb5_create_checksum(context, crypto, + ret = krb5_create_checksum(context, cryptox, KRB5_KU_CANONICALIZED_NAMES, 0, data.data, data.length, &canon.canon_checksum); free(data.data); - krb5_crypto_destroy(context, crypto); + krb5_crypto_destroy(context, cryptox); if (ret) goto out; - + ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length, &canon, &len, ret); free_Checksum(&canon.canon_checksum); @@ -1826,7 +1866,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, const krb5_data *data) { krb5_error_code ret; - size_t size; + size_t size = 0; if (tkt->authorization_data == NULL) { tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); @@ -1835,7 +1875,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, return ENOMEM; } } - + /* add the entry to the last element */ { AuthorizationData ad = { 0, NULL }; @@ -1863,7 +1903,7 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context, } if (ade.ad_data.length != size) krb5_abortx(context, "internal asn.1 encoder error"); - + ret = add_AuthorizationData(tkt->authorization_data, &ade); der_free_octet_string(&ade.ad_data); if (ret) { diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 55d5d09ede..92cce5759f 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -64,7 +64,7 @@ find_KRB5SignedPath(krb5_context context, AuthorizationData child; krb5_error_code ret; int pos; - + if (ad == NULL || ad->len == 0) return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; @@ -113,7 +113,7 @@ _kdc_add_KRB5SignedPath(krb5_context context, KRB5SignedPath sp; krb5_data data; krb5_crypto crypto = NULL; - size_t size; + size_t size = 0; if (server && principals) { ret = add_Principals(principals, server); @@ -123,12 +123,12 @@ _kdc_add_KRB5SignedPath(krb5_context context, { KRB5SignedPathData spd; - + spd.client = client; spd.authtime = tkt->authtime; spd.delegated = principals; spd.method_data = NULL; - + ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, &spd, &size, ret); if (ret) @@ -203,7 +203,7 @@ check_KRB5SignedPath(krb5_context context, if (ret == 0) { KRB5SignedPathData spd; KRB5SignedPath sp; - size_t size; + size_t size = 0; ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL); krb5_data_free(&data); @@ -357,7 +357,7 @@ check_PAC(krb5_context context, server_sign_key, krbtgt_sign_key, rspac); } krb5_pac_free(context, pac); - + return ret; } } @@ -376,7 +376,7 @@ check_tgs_flags(krb5_context context, KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et) { KDCOptions f = b->kdc_options; - + if(f.validate){ if(!tgt->flags.invalid || tgt->starttime == NULL){ kdc_log(context, config, 0, @@ -415,7 +415,7 @@ check_tgs_flags(krb5_context context, } if(tgt->flags.forwarded) et->flags.forwarded = 1; - + if(f.proxiable){ if(!tgt->flags.proxiable){ kdc_log(context, config, 0, @@ -485,7 +485,7 @@ 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 */ @@ -512,7 +512,7 @@ check_constrained_delegation(krb5_context context, { const HDB_Ext_Constrained_delegation_acl *acl; krb5_error_code ret; - int i; + size_t i; /* * constrained_delegation (S4U2Proxy) only works within @@ -541,7 +541,7 @@ check_constrained_delegation(krb5_context context, krb5_clear_error_message(context); return ret; } - + if (acl) { for (i = 0; i < acl->len; i++) { if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE) @@ -623,7 +623,7 @@ fix_transited_encoding(krb5_context context, krb5_error_code ret = 0; char **realms, **tmp; unsigned int num_realms; - int i; + size_t i; switch (tr->tr_type) { case DOMAIN_X500_COMPRESS: @@ -843,7 +843,7 @@ 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); @@ -877,7 +877,7 @@ tgs_make_reply(krb5_context context, if (ret) goto out; } - + if (auth_data) { unsigned int i = 0; @@ -919,7 +919,7 @@ tgs_make_reply(krb5_context context, goto out; et.crealm = tgt_name->realm; et.cname = tgt_name->name; - + ek.key = et.key; /* MIT must have at least one last_req */ ek.last_req.len = 1; @@ -1021,7 +1021,7 @@ tgs_check_authenticator(krb5_context context, krb5_keyblock *key) { krb5_authenticator auth; - size_t len; + size_t len = 0; unsigned char *buf; size_t buf_size; krb5_error_code ret; @@ -1048,7 +1048,7 @@ tgs_check_authenticator(krb5_context context, ret = KRB5KRB_AP_ERR_INAPP_CKSUM; goto out; } - + /* XXX should not re-encode this */ ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); if(ret){ @@ -1107,7 +1107,7 @@ find_rpath(krb5_context context, Realm crealm, Realm srealm) NULL); return new_realm; } - + static krb5_boolean need_referral(krb5_context context, krb5_kdc_configuration *config, @@ -1148,6 +1148,7 @@ tgs_parse_request(krb5_context context, krb5_keyblock **replykey, int *rk_is_subkey) { + static char failed[] = ""; krb5_ap_req ap_req; krb5_error_code ret; krb5_principal princ; @@ -1191,7 +1192,7 @@ tgs_parse_request(krb5_context context, char *p; ret = krb5_unparse_name(context, princ, &p); if (ret != 0) - p = ""; + p = failed; krb5_free_principal(context, princ); kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p); if (ret == 0) @@ -1203,7 +1204,7 @@ tgs_parse_request(krb5_context context, char *p; ret = krb5_unparse_name(context, princ, &p); if (ret != 0) - p = ""; + p = failed; krb5_free_principal(context, princ); kdc_log(context, config, 0, "Ticket-granting ticket not found in database: %s", msg); @@ -1215,13 +1216,13 @@ tgs_parse_request(krb5_context context, } if(ap_req.ticket.enc_part.kvno && - *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){ + (unsigned int)*ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){ char *p; ret = krb5_unparse_name (context, princ, &p); krb5_free_principal(context, princ); if (ret != 0) - p = ""; + p = failed; kdc_log(context, config, 0, "Ticket kvno = %d, DB kvno = %d (%s)", *ap_req.ticket.enc_part.kvno, @@ -1266,7 +1267,7 @@ tgs_parse_request(krb5_context context, &ap_req_options, ticket, KRB5_KU_TGS_REQ_AUTH); - + krb5_free_principal(context, princ); if(ret) { const char *msg = krb5_get_error_message(context, ret); @@ -1396,12 +1397,12 @@ build_server_referral(krb5_context context, 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; + size_t size = 0; memset(&ref, 0, sizeof(ref)); @@ -1521,7 +1522,7 @@ tgs_build_reply(krb5_context context, hdb_entry_ex *uu; krb5_principal p; Key *uukey; - + if(b->additional_tickets == NULL || b->additional_tickets->len == 0){ ret = KRB5KDC_ERR_BADOPTION; /* ? */ @@ -1567,7 +1568,7 @@ tgs_build_reply(krb5_context context, } _krb5_principalname2krb5_principal(context, &sp, *s, r); - ret = krb5_unparse_name(context, sp, &spn); + ret = krb5_unparse_name(context, sp, &spn); if (ret) goto out; _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); @@ -1612,7 +1613,7 @@ server_lookup: free(spn); krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, new_rlm, NULL); - ret = krb5_unparse_name(context, sp, &spn); + ret = krb5_unparse_name(context, sp, &spn); if (ret) goto out; @@ -1662,7 +1663,7 @@ server_lookup: krb5_enctype etype; if(b->kdc_options.enc_tkt_in_skey) { - int i; + size_t i; ekey = &adtkt.key; for(i = 0; i < b->etype.len; i++) if (b->etype.val[i] == adtkt.key.keytype) @@ -1678,9 +1679,11 @@ server_lookup: kvno = 0; } else { Key *skey; - - ret = _kdc_find_etype(context, server, - b->etype.val, b->etype.len, &skey); + + ret = _kdc_find_etype(context, + config->tgs_use_strongest_session_key, FALSE, + server, b->etype.val, b->etype.len, NULL, + &skey); if(ret) { kdc_log(context, config, 0, "Server (%s) has no support for etypes", spn); @@ -1690,7 +1693,7 @@ server_lookup: etype = skey->key.keytype; kvno = server->entry.kvno; } - + ret = krb5_generate_random_keyblock(context, etype, &sessionkey); if (ret) goto out; @@ -1717,11 +1720,11 @@ server_lookup: /* Now refetch the primary krbtgt, and get the current kvno (the * sign check may have been on an old kvno, and the server may * have been an incoming trust) */ - ret = krb5_make_principal(context, &krbtgt_principal, + ret = krb5_make_principal(context, &krbtgt_principal, krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1), - KRB5_TGS_NAME, + KRB5_TGS_NAME, krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1), NULL); @@ -2052,7 +2055,7 @@ server_lookup: goto out; } - ret = check_constrained_delegation(context, config, clientdb, + ret = check_constrained_delegation(context, config, clientdb, client, server, sp); if (ret) { kdc_log(context, config, 0, @@ -2067,17 +2070,18 @@ server_lookup: } krb5_data_free(&rspac); + /* - * generate the PAC for the user and pass - * dp for the S4U_DELEGATION_INFO blob in the PAC. + * generate the PAC for the user. + * + * TODO: pass in t->sname and t->realm and build + * a S4U_DELEGATION_INFO blob to the PAC. */ ret = check_PAC(context, config, tp, dp, client, server, krbtgt, &clientkey->key, &tkey_check->key, ekey, &tkey_sign->key, &adtkt, &rspac, &ad_signedpath); - if (ret == 0 && !ad_signedpath) - ret = KRB5KDC_ERR_BADOPTION; if (ret) { const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, @@ -2094,12 +2098,10 @@ server_lookup: ret = check_KRB5SignedPath(context, config, krbtgt, - tp, + cp, &adtkt, NULL, &ad_signedpath); - if (ret == 0 && !ad_signedpath) - ret = KRB5KDC_ERR_BADOPTION; if (ret) { const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, @@ -2111,6 +2113,16 @@ server_lookup: goto out; } + if (!ad_signedpath) { + ret = KRB5KDC_ERR_BADOPTION; + kdc_log(context, config, 0, + "Ticket not signed with PAC nor SignedPath service %s failed " + "for delegation to %s for client %s (%s)" + "from %s", + spn, tpn, dpn, cpn, from); + goto out; + } + kdc_log(context, config, 0, "constrained delegation for %s " "from %s (%s) to %s", tpn, cpn, dpn, spn); } @@ -2141,7 +2153,7 @@ server_lookup: kdc_log(context, config, 0, "Request from wrong address"); goto out; } - + /* * If this is an referral, add server referral data to the * auth_data reply . @@ -2203,7 +2215,7 @@ server_lookup: &enc_pa_data, e_text, reply); - + out: if (tpn != cpn) free(tpn); @@ -2279,7 +2291,7 @@ _kdc_tgs_rep(krb5_context context, if(tgs_req == NULL){ ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - + kdc_log(context, config, 0, "TGS-REQ from %s without PA-TGS-REQ", from); goto out; diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c index f6f8f8a3bd..8d683d50a3 100644 --- a/source4/heimdal/kdc/kx509.c +++ b/source4/heimdal/kdc/kx509.c @@ -259,7 +259,7 @@ build_certificate(krb5_context context, hx509_cert_free(cert); if (ret) goto out; - + return 0; out: if (env) @@ -355,7 +355,7 @@ _kdc_do_kx509(krb5_context context, krb5_xfree(expected); goto out; } - + ret = KRB5KDC_ERR_SERVER_NOMATCH; krb5_set_error_message(context, ret, "User %s used wrong Kx509 service " diff --git a/source4/heimdal/kdc/log.c b/source4/heimdal/kdc/log.c index 6657aca5cb..6d85729f51 100644 --- a/source4/heimdal/kdc/log.c +++ b/source4/heimdal/kdc/log.c @@ -50,10 +50,12 @@ kdc_openlog(krb5_context context, krb5_addlog_dest(context, config->logf, *p); krb5_config_free_strings(s); }else { - char *s; - asprintf(&s, "0-1/FILE:%s/%s", hdb_db_dir(context), KDC_LOG_FILE); - krb5_addlog_dest(context, config->logf, s); - free(s); + char *ss; + if (asprintf(&ss, "0-1/FILE:%s/%s", hdb_db_dir(context), + KDC_LOG_FILE) < 0) + err(1, NULL); + krb5_addlog_dest(context, config->logf, ss); + free(ss); } krb5_set_warn_dest(context, config->logf); } diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index 297fa3824b..f9b34571a3 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -62,7 +62,7 @@ _kdc_db_fetch(krb5_context context, for(i = 0; i < config->num_db; i++) { krb5_principal enterprise_principal = NULL; - if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) + if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) && principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { if (principal->name.name_string.len != 1) { ret = KRB5_PARSE_MALFORMED; @@ -134,24 +134,41 @@ _kdc_get_preferred_key(krb5_context context, krb5_enctype *enctype, Key **key) { - const krb5_enctype *p; krb5_error_code ret; int i; - p = krb5_kerberos_enctypes(context); - - for (i = 0; p[i] != ETYPE_NULL; i++) { - if (krb5_enctype_valid(context, p[i]) != 0) - continue; - ret = hdb_enctype2key(context, &h->entry, p[i], key); - if (ret == 0) { - *enctype = p[i]; + if (config->use_strongest_server_key) { + const krb5_enctype *p = krb5_kerberos_enctypes(context); + + for (i = 0; p[i] != ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + ret = hdb_enctype2key(context, &h->entry, p[i], key); + if (ret != 0) + continue; + if (enctype != NULL) + *enctype = p[i]; + return 0; + } + } else { + *key = NULL; + + for (i = 0; i < h->entry.keys.len; i++) { + if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype) + != 0) + continue; + ret = hdb_enctype2key(context, &h->entry, + h->entry.keys.val[i].key.keytype, key); + if (ret != 0) + continue; + if (enctype != NULL) + *enctype = (*key)->key.keytype; return 0; } } krb5_set_error_message(context, EINVAL, "No valid kerberos key found for %s", name); - return EINVAL; + return EINVAL; /* XXX */ } diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c index 9c0be23b14..a02cb816ab 100644 --- a/source4/heimdal/kdc/pkinit.c +++ b/source4/heimdal/kdc/pkinit.c @@ -116,7 +116,7 @@ pk_check_pkauthenticator(krb5_context context, u_char *buf = NULL; size_t buf_size; krb5_error_code ret; - size_t len; + size_t len = 0; krb5_timestamp now; Checksum checksum; @@ -148,7 +148,7 @@ pk_check_pkauthenticator(krb5_context context, krb5_clear_error_message(context); return ret; } - + if (a->paChecksum == NULL) { krb5_clear_error_message(context); ret = KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; @@ -222,7 +222,7 @@ generate_dh_keyblock(krb5_context context, if (!DH_generate_key(client_params->u.dh.key)) { ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, + krb5_set_error_message(context, ret, "Can't generate Diffie-Hellman keys"); goto out; } @@ -237,7 +237,7 @@ generate_dh_keyblock(krb5_context context, } dh_gen_keylen = DH_compute_key(dh_gen_key,client_params->u.dh.public_key, client_params->u.dh.key); - if (dh_gen_keylen == -1) { + if (dh_gen_keylen == (size_t)-1) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, "Can't compute Diffie-Hellman key"); @@ -281,14 +281,14 @@ generate_dh_keyblock(krb5_context context, goto out; } - dh_gen_keylen = ECDH_compute_key(dh_gen_key, size, + dh_gen_keylen = ECDH_compute_key(dh_gen_key, size, EC_KEY_get0_public_key(client_params->u.ecdh.public_key), client_params->u.ecdh.key, NULL); #endif /* HAVE_OPENSSL */ } else { ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, + krb5_set_error_message(context, ret, "Diffie-Hellman not selected keys"); goto out; } @@ -525,7 +525,7 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - ret = hx509_certs_merge(context->hx509ctx, trust_anchors, + ret = hx509_certs_merge(context->hx509ctx, trust_anchors, kdc_identity->anchors); if (ret) { hx509_certs_free(&trust_anchors); @@ -538,7 +538,7 @@ _kdc_pk_rd_padata(krb5_context context, if (ret == 0 && pc != NULL) { hx509_cert cert; unsigned int i; - + for (i = 0; i < pc->len; i++) { ret = hx509_cert_init_data(context->hx509ctx, pc->val[i].cert.data, @@ -572,7 +572,7 @@ _kdc_pk_rd_padata(krb5_context context, if (req->req_body.kdc_options.request_anonymous) { ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; - krb5_set_error_message(context, ret, + krb5_set_error_message(context, ret, "Anon not supported in RSA mode"); goto out; } @@ -586,7 +586,7 @@ _kdc_pk_rd_padata(krb5_context context, "PK-AS-REQ-Win2k: %d", ret); goto out; } - + ret = hx509_cms_unwrap_ContentInfo(&r.signed_auth_pack, &contentInfoOid, &signed_content, @@ -612,7 +612,7 @@ _kdc_pk_rd_padata(krb5_context context, "Can't decode PK-AS-REQ: %d", ret); goto out; } - + /* XXX look at r.kdcPkId */ if (r.trustedCertifiers) { ExternalPrincipalIdentifiers *edi = r.trustedCertifiers; @@ -624,12 +624,12 @@ _kdc_pk_rd_padata(krb5_context context, &cp->client_anchors); if (ret) { krb5_set_error_message(context, ret, - "Can't allocate client anchors: %d", + "Can't allocate client anchors: %d", ret); goto out; } - /* + /* * If the client sent more then 10 EDI, don't bother * looking more then 10 of performance reasons. */ @@ -651,7 +651,7 @@ _kdc_pk_rd_padata(krb5_context context, "Failed to allocate hx509_query"); goto out; } - + ret = decode_IssuerAndSerialNumber(edi->val[i].issuerAndSerialNumber->data, edi->val[i].issuerAndSerialNumber->length, &iasn, @@ -704,7 +704,7 @@ _kdc_pk_rd_padata(krb5_context context, "PK-AS-REQ-Win2k invalid content type oid"); goto out; } - + if (!have_data) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(context, ret, @@ -805,7 +805,7 @@ _kdc_pk_rd_padata(krb5_context context, ap.clientPublicValue == NULL) { free_AuthPack(&ap); ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; - krb5_set_error_message(context, ret, + krb5_set_error_message(context, ret, "Anon not supported in RSA mode"); goto out; } @@ -849,7 +849,7 @@ _kdc_pk_rd_padata(krb5_context context, free_AuthPack(&ap); goto out; } - + if (ap.supportedCMSTypes) { ret = hx509_peer_info_set_cms_algs(context->hx509ctx, cp->peer, @@ -885,7 +885,7 @@ out: der_free_oid(&contentInfoOid); if (ret) { _kdc_pk_free_client_param(context, cp); - } else + } else *ret_params = cp; return ret; } @@ -921,7 +921,7 @@ pk_mk_pa_reply_enckey(krb5_context context, const heim_oid *envelopedAlg = NULL, *sdAlg = NULL, *evAlg = NULL; krb5_error_code ret; krb5_data buf, signed_data; - size_t size; + size_t size = 0; int do_win2k = 0; krb5_data_zero(&buf); @@ -954,7 +954,7 @@ pk_mk_pa_reply_enckey(krb5_context context, break; default: krb5_abortx(context, "internal pkinit error"); - } + } if (do_win2k) { ReplyKeyPack_Win2k kp; @@ -966,7 +966,7 @@ pk_mk_pa_reply_enckey(krb5_context context, goto out; } kp.nonce = cp->nonce; - + ASN1_MALLOC_ENCODE(ReplyKeyPack_Win2k, buf.data, buf.length, &kp, &size,ret); @@ -995,7 +995,7 @@ pk_mk_pa_reply_enckey(krb5_context context, krb5_clear_error_message(context); goto out; } - + ret = krb5_crypto_destroy(context, ascrypto); if (ret) { krb5_clear_error_message(context); @@ -1015,15 +1015,15 @@ pk_mk_pa_reply_enckey(krb5_context context, { hx509_query *q; hx509_cert cert; - + ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) goto out; - + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); if (config->pkinit_kdc_friendly_name) hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); - + ret = hx509_certs_find(context->hx509ctx, kdc_identity->certs, q, @@ -1031,7 +1031,7 @@ pk_mk_pa_reply_enckey(krb5_context context, hx509_query_free(context->hx509ctx, q); if (ret) goto out; - + ret = hx509_cms_create_signed_1(context->hx509ctx, 0, sdAlg, @@ -1078,7 +1078,7 @@ out: hx509_cert_free(*kdc_cert); *kdc_cert = NULL; } - + krb5_data_free(&buf); krb5_data_free(&signed_data); return ret; @@ -1101,7 +1101,7 @@ pk_mk_pa_reply_dh(krb5_context context, krb5_error_code ret; hx509_cert cert; hx509_query *q; - size_t size; + size_t size = 0; memset(&contentinfo, 0, sizeof(contentinfo)); memset(&dh_info, 0, sizeof(dh_info)); @@ -1117,7 +1117,7 @@ pk_mk_pa_reply_dh(krb5_context context, ret = BN_to_integer(context, kdc_dh->pub_key, &i); if (ret) return ret; - + ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret); der_free_heim_integer(&i); if (ret) { @@ -1127,7 +1127,7 @@ pk_mk_pa_reply_dh(krb5_context context, } if (buf.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); - + dh_info.subjectPublicKey.length = buf.length * 8; dh_info.subjectPublicKey.data = buf.data; krb5_data_zero(&buf); @@ -1154,7 +1154,7 @@ pk_mk_pa_reply_dh(krb5_context context, } else krb5_abortx(context, "no keyex selected ?"); - + dh_info.nonce = cp->nonce; ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size, @@ -1175,11 +1175,11 @@ pk_mk_pa_reply_dh(krb5_context context, ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) goto out; - + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); if (config->pkinit_kdc_friendly_name) hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); - + ret = hx509_certs_find(context->hx509ctx, kdc_identity->certs, q, @@ -1187,7 +1187,7 @@ pk_mk_pa_reply_dh(krb5_context context, hx509_query_free(context->hx509ctx, q); if (ret) goto out; - + ret = hx509_cms_create_signed_1(context->hx509ctx, 0, &asn1_oid_id_pkdhkeydata, @@ -1242,12 +1242,12 @@ _kdc_pk_mk_pa_reply(krb5_context context, METHOD_DATA *md) { krb5_error_code ret; - void *buf; - size_t len, size; + void *buf = NULL; + size_t len = 0, size = 0; krb5_enctype enctype; int pa_type; hx509_cert kdc_cert = NULL; - int i; + size_t i; if (!config->enable_pkinit) { krb5_clear_error_message(context); @@ -1263,7 +1263,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, 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; @@ -1314,7 +1314,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, if (rep.u.encKeyPack.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); - ret = krb5_generate_random_keyblock(context, sessionetype, + ret = krb5_generate_random_keyblock(context, sessionetype, sessionkey); if (ret) { free_PA_PK_AS_REP(&rep); @@ -1368,7 +1368,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, krb5_abortx(context, "Internal ASN.1 encoder error"); /* XXX KRB-FX-CF2 */ - ret = krb5_generate_random_keyblock(context, sessionetype, + ret = krb5_generate_random_keyblock(context, sessionetype, sessionkey); if (ret) { free_PA_PK_AS_REP(&rep); @@ -1463,7 +1463,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, if (len != size) krb5_abortx(context, "Internal ASN.1 encoder error"); - ret = krb5_generate_random_keyblock(context, sessionetype, + ret = krb5_generate_random_keyblock(context, sessionetype, sessionkey); if (ret) { free(buf); @@ -1507,7 +1507,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, "PK-INIT failed to stat ocsp data %d", ret); goto out_ocsp; } - + ret = krb5_data_alloc(&ocsp.data, sb.st_size); if (ret) { close(fd); @@ -1575,7 +1575,8 @@ match_rfc_san(krb5_context context, krb5_const_principal match) { hx509_octet_string_list list; - int ret, i, found = 0; + int ret, found = 0; + size_t i; memset(&list, 0 , sizeof(list)); @@ -1679,12 +1680,12 @@ match_ms_upn_san(krb5_context context, if (clientdb->hdb_check_pkinit_ms_upn_match) { ret = clientdb->hdb_check_pkinit_ms_upn_match(context, clientdb, client, principal); } else { - + /* * This is very wrong, but will do for a fallback */ strupr(principal->realm); - + if (krb5_principal_compare(context, principal, client->entry.principal) == FALSE) ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; } @@ -1709,7 +1710,7 @@ _kdc_pk_check_client(krb5_context context, const HDB_Ext_PKINIT_cert *pc; krb5_error_code ret; hx509_name name; - int i; + size_t i; if (cp->cert == NULL) { @@ -1737,12 +1738,12 @@ _kdc_pk_check_client(krb5_context context, ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); if (ret == 0 && pc) { hx509_cert cert; - unsigned int i; - - for (i = 0; i < pc->len; i++) { + size_t j; + + for (j = 0; j < pc->len; j++) { ret = hx509_cert_init_data(context->hx509ctx, - pc->val[i].cert.data, - pc->val[i].cert.length, + pc->val[j].cert.data, + pc->val[j].cert.length, &cert); if (ret) continue; @@ -1770,7 +1771,7 @@ _kdc_pk_check_client(krb5_context context, ret = match_ms_upn_san(context, config, context->hx509ctx, cp->cert, - clientdb, + clientdb, client); if (ret == 0) { kdc_log(context, config, 5, @@ -1871,7 +1872,7 @@ _kdc_add_inital_verified_cas(krb5_context context, AD_INITIAL_VERIFIED_CAS cas; krb5_error_code ret; krb5_data data; - size_t size; + size_t size = 0; memset(&cas, 0, sizeof(cas)); @@ -1937,7 +1938,7 @@ load_mappings(krb5_context context, const char *fn) fclose(f); } - + /* * */ @@ -1982,17 +1983,17 @@ krb5_kdc_pk_initialize(krb5_context context, { hx509_query *q; hx509_cert cert; - + ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) { krb5_warnx(context, "PKINIT: out of memory"); return ENOMEM; } - + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); if (config->pkinit_kdc_friendly_name) hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); - + ret = hx509_certs_find(context->hx509ctx, kdc_identity->certs, q, diff --git a/source4/heimdal/kdc/process.c b/source4/heimdal/kdc/process.c index 4226600331..6f36915800 100644 --- a/source4/heimdal/kdc/process.c +++ b/source4/heimdal/kdc/process.c @@ -47,7 +47,7 @@ krb5_kdc_update_time(struct timeval *tv) _kdc_now = *tv; } -static krb5_error_code +static krb5_error_code kdc_as_req(krb5_context context, krb5_kdc_configuration *config, krb5_data *req_buffer, @@ -74,7 +74,7 @@ kdc_as_req(krb5_context context, } -static krb5_error_code +static krb5_error_code kdc_tgs_req(krb5_context context, krb5_kdc_configuration *config, krb5_data *req_buffer, @@ -91,10 +91,10 @@ kdc_tgs_req(krb5_context context, ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len); if (ret) return ret; - + *claim = 1; - ret = _kdc_tgs_rep(context, config, &req, reply, + ret = _kdc_tgs_rep(context, config, &req, reply, from, addr, datagram_reply); free_TGS_REQ(&req); return ret; @@ -102,7 +102,7 @@ kdc_tgs_req(krb5_context context, #ifdef DIGEST -static krb5_error_code +static krb5_error_code kdc_digest(krb5_context context, krb5_kdc_configuration *config, krb5_data *req_buffer, @@ -132,7 +132,7 @@ kdc_digest(krb5_context context, #ifdef KX509 -static krb5_error_code +static krb5_error_code kdc_kx509(krb5_context context, krb5_kdc_configuration *config, krb5_data *req_buffer, @@ -193,7 +193,7 @@ krb5_kdc_process_request(krb5_context context, unsigned int i; krb5_data req_buffer; int claim = 0; - + req_buffer.data = buf; req_buffer.length = len; @@ -232,7 +232,7 @@ krb5_kdc_process_krb5_request(krb5_context context, unsigned int i; krb5_data req_buffer; int claim = 0; - + req_buffer.data = buf; req_buffer.length = len; @@ -245,7 +245,7 @@ krb5_kdc_process_krb5_request(krb5_context context, if (claim) return ret; } - + return -1; } diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index a58cebb8b2..ba87abb7cc 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -55,7 +55,7 @@ krb5_kdc_windc_init(krb5_context context) windcft = _krb5_plugin_get_symbol(e); if (windcft->minor_version < KRB5_WINDC_PLUGIN_MINOR) continue; - + (*windcft->init)(context, &windcctx); break; } @@ -119,9 +119,9 @@ _kdc_check_access(krb5_context context, server_ex, server_name, req->msg_type == krb_as_req); - return (windcft->client_access)(windcctx, - context, config, - client_ex, client_name, - server_ex, server_name, + return (windcft->client_access)(windcctx, + context, config, + client_ex, client_name, + server_ex, server_name, req, e_data); } diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index b328e3ffb3..fa4ba434f3 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -66,10 +66,10 @@ typedef krb5_error_code typedef krb5_error_code (*krb5plugin_windc_client_access)( - void *, krb5_context, + void *, krb5_context, krb5_kdc_configuration *config, - hdb_entry_ex *, const char *, - hdb_entry_ex *, const char *, + hdb_entry_ex *, const char *, + hdb_entry_ex *, const char *, KDC_REQ *, krb5_data *); -- cgit