summaryrefslogtreecommitdiff
path: root/source4/heimdal/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/kdc')
-rw-r--r--source4/heimdal/kdc/524.c2
-rw-r--r--source4/heimdal/kdc/default_config.c376
-rw-r--r--source4/heimdal/kdc/digest.c277
-rw-r--r--source4/heimdal/kdc/headers.h2
-rw-r--r--source4/heimdal/kdc/kaserver.c2
-rw-r--r--source4/heimdal/kdc/kdc-private.h11
-rw-r--r--source4/heimdal/kdc/kdc-protos.h21
-rw-r--r--source4/heimdal/kdc/kdc.h4
-rw-r--r--source4/heimdal/kdc/kdc_locl.h17
-rw-r--r--source4/heimdal/kdc/kerberos4.c2
-rw-r--r--source4/heimdal/kdc/kerberos5.c198
-rw-r--r--source4/heimdal/kdc/krb5tgs.c35
-rw-r--r--source4/heimdal/kdc/kx509.c196
-rw-r--r--source4/heimdal/kdc/log.c2
-rw-r--r--source4/heimdal/kdc/misc.c2
-rwxr-xr-xsource4/heimdal/kdc/pkinit.c264
-rw-r--r--source4/heimdal/kdc/process.c84
-rw-r--r--source4/heimdal/kdc/rx.h2
-rw-r--r--source4/heimdal/kdc/windc.c9
-rw-r--r--source4/heimdal/kdc/windc_plugin.h6
20 files changed, 1024 insertions, 488 deletions
diff --git a/source4/heimdal/kdc/524.c b/source4/heimdal/kdc/524.c
index 56c12efd60..3e4ad29253 100644
--- a/source4/heimdal/kdc/524.c
+++ b/source4/heimdal/kdc/524.c
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: 524.c,v 1.40 2006/10/06 17:06:30 lha Exp $");
+RCSID("$Id: 524.c 18270 2006-10-06 17:06:30Z lha $");
#include <krb5-v4compat.h>
diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c
index 2352020d86..c28bd424ea 100644
--- a/source4/heimdal/kdc/default_config.c
+++ b/source4/heimdal/kdc/default_config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
*
* All rights reserved.
@@ -33,110 +33,61 @@
*/
#include "kdc_locl.h"
+#include <getarg.h>
+#include <parse_bytes.h>
-int require_preauth = -1; /* 1 == require preauth for all principals */
+RCSID("$Id: default_config.c 20532 2007-04-23 07:46:57Z lha $");
-const char *trpolicy_str;
-int disable_des = -1;
-int enable_v4 = -1;
-int enable_kaserver = -1;
-int enable_524 = -1;
-int enable_v4_cross_realm = -1;
-int detach_from_console = -1;
-
-char *v4_realm;
-
-/*
- * Setup some of the defaults for the KDC configuration.
- *
- * Note: Caller must also fill in:
- * - db
- * - num_db
- * - logf
- *
-*/
-
-void
-krb5_kdc_default_config(krb5_kdc_configuration *config)
-{
- memset(config, 0, sizeof(*config));
- config->require_preauth = TRUE;
- config->kdc_warn_pwexpire = 0;
- config->encode_as_rep_as_tgs_rep = FALSE; /* bug compatibility */
- config->check_ticket_addresses = TRUE;
- config->allow_null_ticket_addresses = TRUE;
- config->allow_anonymous = FALSE;
- config->trpolicy = TRPOLICY_ALWAYS_CHECK;
- config->enable_v4 = FALSE;
- config->enable_kaserver = FALSE;
- config->enable_524 = FALSE; /* overriden by enable_v4 in configure()) */
- config->enable_v4_cross_realm = FALSE;
- config->enable_pkinit = FALSE;
- config->enable_pkinit_princ_in_cert = TRUE;
- config->db = NULL;
- config->num_db = 0;
- config->logf = NULL;
-}
-
-
-/*
- * Setup some valudes for the KDC configuration, from the config file
- *
- * Note: Caller must also fill in:
- * - db
- * - num_db
- * - logf
- *
-*/
-
-void krb5_kdc_configure(krb5_context context, krb5_kdc_configuration *config)
+int
+krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
{
- const char *p;
- if(require_preauth == -1) {
- config->require_preauth = krb5_config_get_bool_default(context, NULL,
- config->require_preauth,
- "kdc",
- "require-preauth", NULL);
- } else {
- config->require_preauth = require_preauth;
- }
+ krb5_kdc_configuration *c;
- if(enable_v4 == -1) {
- config->enable_v4 = krb5_config_get_bool_default(context, NULL,
- config->enable_v4,
- "kdc",
- "enable-kerberos4",
- NULL);
- } else {
- config->enable_v4 = enable_v4;
+ c = calloc(1, sizeof(*c));
+ if (c == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
}
- if(enable_v4_cross_realm == -1) {
- config->enable_v4_cross_realm =
- krb5_config_get_bool_default(context, NULL,
- config->enable_v4_cross_realm,
- "kdc",
- "enable-kerberos4-cross-realm",
- NULL);
- } else {
- config->enable_v4_cross_realm = enable_v4_cross_realm;
- }
-
- if(enable_524 == -1) {
- config->enable_524 = krb5_config_get_bool_default(context, NULL,
- config->enable_v4,
- "kdc", "enable-524",
- NULL);
- } else {
- config->enable_524 = enable_524;
- }
-
- config->enable_digest =
+ c->require_preauth = TRUE;
+ c->kdc_warn_pwexpire = 0;
+ c->encode_as_rep_as_tgs_rep = 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->enable_pkinit_princ_in_cert = TRUE;
+ c->db = NULL;
+ c->num_db = 0;
+ c->logf = NULL;
+
+ c->require_preauth =
krb5_config_get_bool_default(context, NULL,
- FALSE,
- "kdc",
- "enable-digest", 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);
+ c->enable_digest =
+ krb5_config_get_bool_default(context, NULL,
+ FALSE,
+ "kdc", "enable-digest", NULL);
{
const char *digests;
@@ -146,46 +97,57 @@ void krb5_kdc_configure(krb5_context context, krb5_kdc_configuration *config)
"digests_allowed", NULL);
if (digests == NULL)
digests = "ntlm-v2";
- config->digests_allowed = parse_flags(digests,
- _kdc_digestunits,
- 0);
- if (config->digests_allowed == -1) {
- kdc_log(context, config, 0,
+ c->digests_allowed = parse_flags(digests,_kdc_digestunits, 0);
+ if (c->digests_allowed == -1) {
+ kdc_log(context, c, 0,
"unparsable digest units (%s), turning off digest",
digests);
- config->enable_digest = 0;
- } else if (config->digests_allowed == 0) {
- kdc_log(context, config, 0,
+ c->enable_digest = 0;
+ } else if (c->digests_allowed == 0) {
+ kdc_log(context, c, 0,
"no digest enable, turning digest off",
digests);
- config->enable_digest = 0;
+ c->enable_digest = 0;
}
}
- config->enable_kx509 =
+ c->enable_kx509 =
krb5_config_get_bool_default(context, NULL,
FALSE,
- "kdc",
- "enable-kx509", NULL);
+ "kdc", "enable-kx509", NULL);
+
+ if (c->enable_kx509) {
+ c->kx509_template =
+ krb5_config_get_string(context, NULL,
+ "kdc", "kx509_template", NULL);
+ c->kx509_ca =
+ krb5_config_get_string(context, NULL,
+ "kdc", "kx509_ca", NULL);
+ if (c->kx509_ca == NULL || c->kx509_template == NULL) {
+ kdc_log(context, c, 0,
+ "missing kx509 configuration, turning off");
+ c->enable_kx509 = FALSE;
+ }
+ }
- config->check_ticket_addresses =
+ c->check_ticket_addresses =
krb5_config_get_bool_default(context, NULL,
- config->check_ticket_addresses,
+ c->check_ticket_addresses,
"kdc",
"check-ticket-addresses", NULL);
- config->allow_null_ticket_addresses =
+ c->allow_null_ticket_addresses =
krb5_config_get_bool_default(context, NULL,
- config->allow_null_ticket_addresses,
+ c->allow_null_ticket_addresses,
"kdc",
"allow-null-ticket-addresses", NULL);
- config->allow_anonymous =
+ c->allow_anonymous =
krb5_config_get_bool_default(context, NULL,
- config->allow_anonymous,
+ c->allow_anonymous,
"kdc",
"allow-anonymous", NULL);
- config->max_datagram_reply_length =
+ c->max_datagram_reply_length =
krb5_config_get_int_default(context,
NULL,
1400,
@@ -193,178 +155,124 @@ void krb5_kdc_configure(krb5_context context, krb5_kdc_configuration *config)
"max-kdc-datagram-reply-length",
NULL);
- trpolicy_str =
- krb5_config_get_string_default(context, NULL, "DEFAULT", "kdc",
- "transited-policy", NULL);
- if(strcasecmp(trpolicy_str, "always-check") == 0) {
- config->trpolicy = TRPOLICY_ALWAYS_CHECK;
- } else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0) {
- config->trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL;
- } else if(strcasecmp(trpolicy_str, "always-honour-request") == 0) {
- config->trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST;
- } else if(strcasecmp(trpolicy_str, "DEFAULT") == 0) {
- /* default */
- } else {
- kdc_log(context, config,
- 0, "unknown transited-policy: %s, reverting to default (always-check)",
- trpolicy_str);
+ {
+ const char *trpolicy_str;
+
+ trpolicy_str =
+ krb5_config_get_string_default(context, NULL, "DEFAULT", "kdc",
+ "transited-policy", NULL);
+ if(strcasecmp(trpolicy_str, "always-check") == 0) {
+ c->trpolicy = TRPOLICY_ALWAYS_CHECK;
+ } else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0) {
+ c->trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL;
+ } else if(strcasecmp(trpolicy_str, "always-honour-request") == 0) {
+ c->trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST;
+ } else if(strcasecmp(trpolicy_str, "DEFAULT") == 0) {
+ /* default */
+ } else {
+ kdc_log(context, c, 0,
+ "unknown transited-policy: %s, "
+ "reverting to default (always-check)",
+ trpolicy_str);
+ }
}
-
- if (krb5_config_get_string(context, NULL, "kdc",
- "enforce-transited-policy", NULL))
- krb5_errx(context, 1, "enforce-transited-policy deprecated, "
- "use [kdc]transited-policy instead");
- if(v4_realm == NULL){
+ {
+ const char *p;
p = krb5_config_get_string (context, NULL,
"kdc",
"v4-realm",
NULL);
if(p != NULL) {
- config->v4_realm = strdup(p);
- if (config->v4_realm == NULL)
+ c->v4_realm = strdup(p);
+ if (c->v4_realm == NULL)
krb5_errx(context, 1, "out of memory");
} else {
- config->v4_realm = NULL;
+ c->v4_realm = NULL;
}
- } else {
- config->v4_realm = v4_realm;
}
- if (enable_kaserver == -1) {
- config->enable_kaserver =
- krb5_config_get_bool_default(context,
- NULL,
- config->enable_kaserver,
- "kdc",
- "enable-kaserver",
- NULL);
- } else {
- config->enable_kaserver = enable_kaserver;
- }
+ c->enable_kaserver =
+ krb5_config_get_bool_default(context,
+ NULL,
+ c->enable_kaserver,
+ "kdc", "enable-kaserver", NULL);
- config->encode_as_rep_as_tgs_rep =
+
+ c->encode_as_rep_as_tgs_rep =
krb5_config_get_bool_default(context, NULL,
- config->encode_as_rep_as_tgs_rep,
+ c->encode_as_rep_as_tgs_rep,
"kdc",
- "encode_as_rep_as_tgs_rep",
- NULL);
-
- config->kdc_warn_pwexpire =
+ "encode_as_rep_as_tgs_rep", NULL);
+
+ c->kdc_warn_pwexpire =
krb5_config_get_time_default (context, NULL,
- config->kdc_warn_pwexpire,
- "kdc",
- "kdc_warn_pwexpire",
- NULL);
+ c->kdc_warn_pwexpire,
+ "kdc", "kdc_warn_pwexpire", NULL);
- if(detach_from_console == -1)
- detach_from_console = krb5_config_get_bool_default(context, NULL,
- DETACH_IS_DEFAULT,
- "kdc",
- "detach", NULL);
#ifdef PKINIT
- config->enable_pkinit =
+ c->enable_pkinit =
krb5_config_get_bool_default(context,
NULL,
- config->enable_pkinit,
+ c->enable_pkinit,
"kdc",
"enable-pkinit",
NULL);
- if (config->enable_pkinit) {
+ if (c->enable_pkinit) {
const char *user_id, *anchors, *ocsp_file;
char **pool_list, **revoke_list;
- user_id = krb5_config_get_string(context, NULL,
- "kdc",
- "pkinit_identity",
- NULL);
+ user_id =
+ krb5_config_get_string(context, NULL,
+ "kdc", "pkinit_identity", NULL);
if (user_id == NULL)
krb5_errx(context, 1, "pkinit enabled but no identity");
anchors = krb5_config_get_string(context, NULL,
- "kdc",
- "pkinit_anchors",
- NULL);
+ "kdc", "pkinit_anchors", NULL);
if (anchors == NULL)
krb5_errx(context, 1, "pkinit enabled but no X509 anchors");
- pool_list = krb5_config_get_strings(context, NULL,
- "kdc",
- "pkinit_pool",
- NULL);
+ pool_list =
+ krb5_config_get_strings(context, NULL,
+ "kdc", "pkinit_pool", NULL);
- revoke_list = krb5_config_get_strings(context, NULL,
- "kdc",
- "pkinit_revoke",
- NULL);
+ revoke_list =
+ krb5_config_get_strings(context, NULL,
+ "kdc", "pkinit_revoke", NULL);
ocsp_file =
krb5_config_get_string(context, NULL,
- "kdc",
- "pkinit_kdc_ocsp",
- NULL);
+ "kdc", "pkinit_kdc_ocsp", NULL);
if (ocsp_file) {
- config->pkinit_kdc_ocsp_file = strdup(ocsp_file);
- if (config->pkinit_kdc_ocsp_file == NULL)
+ c->pkinit_kdc_ocsp_file = strdup(ocsp_file);
+ if (c->pkinit_kdc_ocsp_file == NULL)
krb5_errx(context, 1, "out of memory");
}
- _kdc_pk_initialize(context, config, user_id, anchors,
+
+ _kdc_pk_initialize(context, c, user_id, anchors,
pool_list, revoke_list);
krb5_config_free_strings(pool_list);
krb5_config_free_strings(revoke_list);
- config->enable_pkinit_princ_in_cert =
- krb5_config_get_bool_default(context,
- NULL,
- config->enable_pkinit_princ_in_cert,
+ c->enable_pkinit_princ_in_cert =
+ krb5_config_get_bool_default(context, NULL,
+ c->enable_pkinit_princ_in_cert,
"kdc",
"pkinit_principal_in_certificate",
NULL);
}
- config->pkinit_dh_min_bits =
- krb5_config_get_int_default(context,
- NULL,
+ c->pkinit_dh_min_bits =
+ krb5_config_get_int_default(context, NULL,
0,
- "kdc",
- "pkinit_dh_min_bits",
- NULL);
+ "kdc", "pkinit_dh_min_bits", NULL);
#endif
- if(config->v4_realm == NULL && (config->enable_kaserver || config->enable_v4)){
-#ifdef KRB4
- config->v4_realm = malloc(40); /* REALM_SZ */
- if (config->v4_realm == NULL)
- krb5_errx(context, 1, "out of memory");
- krb_get_lrealm(config->v4_realm, 1);
-#else
- krb5_errx(context, 1, "No Kerberos 4 realm configured");
-#endif
- }
- if(disable_des == -1)
- disable_des = krb5_config_get_bool_default(context, NULL,
- FALSE,
- "kdc",
- "disable-des", NULL);
- if(disable_des) {
- krb5_enctype_disable(context, ETYPE_DES_CBC_CRC);
- krb5_enctype_disable(context, ETYPE_DES_CBC_MD4);
- krb5_enctype_disable(context, ETYPE_DES_CBC_MD5);
- krb5_enctype_disable(context, ETYPE_DES_CBC_NONE);
- krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE);
- krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);
-
- kdc_log(context, config,
- 0, "DES was disabled, turned off Kerberos V4, 524 "
- "and kaserver");
- config->enable_v4 = 0;
- config->enable_524 = 0;
- config->enable_kaserver = 0;
- }
+ *config = c;
- _kdc_windc_init(context);
+ return 0;
}
-
diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c
index 2c012a2ead..811ab639f1 100644
--- a/source4/heimdal/kdc/digest.c
+++ b/source4/heimdal/kdc/digest.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -34,8 +34,9 @@
#include "kdc_locl.h"
#include <hex.h>
-RCSID("$Id: digest.c,v 1.19 2006/12/28 17:03:51 lha Exp $");
+RCSID("$Id: digest.c 20877 2007-06-04 04:07:26Z lha $");
+#define MS_CHAP_V2 0x20
#define CHAP_MD5 0x10
#define DIGEST_MD5 0x08
#define NTLM_V2 0x04
@@ -43,6 +44,7 @@ RCSID("$Id: digest.c,v 1.19 2006/12/28 17:03:51 lha Exp $");
#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},
@@ -135,6 +137,25 @@ fill_targetinfo(krb5_context context,
}
+static const unsigned char ms_chap_v2_magic1[39] = {
+ 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
+ 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
+ 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
+};
+static const unsigned char ms_chap_v2_magic2[41] = {
+ 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
+ 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
+ 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
+ 0x6E
+};
+static const unsigned char ms_rfc3079_magic1[27] = {
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
+};
+
/*
*
*/
@@ -382,11 +403,6 @@ _kdc_do_digest(krb5_context context,
goto out;
}
- ret = krb5_store_stringz(sp, *r.u.initReply.identifier);
- if (ret) {
- krb5_clear_error_string(context);
- goto out;
- }
} else
r.u.initReply.identifier = NULL;
@@ -461,13 +477,7 @@ _kdc_do_digest(krb5_context context,
}
krb5_store_stringz(sp, ireq.u.digestRequest.serverNonce);
- if (ireq.u.digestRequest.identifier) {
- ret = krb5_store_stringz(sp, *ireq.u.digestRequest.identifier);
- if (ret) {
- krb5_clear_error_string(context);
- goto out;
- }
- }
+
if (ireq.u.digestRequest.hostname) {
ret = krb5_store_stringz(sp, *ireq.u.digestRequest.hostname);
if (ret) {
@@ -587,6 +597,7 @@ _kdc_do_digest(krb5_context context,
if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) {
MD5_CTX ctx;
unsigned char md[MD5_DIGEST_LENGTH];
+ char *mdx;
char id;
if ((config->digests_allowed & CHAP_MD5) == 0) {
@@ -613,16 +624,30 @@ _kdc_do_digest(krb5_context context,
MD5_Update(&ctx, serverNonce.data, serverNonce.length);
MD5_Final(md, &ctx);
- r.element = choice_DigestRepInner_response;
- hex_encode(md, sizeof(md), &r.u.response.responseData);
- if (r.u.response.responseData == NULL) {
+ hex_encode(md, sizeof(md), &mdx);
+ if (mdx == NULL) {
krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
+
+ r.element = choice_DigestRepInner_response;
+
+ ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);
+ free(mdx);
+ if (ret == 0) {
+ r.u.response.success = TRUE;
+ } else {
+ kdc_log(context, config, 0,
+ "CHAP reply mismatch for %s",
+ ireq.u.digestRequest.username);
+ r.u.response.success = FALSE;
+ }
+
} else if (strcasecmp(ireq.u.digestRequest.type, "SASL-DIGEST-MD5") == 0) {
MD5_CTX ctx;
unsigned char md[MD5_DIGEST_LENGTH];
+ char *mdx;
char *A1, *A2;
if ((config->digests_allowed & DIGEST_MD5) == 0) {
@@ -709,21 +734,212 @@ _kdc_do_digest(krb5_context context,
MD5_Final(md, &ctx);
- r.element = choice_DigestRepInner_response;
- hex_encode(md, sizeof(md), &r.u.response.responseData);
-
free(A1);
free(A2);
- if (r.u.response.responseData == NULL) {
- krb5_set_error_string(context, "out of memory");
+ hex_encode(md, sizeof(md), &mdx);
+ if (mdx == NULL) {
+ krb5_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ r.element = choice_DigestRepInner_response;
+ ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);
+ free(mdx);
+ if (ret == 0) {
+ r.u.response.success = TRUE;
+ } else {
+ kdc_log(context, config, 0,
+ "DIGEST-MD5 reply mismatch for %s",
+ ireq.u.digestRequest.username);
+ r.u.response.success = FALSE;
+ }
+
+ } else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {
+ unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
+ char *mdx;
+ const char *username;
+ struct ntlm_buf answer;
+ Key *key = NULL;
+ SHA_CTX ctx;
+
+ if ((config->digests_allowed & MS_CHAP_V2) == 0) {
+ kdc_log(context, config, 0, "MS-CHAP-V2 not allowed");
+ goto out;
+ }
+
+ if (ireq.u.digestRequest.clientNonce == NULL) {
+ krb5_set_error_string(context,
+ "MS-CHAP-V2 clientNonce missing");
+ ret = EINVAL;
+ goto out;
+ }
+ if (serverNonce.length != 16) {
+ krb5_set_error_string(context,
+ "MS-CHAP-V2 serverNonce wrong length");
+ ret = EINVAL;
+ goto out;
+ }
+
+ /* strip of the domain component */
+ username = strchr(ireq.u.digestRequest.username, '\\');
+ if (username == NULL)
+ username = ireq.u.digestRequest.username;
+ else
+ username++;
+
+ /* ChallangeHash */
+ SHA1_Init(&ctx);
+ {
+ 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_string(context, "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;
+ goto out;
+ }
+ SHA1_Update(&ctx, clientNonce.data, ssize);
+ free(clientNonce.data);
+ }
+ SHA1_Update(&ctx, serverNonce.data, serverNonce.length);
+ SHA1_Update(&ctx, username, strlen(username));
+ SHA1_Final(challange, &ctx);
+
+ /* NtPasswordHash */
+ ret = krb5_parse_name(context, username, &clientprincipal);
+ if (ret)
+ goto out;
+
+ ret = _kdc_db_fetch(context, config, clientprincipal,
+ 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);
+ goto out;
+ }
+
+ 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);
+ goto out;
+ }
+
+ /* ChallengeResponse */
+ ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data,
+ key->key.keyvalue.length,
+ challange, &answer);
+ if (ret) {
+ krb5_set_error_string(context, "NTLM missing arcfour key");
+ goto out;
+ }
+
+ hex_encode(answer.data, answer.length, &mdx);
+ if (mdx == NULL) {
+ free(answer.data);
+ krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
+ r.element = choice_DigestRepInner_response;
+ ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);
+ free(mdx);
+ if (ret == 0) {
+ r.u.response.success = TRUE;
+ } else {
+ kdc_log(context, config, 0,
+ "MS-CHAP-V2 reply mismatch for %s",
+ ireq.u.digestRequest.username);
+ r.u.response.success = FALSE;
+ }
+
+ if (r.u.response.success) {
+ unsigned char hashhash[MD4_DIGEST_LENGTH];
+
+ /* hashhash */
+ {
+ MD4_CTX hctx;
+
+ MD4_Init(&hctx);
+ MD4_Update(&hctx, key->key.keyvalue.data,
+ key->key.keyvalue.length);
+ MD4_Final(hashhash, &hctx);
+ }
+
+ /* GenerateAuthenticatorResponse */
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, hashhash, sizeof(hashhash));
+ SHA1_Update(&ctx, answer.data, answer.length);
+ SHA1_Update(&ctx, ms_chap_v2_magic1,sizeof(ms_chap_v2_magic1));
+ SHA1_Final(md, &ctx);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, md, sizeof(md));
+ SHA1_Update(&ctx, challange, 8);
+ SHA1_Update(&ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));
+ SHA1_Final(md, &ctx);
+
+ r.u.response.rsp = calloc(1, sizeof(*r.u.response.rsp));
+ if (r.u.response.rsp == NULL) {
+ free(answer.data);
+ krb5_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ hex_encode(md, sizeof(md), r.u.response.rsp);
+ if (r.u.response.rsp == NULL) {
+ free(answer.data);
+ krb5_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ /* get_master, rfc 3079 3.4 */
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, hashhash, 16); /* md4(hash) */
+ SHA1_Update(&ctx, answer.data, answer.length);
+ SHA1_Update(&ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));
+ SHA1_Final(md, &ctx);
+
+ free(answer.data);
+
+ r.u.response.session_key =
+ calloc(1, sizeof(*r.u.response.session_key));
+ if (r.u.response.session_key == NULL) {
+ krb5_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ ret = krb5_data_copy(r.u.response.session_key, md, 16);
+ if (ret) {
+ krb5_clear_error_string(context);
+ goto out;
+ }
+ }
+
} else {
r.element = choice_DigestRepInner_error;
- asprintf(&r.u.error.reason, "unsupported digest type %s",
+ 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");
@@ -745,7 +961,6 @@ _kdc_do_digest(krb5_context context,
goto out;
}
-
r.element = choice_DigestRepInner_ntlmInitReply;
r.u.ntlmInitReply.flags = NTLM_NEG_UNICODE;
@@ -766,12 +981,12 @@ _kdc_do_digest(krb5_context context,
NTLM_NEG_TARGET_DOMAIN |
NTLM_ENC_128;
-#define ALL \
- NTLM_NEG_SIGN| \
- NTLM_NEG_SEAL| \
- NTLM_NEG_ALWAYS_SIGN| \
- NTLM_NEG_NTLM2_SESSION| \
- NTLM_NEG_KEYEX
+#define ALL \
+ NTLM_NEG_SIGN| \
+ NTLM_NEG_SEAL| \
+ NTLM_NEG_ALWAYS_SIGN| \
+ NTLM_NEG_NTLM2_SESSION| \
+ NTLM_NEG_KEYEX
r.u.ntlmInitReply.flags |= (ireq.u.ntlmInit.flags & (ALL));
@@ -989,6 +1204,7 @@ _kdc_do_digest(krb5_context context,
if ((config->digests_allowed & NTLM_V1_SESSION) == 0) {
kdc_log(context, config, 0, "NTLM v1-session not allowed");
+ ret = EINVAL;
goto out;
}
@@ -1048,6 +1264,7 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_string(context,
"NTLM client failed to neg key "
"exchange but still sent key");
+ ret = EINVAL;
goto out;
}
diff --git a/source4/heimdal/kdc/headers.h b/source4/heimdal/kdc/headers.h
index 56ddc8090b..64f6b6e438 100644
--- a/source4/heimdal/kdc/headers.h
+++ b/source4/heimdal/kdc/headers.h
@@ -32,7 +32,7 @@
*/
/*
- * $Id: headers.h,v 1.22 2007/01/04 00:15:34 lha Exp $
+ * $Id: headers.h 19658 2007-01-04 00:15:34Z lha $
*/
#ifndef __HEADERS_H__
diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c
index ac282717ed..deb32e1019 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,v 1.36 2006/08/23 11:43:44 lha Exp $");
+RCSID("$Id: kaserver.c 17904 2006-08-23 11:45:16Z lha $");
#include <krb5-v4compat.h>
#include <rx.h>
diff --git a/source4/heimdal/kdc/kdc-private.h b/source4/heimdal/kdc/kdc-private.h
index d896bd10e9..030be9ae58 100644
--- a/source4/heimdal/kdc/kdc-private.h
+++ b/source4/heimdal/kdc/kdc-private.h
@@ -149,9 +149,9 @@ _kdc_find_etype (
Key **/*ret_key*/,
krb5_enctype */*ret_etype*/);
-PA_DATA*
+const PA_DATA*
_kdc_find_padata (
- KDC_REQ */*req*/,
+ const KDC_REQ */*req*/,
int */*start*/,
int /*type*/);
@@ -249,8 +249,8 @@ krb5_error_code
_kdc_pk_rd_padata (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/,
- KDC_REQ */*req*/,
- PA_DATA */*pa*/,
+ const KDC_REQ */*req*/,
+ const PA_DATA */*pa*/,
pk_client_params **/*ret_params*/);
krb5_error_code
@@ -283,7 +283,4 @@ _kdc_windc_client_access (
struct hdb_entry_ex */*client*/,
KDC_REQ */*req*/);
-krb5_error_code
-_kdc_windc_init (krb5_context /*context*/);
-
#endif /* __kdc_private_h__ */
diff --git a/source4/heimdal/kdc/kdc-protos.h b/source4/heimdal/kdc/kdc-protos.h
index 69bc871b01..f7df365eb2 100644
--- a/source4/heimdal/kdc/kdc-protos.h
+++ b/source4/heimdal/kdc/kdc-protos.h
@@ -37,8 +37,10 @@ kdc_openlog (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/);
-void
-krb5_kdc_default_config (krb5_kdc_configuration */*config*/);
+int
+krb5_kdc_get_config (
+ krb5_context /*context*/,
+ krb5_kdc_configuration **/*config*/);
int
krb5_kdc_process_krb5_request (
@@ -63,6 +65,21 @@ krb5_kdc_process_request (
struct sockaddr */*addr*/,
int /*datagram_reply*/);
+int
+krb5_kdc_save_request (
+ krb5_context /*context*/,
+ const char */*fn*/,
+ const unsigned char */*buf*/,
+ size_t /*len*/,
+ const krb5_data */*reply*/,
+ const struct sockaddr */*sa*/);
+
+void
+krb5_kdc_update_time (struct timeval */*tv*/);
+
+krb5_error_code
+krb5_kdc_windc_init (krb5_context /*context*/);
+
#ifdef __cplusplus
}
#endif
diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h
index ea9eb7125e..eb24b4ee97 100644
--- a/source4/heimdal/kdc/kdc.h
+++ b/source4/heimdal/kdc/kdc.h
@@ -35,7 +35,7 @@
*/
/*
- * $Id: kdc.h,v 1.11 2006/12/28 21:06:56 lha Exp $
+ * $Id: kdc.h 19907 2007-01-14 23:10:24Z lha $
*/
#ifndef __KDC_H__
@@ -86,6 +86,8 @@ typedef struct krb5_kdc_configuration {
size_t max_datagram_reply_length;
int enable_kx509;
+ const char *kx509_template;
+ const char *kx509_ca;
} krb5_kdc_configuration;
diff --git a/source4/heimdal/kdc/kdc_locl.h b/source4/heimdal/kdc/kdc_locl.h
index ae3b6584a5..fdbdf271de 100644
--- a/source4/heimdal/kdc/kdc_locl.h
+++ b/source4/heimdal/kdc/kdc_locl.h
@@ -32,7 +32,7 @@
*/
/*
- * $Id: kdc_locl.h,v 1.76 2006/12/26 17:18:14 lha Exp $
+ * $Id: kdc_locl.h 20954 2007-06-07 03:30:15Z lha $
*/
#ifndef __KDC_LOCL_H__
@@ -46,6 +46,7 @@ typedef struct pk_client_params pk_client_params;
extern sig_atomic_t exit_flag;
extern size_t max_request;
+extern const char *request_log;
extern const char *port_str;
extern krb5_addresses explicit_addresses;
@@ -55,18 +56,6 @@ extern int enable_http;
extern int detach_from_console;
-extern int require_preauth; /* 1 == require preauth for all principals */
-
-extern const char *trpolicy_str;
-
-extern int disable_des;
-extern int enable_v4;
-extern int enable_kaserver;
-extern int enable_524;
-extern int enable_v4_cross_realm;
-
-extern char *v4_realm;
-
extern const struct units _kdc_digestunits[];
#define _PATH_KDC_CONF HDB_DB_DIR "/kdc.conf"
@@ -81,6 +70,4 @@ loop(krb5_context context, krb5_kdc_configuration *config);
krb5_kdc_configuration *
configure(krb5_context context, int argc, char **argv);
-void krb5_kdc_configure(krb5_context context, krb5_kdc_configuration *config);
-
#endif /* __KDC_LOCL_H__ */
diff --git a/source4/heimdal/kdc/kerberos4.c b/source4/heimdal/kdc/kerberos4.c
index 97e98d86ad..3c76bb99b2 100644
--- a/source4/heimdal/kdc/kerberos4.c
+++ b/source4/heimdal/kdc/kerberos4.c
@@ -35,7 +35,7 @@
#include <krb5-v4compat.h>
-RCSID("$Id: kerberos4.c,v 1.63 2006/10/08 13:43:27 lha Exp $");
+RCSID("$Id: kerberos4.c 18349 2006-10-08 13:43:52Z lha $");
#ifndef swap32
static uint32_t
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index bb0fda89e7..e34938447a 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: kerberos5.c,v 1.231 2007/01/04 13:27:27 lha Exp $");
+RCSID("$Id: kerberos5.c 21040 2007-06-10 06:20:59Z lha $");
#define MAX_TIME ((time_t)((1U << 31) - 1))
@@ -70,9 +70,12 @@ set_salt_padata (METHOD_DATA *md, Salt *salt)
}
}
-PA_DATA*
-_kdc_find_padata(KDC_REQ *req, int *start, int type)
+const PA_DATA*
+_kdc_find_padata(const KDC_REQ *req, int *start, int type)
{
+ if (req->padata == NULL)
+ return NULL;
+
while(*start < req->padata->len){
(*start)++;
if(req->padata->val[*start - 1].padata_type == type)
@@ -431,7 +434,8 @@ get_pa_etype_info(krb5_context context,
ret = krb5_unparse_name(context, client->principal, &name);
if (ret)
name = rk_UNCONST("<unparse_name failed>");
- kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
+ kdc_log(context, config, 0,
+ "internal error in get_pa_etype_info(%s): %d != %d",
name, n, pa.len);
if (ret == 0)
free(name);
@@ -689,11 +693,11 @@ log_as_req(krb5_context context,
}
{
- char _str[128];
+ char fixedstr[128];
unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
- _str, sizeof(_str));
- if(*_str)
- kdc_log(context, config, 2, "Requested flags: %s", _str);
+ fixedstr, sizeof(fixedstr));
+ if(*fixedstr)
+ kdc_log(context, config, 2, "Requested flags: %s", fixedstr);
}
}
@@ -870,7 +874,7 @@ send_pac_p(krb5_context context, KDC_REQ *req)
{
krb5_error_code ret;
PA_PAC_REQUEST pacreq;
- PA_DATA *pa;
+ const PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
@@ -909,32 +913,37 @@ _kdc_as_rep(krb5_context context,
KDCOptions f = b->kdc_options;
hdb_entry_ex *client = NULL, *server = NULL;
krb5_enctype cetype, setype, sessionetype;
+ krb5_data e_data;
EncTicketPart et;
EncKDCRepPart ek;
krb5_principal client_princ = NULL, server_princ = NULL;
char *client_name = NULL, *server_name = NULL;
krb5_error_code ret = 0;
const char *e_text = NULL;
- krb5_data e_data;
krb5_crypto crypto;
Key *ckey, *skey;
EncryptionKey *reply_key;
+ int flags = 0;
#ifdef PKINIT
pk_client_params *pkp = NULL;
#endif
memset(&rep, 0, sizeof(rep));
- memset(&e_data, 0, sizeof(e_data));
+ krb5_data_zero(&e_data);
+
+ if (f.canonicalize)
+ flags |= HDB_F_CANON;
if(b->sname == NULL){
ret = KRB5KRB_ERR_GENERIC;
e_text = "No server in request";
} else{
- _krb5_principalname2krb5_principal (context,
- &server_princ,
- *(b->sname),
- b->realm);
- ret = krb5_unparse_name(context, server_princ, &server_name);
+ ret = _krb5_principalname2krb5_principal (context,
+ &server_princ,
+ *(b->sname),
+ b->realm);
+ if (ret == 0)
+ ret = krb5_unparse_name(context, server_princ, &server_name);
}
if (ret) {
kdc_log(context, config, 0,
@@ -946,10 +955,26 @@ _kdc_as_rep(krb5_context context,
ret = KRB5KRB_ERR_GENERIC;
e_text = "No client in request";
} else {
- _krb5_principalname2krb5_principal (context,
- &client_princ,
- *(b->cname),
- b->realm);
+
+ if (b->cname->name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
+ if (b->cname->name_string.len != 1) {
+ kdc_log(context, config, 0,
+ "AS-REQ malformed canon request from %s", from);
+ ret = KRB5_PARSE_MALFORMED;
+ goto out;
+ }
+ ret = krb5_parse_name(context, b->cname->name_string.val[0],
+ &client_princ);
+ if (ret)
+ goto out;
+ } else {
+ ret = _krb5_principalname2krb5_principal (context,
+ &client_princ,
+ *(b->cname),
+ b->realm);
+ if (ret)
+ goto out;
+ }
ret = krb5_unparse_name(context, client_princ, &client_name);
}
if (ret) {
@@ -962,7 +987,7 @@ _kdc_as_rep(krb5_context context,
client_name, from, server_name);
ret = _kdc_db_fetch(context, config, client_princ,
- HDB_F_GET_CLIENT, NULL, &client);
+ HDB_F_GET_CLIENT | flags, NULL, &client);
if(ret){
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
krb5_get_err_text(context, ret));
@@ -996,7 +1021,7 @@ _kdc_as_rep(krb5_context context,
if(req->padata){
int i;
- PA_DATA *pa;
+ const PA_DATA *pa;
int found_pa = 0;
log_patypes(context, config, req->padata);
@@ -1041,7 +1066,7 @@ _kdc_as_rep(krb5_context context,
kdc_log(context, config, 0, "%s", e_text);
pkp = NULL;
- goto ts_enc;
+ goto out;
}
found_pa = 1;
et.flags.pre_authent = 1;
@@ -1169,6 +1194,8 @@ _kdc_as_rep(krb5_context context,
(unsigned)abs(kdc_time - p.patimestamp),
context->max_skew,
client_name);
+#if 1
+ /* This code is from samba, needs testing */
/*
* the following is needed to make windows clients
* to retry using the timestamp in the error message
@@ -1177,6 +1204,9 @@ _kdc_as_rep(krb5_context context,
* is present...
*/
e_text = NULL;
+#else
+ e_text = "Too large time skew";
+#endif
goto out;
}
et.flags.pre_authent = 1;
@@ -1227,6 +1257,12 @@ _kdc_as_rep(krb5_context context,
pa->padata_type = KRB5_PADATA_PK_AS_REQ;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
+
+ ret = realloc_method_data(&method_data);
+ pa = &method_data.val[method_data.len-1];
+ pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN;
+ pa->padata_value.length = 0;
+ pa->padata_value.data = NULL;
#endif
/*
@@ -1253,12 +1289,12 @@ _kdc_as_rep(krb5_context context,
e_data.data = buf;
e_data.length = len;
e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
+
ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
kdc_log(context, config, 0,
"No preauth found, returning PREAUTH-REQUIRED -- %s",
client_name);
-
goto out;
}
@@ -1283,45 +1319,57 @@ _kdc_as_rep(krb5_context context,
if(ret)
goto out;
+ /*
+ * 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.
+ *
+ * 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
+ * decrypt.
+ *
+ * But if the KDC admin is paranoid and doesn't want to have "no
+ * 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;
- int i, j, y;
+ 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++) {
- /* check it's valid */
if (krb5_enctype_valid(context, p[i]) != 0)
continue;
- /* check if the client supports it */
for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {
- if (p[i] == b->etype.val[j]) {
- /*
- * if the server (krbtgt) has explicit etypes,
- * check if it also supports it
- */
- if (server->entry.etypes) {
- for (y = 0; y < server->entry.etypes->len; y++) {
- if (p[i] == server->entry.etypes->val[y]) {
- sessionetype = p[i];
- break;
- }
- }
- } else {
- sessionetype = p[i];
- break;
- }
- }
+ 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 (sessionetype == ETYPE_NULL) {
- kdc_log(context, config, 0,
+ /* 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);
+ "to use for the session key",
+ client_name, from);
goto out;
}
}
@@ -1534,6 +1582,58 @@ _kdc_as_rep(krb5_context context,
set_salt_padata (rep.padata, ckey->salt);
+ /* Add signing of alias referral */
+ if (f.canonicalize) {
+ PA_ClientCanonicalized canon;
+ krb5_data data;
+ PA_DATA pa;
+ krb5_crypto crypto;
+ size_t len;
+
+ memset(&canon, 0, sizeof(canon));
+
+ canon.names.requested_name = *b->cname;
+ canon.names.real_name = client->entry.principal->name;
+
+ ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
+ &canon.names, &len, ret);
+ if (ret)
+ goto out;
+ if (data.length != len)
+ krb5_abortx(context, "internal asn.1 error");
+
+ /* sign using "returned session key" */
+ ret = krb5_crypto_init(context, &et.key, 0, &crypto);
+ if (ret) {
+ free(data.data);
+ goto out;
+ }
+
+ ret = krb5_create_checksum(context, crypto,
+ KRB5_KU_CANONICALIZED_NAMES, 0,
+ data.data, data.length,
+ &canon.canon_checksum);
+ free(data.data);
+ krb5_crypto_destroy(context, crypto);
+ if (ret)
+ goto out;
+
+ ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
+ &canon, &len, ret);
+ free_Checksum(&canon.canon_checksum);
+ if (ret)
+ goto out;
+ if (data.length != len)
+ krb5_abortx(context, "internal asn.1 error");
+
+ pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
+ pa.padata_value = data;
+ ret = add_METHOD_DATA(rep.padata, &pa);
+ free(data.data);
+ if (ret)
+ goto out;
+ }
+
if (rep.padata->len == 0) {
free(rep.padata);
rep.padata = NULL;
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index a056839e5f..02cd92de2e 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: krb5tgs.c,v 1.25 2007/01/04 12:49:45 lha Exp $");
+RCSID("$Id: krb5tgs.c 21041 2007-06-10 06:21:12Z lha $");
/*
* return the realm of a krbtgt-ticket or NULL
@@ -656,7 +656,7 @@ tgs_make_reply(krb5_context context,
KDC_REQ_BODY *b,
krb5_const_principal tgt_name,
const EncTicketPart *tgt,
- const EncryptionKey *ekey,
+ const EncryptionKey *serverkey,
const krb5_keyblock *sessionkey,
krb5_kvno kvno,
AuthorizationData *auth_data,
@@ -883,7 +883,7 @@ tgs_make_reply(krb5_context context,
ret = _kdc_encode_reply(context, config,
&rep, &et, &ek, et.key.keytype,
kvno,
- ekey, 0, &tgt->key, e_text, reply);
+ serverkey, 0, &tgt->key, e_text, reply);
out:
free_TGS_REP(&rep);
free_TransitedEncoding(&et.transited);
@@ -1010,7 +1010,7 @@ static krb5_error_code
tgs_parse_request(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ_BODY *b,
- PA_DATA *tgs_req,
+ const PA_DATA *tgs_req,
hdb_entry_ex **krbtgt,
krb5_enctype *krbtgt_etype,
krb5_ticket **ticket,
@@ -1258,6 +1258,7 @@ tgs_build_reply(krb5_context context,
krb5_keyblock sessionkey;
krb5_kvno kvno;
krb5_data rspac;
+ int cross_realm = 0;
PrincipalName *s;
Realm r;
@@ -1421,6 +1422,8 @@ server_lookup:
kdc_log(context, config, 1, "Client not found in database: %s: %s",
cpn, krb5_get_err_text(context, ret));
+
+ cross_realm = 1;
}
/*
@@ -1707,21 +1710,25 @@ server_lookup:
/* check PAC if there is one */
{
Key *tkey;
+ krb5_keyblock *tgtkey = NULL;
- 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;
+ if (!cross_realm) {
+ 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;
+ }
+ tgtkey = &tkey->key;
}
ret = check_PAC(context, config, client_principal,
- client, server, ekey, &tkey->key,
+ client, server, ekey, tgtkey,
tgt, &rspac, &require_signedpath);
if (ret) {
kdc_log(context, config, 0,
- "check_PAC check failed for %s (%s) from %s with %s",
+ "Verify PAC failed for %s (%s) from %s with %s",
spn, cpn, from, krb5_get_err_text(context, ret));
goto out;
}
@@ -1804,7 +1811,7 @@ _kdc_tgs_rep(krb5_context context,
AuthorizationData *auth_data = NULL;
krb5_error_code ret;
int i = 0;
- PA_DATA *tgs_req = NULL;
+ const PA_DATA *tgs_req;
hdb_entry_ex *krbtgt = NULL;
krb5_ticket *ticket = NULL;
diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c
index d817338f73..8414ecb4b2 100644
--- a/source4/heimdal/kdc/kx509.c
+++ b/source4/heimdal/kdc/kx509.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,8 +33,10 @@
#include "kdc_locl.h"
#include <hex.h>
+#include <rfc2459_asn1.h>
+#include <hx509.h>
-RCSID("$Id: kx509.c,v 1.1 2006/12/28 21:03:53 lha Exp $");
+RCSID("$Id: kx509.c 19992 2007-01-20 09:06:18Z lha $");
/*
*
@@ -140,72 +142,146 @@ build_certificate(krb5_context context,
krb5_principal principal,
krb5_data *certificate)
{
- /* XXX write code here to generate certificates */
- FILE *in, *out;
- krb5_error_code ret;
- const char *program;
- char *str, *strkey;
- char tstr[64];
- pid_t pid;
+ hx509_context hxctx = NULL;
+ hx509_ca_tbs tbs = NULL;
+ hx509_env env = NULL;
+ hx509_cert cert = NULL;
+ hx509_cert signer = NULL;
+ int ret;
+
+ if (krb5_principal_get_comp_string(context, principal, 1) != NULL) {
+ kdc_log(context, config, 0, "Principal is not a user");
+ return EINVAL;
+ }
- snprintf(tstr, sizeof(tstr), "%lu", (unsigned long)endtime);
+ ret = hx509_context_init(&hxctx);
+ if (ret)
+ goto out;
- ret = base64_encode(key->data, key->length, &strkey);
- if (ret < 0) {
- krb5_set_error_string(context, "failed to base64 encode key");
- return ENOMEM;
- }
+ ret = hx509_env_init(hxctx, &env);
+ if (ret)
+ goto out;
- program = krb5_config_get_string(context,
- NULL,
- "kdc",
- "kx509_cert_program",
- NULL);
- if (program == NULL) {
- free(strkey);
- krb5_set_error_string(context, "no certificate program configured");
- return ENOENT;
- }
+ ret = hx509_env_add(hxctx, env, "principal-name",
+ krb5_principal_get_comp_string(context, principal, 0));
+ if (ret)
+ goto out;
- ret = krb5_unparse_name(context, principal, &str);
- if (ret) {
- free(strkey);
- return ret;
+ {
+ hx509_certs certs;
+ hx509_query *q;
+
+ ret = hx509_certs_init(hxctx, config->kx509_ca, 0,
+ NULL, &certs);
+ if (ret) {
+ kdc_log(context, config, 0, "Failed to load CA %s",
+ config->kx509_ca);
+ goto out;
+ }
+ ret = hx509_query_alloc(hxctx, &q);
+ if (ret) {
+ hx509_certs_free(&certs);
+ goto out;
+ }
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
+
+ ret = hx509_certs_find(hxctx, certs, q, &signer);
+ hx509_query_free(hxctx, q);
+ hx509_certs_free(&certs);
+ if (ret) {
+ kdc_log(context, config, 0, "Failed to find a CA in %s",
+ config->kx509_ca);
+ goto out;
+ }
}
- pid = pipe_execv(&in, &out, NULL, program, str, tstr, NULL);
- free(str);
- if (pid <= 0) {
- free(strkey);
- krb5_set_error_string(context,
- "Failed to run the cert program %s",
- program);
- return ret;
+ ret = hx509_ca_tbs_init(hxctx, &tbs);
+ if (ret)
+ goto out;
+
+ {
+ SubjectPublicKeyInfo spki;
+ heim_any any;
+
+ memset(&spki, 0, sizeof(spki));
+
+ spki.subjectPublicKey.data = key->data;
+ spki.subjectPublicKey.length = key->length * 8;
+
+ ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(),
+ &spki.algorithm.algorithm);
+
+ any.data = "\x05\x00";
+ any.length = 2;
+ spki.algorithm.parameters = &any;
+
+ ret = hx509_ca_tbs_set_spki(hxctx, tbs, &spki);
+ der_free_oid(&spki.algorithm.algorithm);
+ if (ret)
+ goto out;
}
- fprintf(in, "%s\n", strkey);
- fclose(in);
- free(strkey);
{
- unsigned buf[1024 * 10];
- size_t len;
+ hx509_certs certs;
+ hx509_cert template;
- len = fread(buf, 1, sizeof(buf), out);
- fclose(out);
- if(len == 0) {
- krb5_set_error_string(context,
- "Certificate program returned no data");
- return KRB5KDC_ERR_PREAUTH_FAILED;
+ ret = hx509_certs_init(hxctx, config->kx509_template, 0,
+ NULL, &certs);
+ if (ret) {
+ kdc_log(context, config, 0, "Failed to load template %s",
+ config->kx509_template);
+ goto out;
}
- ret = krb5_data_copy(certificate, buf, len);
+ ret = hx509_get_one_cert(hxctx, certs, &template);
+ hx509_certs_free(&certs);
if (ret) {
- krb5_set_error_string(context, "Failed To copy certificate");
- return ret;
+ kdc_log(context, config, 0, "Failed to find template in %s",
+ config->kx509_template);
+ goto out;
}
+ ret = hx509_ca_tbs_set_template(hxctx, tbs,
+ HX509_CA_TEMPLATE_SUBJECT|
+ HX509_CA_TEMPLATE_KU|
+ HX509_CA_TEMPLATE_EKU,
+ template);
+ hx509_cert_free(template);
+ if (ret)
+ goto out;
}
- kill(pid, SIGKILL);
- waitpid(pid, NULL, 0);
+
+ hx509_ca_tbs_set_notAfter(hxctx, tbs, endtime);
+
+ hx509_ca_tbs_subject_expand(hxctx, tbs, env);
+ hx509_env_free(&env);
+
+ ret = hx509_ca_sign(hxctx, tbs, signer, &cert);
+ hx509_cert_free(signer);
+ if (ret)
+ goto out;
+
+ hx509_ca_tbs_free(&tbs);
+
+ ret = hx509_cert_binary(hxctx, cert, certificate);
+ hx509_cert_free(cert);
+ if (ret)
+ goto out;
+
+ hx509_context_free(&hxctx);
+
return 0;
+out:
+ if (env)
+ hx509_env_free(&env);
+ if (tbs)
+ hx509_ca_tbs_free(&tbs);
+ if (signer)
+ hx509_cert_free(signer);
+ if (hxctx)
+ hx509_context_free(&hxctx);
+ krb5_set_error_string(context, "cert creation failed");
+ return ret;
}
/*
@@ -299,6 +375,20 @@ _kdc_do_kx509(krb5_context context,
if (ret)
goto out;
+ /* Verify that the key is encoded RSA key */
+ {
+ RSAPublicKey key;
+ size_t size;
+
+ ret = decode_RSAPublicKey(req->pk_key.data, req->pk_key.length,
+ &key, &size);
+ if (ret)
+ goto out;
+ free_RSAPublicKey(&key);
+ if (size != req->pk_key.length)
+ ;
+ }
+
ALLOC(rep.certificate);
if (rep.certificate == NULL)
goto out;
diff --git a/source4/heimdal/kdc/log.c b/source4/heimdal/kdc/log.c
index c316b0c5f8..977b1c9476 100644
--- a/source4/heimdal/kdc/log.c
+++ b/source4/heimdal/kdc/log.c
@@ -32,7 +32,7 @@
*/
#include "kdc_locl.h"
-RCSID("$Id: log.c,v 1.16 2005/06/30 01:52:48 lha Exp $");
+RCSID("$Id: log.c 15532 2005-06-30 01:54:49Z lha $");
void
kdc_openlog(krb5_context context,
diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c
index b511e1a7a8..ebf2873599 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,v 1.32 2006/08/28 14:41:49 lha Exp $");
+RCSID("$Id: misc.c 17951 2006-08-28 14:41:49Z lha $");
struct timeval _kdc_now;
diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c
index 418a38d030..bf62f879db 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,v 1.86 2007/01/04 12:54:09 lha Exp $");
+RCSID("$Id: pkinit.c 21039 2007-06-10 06:20:31Z lha $");
#ifdef PKINIT
@@ -97,7 +97,7 @@ static struct {
static krb5_error_code
pk_check_pkauthenticator_win2k(krb5_context context,
PKAuthenticator_Win2k *a,
- KDC_REQ *req)
+ const KDC_REQ *req)
{
krb5_timestamp now;
@@ -114,7 +114,7 @@ pk_check_pkauthenticator_win2k(krb5_context context,
static krb5_error_code
pk_check_pkauthenticator(krb5_context context,
PKAuthenticator *a,
- KDC_REQ *req)
+ const KDC_REQ *req)
{
u_char *buf = NULL;
size_t buf_size;
@@ -365,8 +365,8 @@ get_dh_param(krb5_context context,
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
krb5_kdc_configuration *config,
- KDC_REQ *req,
- PA_DATA *pa,
+ const KDC_REQ *req,
+ const PA_DATA *pa,
pk_client_params **ret_params)
{
pk_client_params *client_params;
@@ -375,7 +375,6 @@ _kdc_pk_rd_padata(krb5_context context,
krb5_data eContent = { 0, NULL };
krb5_data signed_content = { 0, NULL };
const char *type = "unknown type";
- const heim_oid *pa_contentType;
int have_data = 0;
*ret_params = NULL;
@@ -385,6 +384,8 @@ _kdc_pk_rd_padata(krb5_context context,
return 0;
}
+ hx509_verify_set_time(kdc_identity->verify_ctx, _kdc_now.tv_sec);
+
client_params = calloc(1, sizeof(*client_params));
if (client_params == NULL) {
krb5_clear_error_string(context);
@@ -396,7 +397,6 @@ _kdc_pk_rd_padata(krb5_context context,
PA_PK_AS_REQ_Win2k r;
type = "PK-INIT-Win2k";
- pa_contentType = oid_id_pkcs7_data();
ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data,
pa->padata_value.length,
@@ -422,7 +422,6 @@ _kdc_pk_rd_padata(krb5_context context,
PA_PK_AS_REQ r;
type = "PK-INIT-IETF";
- pa_contentType = oid_id_pkauthdata();
ret = decode_PA_PK_AS_REQ(pa->padata_value.data,
pa->padata_value.length,
@@ -467,7 +466,7 @@ _kdc_pk_rd_padata(krb5_context context,
edi->val[i].issuerAndSerialNumber->length,
&iasn,
&size);
- if (ret || size != 0) {
+ if (ret) {
hx509_query_free(kdc_identity->hx509ctx, q);
continue;
}
@@ -527,6 +526,7 @@ _kdc_pk_rd_padata(krb5_context context,
kdc_identity->verify_ctx,
signed_content.data,
signed_content.length,
+ NULL,
kdc_identity->certpool,
&eContentType,
&eContent,
@@ -547,7 +547,9 @@ _kdc_pk_rd_padata(krb5_context context,
}
/* Signature is correct, now verify the signed message */
- if (der_heim_oid_cmp(&eContentType, pa_contentType)) {
+ 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;
goto out;
@@ -639,6 +641,8 @@ _kdc_pk_rd_padata(krb5_context context,
kdc_log(context, config, 0, "PK-INIT request of type %s", type);
out:
+ if (ret)
+ krb5_warn(context, ret, "PKINIT");
if (signed_content.data)
free(signed_content.data);
@@ -678,18 +682,41 @@ pk_mk_pa_reply_enckey(krb5_context context,
krb5_keyblock *reply_key,
ContentInfo *content_info)
{
+ const heim_oid *envelopedAlg = NULL, *sdAlg = NULL;
krb5_error_code ret;
krb5_data buf, signed_data;
size_t size;
+ int do_win2k = 0;
krb5_data_zero(&buf);
krb5_data_zero(&signed_data);
+ /*
+ * If the message client is a win2k-type but it send pa data
+ * 09-binding it expects a IETF (checksum) reply so there can be
+ * no replay attacks.
+ */
+
switch (client_params->type) {
case PKINIT_COMPAT_WIN2K: {
+ int i = 0;
+ if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL)
+ do_win2k = 1;
+ break;
+ }
+ case PKINIT_COMPAT_27:
+ break;
+ default:
+ krb5_abortx(context, "internal pkinit error");
+ }
+
+ if (do_win2k) {
ReplyKeyPack_Win2k kp;
memset(&kp, 0, sizeof(kp));
+ envelopedAlg = oid_id_rsadsi_des_ede3_cbc();
+ sdAlg = oid_id_pkcs7_data();
+
ret = copy_EncryptionKey(reply_key, &kp.replyKey);
if (ret) {
krb5_clear_error_string(context);
@@ -701,13 +728,13 @@ pk_mk_pa_reply_enckey(krb5_context context,
buf.data, buf.length,
&kp, &size,ret);
free_ReplyKeyPack_Win2k(&kp);
- break;
- }
- case PKINIT_COMPAT_27: {
+ } else {
krb5_crypto ascrypto;
ReplyKeyPack kp;
memset(&kp, 0, sizeof(kp));
+ sdAlg = oid_id_pkrkeydata();
+
ret = copy_EncryptionKey(reply_key, &kp.replyKey);
if (ret) {
krb5_clear_error_string(context);
@@ -735,10 +762,6 @@ pk_mk_pa_reply_enckey(krb5_context context,
}
ASN1_MALLOC_ENCODE(ReplyKeyPack, buf.data, buf.length, &kp, &size,ret);
free_ReplyKeyPack(&kp);
- break;
- }
- default:
- krb5_abortx(context, "internal pkinit error");
}
if (ret) {
krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack "
@@ -768,7 +791,8 @@ pk_mk_pa_reply_enckey(krb5_context context,
goto out;
ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
- oid_id_pkrkeydata(),
+ 0,
+ sdAlg,
buf.data,
buf.length,
NULL,
@@ -784,9 +808,21 @@ pk_mk_pa_reply_enckey(krb5_context context,
if (ret)
goto out;
+ if (client_params->type == PKINIT_COMPAT_WIN2K) {
+ ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(),
+ &signed_data,
+ &buf);
+ if (ret)
+ goto out;
+ krb5_data_free(&signed_data);
+ signed_data = buf;
+ }
+
ret = hx509_cms_envelope_1(kdc_identity->hx509ctx,
+ 0,
client_params->cert,
- signed_data.data, signed_data.length, NULL,
+ signed_data.data, signed_data.length,
+ envelopedAlg,
oid_id_pkcs7_signedData(), &buf);
if (ret)
goto out;
@@ -881,6 +917,7 @@ pk_mk_pa_reply_dh(krb5_context context,
goto out;
ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
+ 0,
oid_id_pkdhkeydata(),
buf.data,
buf.length,
@@ -1125,6 +1162,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
krb5_data_free(&ocsp.data);
ocsp.expire = 0;
+ ocsp.next_update = kdc_time + 60 * 5;
fd = open(config->pkinit_kdc_ocsp_file, O_RDONLY);
if (fd < 0) {
@@ -1168,11 +1206,13 @@ _kdc_pk_mk_pa_reply(krb5_context context,
"PK-INIT failed to verify ocsp data %d", ret);
krb5_data_free(&ocsp.data);
ocsp.expire = 0;
- } else if (ocsp.expire > 180)
+ } else if (ocsp.expire > 180) {
ocsp.expire -= 180; /* refetch the ocsp before it expire */
-
+ ocsp.next_update = ocsp.expire;
+ } else {
+ ocsp.next_update = kdc_time;
+ }
out_ocsp:
- ocsp.next_update = kdc_time + 3600;
ret = 0;
}
@@ -1199,10 +1239,10 @@ out:
}
static int
-pk_principal_from_X509(krb5_context context,
- krb5_kdc_configuration *config,
- hx509_cert client_cert,
- krb5_const_principal match)
+match_rfc_san(krb5_context context,
+ krb5_kdc_configuration *config,
+ hx509_cert client_cert,
+ krb5_const_principal match)
{
hx509_octet_string_list list;
int ret, i, found = 0;
@@ -1254,6 +1294,68 @@ out:
return 0;
}
+static int
+match_ms_upn_san(krb5_context context,
+ krb5_kdc_configuration *config,
+ hx509_cert client_cert,
+ krb5_const_principal match)
+{
+ hx509_octet_string_list list;
+ krb5_principal principal = NULL;
+ int ret, found = 0;
+ MS_UPN_SAN upn;
+ size_t size;
+
+ memset(&list, 0 , sizeof(list));
+
+ ret = hx509_cert_find_subjectAltName_otherName(client_cert,
+ oid_id_pkinit_ms_san(),
+ &list);
+ if (ret)
+ goto out;
+
+ if (list.len != 1) {
+ kdc_log(context, config, 0,
+ "More then one PK-INIT MS UPN SAN");
+ goto out;
+ }
+
+ ret = decode_MS_UPN_SAN(list.val[0].data, list.val[0].length, &upn, &size);
+ if (ret) {
+ kdc_log(context, config, 0, "Decode of MS-UPN-SAN failed");
+ goto out;
+ }
+
+ kdc_log(context, config, 0, "found MS UPN SAN: %s", upn);
+
+ ret = krb5_parse_name(context, upn, &principal);
+ free_MS_UPN_SAN(&upn);
+ if (ret) {
+ kdc_log(context, config, 0, "Failed to parse principal in MS UPN SAN");
+ goto out;
+ }
+
+ /*
+ * This is very wrong, but will do for now, should really and a
+ * plugin to the windc layer to very this ACL.
+ */
+ strupr(principal->realm);
+
+ if (krb5_principal_compare(context, principal, match) == TRUE)
+ found = 1;
+
+out:
+ if (principal)
+ krb5_free_principal(context, principal);
+ hx509_free_octet_string_list(&list);
+ if (ret)
+ return ret;
+
+ if (!found)
+ return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
+
+ return 0;
+}
krb5_error_code
_kdc_pk_check_client(krb5_context context,
@@ -1283,14 +1385,22 @@ _kdc_pk_check_client(krb5_context context,
*subject_name);
if (config->enable_pkinit_princ_in_cert) {
- ret = pk_principal_from_X509(context, config,
- client_params->cert,
- client->entry.principal);
+ ret = match_rfc_san(context, config,
+ client_params->cert,
+ client->entry.principal);
if (ret == 0) {
kdc_log(context, config, 5,
"Found matching PK-INIT SAN in certificate");
return 0;
}
+ ret = match_ms_upn_san(context, config,
+ client_params->cert,
+ client->entry.principal);
+ if (ret == 0) {
+ kdc_log(context, config, 5,
+ "Found matching MS UPN SAN in certificate");
+ return 0;
+ }
}
ret = hdb_entry_get_pkinit_acl(&client->entry, &acl);
@@ -1330,10 +1440,17 @@ _kdc_pk_check_client(krb5_context context,
return 0;
}
+ krb5_set_error_string(context,
+ "PKINIT no matching principals for %s",
+ *subject_name);
+
+ kdc_log(context, config, 5,
+ "PKINIT no matching principals for %s",
+ *subject_name);
+
free(*subject_name);
*subject_name = NULL;
- krb5_set_error_string(context, "PKINIT no matching principals");
return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
}
@@ -1396,7 +1513,56 @@ _kdc_add_inital_verified_cas(krb5_context context,
return ret;
}
+/*
+ *
+ */
+static void
+load_mappings(krb5_context context, const char *fn)
+{
+ krb5_error_code ret;
+ char buf[1024];
+ unsigned long lineno = 0;
+ FILE *f;
+
+ f = fopen(fn, "r");
+ if (f == NULL)
+ return;
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *subject_name, *p;
+
+ buf[strcspn(buf, "\n")] = '\0';
+ lineno++;
+
+ p = buf + strspn(buf, " \t");
+
+ if (*p == '#' || *p == '\0')
+ continue;
+
+ subject_name = strchr(p, ':');
+ if (subject_name == NULL) {
+ krb5_warnx(context, "pkinit mapping file line %lu "
+ "missing \":\" :%s",
+ lineno, buf);
+ continue;
+ }
+ *subject_name++ = '\0';
+
+ ret = add_principal_mapping(context, p, subject_name);
+ if (ret) {
+ krb5_warn(context, ret, "failed to add line %lu \":\" :%s\n",
+ lineno, buf);
+ continue;
+ }
+ }
+
+ fclose(f);
+}
+
+/*
+ *
+ */
krb5_error_code
_kdc_pk_initialize(krb5_context context,
@@ -1408,9 +1574,6 @@ _kdc_pk_initialize(krb5_context context,
{
const char *file;
krb5_error_code ret;
- char buf[1024];
- unsigned long lineno = 0;
- FILE *f;
file = krb5_config_get_string(context, NULL,
"libdefaults", "moduli", NULL);
@@ -1481,41 +1644,8 @@ _kdc_pk_initialize(krb5_context context,
"kdc",
"pkinit_mappings_file",
NULL);
- f = fopen(file, "r");
- if (f == NULL) {
- krb5_warnx(context, "PKINIT: failed to load mappings file %s", file);
- return 0;
- }
-
- while (fgets(buf, sizeof(buf), f) != NULL) {
- char *subject_name, *p;
-
- buf[strcspn(buf, "\n")] = '\0';
- lineno++;
-
- p = buf + strspn(buf, " \t");
-
- if (*p == '#' || *p == '\0')
- continue;
- subject_name = strchr(p, ':');
- if (subject_name == NULL) {
- krb5_warnx(context, "pkinit mapping file line %lu "
- "missing \":\" :%s",
- lineno, buf);
- continue;
- }
- *subject_name++ = '\0';
-
- ret = add_principal_mapping(context, p, subject_name);
- if (ret) {
- krb5_warn(context, ret, "failed to add line %lu \":\" :%s\n",
- lineno, buf);
- continue;
- }
- }
-
- fclose(f);
+ load_mappings(context, file);
return 0;
}
diff --git a/source4/heimdal/kdc/process.c b/source4/heimdal/kdc/process.c
index a64efaa05d..1d0a01a215 100644
--- a/source4/heimdal/kdc/process.c
+++ b/source4/heimdal/kdc/process.c
@@ -34,7 +34,20 @@
#include "kdc_locl.h"
-RCSID("$Id: process.c,v 1.7 2006/12/28 21:09:35 lha Exp $");
+RCSID("$Id: process.c 20959 2007-06-07 04:46:06Z lha $");
+
+/*
+ *
+ */
+
+void
+krb5_kdc_update_time(struct timeval *tv)
+{
+ if (tv == NULL)
+ gettimeofday(&_kdc_now, NULL);
+ else
+ _kdc_now = *tv;
+}
/*
* handle the request in `buf, len', from `addr' (or `from' as a string),
@@ -59,7 +72,6 @@ krb5_kdc_process_request(krb5_context context,
krb5_error_code ret;
size_t i;
- gettimeofday(&_kdc_now, NULL);
if(decode_AS_REQ(buf, len, &req, &i) == 0){
krb5_data req_buffer;
@@ -121,7 +133,6 @@ krb5_kdc_process_krb5_request(krb5_context context,
krb5_error_code ret;
size_t i;
- gettimeofday(&_kdc_now, NULL);
if(decode_AS_REQ(buf, len, &req, &i) == 0){
krb5_data req_buffer;
@@ -139,3 +150,70 @@ krb5_kdc_process_krb5_request(krb5_context context,
}
return -1;
}
+
+/*
+ *
+ */
+
+int
+krb5_kdc_save_request(krb5_context context,
+ const char *fn,
+ const unsigned char *buf,
+ size_t len,
+ const krb5_data *reply,
+ const struct sockaddr *sa)
+{
+ krb5_storage *sp;
+ krb5_address a;
+ int fd, ret;
+ uint32_t t;
+ krb5_data d;
+
+ memset(&a, 0, sizeof(a));
+
+ d.data = rk_UNCONST(buf);
+ d.length = len;
+ t = _kdc_now.tv_sec;
+
+ 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;
+ }
+
+ sp = krb5_storage_from_fd(fd);
+ close(fd);
+ if (sp == NULL) {
+ krb5_set_error_string(context, "Storage failed to open fd");
+ return ENOMEM;
+ }
+
+ ret = krb5_sockaddr2address(context, sa, &a);
+ if (ret)
+ goto out;
+
+ krb5_store_uint32(sp, 1);
+ krb5_store_uint32(sp, t);
+ krb5_store_address(sp, a);
+ krb5_store_data(sp, d);
+ {
+ Der_class cl;
+ Der_type ty;
+ unsigned int tag;
+ ret = der_get_tag (reply->data, reply->length,
+ &cl, &ty, &tag, NULL);
+ if (ret) {
+ krb5_store_uint32(sp, 0xffffffff);
+ krb5_store_uint32(sp, 0xffffffff);
+ } else {
+ krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
+ krb5_store_uint32(sp, tag);
+ }
+ }
+
+ krb5_free_address(context, &a);
+out:
+ krb5_storage_free(sp);
+
+ return 0;
+}
diff --git a/source4/heimdal/kdc/rx.h b/source4/heimdal/kdc/rx.h
index 370e33732f..18806d79da 100644
--- a/source4/heimdal/kdc/rx.h
+++ b/source4/heimdal/kdc/rx.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: rx.h,v 1.5 2006/05/05 10:51:10 lha Exp $ */
+/* $Id: rx.h 17447 2006-05-05 10:52:01Z lha $ */
#ifndef __RX_H__
#define __RX_H__
diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c
index 41e4ad1bbc..395ab73432 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,v 1.3 2007/01/04 11:10:06 lha Exp $");
+RCSID("$Id: windc.c 20559 2007-04-24 16:00:07Z lha $");
static krb5plugin_windc_ftable *windcft;
static void *windcctx;
@@ -43,7 +43,7 @@ static void *windcctx;
*/
krb5_error_code
-_kdc_windc_init(krb5_context context)
+krb5_kdc_windc_init(krb5_context context)
{
struct krb5_plugin *list = NULL, *e;
krb5_error_code ret;
@@ -91,10 +91,11 @@ _kdc_pac_verify(krb5_context context,
krb5_pac *pac)
{
if (windcft == NULL) {
- krb5_set_error_string(context, "Can't verify WINDC, no function");
+ krb5_set_error_string(context, "Can't verify PAC, no function");
return EINVAL;
}
- return (windcft->pac_verify)(windcctx, context, client_principal, client, server, pac);
+ return (windcft->pac_verify)(windcctx, context,
+ client_principal, client, server, pac);
}
krb5_error_code
diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h
index a3b7534480..ec480cf950 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,v 1.2 2007/01/04 11:13:51 lha Exp $ */
+/* $Id: windc_plugin.h 19798 2007-01-10 15:24:51Z lha $ */
#ifndef HEIMDAL_KRB5_PAC_PLUGIN_H
#define HEIMDAL_KRB5_PAC_PLUGIN_H 1
@@ -58,7 +58,9 @@ typedef krb5_error_code
typedef krb5_error_code
(*krb5plugin_windc_pac_verify)(void *, krb5_context,
const krb5_principal,
- struct hdb_entry_ex *, struct hdb_entry_ex *, krb5_pac *);
+ struct hdb_entry_ex *,
+ struct hdb_entry_ex *,
+ krb5_pac *);
typedef krb5_error_code
(*krb5plugin_windc_client_access)(