summaryrefslogtreecommitdiff
path: root/source4/heimdal
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal')
-rw-r--r--source4/heimdal/kdc/default_config.c19
-rw-r--r--source4/heimdal/kdc/digest.c140
-rw-r--r--source4/heimdal/kdc/kdc-protos.h7
-rw-r--r--source4/heimdal/kdc/kdc.h8
-rw-r--r--source4/heimdal/kdc/krb5tgs.c32
-rw-r--r--source4/heimdal/kdc/misc.c11
-rwxr-xr-xsource4/heimdal/kdc/pkinit.c16
-rw-r--r--source4/heimdal/lib/asn1/k5.asn13
-rw-r--r--source4/heimdal/lib/asn1/lex.c33
-rw-r--r--source4/heimdal/lib/asn1/pkinit.asn14
-rw-r--r--source4/heimdal/lib/com_err/lex.c33
-rw-r--r--source4/heimdal/lib/gssapi/krb5/acquire_cred.c4
-rw-r--r--source4/heimdal/lib/gssapi/krb5/display_name.c5
-rw-r--r--source4/heimdal/lib/gssapi/krb5/prf.c3
-rw-r--r--source4/heimdal/lib/gssapi/krb5/release_name.c5
-rw-r--r--source4/heimdal/lib/gssapi/mech/context.c6
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c10
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_display_name.c7
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_display_status.c8
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c39
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_inquire_context.c11
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c14
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_krb5.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c6
-rw-r--r--source4/heimdal/lib/gssapi/spnego/accept_sec_context.c135
-rw-r--r--source4/heimdal/lib/hcrypto/pkcs12.c7
-rw-r--r--source4/heimdal/lib/hcrypto/rand-egd.c4
-rw-r--r--source4/heimdal/lib/hcrypto/rand-fortuna.c38
-rw-r--r--source4/heimdal/lib/hcrypto/rand-timer.c206
-rw-r--r--source4/heimdal/lib/hcrypto/rand.c8
-rw-r--r--source4/heimdal/lib/hcrypto/randi.h5
-rw-r--r--source4/heimdal/lib/hcrypto/rsa-imath.c3
-rw-r--r--source4/heimdal/lib/hdb/ext.c12
-rw-r--r--source4/heimdal/lib/hx509/cert.c186
-rw-r--r--source4/heimdal/lib/hx509/cms.c79
-rw-r--r--source4/heimdal/lib/hx509/crypto.c66
-rw-r--r--source4/heimdal/lib/hx509/file.c240
-rw-r--r--source4/heimdal/lib/hx509/hx509-private.h42
-rw-r--r--source4/heimdal/lib/hx509/hx509-protos.h57
-rw-r--r--source4/heimdal/lib/hx509/hx509.h19
-rw-r--r--source4/heimdal/lib/hx509/hx_locl.h6
-rw-r--r--source4/heimdal/lib/hx509/keyset.c23
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c418
-rw-r--r--source4/heimdal/lib/hx509/ks_keychain.c129
-rw-r--r--source4/heimdal/lib/hx509/ks_p11.c15
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c16
-rw-r--r--source4/heimdal/lib/hx509/req.c110
-rw-r--r--source4/heimdal/lib/hx509/revoke.c19
-rw-r--r--source4/heimdal/lib/krb5/crypto.c7
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c89
-rw-r--r--source4/heimdal/lib/krb5/init_creds_pw.c28
-rw-r--r--source4/heimdal/lib/krb5/krb5-private.h8
-rw-r--r--source4/heimdal/lib/krb5/krb5-protos.h53
-rw-r--r--source4/heimdal/lib/krb5/krb5.h14
-rw-r--r--source4/heimdal/lib/krb5/krb5_err.et8
-rw-r--r--source4/heimdal/lib/krb5/krbhst.c6
-rw-r--r--source4/heimdal/lib/krb5/misc.c3
-rw-r--r--source4/heimdal/lib/krb5/pac.c4
-rwxr-xr-xsource4/heimdal/lib/krb5/pkinit.c203
-rw-r--r--source4/heimdal/lib/krb5/plugin.c3
-rw-r--r--source4/heimdal/lib/krb5/principal.c49
-rw-r--r--source4/heimdal/lib/krb5/rd_error.c4
-rw-r--r--source4/heimdal/lib/krb5/send_to_kdc.c177
-rw-r--r--source4/heimdal/lib/ntlm/heimntlm-protos.h8
-rw-r--r--source4/heimdal/lib/ntlm/ntlm.c111
-rw-r--r--source4/heimdal/lib/roken/roken_gethostby.c4
66 files changed, 2166 insertions, 884 deletions
diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c
index c28bd424ea..e06366f214 100644
--- a/source4/heimdal/kdc/default_config.c
+++ b/source4/heimdal/kdc/default_config.c
@@ -36,10 +36,9 @@
#include <getarg.h>
#include <parse_bytes.h>
-RCSID("$Id: default_config.c 20532 2007-04-23 07:46:57Z lha $");
+RCSID("$Id: default_config.c 21296 2007-06-25 14:49:11Z lha $");
-
-int
+krb5_error_code
krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
{
krb5_kdc_configuration *c;
@@ -62,7 +61,8 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
c->enable_524 = FALSE;
c->enable_v4_cross_realm = FALSE;
c->enable_pkinit = FALSE;
- c->enable_pkinit_princ_in_cert = TRUE;
+ c->pkinit_princ_in_cert = TRUE;
+ c->pkinit_require_binding = TRUE;
c->db = NULL;
c->num_db = 0;
c->logf = NULL;
@@ -257,12 +257,19 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
krb5_config_free_strings(pool_list);
krb5_config_free_strings(revoke_list);
- c->enable_pkinit_princ_in_cert =
+ c->pkinit_princ_in_cert =
krb5_config_get_bool_default(context, NULL,
- c->enable_pkinit_princ_in_cert,
+ c->pkinit_princ_in_cert,
"kdc",
"pkinit_principal_in_certificate",
NULL);
+
+ c->pkinit_require_binding =
+ krb5_config_get_bool_default(context, NULL,
+ c->pkinit_require_binding,
+ "kdc",
+ "pkinit_win2k_require_binding",
+ NULL);
}
c->pkinit_dh_min_bits =
diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c
index 811ab639f1..801449fe5e 100644
--- a/source4/heimdal/kdc/digest.c
+++ b/source4/heimdal/kdc/digest.c
@@ -34,7 +34,7 @@
#include "kdc_locl.h"
#include <hex.h>
-RCSID("$Id: digest.c 20877 2007-06-04 04:07:26Z lha $");
+RCSID("$Id: digest.c 21241 2007-06-20 11:30:19Z lha $");
#define MS_CHAP_V2 0x20
#define CHAP_MD5 0x10
@@ -160,6 +160,44 @@ static const unsigned char ms_rfc3079_magic1[27] = {
*
*/
+static krb5_error_code
+get_password_entry(krb5_context context,
+ krb5_kdc_configuration *config,
+ const char *username,
+ char **password)
+{
+ krb5_principal clientprincipal;
+ krb5_error_code ret;
+ hdb_entry_ex *user;
+ HDB *db;
+
+ /* get username */
+ ret = krb5_parse_name(context, username, &clientprincipal);
+ if (ret)
+ return ret;
+
+ ret = _kdc_db_fetch(context, config, clientprincipal,
+ HDB_F_GET_CLIENT, &db, &user);
+ krb5_free_principal(context, clientprincipal);
+ if (ret)
+ return ret;
+
+ ret = hdb_entry_get_password(context, db, &user->entry, password);
+ if (ret || password == NULL) {
+ if (ret == 0) {
+ ret = EINVAL;
+ krb5_set_error_string(context, "password missing");
+ }
+ memset(user, 0, sizeof(*user));
+ }
+ _kdc_free_ent (context, user);
+ return ret;
+}
+
+/*
+ *
+ */
+
krb5_error_code
_kdc_do_digest(krb5_context context,
krb5_kdc_configuration *config,
@@ -461,9 +499,6 @@ _kdc_do_digest(krb5_context context,
break;
}
case choice_DigestReqInner_digestRequest: {
- krb5_principal clientprincipal;
- HDB *db;
-
sp = krb5_storage_emem();
if (sp == NULL) {
ret = ENOMEM;
@@ -571,29 +606,6 @@ _kdc_do_digest(krb5_context context,
}
}
- /* get username */
- ret = krb5_parse_name(context,
- ireq.u.digestRequest.username,
- &clientprincipal);
- if (ret)
- goto out;
-
- ret = _kdc_db_fetch(context, config, clientprincipal,
- HDB_F_GET_CLIENT, &db, &user);
-
- krb5_free_principal(context, clientprincipal);
- if (ret)
- goto out;
-
- ret = hdb_entry_get_password(context, db, &user->entry, &password);
- if (ret || password == NULL) {
- if (ret == 0) {
- ret = EINVAL;
- krb5_set_error_string(context, "password missing");
- }
- goto out;
- }
-
if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) {
MD5_CTX ctx;
unsigned char md[MD5_DIGEST_LENGTH];
@@ -618,6 +630,12 @@ _kdc_do_digest(krb5_context context,
goto out;
}
+ ret = get_password_entry(context, config,
+ ireq.u.digestRequest.username,
+ &password);
+ if (ret)
+ goto out;
+
MD5_Init(&ctx);
MD5_Update(&ctx, &id, 1);
MD5_Update(&ctx, password, strlen(password));
@@ -664,6 +682,12 @@ _kdc_do_digest(krb5_context context,
if (ireq.u.digestRequest.realm == NULL)
goto out;
+ ret = get_password_entry(context, config,
+ ireq.u.digestRequest.username,
+ &password);
+ if (ret)
+ goto failed;
+
MD5_Init(&ctx);
MD5_Update(&ctx, ireq.u.digestRequest.username,
strlen(ireq.u.digestRequest.username));
@@ -692,7 +716,7 @@ _kdc_do_digest(krb5_context context,
if (A1 == NULL) {
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
- goto out;
+ goto failed;
}
MD5_Init(&ctx);
@@ -712,7 +736,7 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
free(A1);
- goto out;
+ goto failed;
}
MD5_Init(&ctx);
@@ -758,6 +782,7 @@ _kdc_do_digest(krb5_context context,
} else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {
unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
+ krb5_principal clientprincipal = NULL;
char *mdx;
const char *username;
struct ntlm_buf answer;
@@ -766,20 +791,20 @@ _kdc_do_digest(krb5_context context,
if ((config->digests_allowed & MS_CHAP_V2) == 0) {
kdc_log(context, config, 0, "MS-CHAP-V2 not allowed");
- goto out;
+ goto failed;
}
if (ireq.u.digestRequest.clientNonce == NULL) {
krb5_set_error_string(context,
"MS-CHAP-V2 clientNonce missing");
ret = EINVAL;
- goto out;
+ goto failed;
}
if (serverNonce.length != 16) {
krb5_set_error_string(context,
"MS-CHAP-V2 serverNonce wrong length");
ret = EINVAL;
- goto out;
+ goto failed;
}
/* strip of the domain component */
@@ -821,7 +846,7 @@ _kdc_do_digest(krb5_context context,
/* NtPasswordHash */
ret = krb5_parse_name(context, username, &clientprincipal);
if (ret)
- goto out;
+ goto failed;
ret = _kdc_db_fetch(context, config, clientprincipal,
HDB_F_GET_CLIENT, NULL, &user);
@@ -830,7 +855,7 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_string(context,
"MS-CHAP-V2 user %s not in database",
username);
- goto out;
+ goto failed;
}
ret = hdb_enctype2key(context, &user->entry,
@@ -839,7 +864,7 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_string(context,
"MS-CHAP-V2 missing arcfour key %s",
username);
- goto out;
+ goto failed;
}
/* ChallengeResponse */
@@ -848,7 +873,7 @@ _kdc_do_digest(krb5_context context,
challange, &answer);
if (ret) {
krb5_set_error_string(context, "NTLM missing arcfour key");
- goto out;
+ goto failed;
}
hex_encode(answer.data, answer.length, &mdx);
@@ -861,15 +886,15 @@ _kdc_do_digest(krb5_context context,
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",
+ "MS-CHAP-V2 hash mismatch for %s",
ireq.u.digestRequest.username);
r.u.response.success = FALSE;
}
+ free(mdx);
if (r.u.response.success) {
unsigned char hashhash[MD4_DIGEST_LENGTH];
@@ -958,7 +983,7 @@ _kdc_do_digest(krb5_context context,
if ((config->digests_allowed & (NTLM_V1|NTLM_V1_SESSION|NTLM_V2)) == 0) {
kdc_log(context, config, 0, "NTLM not allowed");
- goto out;
+ goto failed;
}
r.element = choice_DigestRepInner_ntlmInitReply;
@@ -967,14 +992,14 @@ _kdc_do_digest(krb5_context context,
if ((ireq.u.ntlmInit.flags & NTLM_NEG_UNICODE) == 0) {
kdc_log(context, config, 0, "NTLM client have no unicode");
- goto out;
+ goto failed;
}
if (ireq.u.ntlmInit.flags & NTLM_NEG_NTLM)
r.u.ntlmInitReply.flags |= NTLM_NEG_NTLM;
else {
kdc_log(context, config, 0, "NTLM client doesn't support NTLM");
- goto out;
+ goto failed;
}
r.u.ntlmInitReply.flags |=
@@ -1095,7 +1120,7 @@ _kdc_do_digest(krb5_context context,
ireq.u.ntlmRequest.username,
&clientprincipal);
if (ret)
- goto out;
+ goto failed;
ret = _kdc_db_fetch(context, config, clientprincipal,
HDB_F_GET_CLIENT, NULL, &user);
@@ -1103,20 +1128,23 @@ _kdc_do_digest(krb5_context context,
if (ret) {
krb5_set_error_string(context, "NTLM user %s not in database",
ireq.u.ntlmRequest.username);
- goto out;
+ goto failed;
}
ret = get_digest_key(context, config, server, &crypto);
if (ret)
- goto out;
+ goto failed;
ret = krb5_decrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE,
ireq.u.ntlmRequest.opaque.data,
ireq.u.ntlmRequest.opaque.length, &buf);
krb5_crypto_destroy(context, crypto);
crypto = NULL;
- if (ret)
- goto out;
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Failed to decrypt nonce from %s", from);
+ goto failed;
+ }
sp = krb5_storage_from_data(&buf);
if (sp == NULL) {
@@ -1185,7 +1213,7 @@ _kdc_do_digest(krb5_context context,
free(targetname);
if (ret) {
krb5_set_error_string(context, "NTLM v2 verify failed");
- goto out;
+ goto failed;
}
/* XXX verify infotarget matches client (checksum ?) */
@@ -1205,14 +1233,14 @@ _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;
+ goto failed;
}
if (ireq.u.ntlmRequest.lm.length != 24) {
krb5_set_error_string(context, "LM hash have wrong length "
"for NTLM session key");
ret = EINVAL;
- goto out;
+ goto failed;
}
MD5_Init(&md5ctx);
@@ -1223,7 +1251,7 @@ _kdc_do_digest(krb5_context context,
} else {
if ((config->digests_allowed & NTLM_V1) == 0) {
kdc_log(context, config, 0, "NTLM v1 not allowed");
- goto out;
+ goto failed;
}
}
@@ -1232,7 +1260,7 @@ _kdc_do_digest(krb5_context context,
challange, &answer);
if (ret) {
krb5_set_error_string(context, "NTLM missing arcfour key");
- goto out;
+ goto failed;
}
if (ireq.u.ntlmRequest.ntlm.length != answer.length ||
@@ -1241,7 +1269,7 @@ _kdc_do_digest(krb5_context context,
free(answer.data);
ret = EINVAL;
krb5_set_error_string(context, "NTLM hash mismatch");
- goto out;
+ goto failed;
}
free(answer.data);
@@ -1265,7 +1293,7 @@ _kdc_do_digest(krb5_context context,
"NTLM client failed to neg key "
"exchange but still sent key");
ret = EINVAL;
- goto out;
+ goto failed;
}
len = ireq.u.ntlmRequest.sessionkey->length;
@@ -1273,7 +1301,7 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_string(context,
"NTLM master key wrong length: %lu",
(unsigned long)len);
- goto out;
+ goto failed;
}
RC4_set_key(&rc4, sizeof(sessionkey), sessionkey);
@@ -1301,12 +1329,12 @@ _kdc_do_digest(krb5_context context,
r.u.ntlmResponse.success = 1;
kdc_log(context, config, 0, "NTLM version %d successful for %s",
version, ireq.u.ntlmRequest.username);
-
break;
}
default:
+ failed:
r.element = choice_DigestRepInner_error;
- r.u.error.reason = strdup("unknown operation");
+ r.u.error.reason = strdup("unknown/failed operation");
if (r.u.error.reason == NULL) {
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
diff --git a/source4/heimdal/kdc/kdc-protos.h b/source4/heimdal/kdc/kdc-protos.h
index f7df365eb2..15e8c29f4c 100644
--- a/source4/heimdal/kdc/kdc-protos.h
+++ b/source4/heimdal/kdc/kdc-protos.h
@@ -37,7 +37,7 @@ kdc_openlog (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/);
-int
+krb5_error_code
krb5_kdc_get_config (
krb5_context /*context*/,
krb5_kdc_configuration **/*config*/);
@@ -74,6 +74,11 @@ krb5_kdc_save_request (
const krb5_data */*reply*/,
const struct sockaddr */*sa*/);
+krb5_error_code
+krb5_kdc_set_dbinfo (
+ krb5_context /*context*/,
+ struct krb5_kdc_configuration */*c*/);
+
void
krb5_kdc_update_time (struct timeval */*tv*/);
diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h
index eb24b4ee97..6c129f38f5 100644
--- a/source4/heimdal/kdc/kdc.h
+++ b/source4/heimdal/kdc/kdc.h
@@ -35,7 +35,7 @@
*/
/*
- * $Id: kdc.h 19907 2007-01-14 23:10:24Z lha $
+ * $Id: kdc.h 21287 2007-06-25 14:09:03Z lha $
*/
#ifndef __KDC_H__
@@ -73,13 +73,13 @@ typedef struct krb5_kdc_configuration {
krb5_boolean enable_524;
krb5_boolean enable_pkinit;
- krb5_boolean enable_pkinit_princ_in_cert;
+ krb5_boolean pkinit_princ_in_cert;
char *pkinit_kdc_ocsp_file;
+ int pkinit_dh_min_bits;
+ int pkinit_require_binding;
krb5_log_facility *logf;
- int pkinit_dh_min_bits;
-
int enable_digest;
int digests_allowed;
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index 02cd92de2e..4d6be60f68 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: krb5tgs.c 21041 2007-06-10 06:21:12Z lha $");
+RCSID("$Id: krb5tgs.c 21262 2007-06-21 15:18:37Z lha $");
/*
* return the realm of a krbtgt-ticket or NULL
@@ -475,12 +475,14 @@ check_tgs_flags(krb5_context context,
et->endtime = min(*et->renew_till, et->endtime);
}
+#if 0
/* checks for excess flags */
if(f.request_anonymous && !config->allow_anonymous){
kdc_log(context, config, 0,
"Request for anonymous ticket");
return KRB5KDC_ERR_BADOPTION;
}
+#endif
return 0;
}
@@ -731,10 +733,12 @@ tgs_make_reply(krb5_context context,
&rep.ticket.realm);
_krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
copy_Realm(&tgt_name->realm, &rep.crealm);
+/*
if (f.request_anonymous)
_kdc_make_anonymous_principalname (&rep.cname);
- else
- copy_PrincipalName(&tgt_name->name, &rep.cname);
+ else */
+
+ copy_PrincipalName(&tgt_name->name, &rep.cname);
rep.ticket.tkt_vno = 5;
ek.caddr = et.caddr;
@@ -1707,24 +1711,20 @@ server_lookup:
goto out;
}
- /* check PAC if there is one */
- {
+ /* check PAC if not cross realm and if there is one */
+ if (!cross_realm) {
Key *tkey;
- krb5_keyblock *tgtkey = NULL;
- 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 = hdb_enctype2key(context, &krbtgt->entry,
+ krbtgt_etype, &tkey);
+ if(ret) {
+ kdc_log(context, config, 0,
+ "Failed to find key for krbtgt PAC check");
+ goto out;
}
ret = check_PAC(context, config, client_principal,
- client, server, ekey, tgtkey,
+ client, server, ekey, &tkey->key,
tgt, &rspac, &require_signedpath);
if (ret) {
kdc_log(context, config, 0,
diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c
index ebf2873599..072df44042 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 17951 2006-08-28 14:41:49Z lha $");
+RCSID("$Id: misc.c 21106 2007-06-18 10:18:11Z lha $");
struct timeval _kdc_now;
@@ -46,12 +46,14 @@ _kdc_db_fetch(krb5_context context,
hdb_entry_ex **h)
{
hdb_entry_ex *ent;
- krb5_error_code ret = HDB_ERR_NOENTRY;
+ krb5_error_code ret;
int i;
ent = calloc (1, sizeof (*ent));
- if (ent == NULL)
+ if (ent == NULL) {
+ krb5_set_error_string(context, "out of memory");
return ENOMEM;
+ }
for(i = 0; i < config->num_db; i++) {
ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
@@ -74,7 +76,8 @@ _kdc_db_fetch(krb5_context context,
}
}
free(ent);
- return ret;
+ krb5_set_error_string(context, "no such entry found in hdb");
+ return HDB_ERR_NOENTRY;
}
void
diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c
index bf62f879db..ead961022d 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 21039 2007-06-10 06:20:31Z lha $");
+RCSID("$Id: pkinit.c 21290 2007-06-25 14:13:23Z lha $");
#ifdef PKINIT
@@ -380,6 +380,7 @@ _kdc_pk_rd_padata(krb5_context context,
*ret_params = NULL;
if (!config->enable_pkinit) {
+ kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled");
krb5_clear_error_string(context);
return 0;
}
@@ -676,6 +677,7 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
static krb5_error_code
pk_mk_pa_reply_enckey(krb5_context context,
+ krb5_kdc_configuration *config,
pk_client_params *client_params,
const KDC_REQ *req,
const krb5_data *req_buffer,
@@ -700,8 +702,11 @@ pk_mk_pa_reply_enckey(krb5_context context,
switch (client_params->type) {
case PKINIT_COMPAT_WIN2K: {
int i = 0;
- if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL)
+ if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL
+ && config->pkinit_require_binding == 0)
+ {
do_win2k = 1;
+ }
break;
}
case PKINIT_COMPAT_27:
@@ -1015,6 +1020,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
goto out;
}
ret = pk_mk_pa_reply_enckey(context,
+ config,
client_params,
req,
req_buffer,
@@ -1110,6 +1116,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
goto out;
}
ret = pk_mk_pa_reply_enckey(context,
+ config,
client_params,
req,
req_buffer,
@@ -1384,7 +1391,7 @@ _kdc_pk_check_client(krb5_context context,
"Trying to authorize PK-INIT subject DN %s",
*subject_name);
- if (config->enable_pkinit_princ_in_cert) {
+ if (config->pkinit_princ_in_cert) {
ret = match_rfc_san(context, config,
client_params->cert,
client->entry.principal);
@@ -1508,7 +1515,8 @@ _kdc_add_inital_verified_cas(krb5_context context,
krb5_abortx(context, "internal asn.1 encoder error");
ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
- ad_initial_verified_cas, &data);
+ KRB5_AUTHDATA_INITIAL_VERIFIED_CAS,
+ &data);
krb5_data_free(&data);
return ret;
}
diff --git a/source4/heimdal/lib/asn1/k5.asn1 b/source4/heimdal/lib/asn1/k5.asn1
index 0c7021f87f..14e9793fdc 100644
--- a/source4/heimdal/lib/asn1/k5.asn1
+++ b/source4/heimdal/lib/asn1/k5.asn1
@@ -1,4 +1,4 @@
--- $Id: k5.asn1 21004 2007-06-08 01:53:10Z lha $
+-- $Id: k5.asn1 21092 2007-06-15 19:47:46Z lha $
KERBEROS5 DEFINITIONS ::=
BEGIN
@@ -88,6 +88,7 @@ AUTHDATA-TYPE ::= INTEGER {
KRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6),
KRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7),
KRB5-AUTHDATA-MANDATORY-FOR-KDC(8),
+ KRB5-AUTHDATA-INITIAL-VERIFIED-CAS(9),
KRB5-AUTHDATA-OSF-DCE(64),
KRB5-AUTHDATA-SESAME(65),
KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66),
diff --git a/source4/heimdal/lib/asn1/lex.c b/source4/heimdal/lib/asn1/lex.c
index fe488eb904..d628e4696f 100644
--- a/source4/heimdal/lib/asn1/lex.c
+++ b/source4/heimdal/lib/asn1/lex.c
@@ -1,6 +1,5 @@
-#include "config.h"
-#line 3 "lex.yy.c"
+#line 3 "lex.c"
#define YY_INT_ALIGNED short int
@@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
typedef int yy_state_type;
extern int yylineno;
+
+int yylineno = 1;
+
extern char *yytext;
#define yytext_ptr yytext
@@ -824,7 +826,7 @@ char *yytext;
* SUCH DAMAGE.
*/
-/* $Id: lex.l,v 1.31 2006/10/21 11:57:22 lha Exp $ */
+/* $Id: lex.l 18738 2006-10-21 11:57:22Z lha $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -849,7 +851,7 @@ static unsigned lineno = 1;
static void unterminated(const char *, unsigned);
/* This is for broken old lexes (solaris 10 and hpux) */
-#line 852 "lex.yy.c"
+#line 855 "lex.c"
#define INITIAL 0
@@ -1004,7 +1006,7 @@ YY_DECL
#line 68 "lex.l"
-#line 1007 "lex.yy.c"
+#line 1010 "lex.c"
if ( !(yy_init) )
{
@@ -1673,7 +1675,7 @@ YY_RULE_SETUP
#line 274 "lex.l"
ECHO;
YY_BREAK
-#line 1676 "lex.yy.c"
+#line 1679 "lex.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -2483,6 +2485,15 @@ static void yy_fatal_error (yyconst char* msg )
/* Accessor methods (get/set functions) to struct members. */
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
/** Get the input stream.
*
*/
@@ -2516,6 +2527,16 @@ char *yyget_text (void)
return yytext;
}
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
+
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
diff --git a/source4/heimdal/lib/asn1/pkinit.asn1 b/source4/heimdal/lib/asn1/pkinit.asn1
index e89a7217af..1bfc11ad74 100644
--- a/source4/heimdal/lib/asn1/pkinit.asn1
+++ b/source4/heimdal/lib/asn1/pkinit.asn1
@@ -34,8 +34,6 @@ MS-UPN-SAN ::= UTF8String
pa-pk-as-req INTEGER ::= 16
pa-pk-as-rep INTEGER ::= 17
-ad-initial-verified-cas INTEGER ::= 9
-
td-trusted-certifiers INTEGER ::= 104
td-invalid-certificates INTEGER ::= 105
td-dh-parameters INTEGER ::= 109
@@ -160,7 +158,7 @@ KDCDHKeyInfo-Win2k ::= SEQUENCE {
ReplyKeyPack-Win2k ::= SEQUENCE {
replyKey [0] EncryptionKey,
- nonce [1] INTEGER (0..4294967295),
+ nonce [1] INTEGER (-2147483648..2147483647),
...
}
diff --git a/source4/heimdal/lib/com_err/lex.c b/source4/heimdal/lib/com_err/lex.c
index 83f1f309a4..c5af2ead5c 100644
--- a/source4/heimdal/lib/com_err/lex.c
+++ b/source4/heimdal/lib/com_err/lex.c
@@ -1,6 +1,5 @@
-#include "config.h"
-#line 3 "lex.yy.c"
+#line 3 "lex.c"
#define YY_INT_ALIGNED short int
@@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
typedef int yy_state_type;
extern int yylineno;
+
+int yylineno = 1;
+
extern char *yytext;
#define yytext_ptr yytext
@@ -521,7 +523,7 @@ char *yytext;
#include "parse.h"
#include "lex.h"
-RCSID("$Id: lex.l,v 1.8 2005/05/16 08:52:54 lha Exp $");
+RCSID("$Id: lex.l 15143 2005-05-16 08:52:54Z lha $");
static unsigned lineno = 1;
static int getstring(void);
@@ -530,7 +532,7 @@ static int getstring(void);
#undef ECHO
-#line 533 "lex.yy.c"
+#line 536 "lex.c"
#define INITIAL 0
@@ -685,7 +687,7 @@ YY_DECL
#line 59 "lex.l"
-#line 688 "lex.yy.c"
+#line 691 "lex.c"
if ( !(yy_init) )
{
@@ -849,7 +851,7 @@ YY_RULE_SETUP
#line 75 "lex.l"
ECHO;
YY_BREAK
-#line 852 "lex.yy.c"
+#line 855 "lex.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1659,6 +1661,15 @@ static void yy_fatal_error (yyconst char* msg )
/* Accessor methods (get/set functions) to struct members. */
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
/** Get the input stream.
*
*/
@@ -1692,6 +1703,16 @@ char *yyget_text (void)
return yytext;
}
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
+
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
index 42b57cdadd..d5c70636bc 100644
--- a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
+++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
@@ -33,7 +33,7 @@
#include "krb5/gsskrb5_locl.h"
-RCSID("$Id: acquire_cred.c 20688 2007-05-17 18:44:31Z lha $");
+RCSID("$Id: acquire_cred.c 21221 2007-06-20 08:42:10Z lha $");
OM_uint32
__gsskrb5_ccache_lifetime(OM_uint32 *minor_status,
@@ -256,8 +256,8 @@ static OM_uint32 acquire_acceptor_cred
if (kret)
goto end;
krb5_kt_free_entry(context, &entry);
+ ret = GSS_S_COMPLETE;
}
- ret = GSS_S_COMPLETE;
end:
if (ret != GSS_S_COMPLETE) {
diff --git a/source4/heimdal/lib/gssapi/krb5/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c
index 93fac8d67b..727c447d2a 100644
--- a/source4/heimdal/lib/gssapi/krb5/display_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/display_name.c
@@ -33,7 +33,7 @@
#include "krb5/gsskrb5_locl.h"
-RCSID("$Id: display_name.c 19031 2006-11-13 18:02:57Z lha $");
+RCSID("$Id: display_name.c 21077 2007-06-12 22:42:56Z lha $");
OM_uint32 _gsskrb5_display_name
(OM_uint32 * minor_status,
@@ -50,7 +50,8 @@ OM_uint32 _gsskrb5_display_name
GSSAPI_KRB5_INIT (&context);
- kret = krb5_unparse_name (context, name, &buf);
+ kret = krb5_unparse_name_flags (context, name,
+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, &buf);
if (kret) {
*minor_status = kret;
return GSS_S_FAILURE;
diff --git a/source4/heimdal/lib/gssapi/krb5/prf.c b/source4/heimdal/lib/gssapi/krb5/prf.c
index 3eb90d279f..f79c9374a9 100644
--- a/source4/heimdal/lib/gssapi/krb5/prf.c
+++ b/source4/heimdal/lib/gssapi/krb5/prf.c
@@ -33,7 +33,7 @@
#include "krb5/gsskrb5_locl.h"
-RCSID("$Id: prf.c 20679 2007-05-14 03:12:05Z lha $");
+RCSID("$Id: prf.c 21129 2007-06-18 20:28:44Z lha $");
OM_uint32
_gsskrb5_pseudo_random(OM_uint32 *minor_status,
@@ -67,6 +67,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status,
switch(prf_key) {
case GSS_C_PRF_KEY_FULL:
_gsskrb5i_get_acceptor_subkey(ctx, context, &key);
+ break;
case GSS_C_PRF_KEY_PARTIAL:
_gsskrb5i_get_initiator_subkey(ctx, context, &key);
break;
diff --git a/source4/heimdal/lib/gssapi/krb5/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c
index a01a9a2a62..80b91930fd 100644
--- a/source4/heimdal/lib/gssapi/krb5/release_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/release_name.c
@@ -33,7 +33,7 @@
#include "krb5/gsskrb5_locl.h"
-RCSID("$Id: release_name.c 19031 2006-11-13 18:02:57Z lha $");
+RCSID("$Id: release_name.c 21128 2007-06-18 20:26:50Z lha $");
OM_uint32 _gsskrb5_release_name
(OM_uint32 * minor_status,
@@ -43,8 +43,7 @@ OM_uint32 _gsskrb5_release_name
krb5_context context;
krb5_principal name = (krb5_principal)*input_name;
- if (minor_status)
- *minor_status = 0;
+ *minor_status = 0;
GSSAPI_KRB5_INIT (&context);
diff --git a/source4/heimdal/lib/gssapi/mech/context.c b/source4/heimdal/lib/gssapi/mech/context.c
index 1691fd9401..e4517bee44 100644
--- a/source4/heimdal/lib/gssapi/mech/context.c
+++ b/source4/heimdal/lib/gssapi/mech/context.c
@@ -1,7 +1,7 @@
#include "mech/mech_locl.h"
#include "heim_threads.h"
-RCSID("$Id: context.c 19924 2007-01-16 10:17:01Z lha $");
+RCSID("$Id: context.c 21248 2007-06-21 00:45:13Z lha $");
struct mg_thread_ctx {
gss_OID mech;
@@ -79,7 +79,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
switch (type) {
case GSS_C_GSS_CODE: {
- if (value != mg->maj_stat)
+ if (value != mg->maj_stat || mg->maj_error.length == 0)
break;
string->value = malloc(mg->maj_error.length);
string->length = mg->maj_error.length;
@@ -87,7 +87,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
return GSS_S_COMPLETE;
}
case GSS_C_MECH_CODE: {
- if (value != mg->min_stat)
+ if (value != mg->min_stat || mg->min_error.length == 0)
break;
string->value = malloc(mg->min_error.length);
string->length = mg->min_error.length;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
index 8c5f4d0b08..d1e243d8b8 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_accept_sec_context.c 20626 2007-05-08 13:56:49Z lha $");
+RCSID("$Id: gss_accept_sec_context.c 21237 2007-06-20 11:21:09Z lha $");
static OM_uint32
parse_header(const gss_buffer_t input_token, gss_OID mech_oid)
@@ -237,9 +237,7 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
return (major_status);
}
- if (!src_name) {
- m->gm_release_name(minor_status, &src_mn);
- } else {
+ if (src_name && src_mn) {
/*
* Make a new name and mark it as an MN.
*/
@@ -250,13 +248,15 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
return (GSS_S_FAILURE);
}
*src_name = (gss_name_t) name;
+ } else if (src_mn) {
+ m->gm_release_name(minor_status, &src_mn);
}
if (mech_ret_flags & GSS_C_DELEG_FLAG) {
if (!delegated_cred_handle) {
m->gm_release_cred(minor_status, &delegated_mc);
*ret_flags &= ~GSS_C_DELEG_FLAG;
- } else {
+ } else if (delegated_mc) {
struct _gss_cred *dcred;
struct _gss_mechanism_cred *dmc;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_name.c b/source4/heimdal/lib/gssapi/mech/gss_display_name.c
index e57e5dd795..fc10933692 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_display_name.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_display_name.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_display_name.c 19952 2007-01-17 10:16:15Z lha $");
+RCSID("$Id: gss_display_name.c 21246 2007-06-20 15:25:19Z lha $");
OM_uint32
gss_display_name(OM_uint32 *minor_status,
@@ -43,6 +43,11 @@ gss_display_name(OM_uint32 *minor_status,
if (output_name_type)
*output_name_type = GSS_C_NO_OID;
+ if (name == NULL) {
+ *minor_status = 0;
+ return (GSS_S_BAD_NAME);
+ }
+
/*
* If we know it, copy the buffer used to import the name in
* the first place. Otherwise, ask all the MNs in turn if
diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_status.c b/source4/heimdal/lib/gssapi/mech/gss_display_status.c
index c316c26fd7..37ded26db6 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_display_status.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_display_status.c
@@ -59,7 +59,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_display_status.c 20084 2007-01-31 12:12:08Z lha $");
+RCSID("$Id: gss_display_status.c 21247 2007-06-21 00:37:27Z lha $");
static const char *
calling_error(OM_uint32 v)
@@ -85,7 +85,7 @@ static const char *
routine_error(OM_uint32 v)
{
static const char *msgs[] = {
- NULL, /* 0 */
+ "Function completed successfully", /* 0 */
"An unsupported mechanism was requested",
"An invalid name was supplied",
"A supplied name was of an unsupported type",
@@ -109,9 +109,7 @@ routine_error(OM_uint32 v)
v >>= GSS_C_ROUTINE_ERROR_OFFSET;
- if (v == 0)
- return "";
- else if (v >= sizeof(msgs)/sizeof(*msgs))
+ if (v >= sizeof(msgs)/sizeof(*msgs))
return "unknown routine error";
else
return msgs[v];
diff --git a/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c
index 3aab0b9bbc..4ff81fdf2d 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_duplicate_name.c 19953 2007-01-17 11:16:35Z lha $");
+RCSID("$Id: gss_duplicate_name.c 21219 2007-06-20 08:27:11Z lha $");
OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
const gss_name_t src_name,
@@ -44,7 +44,7 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
/*
* If this name has a value (i.e. it didn't come from
* gss_canonicalize_name(), we re-import the thing. Otherwise,
- * we make an empty name to hold the MN copy.
+ * we make copy of each mech names.
*/
if (name->gn_value.value) {
major_status = gss_import_name(minor_status,
@@ -52,6 +52,10 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
if (major_status != GSS_S_COMPLETE)
return (major_status);
new_name = (struct _gss_name *) *dest_name;
+
+ SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
+ _gss_find_mn(new_name, mn->gmn_mech_oid);
+ }
} else {
new_name = malloc(sizeof(struct _gss_name));
if (!new_name) {
@@ -59,17 +63,30 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
return (GSS_S_FAILURE);
}
memset(new_name, 0, sizeof(struct _gss_name));
- SLIST_INIT(&name->gn_mn);
+ SLIST_INIT(&new_name->gn_mn);
*dest_name = (gss_name_t) new_name;
- }
+
+ SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
+ struct _gss_mechanism_name *new_mn;
+
+ new_mn = malloc(sizeof(*new_mn));
+ if (!new_mn) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ new_mn->gmn_mech = mn->gmn_mech;
+ new_mn->gmn_mech_oid = mn->gmn_mech_oid;
+
+ major_status =
+ mn->gmn_mech->gm_duplicate_name(minor_status,
+ mn->gmn_name, &new_mn->gmn_name);
+ if (major_status != GSS_S_COMPLETE) {
+ free(new_mn);
+ continue;
+ }
+ SLIST_INSERT_HEAD(&new_name->gn_mn, new_mn, gmn_link);
+ }
- /*
- * Import the new name into any mechanisms listed in the
- * original name. We could probably get away with only doing
- * this if the original was canonical.
- */
- SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
- _gss_find_mn(new_name, mn->gmn_mech_oid);
}
return (GSS_S_COMPLETE);
diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c
index 5cce30c6bd..d45baac602 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_inquire_context.c 19958 2007-01-17 13:56:18Z lha $");
+RCSID("$Id: gss_inquire_context.c 21125 2007-06-18 20:11:07Z lha $");
OM_uint32
gss_inquire_context(OM_uint32 *minor_status,
@@ -79,7 +79,8 @@ gss_inquire_context(OM_uint32 *minor_status,
if (src_name) {
name = _gss_make_name(m, src_mn);
if (!name) {
- *mech_type = GSS_C_NO_OID;
+ if (mech_type)
+ *mech_type = GSS_C_NO_OID;
m->gm_release_name(minor_status, &src_mn);
*minor_status = 0;
return (GSS_S_FAILURE);
@@ -90,8 +91,10 @@ gss_inquire_context(OM_uint32 *minor_status,
if (targ_name) {
name = _gss_make_name(m, targ_mn);
if (!name) {
- *mech_type = GSS_C_NO_OID;
- gss_release_name(minor_status, src_name);
+ if (mech_type)
+ *mech_type = GSS_C_NO_OID;
+ if (src_name)
+ gss_release_name(minor_status, src_name);
m->gm_release_name(minor_status, &targ_mn);
*minor_status = 0;
return (GSS_S_FAILURE);
diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c
index a4ace9e9e9..aa83efb0c2 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_inquire_cred_by_mech.c 19960 2007-01-17 15:09:24Z lha $");
+RCSID("$Id: gss_inquire_cred_by_mech.c 21124 2007-06-18 20:08:24Z lha $");
OM_uint32
gss_inquire_cred_by_mech(OM_uint32 *minor_status,
@@ -78,12 +78,16 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status,
return (major_status);
}
- name = _gss_make_name(m, mn);
- if (!name) {
+ if (cred_name) {
+ name = _gss_make_name(m, mn);
+ if (!name) {
m->gm_release_name(minor_status, &mn);
return (GSS_S_NO_CRED);
- }
+ }
+ *cred_name = (gss_name_t) name;
+ } else
+ m->gm_release_name(minor_status, &mn);
+
- *cred_name = (gss_name_t) name;
return (GSS_S_COMPLETE);
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_krb5.c b/source4/heimdal/lib/gssapi/mech/gss_krb5.c
index 2500928baf..9e77f42982 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_krb5.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_krb5.c
@@ -27,7 +27,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_krb5.c 20383 2007-04-18 08:49:53Z lha $");
+RCSID("$Id: gss_krb5.c 21123 2007-06-18 20:05:26Z lha $");
#include <krb5.h>
#include <roken.h>
@@ -650,7 +650,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
oid_flat.length, &oid, &size) != 0) {
free(oid.components);
-
+ free(oid_flat.elements);
*minor_status = EINVAL;
return GSS_S_FAILURE;
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c
index 78c8cc79c1..c32291396f 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c
@@ -31,7 +31,7 @@
*/
#include "mech_locl.h"
-RCSID("$Id: gss_set_cred_option.c 20626 2007-05-08 13:56:49Z lha $");
+RCSID("$Id: gss_set_cred_option.c 21126 2007-06-18 20:19:59Z lha $");
OM_uint32
gss_set_cred_option (OM_uint32 *minor_status,
@@ -64,7 +64,9 @@ gss_set_cred_option (OM_uint32 *minor_status,
mc = malloc(sizeof(*mc));
if (mc == NULL) {
- /* XXX free the other mc's */
+ *cred_handle = (gss_cred_id_t)cred;
+ gss_release_cred(minor_status, cred_handle);
+ *minor_status = ENOMEM;
return GSS_S_FAILURE;
}
diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
index 106897b9b0..d20c913bf0 100644
--- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
@@ -33,7 +33,7 @@
#include "spnego/spnego_locl.h"
-RCSID("$Id: accept_sec_context.c 20929 2007-06-05 21:19:22Z lha $");
+RCSID("$Id: accept_sec_context.c 21243 2007-06-20 15:16:22Z lha $");
static OM_uint32
send_reject (OM_uint32 *minor_status,
@@ -540,12 +540,12 @@ acceptor_start
gss_cred_id_t *delegated_cred_handle
)
{
- OM_uint32 ret, ret2, minor;
- NegTokenInit ni;
- size_t ni_len;
+ OM_uint32 ret, junk, minor;
+ NegotiationToken nt;
+ size_t nt_len;
+ NegTokenInit *ni;
int i;
gss_buffer_desc data;
- size_t len, taglen;
gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
gss_buffer_desc mech_output_token;
gss_buffer_desc mech_buf;
@@ -555,6 +555,9 @@ acceptor_start
int get_mic = 0;
int first_ok = 0;
+ if (src_name)
+ *src_name = GSS_C_NO_NAME;
+
mech_output_token.value = NULL;
mech_output_token.length = 0;
mech_buf.value = NULL;
@@ -582,39 +585,30 @@ acceptor_start
if (ret)
return ret;
- ret = der_match_tag_and_length(data.value, data.length,
- ASN1_C_CONTEXT, CONS,
- 0,
- &len, &taglen);
+ ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len);
+ gss_release_buffer(minor_status, &data);
if (ret) {
*minor_status = ret;
- return GSS_S_FAILURE;
- }
-
- if (len > data.length - taglen) {
- *minor_status = ASN1_OVERRUN;
- return GSS_S_FAILURE;
+ return GSS_S_DEFECTIVE_TOKEN;
}
-
- ret = decode_NegTokenInit((const unsigned char *)data.value + taglen,
- len, &ni, &ni_len);
- if (ret) {
- *minor_status = ret;
+ if (nt.element != choice_NegotiationToken_negTokenInit) {
+ *minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
+ ni = &nt.u.negTokenInit;
- if (ni.mechTypes.len < 1) {
- free_NegTokenInit(&ni);
+ if (ni->mechTypes.len < 1) {
+ free_NegotiationToken(&nt);
*minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
- ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types);
+ ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types);
if (ret) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- free_NegTokenInit(&ni);
+ free_NegotiationToken(&nt);
*minor_status = ret;
return GSS_S_FAILURE;
}
@@ -627,17 +621,17 @@ acceptor_start
*/
ret = select_mech(minor_status,
- &ni.mechTypes.val[0],
+ &ni->mechTypes.val[0],
0,
&preferred_mech_type);
- if (ret == 0 && ni.mechToken != NULL) {
+ if (ret == 0 && ni->mechToken != NULL) {
gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL;
gss_cred_id_t mech_cred;
gss_buffer_desc ibuf;
- ibuf.length = ni.mechToken->length;
- ibuf.value = ni.mechToken->data;
+ ibuf.length = ni->mechToken->length;
+ ibuf.value = ni->mechToken->data;
mech_input_token = &ibuf;
if (acceptor_cred != NULL)
@@ -668,12 +662,12 @@ acceptor_start
if (ret == GSS_S_COMPLETE)
ctx->open = 1;
- if (delegated_cred_handle)
+ if (mech_delegated_cred && delegated_cred_handle)
ret = _gss_spnego_alloc_cred(minor_status,
mech_delegated_cred,
delegated_cred_handle);
else
- gss_release_cred(&ret2, &mech_delegated_cred);
+ gss_release_cred(&junk, &mech_delegated_cred);
ret = acceptor_complete(minor_status,
ctx,
@@ -681,7 +675,7 @@ acceptor_start
&mech_buf,
mech_input_token,
&mech_output_token,
- ni.mechListMIC,
+ ni->mechListMIC,
output_token);
if (ret != GSS_S_COMPLETE)
goto out;
@@ -697,9 +691,9 @@ acceptor_start
if (!first_ok) {
/* Call glue layer to find first mech we support */
- for (i = 1; i < ni.mechTypes.len; ++i) {
+ for (i = 1; i < ni->mechTypes.len; ++i) {
ret = select_mech(minor_status,
- &ni.mechTypes.val[i],
+ &ni->mechTypes.val[i],
1,
&preferred_mech_type);
if (ret == 0)
@@ -707,7 +701,7 @@ acceptor_start
}
if (preferred_mech_type == GSS_C_NO_OID) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- free_NegTokenInit(&ni);
+ free_NegotiationToken(&nt);
return GSS_S_BAD_MECH;
}
@@ -735,7 +729,8 @@ out:
free(mech_buf.value);
mech_buf.value = NULL;
}
- free_NegTokenInit(&ni);
+ free_NegotiationToken(&nt);
+
if (ret == GSS_S_COMPLETE) {
if (src_name != NULL && ctx->mech_src_name != NULL) {
@@ -746,8 +741,7 @@ out:
name->mech = ctx->mech_src_name;
ctx->mech_src_name = NULL;
*src_name = (gss_name_t)name;
- } else
- *src_name = GSS_C_NO_NAME;
+ }
}
if (delegated_cred_handle != NULL) {
*delegated_cred_handle = ctx->delegated_cred_id;
@@ -790,10 +784,9 @@ acceptor_continue
)
{
OM_uint32 ret, ret2, minor;
- NegTokenResp na;
- size_t na_len;
- gss_buffer_desc data;
- size_t len, taglen;
+ NegotiationToken nt;
+ size_t nt_len;
+ NegTokenResp *na;
unsigned int negResult = accept_incomplete;
gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
gss_buffer_t mech_output_token = GSS_C_NO_BUFFER;
@@ -810,45 +803,34 @@ acceptor_continue
* context token (negTokenInit).
*/
- data.value = input_token_buffer->value;
- data.length = input_token_buffer->length;
-
- ret = der_match_tag_and_length(data.value, data.length,
- ASN1_C_CONTEXT, CONS,
- 1,
- &len, &taglen);
+ ret = decode_NegotiationToken(input_token_buffer->value,
+ input_token_buffer->length,
+ &nt, &nt_len);
if (ret) {
*minor_status = ret;
- return GSS_S_FAILURE;
- }
-
- if (len > data.length - taglen) {
- *minor_status = ASN1_OVERRUN;
- return GSS_S_FAILURE;
+ return GSS_S_DEFECTIVE_TOKEN;
}
-
- ret = decode_NegTokenResp((const unsigned char *)data.value + taglen,
- len, &na, &na_len);
- if (ret) {
- *minor_status = ret;
+ if (nt.element != choice_NegotiationToken_negTokenResp) {
+ *minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
+ na = &nt.u.negTokenResp;
- if (na.negResult != NULL) {
- negResult = *(na.negResult);
+ if (na->negResult != NULL) {
+ negResult = *(na->negResult);
}
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
{
gss_buffer_desc ibuf, obuf;
- int require_mic, get_mic;
+ int require_mic, get_mic = 0;
int require_response;
heim_octet_string *mic;
- if (na.responseToken != NULL) {
- ibuf.length = na.responseToken->length;
- ibuf.value = na.responseToken->data;
+ if (na->responseToken != NULL) {
+ ibuf.length = na->responseToken->length;
+ ibuf.value = na->responseToken->data;
mech_input_token = &ibuf;
} else {
ibuf.value = NULL;
@@ -901,7 +883,7 @@ acceptor_continue
mech_output_token = &obuf;
}
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
- free_NegTokenResp(&na);
+ free_NegotiationToken(&nt);
send_reject (minor_status, output_token);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return ret;
@@ -919,7 +901,7 @@ acceptor_continue
ctx->require_mic = require_mic;
- mic = na.mechListMIC;
+ mic = na->mechListMIC;
if (mic != NULL)
require_mic = 1;
@@ -930,7 +912,7 @@ acceptor_continue
&mech_buf,
mech_input_token,
mech_output_token,
- na.mechListMIC,
+ na->mechListMIC,
output_token);
if (ctx->mech_flags & GSS_C_DCE_STYLE)
@@ -964,16 +946,19 @@ acceptor_continue
gss_release_buffer(&minor, mech_output_token);
if (mech_buf.value != NULL)
free(mech_buf.value);
- free_NegTokenResp(&na);
+ free_NegotiationToken(&nt);
}
if (ret == GSS_S_COMPLETE) {
- if (src_name != NULL) {
- ret2 = gss_duplicate_name(minor_status,
- ctx->mech_src_name,
- src_name);
- if (ret2 != GSS_S_COMPLETE)
- ret = ret2;
+ if (src_name != NULL && ctx->mech_src_name != NULL) {
+ spnego_name name;
+
+ name = calloc(1, sizeof(*name));
+ if (name) {
+ name->mech = ctx->mech_src_name;
+ ctx->mech_src_name = NULL;
+ *src_name = (gss_name_t)name;
+ }
}
if (delegated_cred_handle != NULL) {
*delegated_cred_handle = ctx->delegated_cred_id;
diff --git a/source4/heimdal/lib/hcrypto/pkcs12.c b/source4/heimdal/lib/hcrypto/pkcs12.c
index dcfbdfad42..b43fe571d6 100644
--- a/source4/heimdal/lib/hcrypto/pkcs12.c
+++ b/source4/heimdal/lib/hcrypto/pkcs12.c
@@ -35,7 +35,7 @@
#include <config.h>
#endif
-RCSID("$Id: pkcs12.c 20661 2007-05-10 21:57:58Z lha $");
+RCSID("$Id: pkcs12.c 21155 2007-06-18 21:59:44Z lha $");
#include <stdio.h>
#include <stdlib.h>
@@ -93,8 +93,11 @@ PKCS12_key_gen(const void *key, size_t keylen,
while (1) {
BIGNUM *bnB, *bnOne;
- if (!EVP_DigestInit_ex(&ctx, md, NULL))
+ if (!EVP_DigestInit_ex(&ctx, md, NULL)) {
+ free(I);
+ free(v);
return 0;
+ }
for (i = 0; i < vlen; i++)
EVP_DigestUpdate(&ctx, &idc, 1);
EVP_DigestUpdate(&ctx, I, size_I);
diff --git a/source4/heimdal/lib/hcrypto/rand-egd.c b/source4/heimdal/lib/hcrypto/rand-egd.c
index d1b024b535..497a3ab5f8 100644
--- a/source4/heimdal/lib/hcrypto/rand-egd.c
+++ b/source4/heimdal/lib/hcrypto/rand-egd.c
@@ -35,7 +35,7 @@
#include <config.h>
#endif
-RCSID("$Id: rand-egd.c 20093 2007-01-31 12:44:28Z lha $");
+RCSID("$Id: rand-egd.c 21156 2007-06-18 22:00:59Z lha $");
#include <sys/types.h>
#ifdef HAVE_SYS_UN_H
@@ -255,7 +255,7 @@ RAND_egd_bytes(const char *filename, int size)
RAND_seed(data, size);
- memset(data, 0, sizeof(data));
+ memset(data, 0, size);
free(data);
return 1;
diff --git a/source4/heimdal/lib/hcrypto/rand-fortuna.c b/source4/heimdal/lib/hcrypto/rand-fortuna.c
index 6cc4267c13..1d47ed49cc 100644
--- a/source4/heimdal/lib/hcrypto/rand-fortuna.c
+++ b/source4/heimdal/lib/hcrypto/rand-fortuna.c
@@ -33,7 +33,7 @@
#include <config.h>
#endif
-RCSID("$Id: rand-fortuna.c 20029 2007-01-21 09:55:42Z lha $");
+RCSID("$Id: rand-fortuna.c 21196 2007-06-20 05:08:58Z lha $");
#include <stdio.h>
#include <stdlib.h>
@@ -427,6 +427,8 @@ extract_data(FState * st, unsigned count, unsigned char *dst)
static FState main_state;
static int init_done;
static int have_entropy;
+#define FORTUNA_RESEED_BYTE 10000
+static unsigned resend_bytes;
/*
* Try our best to do an inital seed
@@ -472,6 +474,35 @@ fortuna_reseed(void)
memset(buf, 0, sizeof(buf));
}
}
+ /*
+ * Fall back to gattering data from timer and secret files, this
+ * is really the last resort.
+ */
+ if (!entropy_p) {
+ /* to save stackspace */
+ union {
+ unsigned char buf[INIT_BYTES];
+ unsigned char shad[1001];
+ } u;
+ int fd;
+
+ /* add timer info */
+ if ((*hc_rand_timer_method.bytes)(u.buf, sizeof(u.buf)) == 1)
+ add_entropy(&main_state, u.buf, sizeof(u.buf));
+ /* add /etc/shadow */
+ fd = open("/etc/shadow", O_RDONLY, 0);
+ if (fd >= 0) {
+ ssize_t n;
+ /* add_entropy will hash the buf */
+ while ((n = read(fd, (char *)u.shad, sizeof(u.shad))) > 0)
+ add_entropy(&main_state, u.shad, sizeof(u.shad));
+ close(fd);
+ }
+
+ memset(&u, 0, sizeof(u));
+
+ entropy_p = 1; /* sure about this ? */
+ }
{
pid_t pid = getpid();
add_entropy(&main_state, (void *)&pid, sizeof(pid));
@@ -517,6 +548,11 @@ fortuna_bytes(unsigned char *outdata, int size)
{
if (!fortuna_init())
return 0;
+ resend_bytes += size;
+ if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) {
+ resend_bytes = 0;
+ fortuna_reseed();
+ }
extract_data(&main_state, size, outdata);
return 1;
}
diff --git a/source4/heimdal/lib/hcrypto/rand-timer.c b/source4/heimdal/lib/hcrypto/rand-timer.c
new file mode 100644
index 0000000000..67a77b01fc
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/rand-timer.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1999, 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rand.h>
+
+#include <roken.h>
+
+#include "randi.h"
+
+#ifndef WIN32 /* don't bother with this on windows */
+
+static volatile int counter;
+static volatile unsigned char *gdata; /* Global data */
+static volatile int igdata; /* Index into global data */
+static int gsize;
+
+static
+RETSIGTYPE
+sigALRM(int sig)
+{
+ if (igdata < gsize)
+ gdata[igdata++] ^= counter & 0xff;
+
+#ifndef HAVE_SIGACTION
+ signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */
+#endif
+ SIGRETURN(0);
+}
+
+#ifndef HAVE_SETITIMER
+static void
+pacemaker(struct timeval *tv)
+{
+ fd_set fds;
+ pid_t pid;
+ pid = getppid();
+ while(1){
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ select(1, &fds, NULL, NULL, tv);
+ kill(pid, SIGALRM);
+ }
+}
+#endif
+
+#ifdef HAVE_SIGACTION
+/* XXX ugly hack, should perhaps use function from roken */
+static RETSIGTYPE
+(*fake_signal(int sig, RETSIGTYPE (*f)(int)))(int)
+{
+ struct sigaction sa, osa;
+ sa.sa_handler = f;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(sig, &sa, &osa);
+ return osa.sa_handler;
+}
+#define signal(S, F) fake_signal((S), (F))
+#endif
+
+#endif /* WIN32*/
+
+/*
+ *
+ */
+
+static void
+timer_seed(const void *indata, int size)
+{
+}
+
+static int
+timer_bytes(unsigned char *outdata, int size)
+{
+#ifdef WIN32
+ return 0;
+#else /* WIN32 */
+ struct itimerval tv, otv;
+ RETSIGTYPE (*osa)(int);
+ int i, j;
+#ifndef HAVE_SETITIMER
+ RETSIGTYPE (*ochld)(int);
+ pid_t pid;
+#endif
+
+ gdata = outdata;
+ gsize = size;
+ igdata = 0;
+
+ osa = signal(SIGALRM, sigALRM);
+
+ /* Start timer */
+ tv.it_value.tv_sec = 0;
+ tv.it_value.tv_usec = 10 * 1000; /* 10 ms */
+ tv.it_interval = tv.it_value;
+#ifdef HAVE_SETITIMER
+ setitimer(ITIMER_REAL, &tv, &otv);
+#else
+ ochld = signal(SIGCHLD, SIG_IGN);
+ pid = fork();
+ if(pid == -1){
+ signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
+ des_not_rand_data(data, size);
+ return;
+ }
+ if(pid == 0)
+ pacemaker(&tv.it_interval);
+#endif
+
+ for(i = 0; i < 4; i++) {
+ for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */
+ counter++;
+ for (j = 0; j < size; j++) /* Only use 2 bits each lap */
+ gdata[j] = (gdata[j]>>2) | (gdata[j]<<6);
+ }
+#ifdef HAVE_SETITIMER
+ setitimer(ITIMER_REAL, &otv, 0);
+#else
+ kill(pid, SIGKILL);
+ while(waitpid(pid, NULL, 0) != pid);
+ signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
+#endif
+ signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL);
+
+ return 1;
+#endif
+}
+
+static void
+timer_cleanup(void)
+{
+}
+
+static void
+timer_add(const void *indata, int size, double entropi)
+{
+}
+
+static int
+timer_pseudorand(unsigned char *outdata, int size)
+{
+ return timer_bytes(outdata, size);
+}
+
+static int
+timer_status(void)
+{
+#ifdef WIN32
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+const RAND_METHOD hc_rand_timer_method = {
+ timer_seed,
+ timer_bytes,
+ timer_cleanup,
+ timer_add,
+ timer_pseudorand,
+ timer_status
+};
+
+const RAND_METHOD *
+RAND_timer_method(void)
+{
+ return &hc_rand_timer_method;
+}
diff --git a/source4/heimdal/lib/hcrypto/rand.c b/source4/heimdal/lib/hcrypto/rand.c
index 29f2d46dba..248fdde620 100644
--- a/source4/heimdal/lib/hcrypto/rand.c
+++ b/source4/heimdal/lib/hcrypto/rand.c
@@ -35,7 +35,7 @@
#include <config.h>
#endif
-RCSID("$Id: rand.c 20126 2007-02-01 22:08:41Z lha $");
+RCSID("$Id: rand.c 21198 2007-06-20 05:10:41Z lha $");
#include <stdio.h>
#include <stdlib.h>
@@ -56,11 +56,7 @@ init_method(void)
{
if (selected_meth != NULL)
return;
-
- if ((*hc_rand_unix_method.status)() == 1)
- selected_meth = &hc_rand_unix_method;
- else
- selected_meth = &hc_rand_fortuna_method;
+ selected_meth = &hc_rand_fortuna_method;
}
void
diff --git a/source4/heimdal/lib/hcrypto/randi.h b/source4/heimdal/lib/hcrypto/randi.h
index b9b9b5309c..6ae75f262b 100644
--- a/source4/heimdal/lib/hcrypto/randi.h
+++ b/source4/heimdal/lib/hcrypto/randi.h
@@ -32,7 +32,7 @@
*/
/*
- * $Id: randi.h 20027 2007-01-21 09:54:00Z lha $
+ * $Id: randi.h 21101 2007-06-18 03:53:46Z lha $
*/
#ifndef _HEIM_RANDI_H
@@ -41,5 +41,8 @@
extern const RAND_METHOD hc_rand_fortuna_method;
extern const RAND_METHOD hc_rand_unix_method;
extern const RAND_METHOD hc_rand_egd_method;
+extern const RAND_METHOD hc_rand_timer_method;
+
+const RAND_METHOD * RAND_timer_method(void);
#endif /* _HEIM_RANDI_H */
diff --git a/source4/heimdal/lib/hcrypto/rsa-imath.c b/source4/heimdal/lib/hcrypto/rsa-imath.c
index e05ead1e66..74093ff7ba 100644
--- a/source4/heimdal/lib/hcrypto/rsa-imath.c
+++ b/source4/heimdal/lib/hcrypto/rsa-imath.c
@@ -35,7 +35,7 @@
#include <config.h>
#endif
-RCSID("$Id: rsa-imath.c 19750 2007-01-06 13:45:25Z lha $");
+RCSID("$Id: rsa-imath.c 21154 2007-06-18 21:58:12Z lha $");
#include <stdio.h>
#include <stdlib.h>
@@ -180,7 +180,6 @@ imath_rsa_public_encrypt(int flen, const unsigned char* from,
}
padlen = size - flen - 3;
- assert(padlen >= 8);
*p++ = 2;
if (RAND_bytes(p, padlen) != 1) {
diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c
index aac0ff5367..5f60999946 100644
--- a/source4/heimdal/lib/hdb/ext.c
+++ b/source4/heimdal/lib/hdb/ext.c
@@ -34,7 +34,7 @@
#include "hdb_locl.h"
#include <der.h>
-RCSID("$Id: ext.c 20236 2007-02-16 23:52:29Z lha $");
+RCSID("$Id: ext.c 21113 2007-06-18 12:59:32Z lha $");
krb5_error_code
hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent)
@@ -268,6 +268,7 @@ hdb_entry_get_password(krb5_context context, HDB *db,
const hdb_entry *entry, char **p)
{
HDB_extension *ext;
+ char *str;
int ret;
ext = hdb_find_extension(entry, choice_HDB_extension_data_password);
@@ -314,7 +315,14 @@ hdb_entry_get_password(krb5_context context, HDB *db,
}
return 0;
}
- krb5_set_error_string(context, "password attribute not found");
+
+ ret = krb5_unparse_name(context, entry->principal, &str);
+ if (ret == 0) {
+ krb5_set_error_string(context, "no password attributefor %s", str);
+ free(str);
+ } else
+ krb5_clear_error_string(context);
+
return ENOENT;
}
diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c
index 27b17a0204..caf163f8e4 100644
--- a/source4/heimdal/lib/hx509/cert.c
+++ b/source4/heimdal/lib/hx509/cert.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $");
+RCSID("$Id: cert.c 21294 2007-06-25 14:37:15Z lha $");
#include "crypto-headers.h"
#include <rtbl.h>
@@ -43,6 +43,7 @@ struct hx509_verify_ctx_data {
#define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
+#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
time_t time_now;
unsigned int max_depth;
#define HX509_VERIFY_MAX_DEPTH 30
@@ -51,6 +52,7 @@ struct hx509_verify_ctx_data {
#define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
#define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
+#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
struct _hx509_cert_attrs {
size_t len;
@@ -80,22 +82,6 @@ typedef struct hx509_name_constraints {
*
*/
-void
-_hx509_abort(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
- fflush(stdout);
- abort();
-}
-
-/*
- *
- */
-
int
hx509_context_init(hx509_context *context)
{
@@ -227,7 +213,34 @@ hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
if (ret) {
free((*cert)->data);
free(*cert);
+ *cert = NULL;
+ }
+ return ret;
+}
+
+int
+hx509_cert_init_data(hx509_context context,
+ const void *ptr,
+ size_t len,
+ hx509_cert *cert)
+{
+ Certificate t;
+ size_t size;
+ int ret;
+
+ ret = decode_Certificate(ptr, len, &t, &size);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
+ return ret;
+ }
+ if (size != len) {
+ hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
+ "Extra data after certificate");
+ return HX509_EXTRA_DATA_AFTER_STRUCTURE;
}
+
+ ret = hx509_cert_init(context, &t, cert);
+ free_Certificate(&t);
return ret;
}
@@ -291,10 +304,10 @@ hx509_cert
hx509_cert_ref(hx509_cert cert)
{
if (cert->ref <= 0)
- _hx509_abort("refcount <= 0");
+ _hx509_abort("cert refcount <= 0");
cert->ref++;
if (cert->ref == 0)
- _hx509_abort("refcount == 0");
+ _hx509_abort("cert refcount == 0");
return cert;
}
@@ -342,6 +355,12 @@ hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
}
void
+hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
+{
+ ctx->max_depth = max_depth;
+}
+
+void
hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
{
if (boolean)
@@ -359,6 +378,15 @@ hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
}
+void
+hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
+{
+ if (boolean)
+ ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
+ else
+ ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
+}
+
static const Extension *
find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
{
@@ -1295,13 +1323,15 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match)
return 0;
}
case choice_GeneralName_dNSName: {
- size_t len1, len2;
+ size_t lenc, lenn;
- len1 = strlen(c->u.dNSName);
- len2 = strlen(n->u.dNSName);
- if (len1 > len2)
+ lenc = strlen(c->u.dNSName);
+ lenn = strlen(n->u.dNSName);
+ if (lenc > lenn)
return HX509_NAME_CONSTRAINT_ERROR;
- if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0)
+ if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
+ return HX509_NAME_CONSTRAINT_ERROR;
+ if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
return HX509_NAME_CONSTRAINT_ERROR;
*match = 1;
return 0;
@@ -1488,15 +1518,15 @@ hx509_verify_path(hx509_context context,
/*
*
*/
- ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors);
- if (ret)
- goto out;
- ret = hx509_certs_merge(context, anchors, ctx->trust_anchors);
- if (ret)
- goto out;
- ret = hx509_certs_merge(context, anchors, context->default_trust_anchors);
- if (ret)
- goto out;
+ if (ctx->trust_anchors)
+ anchors = _hx509_certs_ref(ctx->trust_anchors);
+ else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
+ anchors = _hx509_certs_ref(context->default_trust_anchors);
+ else {
+ ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
+ if (ret)
+ goto out;
+ }
/*
* Calculate the path from the certificate user presented to the
@@ -1843,17 +1873,82 @@ hx509_verify_signature(hx509_context context,
return _hx509_verify_signature(context, signer->data, alg, data, sig);
}
+#define HX509_VHN_F_ALLOW_NO_MATCH 1
+
int
hx509_verify_hostname(hx509_context context,
const hx509_cert cert,
- int require_match,
+ int flags,
+ hx509_hostname_type type,
const char *hostname,
const struct sockaddr *sa,
/* XXX krb5_socklen_t */ int sa_size)
{
+ GeneralNames san;
+ int ret, i, j;
+
if (sa && sa_size <= 0)
return EINVAL;
- return 0;
+
+ memset(&san, 0, sizeof(san));
+
+ i = 0;
+ do {
+ ret = find_extension_subject_alt_name(cert->data, &i, &san);
+ if (ret == HX509_EXTENSION_NOT_FOUND) {
+ ret = 0;
+ break;
+ } else if (ret != 0)
+ break;
+
+ for (j = 0; j < san.len; j++) {
+ switch (san.val[j].element) {
+ case choice_GeneralName_dNSName:
+ if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
+ free_GeneralNames(&san);
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ free_GeneralNames(&san);
+ } while (1);
+
+ {
+ Name *name = &cert->data->tbsCertificate.subject;
+
+ /* match if first component is a CN= */
+ if (name->u.rdnSequence.len > 0
+ && name->u.rdnSequence.val[0].len == 1
+ && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
+ oid_id_at_commonName()) == 0)
+ {
+ DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
+
+ switch (ds->element) {
+ case choice_DirectoryString_printableString:
+ if (strcasecmp(ds->u.printableString, hostname) == 0)
+ return 0;
+ break;
+ case choice_DirectoryString_ia5String:
+ if (strcasecmp(ds->u.ia5String, hostname) == 0)
+ return 0;
+ break;
+ case choice_DirectoryString_utf8String:
+ if (strcasecmp(ds->u.utf8String, hostname) == 0)
+ return 0;
+ default:
+ break;
+ }
+ }
+ }
+
+ if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
+ ret = HX509_NAME_CONSTRAINT_ERROR;
+
+ return ret;
}
int
@@ -2434,3 +2529,24 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
return ret;
}
+
+/*
+ * Last to avoid lost __attribute__s due to #undef.
+ */
+
+#undef __attribute__
+#define __attribute__(X)
+
+void
+_hx509_abort(const char *fmt, ...)
+ __attribute__ ((noreturn, format (printf, 1, 2)))
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+ fflush(stdout);
+ abort();
+}
+
diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c
index 29ca80e194..30f364060d 100644
--- a/source4/heimdal/lib/hx509/cms.c
+++ b/source4/heimdal/lib/hx509/cms.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: cms.c 20937 2007-06-06 20:50:55Z lha $");
+RCSID("$Id: cms.c 21319 2007-06-25 19:46:52Z lha $");
#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
@@ -115,24 +115,42 @@ hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
return 0;
}
+#define CMS_ID_SKI 0
+#define CMS_ID_NAME 1
+
static int
-fill_CMSIdentifier(const hx509_cert cert, CMSIdentifier *id)
+fill_CMSIdentifier(const hx509_cert cert,
+ int type,
+ CMSIdentifier *id)
{
- hx509_name name;
int ret;
- id->element = choice_CMSIdentifier_issuerAndSerialNumber;
- ret = hx509_cert_get_issuer(cert, &name);
- if (ret)
- return ret;
- ret = copy_Name(&name->der_name,
- &id->u.issuerAndSerialNumber.issuer);
- hx509_name_free(&name);
- if (ret)
- return ret;
+ switch (type) {
+ case CMS_ID_SKI:
+ id->element = choice_CMSIdentifier_subjectKeyIdentifier;
+ ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
+ &id->u.subjectKeyIdentifier);
+ if (ret == 0)
+ break;
+ /* FALL THOUGH */
+ case CMS_ID_NAME: {
+ hx509_name name;
- ret = hx509_cert_get_serialnumber(cert,
- &id->u.issuerAndSerialNumber.serialNumber);
+ id->element = choice_CMSIdentifier_issuerAndSerialNumber;
+ ret = hx509_cert_get_issuer(cert, &name);
+ if (ret)
+ return ret;
+ ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
+ hx509_name_free(&name);
+ if (ret)
+ return ret;
+
+ ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
+ break;
+ }
+ default:
+ _hx509_abort("CMS fill identifier with unknown type");
+ }
return ret;
}
@@ -467,6 +485,13 @@ hx509_cms_envelope_1(hx509_context context,
goto out;
}
+ ret = hx509_crypto_random_iv(crypto, &ivec);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to create a random iv");
+ goto out;
+ }
+
ret = hx509_crypto_encrypt(crypto,
data,
length,
@@ -518,7 +543,7 @@ hx509_cms_envelope_1(hx509_context context,
ri = &ed.recipientInfos.val[0];
ri->version = 0;
- ret = fill_CMSIdentifier(cert, &ri->rid);
+ ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid);
if (ret) {
hx509_set_error_string(context, 0, ret,
"Failed to set CMS identifier info "
@@ -585,22 +610,12 @@ any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
return 0;
for (i = 0; i < sd->certificates->len; i++) {
- Certificate cert;
hx509_cert c;
- const void *p = sd->certificates->val[i].data;
- size_t size, length = sd->certificates->val[i].length;
-
- ret = decode_Certificate(p, length, &cert, &size);
- if (ret) {
- hx509_set_error_string(context, 0, ret,
- "Failed to decode certificate %d "
- "in SignedData.certificates", i);
- return ret;
- }
-
- ret = hx509_cert_init(context, &cert, &c);
- free_Certificate(&cert);
+ ret = hx509_cert_init_data(context,
+ sd->certificates->val[i].data,
+ sd->certificates->val[i].length,
+ &c);
if (ret)
return ret;
ret = hx509_certs_add(context, certs, c);
@@ -951,6 +966,7 @@ hx509_cms_create_signed_1(hx509_context context,
int ret;
size_t size;
hx509_path path;
+ int cmsidflag = CMS_ID_SKI;
memset(&sd, 0, sizeof(sd));
memset(&name, 0, sizeof(name));
@@ -960,6 +976,9 @@ hx509_cms_create_signed_1(hx509_context context,
content.data = rk_UNCONST(data);
content.length = length;
+ if (flags & HX509_CMS_SIGATURE_ID_NAME)
+ cmsidflag = CMS_ID_NAME;
+
if (_hx509_cert_private_key(cert) == NULL) {
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
"Private key missing for signing");
@@ -1014,7 +1033,7 @@ hx509_cms_create_signed_1(hx509_context context,
signer_info->version = 1;
- ret = fill_CMSIdentifier(cert, &signer_info->sid);
+ ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
if (ret) {
hx509_clear_error_string(context);
goto out;
diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c
index 96d9693cc2..d86300bd58 100644
--- a/source4/heimdal/lib/hx509/crypto.c
+++ b/source4/heimdal/lib/hx509/crypto.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: crypto.c 20939 2007-06-06 20:53:02Z lha $");
+RCSID("$Id: crypto.c 21318 2007-06-25 19:46:32Z lha $");
struct hx509_crypto;
@@ -362,6 +362,7 @@ rsa_create_signature(hx509_context context,
sig->length = RSA_size(signer->private_key.rsa);
sig->data = malloc(sig->length);
if (sig->data == NULL) {
+ der_free_octet_string(&indata);
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
@@ -1761,15 +1762,17 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
p->maximum_effective_key = 128;
break;
default:
+ free(p);
free_CMSRC2CBCParameter(&rc2param);
return HX509_CRYPTO_SIG_INVALID_FORMAT;
}
if (ivec)
ret = der_copy_octet_string(&rc2param.iv, ivec);
free_CMSRC2CBCParameter(&rc2param);
- if (ret)
+ if (ret) {
+ free(p);
hx509_clear_error_string(context);
- else
+ } else
crypto->param = p;
return ret;
@@ -2009,10 +2012,29 @@ hx509_crypto_get_params(hx509_context context,
}
int
+hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
+{
+ ivec->length = EVP_CIPHER_iv_length(crypto->c);
+ ivec->data = malloc(ivec->length);
+ if (ivec->data == NULL) {
+ ivec->length = 0;
+ return ENOMEM;
+ }
+
+ if (RAND_bytes(ivec->data, ivec->length) <= 0) {
+ free(ivec->data);
+ ivec->data = NULL;
+ ivec->length = 0;
+ return HX509_CRYPTO_INTERNAL_ERROR;
+ }
+ return 0;
+}
+
+int
hx509_crypto_encrypt(hx509_crypto crypto,
const void *data,
const size_t length,
- heim_octet_string *ivec,
+ const heim_octet_string *ivec,
heim_octet_string **ciphertext)
{
EVP_CIPHER_CTX evp;
@@ -2021,19 +2043,9 @@ hx509_crypto_encrypt(hx509_crypto crypto,
*ciphertext = NULL;
- EVP_CIPHER_CTX_init(&evp);
-
- ivec->length = EVP_CIPHER_iv_length(crypto->c);
- ivec->data = malloc(ivec->length);
- if (ivec->data == NULL) {
- ret = ENOMEM;
- goto out;
- }
+ assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
- if (RAND_bytes(ivec->data, ivec->length) <= 0) {
- ret = HX509_CRYPTO_INTERNAL_ERROR;
- goto out;
- }
+ EVP_CIPHER_CTX_init(&evp);
ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
crypto->key.data, ivec->data, 1);
@@ -2082,10 +2094,6 @@ hx509_crypto_encrypt(hx509_crypto crypto,
out:
if (ret) {
- if (ivec->data) {
- free(ivec->data);
- memset(ivec, 0, sizeof(*ivec));
- }
if (*ciphertext) {
if ((*ciphertext)->data) {
free((*ciphertext)->data);
@@ -2286,6 +2294,24 @@ find_string2key(const heim_oid *oid,
return NULL;
}
+/*
+ *
+ */
+
+int
+_hx509_pbe_encrypt(hx509_context context,
+ hx509_lock lock,
+ const AlgorithmIdentifier *ai,
+ const heim_octet_string *content,
+ heim_octet_string *econtent)
+{
+ hx509_clear_error_string(context);
+ return EINVAL;
+}
+
+/*
+ *
+ */
int
_hx509_pbe_decrypt(hx509_context context,
diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c
index 1152af2423..b076b74f44 100644
--- a/source4/heimdal/lib/hx509/file.c
+++ b/source4/heimdal/lib/hx509/file.c
@@ -134,3 +134,243 @@ _hx509_write_file(const char *fn, const void *data, size_t length)
return 0;
}
+
+/*
+ *
+ */
+
+static void
+header(FILE *f, const char *type, const char *str)
+{
+ fprintf(f, "-----%s %s-----\n", type, str);
+}
+
+int
+hx509_pem_write(hx509_context context, const char *type,
+ hx509_pem_header *headers, FILE *f,
+ const void *data, size_t size)
+{
+ const char *p = data;
+ size_t length;
+ char *line;
+
+#define ENCODE_LINE_LENGTH 54
+
+ header(f, "BEGIN", type);
+
+ while (headers) {
+ fprintf(f, "%s: %s\n%s",
+ headers->header, headers->value,
+ headers->next ? "" : "\n");
+ headers = headers->next;
+ }
+
+ while (size > 0) {
+ ssize_t l;
+
+ length = size;
+ if (length > ENCODE_LINE_LENGTH)
+ length = ENCODE_LINE_LENGTH;
+
+ l = base64_encode(p, length, &line);
+ if (l < 0) {
+ hx509_set_error_string(context, 0, ENOMEM,
+ "malloc - out of memory");
+ return ENOMEM;
+ }
+ size -= length;
+ fprintf(f, "%s\n", line);
+ p += length;
+ free(line);
+ }
+
+ header(f, "END", type);
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+int
+hx509_pem_add_header(hx509_pem_header **headers,
+ const char *header, const char *value)
+{
+ hx509_pem_header *h;
+
+ h = calloc(1, sizeof(*h));
+ if (h == NULL)
+ return ENOMEM;
+ h->header = strdup(header);
+ if (h->header == NULL) {
+ free(h);
+ return ENOMEM;
+ }
+ h->value = strdup(value);
+ if (h->value == NULL) {
+ free(h->header);
+ free(h);
+ return ENOMEM;
+ }
+
+ h->next = *headers;
+ *headers = h;
+
+ return 0;
+}
+
+void
+hx509_pem_free_header(hx509_pem_header *headers)
+{
+ hx509_pem_header *h;
+ while (headers) {
+ h = headers;
+ headers = headers->next;
+ free(h->header);
+ free(h->value);
+ free(h);
+ }
+}
+
+/*
+ *
+ */
+
+const char *
+hx509_pem_find_header(const hx509_pem_header *h, const char *header)
+{
+ while(h) {
+ if (strcmp(header, h->header) == 0)
+ return h->value;
+ h = h->next;
+ }
+ return NULL;
+}
+
+
+/*
+ *
+ */
+
+int
+hx509_pem_read(hx509_context context,
+ FILE *f,
+ hx509_pem_read_func func,
+ void *ctx)
+{
+ hx509_pem_header *headers = NULL;
+ char *type = NULL;
+ void *data = NULL;
+ size_t len = 0;
+ char buf[1024];
+ int ret = HX509_PARSING_KEY_FAILED;
+
+ enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
+
+ where = BEFORE;
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *p;
+ int i;
+
+ i = strcspn(buf, "\n");
+ if (buf[i] == '\n') {
+ buf[i] = '\0';
+ if (i > 0)
+ i--;
+ }
+ if (buf[i] == '\r') {
+ buf[i] = '\0';
+ if (i > 0)
+ i--;
+ }
+
+ switch (where) {
+ case BEFORE:
+ if (strncmp("-----BEGIN ", buf, 11) == 0) {
+ type = strdup(buf + 11);
+ if (type == NULL)
+ break;
+ p = strchr(type, '-');
+ if (p)
+ *p = '\0';
+ where = SEARCHHEADER;
+ }
+ break;
+ case SEARCHHEADER:
+ p = strchr(buf, ':');
+ if (p == NULL) {
+ where = INDATA;
+ goto indata;
+ }
+ /* FALLTHOUGH */
+ case INHEADER:
+ if (buf[0] == '\0') {
+ where = INDATA;
+ break;
+ }
+ p = strchr(buf, ':');
+ if (p) {
+ *p++ = '\0';
+ while (isspace((int)*p))
+ p++;
+ ret = hx509_pem_add_header(&headers, buf, p);
+ if (ret)
+ abort();
+ }
+ break;
+ case INDATA:
+ indata:
+
+ if (strncmp("-----END ", buf, 9) == 0) {
+ where = DONE;
+ break;
+ }
+
+ p = emalloc(i);
+ i = base64_decode(buf, p);
+ if (i < 0) {
+ free(p);
+ goto out;
+ }
+
+ data = erealloc(data, len + i);
+ memcpy(((char *)data) + len, p, i);
+ free(p);
+ len += i;
+ break;
+ case DONE:
+ abort();
+ }
+
+ if (where == DONE) {
+ ret = (*func)(context, type, headers, data, len, ctx);
+ out:
+ free(data);
+ data = NULL;
+ len = 0;
+ free(type);
+ type = NULL;
+ where = BEFORE;
+ hx509_pem_free_header(headers);
+ headers = NULL;
+ if (ret)
+ break;
+ }
+ }
+
+ if (where != BEFORE) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "File ends before end of PEM end tag");
+ ret = HX509_PARSING_KEY_FAILED;
+ }
+ if (data)
+ free(data);
+ if (type)
+ free(type);
+ if (headers)
+ hx509_pem_free_header(headers);
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/hx509/hx509-private.h b/source4/heimdal/lib/hx509/hx509-private.h
index 2763df957f..451c3c89f2 100644
--- a/source4/heimdal/lib/hx509/hx509-private.h
+++ b/source4/heimdal/lib/hx509/hx509-private.h
@@ -4,6 +4,10 @@
#include <stdarg.h>
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
int
_hx509_Certificate_cmp (
const Certificate */*p*/,
@@ -20,7 +24,8 @@ _hx509_Time2time_t (const Time */*t*/);
void
_hx509_abort (
const char */*fmt*/,
- ...);
+ ...)
+ __attribute__ ((noreturn, format (printf, 1, 2)));
int
_hx509_calculate_path (
@@ -104,6 +109,9 @@ _hx509_certs_keys_get (
hx509_certs /*certs*/,
hx509_private_key **/*keys*/);
+hx509_certs
+_hx509_certs_ref (hx509_certs /*certs*/);
+
int
_hx509_check_key_usage (
hx509_context /*context*/,
@@ -306,6 +314,14 @@ _hx509_pbe_decrypt (
const heim_octet_string */*econtent*/,
heim_octet_string */*content*/);
+int
+_hx509_pbe_encrypt (
+ hx509_context /*context*/,
+ hx509_lock /*lock*/,
+ const AlgorithmIdentifier */*ai*/,
+ const heim_octet_string */*content*/,
+ heim_octet_string */*econtent*/);
+
void
_hx509_pi_printf (
int (*/*func*/)(void *, const char *),
@@ -407,11 +423,35 @@ void
_hx509_request_free (hx509_request */*req*/);
int
+_hx509_request_get_SubjectPublicKeyInfo (
+ hx509_context /*context*/,
+ hx509_request /*req*/,
+ SubjectPublicKeyInfo */*key*/);
+
+int
+_hx509_request_get_name (
+ hx509_context /*context*/,
+ hx509_request /*req*/,
+ hx509_name */*name*/);
+
+int
_hx509_request_init (
hx509_context /*context*/,
hx509_request */*req*/);
int
+_hx509_request_parse (
+ hx509_context /*context*/,
+ const char */*path*/,
+ hx509_request */*req*/);
+
+int
+_hx509_request_print (
+ hx509_context /*context*/,
+ hx509_request /*req*/,
+ FILE */*f*/);
+
+int
_hx509_request_set_SubjectPublicKeyInfo (
hx509_context /*context*/,
hx509_request /*req*/,
diff --git a/source4/heimdal/lib/hx509/hx509-protos.h b/source4/heimdal/lib/hx509/hx509-protos.h
index ab312cdbdf..71fb29d59d 100644
--- a/source4/heimdal/lib/hx509/hx509-protos.h
+++ b/source4/heimdal/lib/hx509/hx509-protos.h
@@ -237,6 +237,13 @@ hx509_cert_init (
hx509_cert */*cert*/);
int
+hx509_cert_init_data (
+ hx509_context /*context*/,
+ const void */*ptr*/,
+ size_t /*len*/,
+ hx509_cert */*cert*/);
+
+int
hx509_cert_keyusage_print (
hx509_context /*context*/,
hx509_cert /*c*/,
@@ -479,7 +486,7 @@ hx509_crypto_encrypt (
hx509_crypto /*crypto*/,
const void */*data*/,
const size_t /*length*/,
- heim_octet_string */*ivec*/,
+ const heim_octet_string */*ivec*/,
heim_octet_string **/*ciphertext*/);
const heim_oid *
@@ -508,6 +515,11 @@ const char *
hx509_crypto_provider (hx509_crypto /*crypto*/);
int
+hx509_crypto_random_iv (
+ hx509_crypto /*crypto*/,
+ heim_octet_string */*ivec*/);
+
+int
hx509_crypto_select (
const hx509_context /*context*/,
int /*type*/,
@@ -740,6 +752,36 @@ hx509_peer_info_set_cms_algs (
const AlgorithmIdentifier */*val*/,
size_t /*len*/);
+int
+hx509_pem_add_header (
+ hx509_pem_header **/*headers*/,
+ const char */*header*/,
+ const char */*value*/);
+
+const char *
+hx509_pem_find_header (
+ const hx509_pem_header */*h*/,
+ const char */*header*/);
+
+void
+hx509_pem_free_header (hx509_pem_header */*headers*/);
+
+int
+hx509_pem_read (
+ hx509_context /*context*/,
+ FILE */*f*/,
+ hx509_pem_read_func /*func*/,
+ void */*ctx*/);
+
+int
+hx509_pem_write (
+ hx509_context /*context*/,
+ const char */*type*/,
+ hx509_pem_header */*headers*/,
+ FILE */*f*/,
+ const void */*data*/,
+ size_t /*size*/);
+
void
hx509_print_func (
hx509_vprint_func /*func*/,
@@ -931,13 +973,19 @@ hx509_verify_attach_revoke (
hx509_revoke_ctx /*revoke_ctx*/);
void
+hx509_verify_ctx_f_allow_default_trustanchors (
+ hx509_verify_ctx /*ctx*/,
+ int /*boolean*/);
+
+void
hx509_verify_destroy_ctx (hx509_verify_ctx /*ctx*/);
int
hx509_verify_hostname (
hx509_context /*context*/,
const hx509_cert /*cert*/,
- int /*require_match*/,
+ int /*flags*/,
+ hx509_hostname_type /*type*/,
const char */*hostname*/,
const struct sockaddr */*sa*/,
int /*sa_size*/);
@@ -955,6 +1003,11 @@ hx509_verify_path (
hx509_certs /*pool*/);
void
+hx509_verify_set_max_depth (
+ hx509_verify_ctx /*ctx*/,
+ unsigned int /*max_depth*/);
+
+void
hx509_verify_set_proxy_certificate (
hx509_verify_ctx /*ctx*/,
int /*boolean*/);
diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h
index 664c12e045..2f22cedfbc 100644
--- a/source4/heimdal/lib/hx509/hx509.h
+++ b/source4/heimdal/lib/hx509/hx509.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: hx509.h 20798 2007-06-02 03:28:55Z lha $ */
+/* $Id: hx509.h 21310 2007-06-25 18:26:06Z lha $ */
typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
typedef struct hx509_cert_data *hx509_cert;
@@ -84,6 +84,16 @@ typedef struct hx509_octet_string_list {
heim_octet_string *val;
} hx509_octet_string_list;
+typedef struct hx509_pem_header {
+ struct hx509_pem_header *next;
+ char *header;
+ char *value;
+} hx509_pem_header;
+
+typedef int
+(*hx509_pem_read_func)(hx509_context, const char *, const hx509_pem_header *,
+ const void *, size_t, void *ctx);
+
/*
* Options passed to hx509_query_match_option.
*/
@@ -122,5 +132,12 @@ typedef enum {
/* flags hx509_cms_create_signed* */
#define HX509_CMS_SIGATURE_DETACHED 1
+#define HX509_CMS_SIGATURE_ID_NAME 2
+
+/* hx509_verify_hostname nametype */
+typedef enum {
+ HX509_HN_HOSTNAME = 0,
+ HX509_HN_DNSSRV
+} hx509_hostname_type;
#include <hx509-protos.h>
diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h
index bfbee0943e..145bfcc006 100644
--- a/source4/heimdal/lib/hx509/hx_locl.h
+++ b/source4/heimdal/lib/hx509/hx_locl.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: hx_locl.h 20930 2007-06-06 00:23:42Z lha $ */
+/* $Id: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -194,6 +194,6 @@ extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;
* Configurable options
*/
-#if 0 /* fdef __APPLE__*/
-#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system"
+#ifdef __APPLE__
+#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors"
#endif
diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c
index 475835b9b0..7da5705a80 100644
--- a/source4/heimdal/lib/hx509/keyset.c
+++ b/source4/heimdal/lib/hx509/keyset.c
@@ -32,9 +32,10 @@
*/
#include "hx_locl.h"
-RCSID("$Id: keyset.c 20911 2007-06-05 03:41:17Z lha $");
+RCSID("$Id: keyset.c 21140 2007-06-18 21:24:19Z lha $");
struct hx509_certs_data {
+ int ref;
struct hx509_keyset_ops *ops;
void *ops_data;
};
@@ -99,18 +100,20 @@ hx509_certs_init(hx509_context context,
}
ops = _hx509_ks_type(context, type);
- free(type);
if (ops == NULL) {
hx509_set_error_string(context, 0, ENOENT,
"Keyset type %s is not supported", type);
+ free(type);
return ENOENT;
}
+ free(type);
c = calloc(1, sizeof(*c));
if (c == NULL) {
hx509_clear_error_string(context);
return ENOMEM;
}
c->ops = ops;
+ c->ref = 1;
ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
if (ret) {
@@ -140,10 +143,26 @@ hx509_certs_store(hx509_context context,
}
+hx509_certs
+_hx509_certs_ref(hx509_certs certs)
+{
+ if (certs->ref <= 0)
+ _hx509_abort("certs refcount <= 0");
+ certs->ref++;
+ if (certs->ref == 0)
+ _hx509_abort("certs refcount == 0");
+ return certs;
+}
+
void
hx509_certs_free(hx509_certs *certs)
{
if (*certs) {
+ if ((*certs)->ref <= 0)
+ _hx509_abort("refcount <= 0");
+ if (--(*certs)->ref > 0)
+ return;
+
(*(*certs)->ops->free)(*certs, (*certs)->ops_data);
free(*certs);
*certs = NULL;
diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c
index f9a3580880..269afd03b1 100644
--- a/source4/heimdal/lib/hx509/ks_file.c
+++ b/source4/heimdal/lib/hx509/ks_file.c
@@ -32,68 +32,16 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_file.c 20776 2007-06-01 22:02:01Z lha $");
+RCSID("$Id: ks_file.c 21314 2007-06-25 18:45:07Z lha $");
+
+typedef enum { USE_PEM, USE_DER } outformat;
struct ks_file {
hx509_certs certs;
char *fn;
+ outformat format;
};
-struct header {
- char *header;
- char *value;
- struct header *next;
-};
-
-static int
-add_headers(struct header **headers, const char *header, const char *value)
-{
- struct header *h;
- h = calloc(1, sizeof(*h));
- if (h == NULL)
- return ENOMEM;
- h->header = strdup(header);
- if (h->header == NULL) {
- free(h);
- return ENOMEM;
- }
- h->value = strdup(value);
- if (h->value == NULL) {
- free(h->header);
- free(h);
- return ENOMEM;
- }
-
- h->next = *headers;
- *headers = h;
-
- return 0;
-}
-
-static void
-free_headers(struct header *headers)
-{
- struct header *h;
- while (headers) {
- h = headers;
- headers = headers->next;
- free(h->header);
- free(h->value);
- free(h);
- }
-}
-
-static const char *
-find_header(const struct header *headers, const char *header)
-{
- while(headers) {
- if (strcmp(header, headers->header) == 0)
- return headers->value;
- headers = headers->next;
- }
- return NULL;
-}
-
/*
*
*/
@@ -101,24 +49,13 @@ find_header(const struct header *headers, const char *header)
static int
parse_certificate(hx509_context context, const char *fn,
struct hx509_collector *c,
- const struct header *headers,
+ const hx509_pem_header *headers,
const void *data, size_t len)
{
hx509_cert cert;
- Certificate t;
- size_t size;
int ret;
- ret = decode_Certificate(data, len, &t, &size);
- if (ret) {
- hx509_set_error_string(context, 0, ret,
- "Failed to parse certificate in %s",
- fn);
- return ret;
- }
-
- ret = hx509_cert_init(context, &t, &cert);
- free_Certificate(&t);
+ ret = hx509_cert_init_data(context, data, len, &cert);
if (ret)
return ret;
@@ -195,13 +132,13 @@ out:
static int
parse_rsa_private_key(hx509_context context, const char *fn,
struct hx509_collector *c,
- const struct header *headers,
+ const hx509_pem_header *headers,
const void *data, size_t len)
{
int ret = 0;
const char *enc;
- enc = find_header(headers, "Proc-Type");
+ enc = hx509_pem_find_header(headers, "Proc-Type");
if (enc) {
const char *dek;
char *type, *iv;
@@ -229,7 +166,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
return HX509_PARSING_KEY_FAILED;
}
- dek = find_header(headers, "DEK-Info");
+ dek = hx509_pem_find_header(headers, "DEK-Info");
if (dek == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Encrypted RSA missing DEK-Info");
@@ -243,8 +180,14 @@ parse_rsa_private_key(hx509_context context, const char *fn,
}
iv = strchr(type, ',');
- if (iv)
- *iv++ = '\0';
+ if (iv == NULL) {
+ free(type);
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "IV missing");
+ return HX509_PARSING_KEY_FAILED;
+ }
+
+ *iv++ = '\0';
size = strlen(iv);
ivdata = malloc(size);
@@ -339,7 +282,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
struct pem_formats {
const char *name;
int (*func)(hx509_context, const char *, struct hx509_collector *,
- const struct header *, const void *, size_t);
+ const hx509_pem_header *, const void *, size_t);
} formats[] = {
{ "CERTIFICATE", parse_certificate },
{ "RSA PRIVATE KEY", parse_rsa_private_key }
@@ -347,152 +290,27 @@ struct pem_formats {
static int
-parse_pem_file(hx509_context context,
- const char *fn,
- struct hx509_collector *c,
- int *found_data)
+pem_func(hx509_context context, const char *type,
+ const hx509_pem_header *header,
+ const void *data, size_t len, void *ctx)
{
- struct header *headers = NULL;
- char *type = NULL;
- void *data = NULL;
- size_t len = 0;
- char buf[1024];
- int ret;
- FILE *f;
-
-
- enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
-
- where = BEFORE;
- *found_data = 0;
+ struct hx509_collector *c = ctx;
+ int ret, j;
- if ((f = fopen(fn, "r")) == NULL) {
- hx509_set_error_string(context, 0, ENOENT,
- "Failed to open PEM file \"%s\": %s",
- fn, strerror(errno));
- return ENOENT;
- }
- ret = 0;
-
- while (fgets(buf, sizeof(buf), f) != NULL) {
- char *p;
- int i;
-
- i = strcspn(buf, "\n");
- if (buf[i] == '\n') {
- buf[i] = '\0';
- if (i > 0)
- i--;
- }
- if (buf[i] == '\r') {
- buf[i] = '\0';
- if (i > 0)
- i--;
- }
-
- switch (where) {
- case BEFORE:
- if (strncmp("-----BEGIN ", buf, 11) == 0) {
- type = strdup(buf + 11);
- if (type == NULL)
- break;
- p = strchr(type, '-');
- if (p)
- *p = '\0';
- *found_data = 1;
- where = SEARCHHEADER;
- }
+ for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
+ const char *q = formats[j].name;
+ if (strcasecmp(type, q) == 0) {
+ ret = (*formats[j].func)(context, NULL, c, header, data, len);
break;
- case SEARCHHEADER:
- p = strchr(buf, ':');
- if (p == NULL) {
- where = INDATA;
- goto indata;
- }
- /* FALLTHOUGH */
- case INHEADER:
- if (buf[0] == '\0') {
- where = INDATA;
- break;
- }
- p = strchr(buf, ':');
- if (p) {
- *p++ = '\0';
- while (isspace((int)*p))
- p++;
- add_headers(&headers, buf, p);
- }
- break;
- case INDATA:
- indata:
-
- if (strncmp("-----END ", buf, 9) == 0) {
- where = DONE;
- break;
- }
-
- p = emalloc(i);
- i = base64_decode(buf, p);
- if (i < 0) {
- free(p);
- goto out;
- }
-
- data = erealloc(data, len + i);
- memcpy(((char *)data) + len, p, i);
- free(p);
- len += i;
- break;
- case DONE:
- abort();
- }
-
- if (where == DONE) {
- int j;
-
- for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
- const char *q = formats[j].name;
- if (strcasecmp(type, q) == 0) {
- ret = (*formats[j].func)(context, fn, c,
- headers, data, len);
- break;
- }
- }
- if (j == sizeof(formats)/sizeof(formats[0])) {
- ret = HX509_UNSUPPORTED_OPERATION;
- hx509_set_error_string(context, 0, ret,
- "Found no matching PEM format for %s",
- type);
- }
- out:
- free(data);
- data = NULL;
- len = 0;
- free(type);
- type = NULL;
- where = BEFORE;
- free_headers(headers);
- headers = NULL;
- if (ret)
- break;
}
}
-
- fclose(f);
-
- if (where != BEFORE) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "File ends before end of PEM end tag");
- ret = HX509_PARSING_KEY_FAILED;
+ if (j == sizeof(formats)/sizeof(formats[0])) {
+ ret = HX509_UNSUPPORTED_OPERATION;
+ hx509_set_error_string(context, 0, ret,
+ "Found no matching PEM format for %s", type);
+ return ret;
}
- if (data)
- free(data);
- if (type)
- free(type);
- if (headers)
- free_headers(headers);
-
- return ret;
+ return 0;
}
/*
@@ -500,9 +318,9 @@ parse_pem_file(hx509_context context,
*/
static int
-file_init(hx509_context context,
- hx509_certs certs, void **data, int flags,
- const char *residue, hx509_lock lock)
+file_init_common(hx509_context context,
+ hx509_certs certs, void **data, int flags,
+ const char *residue, hx509_lock lock, outformat format)
{
char *p, *pnext;
struct ks_file *f = NULL;
@@ -520,6 +338,7 @@ file_init(hx509_context context,
hx509_clear_error_string(context);
return ENOMEM;
}
+ f->format = format;
f->fn = strdup(residue);
if (f->fn == NULL) {
@@ -547,17 +366,26 @@ file_init(hx509_context context,
goto out;
for (p = f->fn; p != NULL; p = pnext) {
- int found_data;
+ FILE *f;
pnext = strchr(p, ',');
if (pnext)
*pnext++ = '\0';
- ret = parse_pem_file(context, p, c, &found_data);
- if (ret)
+
+ if ((f = fopen(p, "r")) == NULL) {
+ ret = ENOENT;
+ hx509_set_error_string(context, 0, ret,
+ "Failed to open PEM file \"%s\": %s",
+ p, strerror(errno));
goto out;
+ }
- if (!found_data) {
+ ret = hx509_pem_read(context, f, pem_func, c);
+ fclose(f);
+ if (ret != 0 && ret != HX509_PARSING_KEY_FAILED)
+ goto out;
+ else if (ret == HX509_PARSING_KEY_FAILED) {
size_t length;
void *ptr;
int i;
@@ -606,75 +434,40 @@ out:
}
static int
-file_free(hx509_certs certs, void *data)
+file_init_pem(hx509_context context,
+ hx509_certs certs, void **data, int flags,
+ const char *residue, hx509_lock lock)
{
- struct ks_file *f = data;
- hx509_certs_free(&f->certs);
- free(f->fn);
- free(f);
- return 0;
+ return file_init_common(context, certs, data, flags, residue, lock, USE_PEM);
}
-static void
-pem_header(FILE *f, const char *type, const char *str)
+static int
+file_init_der(hx509_context context,
+ hx509_certs certs, void **data, int flags,
+ const char *residue, hx509_lock lock)
{
- fprintf(f, "-----%s %s-----\n", type, str);
+ return file_init_common(context, certs, data, flags, residue, lock, USE_DER);
}
static int
-dump_pem_file(hx509_context context, const char *header,
- FILE *f, const void *data, size_t size)
+file_free(hx509_certs certs, void *data)
{
- const char *p = data;
- size_t length;
- char *line;
-
-#define ENCODE_LINE_LENGTH 54
-
- pem_header(f, "BEGIN", header);
-
- while (size > 0) {
- ssize_t l;
-
- length = size;
- if (length > ENCODE_LINE_LENGTH)
- length = ENCODE_LINE_LENGTH;
-
- l = base64_encode(p, length, &line);
- if (l < 0) {
- hx509_set_error_string(context, 0, ENOMEM,
- "malloc - out of memory");
- return ENOMEM;
- }
- size -= length;
- fprintf(f, "%s\n", line);
- p += length;
- free(line);
- }
-
- pem_header(f, "END", header);
-
+ struct ks_file *f = data;
+ hx509_certs_free(&f->certs);
+ free(f->fn);
+ free(f);
return 0;
}
-static int
-store_private_key(hx509_context context, FILE *f, hx509_private_key key)
-{
- heim_octet_string data;
- int ret;
-
- ret = _hx509_private_key_export(context, key, &data);
- if (ret == 0)
- dump_pem_file(context, _hx509_private_pem_name(key), f,
- data.data, data.length);
- free(data.data);
- return ret;
-}
+struct store_ctx {
+ FILE *f;
+ outformat format;
+};
static int
store_func(hx509_context context, void *ctx, hx509_cert c)
{
- FILE *f = (FILE *)ctx;
+ struct store_ctx *sc = ctx;
heim_octet_string data;
int ret;
@@ -682,11 +475,26 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
if (ret)
return ret;
- dump_pem_file(context, "CERTIFICATE", f, data.data, data.length);
- free(data.data);
-
- if (_hx509_cert_private_key_exportable(c))
- store_private_key(context, f, _hx509_cert_private_key(c));
+ switch (sc->format) {
+ case USE_DER:
+ fwrite(data.data, data.length, 1, sc->f);
+ free(data.data);
+ break;
+ case USE_PEM:
+ hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
+ data.data, data.length);
+ free(data.data);
+ if (_hx509_cert_private_key_exportable(c)) {
+ hx509_private_key key = _hx509_cert_private_key(c);
+ ret = _hx509_private_key_export(context, key, &data);
+ if (ret)
+ break;
+ hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,
+ data.data, data.length);
+ free(data.data);
+ }
+ break;
+ }
return 0;
}
@@ -696,18 +504,19 @@ file_store(hx509_context context,
hx509_certs certs, void *data, int flags, hx509_lock lock)
{
struct ks_file *f = data;
- FILE *fh;
+ struct store_ctx sc;
int ret;
- fh = fopen(f->fn, "w");
- if (fh == NULL) {
+ sc.f = fopen(f->fn, "w");
+ if (sc.f == NULL) {
hx509_set_error_string(context, 0, ENOENT,
"Failed to open file %s for writing");
return ENOENT;
}
+ sc.format = f->format;
- ret = hx509_certs_iter(context, f->certs, store_func, fh);
- fclose(fh);
+ ret = hx509_certs_iter(context, f->certs, store_func, &sc);
+ fclose(sc.f);
return ret;
}
@@ -767,7 +576,7 @@ file_addkey(hx509_context context,
static struct hx509_keyset_ops keyset_file = {
"FILE",
0,
- file_init,
+ file_init_pem,
file_store,
file_free,
file_add,
@@ -780,8 +589,43 @@ static struct hx509_keyset_ops keyset_file = {
file_addkey
};
+static struct hx509_keyset_ops keyset_pemfile = {
+ "PEM-FILE",
+ 0,
+ file_init_pem,
+ file_store,
+ file_free,
+ file_add,
+ NULL,
+ file_iter_start,
+ file_iter,
+ file_iter_end,
+ NULL,
+ file_getkeys,
+ file_addkey
+};
+
+static struct hx509_keyset_ops keyset_derfile = {
+ "DER-FILE",
+ 0,
+ file_init_der,
+ file_store,
+ file_free,
+ file_add,
+ NULL,
+ file_iter_start,
+ file_iter,
+ file_iter_end,
+ NULL,
+ file_getkeys,
+ file_addkey
+};
+
+
void
_hx509_ks_file_register(hx509_context context)
{
_hx509_ks_register(context, &keyset_file);
+ _hx509_ks_register(context, &keyset_pemfile);
+ _hx509_ks_register(context, &keyset_derfile);
}
diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c
index 2f0f72cd14..33c4d6774b 100644
--- a/source4/heimdal/lib/hx509/ks_keychain.c
+++ b/source4/heimdal/lib/hx509/ks_keychain.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_keychain.c 20945 2007-06-06 22:17:17Z lha $");
+RCSID("$Id: ks_keychain.c 21097 2007-06-16 07:00:49Z lha $");
#ifdef HAVE_FRAMEWORK_SECURITY
@@ -254,6 +254,7 @@ set_private_key(hx509_context context,
*/
struct ks_keychain {
+ int anchors;
SecKeychainRef keychain;
};
@@ -263,7 +264,6 @@ keychain_init(hx509_context context,
const char *residue, hx509_lock lock)
{
struct ks_keychain *ctx;
- OSStatus ret;
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
@@ -272,13 +272,20 @@ keychain_init(hx509_context context,
}
if (residue) {
- if (strcasecmp(residue, "system") == 0)
- residue = "/System/Library/Keychains/X509Anchors";
-
- ret = SecKeychainOpen(residue, &ctx->keychain);
- if (ret != noErr) {
+ if (strcasecmp(residue, "system-anchors") == 0) {
+ ctx->anchors = 1;
+ } else if (strncasecmp(residue, "FILE:", 5) == 0) {
+ OSStatus ret;
+
+ ret = SecKeychainOpen(residue + 5, &ctx->keychain);
+ if (ret != noErr) {
+ hx509_set_error_string(context, 0, ENOENT,
+ "Failed to open %s", residue);
+ return ENOENT;
+ }
+ } else {
hx509_set_error_string(context, 0, ENOENT,
- "Failed to open %s", residue);
+ "Unknown subtype %s", residue);
return ENOENT;
}
}
@@ -307,6 +314,8 @@ keychain_free(hx509_certs certs, void *data)
*/
struct iter {
+ hx509_certs certs;
+ void *cursor;
SecKeychainSearchRef searchRef;
};
@@ -316,7 +325,6 @@ keychain_iter_start(hx509_context context,
{
struct ks_keychain *ctx = data;
struct iter *iter;
- OSStatus ret;
iter = calloc(1, sizeof(*iter));
if (iter == NULL) {
@@ -324,15 +332,66 @@ keychain_iter_start(hx509_context context,
return ENOMEM;
}
- ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
- kSecCertificateItemClass,
- NULL,
- &iter->searchRef);
- if (ret) {
- free(iter);
- hx509_set_error_string(context, 0, ret,
- "Failed to start search for attributes");
- return ENOMEM;
+ if (ctx->anchors) {
+ CFArrayRef anchors;
+ int ret;
+ int i;
+
+ ret = hx509_certs_init(context, "MEMORY:ks-file-create",
+ 0, NULL, &iter->certs);
+ if (ret) {
+ free(iter);
+ return ret;
+ }
+
+ ret = SecTrustCopyAnchorCertificates(&anchors);
+ if (ret != 0) {
+ hx509_certs_free(&iter->certs);
+ free(iter);
+ hx509_set_error_string(context, 0, ENOMEM,
+ "Can't get trust anchors from Keychain");
+ return ENOMEM;
+ }
+ for (i = 0; i < CFArrayGetCount(anchors); i++) {
+ SecCertificateRef cr;
+ hx509_cert cert;
+ CSSM_DATA cssm;
+
+ cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);
+
+ SecCertificateGetData(cr, &cssm);
+
+ ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);
+ if (ret)
+ continue;
+
+ ret = hx509_certs_add(context, iter->certs, cert);
+ hx509_cert_free(cert);
+ }
+ CFRelease(anchors);
+ }
+
+ if (iter->certs) {
+ int ret;
+ ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
+ if (ret) {
+ hx509_certs_free(&iter->certs);
+ free(iter);
+ return ret;
+ }
+ } else {
+ OSStatus ret;
+
+ ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
+ kSecCertificateItemClass,
+ NULL,
+ &iter->searchRef);
+ if (ret) {
+ free(iter);
+ hx509_set_error_string(context, 0, ret,
+ "Failed to start search for attributes");
+ return ENOMEM;
+ }
}
*cursor = iter;
@@ -349,15 +408,16 @@ keychain_iter(hx509_context context,
{
SecKeychainAttributeList *attrs = NULL;
SecKeychainAttributeInfo attrInfo;
- uint32 attrFormat = 0;
+ uint32 attrFormat[1] = { 0 };
SecKeychainItemRef itemRef;
- SecItemAttr item;
+ SecItemAttr item[1];
struct iter *iter = cursor;
- Certificate t;
OSStatus ret;
UInt32 len;
void *ptr = NULL;
- size_t size;
+
+ if (iter->certs)
+ return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);
*cert = NULL;
@@ -371,26 +431,18 @@ keychain_iter(hx509_context context,
* Pick out certificate and matching "keyid"
*/
- item = kSecPublicKeyHashItemAttr;
+ item[0] = kSecPublicKeyHashItemAttr;
attrInfo.count = 1;
- attrInfo.tag = &item;
- attrInfo.format = &attrFormat;
+ attrInfo.tag = item;
+ attrInfo.format = attrFormat;
ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
&attrs, &len, &ptr);
if (ret)
return EINVAL;
-
- ret = decode_Certificate(ptr, len, &t, &size);
- CFRelease(itemRef);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "Failed to parse certificate");
- goto out;
- }
- ret = hx509_cert_init(context, &t, cert);
- free_Certificate(&t);
+ ret = hx509_cert_init_data(context, ptr, len, cert);
if (ret)
goto out;
@@ -449,7 +501,14 @@ keychain_iter_end(hx509_context context,
{
struct iter *iter = cursor;
- CFRelease(iter->searchRef);
+ if (iter->certs) {
+ int ret;
+ ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
+ hx509_certs_free(&iter->certs);
+ } else {
+ CFRelease(iter->searchRef);
+ }
+
memset(iter, 0, sizeof(*iter));
free(iter);
return 0;
diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c
index 90c716213f..b899005b33 100644
--- a/source4/heimdal/lib/hx509/ks_p11.c
+++ b/source4/heimdal/lib/hx509/ks_p11.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_p11.c 20920 2007-06-05 05:47:06Z lha $");
+RCSID("$Id: ks_p11.c 21085 2007-06-13 06:39:53Z lha $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -682,7 +682,6 @@ collect_cert(hx509_context context,
{
struct hx509_collector *collector = ptr;
hx509_cert cert;
- Certificate t;
int ret;
if ((CK_LONG)query[0].ulValueLen == -1 ||
@@ -691,16 +690,8 @@ collect_cert(hx509_context context,
return 0;
}
-
- ret = decode_Certificate(query[1].pValue, query[1].ulValueLen,
- &t, NULL);
- if (ret) {
- hx509_clear_error_string(context);
- return 0;
- }
-
- ret = hx509_cert_init(context, &t, &cert);
- free_Certificate(&t);
+ ret = hx509_cert_init_data(context, query[1].pValue,
+ query[1].ulValueLen, &cert);
if (ret)
return ret;
diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c
index 5fddbd07de..12756e6c07 100644
--- a/source4/heimdal/lib/hx509/ks_p12.c
+++ b/source4/heimdal/lib/hx509/ks_p12.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_p12.c 20909 2007-06-05 03:09:13Z lha $");
+RCSID("$Id: ks_p12.c 21146 2007-06-18 21:37:25Z lha $");
struct ks_pkcs12 {
hx509_certs certs;
@@ -90,7 +90,7 @@ keyBag_parser(hx509_context context,
&ki.privateKeyAlgorithm,
NULL,
&ki.privateKey,
- &attr->attrValues);
+ os);
free_PKCS8PrivateKeyInfo(&ki);
return 0;
}
@@ -132,7 +132,6 @@ certBag_parser(hx509_context context,
const PKCS12_Attributes *attrs)
{
heim_octet_string os;
- Certificate t;
hx509_cert cert;
PKCS12_CertBag cb;
int ret;
@@ -154,16 +153,11 @@ certBag_parser(hx509_context context,
if (ret)
return ret;
- ret = decode_Certificate(os.data, os.length, &t, NULL);
+ ret = hx509_cert_init_data(context, os.data, os.length, &cert);
der_free_octet_string(&os);
if (ret)
return ret;
- ret = hx509_cert_init(context, &t, &cert);
- free_Certificate(&t);
- if (ret)
- return ret;
-
ret = _hx509_collector_certs_add(context, c, cert);
if (ret) {
hx509_cert_free(cert);
@@ -437,7 +431,9 @@ p12_init(hx509_context context,
out:
_hx509_collector_free(c);
- if (ret) {
+ if (ret && p12) {
+ if (p12->fn)
+ free(p12->fn);
if (p12->certs)
hx509_certs_free(&p12->certs);
free(p12);
diff --git a/source4/heimdal/lib/hx509/req.c b/source4/heimdal/lib/hx509/req.c
index 34e3a4ea27..d7a85e1cec 100644
--- a/source4/heimdal/lib/hx509/req.c
+++ b/source4/heimdal/lib/hx509/req.c
@@ -33,7 +33,7 @@
#include "hx_locl.h"
#include <pkcs10_asn1.h>
-RCSID("$Id: req.c 20934 2007-06-06 15:30:02Z lha $");
+RCSID("$Id: req.c 21344 2007-06-26 14:22:34Z lha $");
struct hx509_request_data {
hx509_name name;
@@ -85,6 +85,18 @@ _hx509_request_set_name(hx509_context context,
}
int
+_hx509_request_get_name(hx509_context context,
+ hx509_request req,
+ hx509_name *name)
+{
+ if (req->name == NULL) {
+ hx509_set_error_string(context, 0, EINVAL, "Request have no name");
+ return EINVAL;
+ }
+ return hx509_name_copy(context, req->name, name);
+}
+
+int
_hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
hx509_request req,
const SubjectPublicKeyInfo *key)
@@ -94,6 +106,14 @@ _hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
}
int
+_hx509_request_get_SubjectPublicKeyInfo(hx509_context context,
+ hx509_request req,
+ SubjectPublicKeyInfo *key)
+{
+ return copy_SubjectPublicKeyInfo(&req->key, key);
+}
+
+int
_hx509_request_add_eku(hx509_context context,
hx509_request req,
const heim_oid *oid)
@@ -215,3 +235,91 @@ out:
return ret;
}
+
+int
+_hx509_request_parse(hx509_context context,
+ const char *path,
+ hx509_request *req)
+{
+ CertificationRequest r;
+ CertificationRequestInfo *rinfo;
+ hx509_name subject;
+ size_t len, size;
+ void *p;
+ int ret;
+
+ if (strncmp(path, "PKCS10:", 7) != 0) {
+ hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
+ "unsupport type in %s", path);
+ return HX509_UNSUPPORTED_OPERATION;
+ }
+ path += 7;
+
+ /* XXX PEM request */
+
+ ret = _hx509_map_file(path, &p, &len, NULL);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
+ return ret;
+ }
+
+ ret = decode_CertificationRequest(p, len, &r, &size);
+ _hx509_unmap_file(p, len);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
+ return ret;
+ }
+
+ ret = _hx509_request_init(context, req);
+ if (ret) {
+ free_CertificationRequest(&r);
+ return ret;
+ }
+
+ rinfo = &r.certificationRequestInfo;
+
+ ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req,
+ &rinfo->subjectPKInfo);
+ if (ret) {
+ free_CertificationRequest(&r);
+ _hx509_request_free(req);
+ return ret;
+ }
+
+ ret = _hx509_name_from_Name(&rinfo->subject, &subject);
+ if (ret) {
+ free_CertificationRequest(&r);
+ _hx509_request_free(req);
+ return ret;
+ }
+ ret = _hx509_request_set_name(context, *req, subject);
+ hx509_name_free(&subject);
+ free_CertificationRequest(&r);
+ if (ret) {
+ _hx509_request_free(req);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+int
+_hx509_request_print(hx509_context context, hx509_request req, FILE *f)
+{
+ int ret;
+
+ if (req->name) {
+ char *subject;
+ ret = hx509_name_to_string(req->name, &subject);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Failed to print name");
+ return ret;
+ }
+ fprintf(f, "name: %s\n", subject);
+ free(subject);
+ }
+
+ return 0;
+}
+
diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c
index 0d477945c8..ddcb17ee38 100644
--- a/source4/heimdal/lib/hx509/revoke.c
+++ b/source4/heimdal/lib/hx509/revoke.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
+RCSID("$Id: revoke.c 21153 2007-06-18 21:55:46Z lha $");
struct revoke_crl {
char *path;
@@ -572,10 +572,10 @@ hx509_revoke_verify(hx509_context context,
continue;
}
- for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) {
+ for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) {
heim_octet_string os;
- ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber,
+ ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber,
&c->tbsCertificate.serialNumber);
if (ret != 0)
continue;
@@ -594,13 +594,13 @@ hx509_revoke_verify(hx509_context context,
ret = _hx509_verify_signature(context,
NULL,
- &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
+ &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm,
&os,
- &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash);
+ &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash);
if (ret != 0)
continue;
- switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) {
+ switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) {
case choice_OCSPCertStatus_good:
break;
case choice_OCSPCertStatus_revoked:
@@ -609,13 +609,13 @@ hx509_revoke_verify(hx509_context context,
}
/* don't allow the update to be in the future */
- if (ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate >
+ if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate >
now + context->ocsp_time_diff)
continue;
/* don't allow the next updte to be in the past */
- if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) {
- if (*ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate < now)
+ if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) {
+ if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now)
continue;
} else
/* Should force a refetch, but can we ? */;
@@ -1077,6 +1077,7 @@ hx509_crl_alloc(hx509_context context, hx509_crl *crl)
if (ret) {
free(*crl);
*crl = NULL;
+ return ret;
}
(*crl)->expire = 0;
return ret;
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c
index 93f3e44ba1..12f75d0bcd 100644
--- a/source4/heimdal/lib/krb5/crypto.c
+++ b/source4/heimdal/lib/krb5/crypto.c
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $");
+RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $");
#undef CRYPTO_DEBUG
#ifdef CRYPTO_DEBUG
@@ -3162,8 +3162,9 @@ decrypt_internal_derived(krb5_context context,
unsigned long l;
checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
- if (len < checksum_sz) {
- krb5_set_error_string(context, "Encrypted data shorter then checksum");
+ if (len < checksum_sz + et->confoundersize) {
+ krb5_set_error_string(context, "Encrypted data shorter then "
+ "checksum + confunder");
return KRB5_BAD_MSIZE;
}
diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c
index 761224b82c..8a0af23e40 100644
--- a/source4/heimdal/lib/krb5/get_cred.c
+++ b/source4/heimdal/lib/krb5/get_cred.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $");
+RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $");
/*
* Take the `body' and encode it into `padata' using the credentials
@@ -411,7 +411,6 @@ get_cred_kdc_usage(krb5_context context,
krb5_keyblock *subkey = NULL;
size_t len;
Ticket second_ticket_data;
- int send_to_kdc_flags = 0;
METHOD_DATA padata;
krb5_data_zero(&resp);
@@ -511,11 +510,18 @@ get_cred_kdc_usage(krb5_context context,
/*
* Send and receive
*/
-again:
- ret = krb5_sendto_kdc_flags (context, &enc,
- &krbtgt->server->name.name_string.val[1],
- &resp,
- send_to_kdc_flags);
+ {
+ krb5_sendto_ctx stctx;
+ ret = krb5_sendto_ctx_alloc(context, &stctx);
+ if (ret)
+ return ret;
+ krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+
+ ret = krb5_sendto_context (context, stctx, &enc,
+ krbtgt->server->name.name_string.val[1],
+ &resp);
+ krb5_sendto_ctx_free(context, stctx);
+ }
if(ret)
goto out;
@@ -550,12 +556,6 @@ again:
} else if(krb5_rd_error(context, &resp, &error) == 0) {
ret = krb5_error_from_rd_error(context, &error, in_creds);
krb5_free_error_contents(context, &error);
-
- if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) {
- send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
- krb5_data_free(&resp);
- goto again;
- }
} else if(resp.data && ((char*)resp.data)[0] == 4) {
ret = KRB5KRB_AP_ERR_V4_REPLY;
krb5_clear_error_string(context);
@@ -1191,6 +1191,10 @@ krb5_get_creds(krb5_context context,
flags.b.forwardable = 1;
if (options & KRB5_GC_NO_TRANSIT_CHECK)
flags.b.disable_transited_check = 1;
+ if (options & KRB5_GC_CONSTRAINED_DELEGATION) {
+ flags.b.request_anonymous = 1; /* XXX ARGH confusion */
+ flags.b.constrained_delegation = 1;
+ }
tgts = NULL;
ret = get_cred_from_kdc_flags(context, flags, ccache,
@@ -1206,3 +1210,62 @@ krb5_get_creds(krb5_context context,
krb5_cc_store_cred(context, ccache, *out_creds);
return ret;
}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_renewed_creds(krb5_context context,
+ krb5_creds *creds,
+ krb5_const_principal client,
+ krb5_ccache ccache,
+ const char *in_tkt_service)
+{
+ krb5_error_code ret;
+ krb5_kdc_flags flags;
+ krb5_creds in, *template;
+
+ memset(&in, 0, sizeof(in));
+
+ ret = krb5_copy_principal(context, client, &in.client);
+ if (ret)
+ return ret;
+
+ if (in_tkt_service) {
+ ret = krb5_parse_name(context, in_tkt_service, &in.server);
+ if (ret) {
+ krb5_free_principal(context, in.client);
+ return ret;
+ }
+ } else {
+ const char *realm = krb5_principal_get_realm(context, client);
+
+ ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME,
+ realm, NULL);
+ if (ret) {
+ krb5_free_principal(context, in.client);
+ return ret;
+ }
+ }
+
+ flags.i = 0;
+ flags.b.renewable = flags.b.renew = 1;
+
+ /*
+ * Get template from old credential cache for the same entry, if
+ * this failes, no worries.
+ */
+ ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template);
+ if (ret == 0) {
+ flags.b.forwardable = template->flags.b.forwardable;
+ flags.b.proxiable = template->flags.b.proxiable;
+ krb5_free_creds (context, template);
+ }
+
+ ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds);
+ krb5_free_principal(context, in.client);
+ krb5_free_principal(context, in.server);
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c
index a58435a9ea..1676da3bd6 100644
--- a/source4/heimdal/lib/krb5/init_creds_pw.c
+++ b/source4/heimdal/lib/krb5/init_creds_pw.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $");
+RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $");
typedef struct krb5_get_init_creds_ctx {
KDCOptions flags;
@@ -1221,8 +1221,8 @@ init_cred_loop(krb5_context context,
krb5_data resp;
size_t len;
size_t size;
- int send_to_kdc_flags = 0;
krb5_krbhst_info *hi = NULL;
+ krb5_sendto_ctx stctx = NULL;
memset(&md, 0, sizeof(md));
@@ -1238,6 +1238,11 @@ init_cred_loop(krb5_context context,
if (ret)
return ret;
+ ret = krb5_sendto_ctx_alloc(context, &stctx);
+ if (ret)
+ goto out;
+ krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+
/* Set a new nonce. */
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
ctx->nonce &= 0xffffffff;
@@ -1281,10 +1286,9 @@ init_cred_loop(krb5_context context,
if(len != ctx->req_buffer.length)
krb5_abortx(context, "internal error in ASN.1 encoder");
- ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer,
- &creds->client->realm, &resp,
- send_to_kdc_flags);
- if (ret)
+ ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
+ creds->client->realm, &resp);
+ if (ret)
goto out;
memset (&rep, 0, sizeof(rep));
@@ -1329,16 +1333,6 @@ init_cred_loop(krb5_context context,
krb5_free_error_contents(context, &error);
if (ret)
goto out;
- } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
- if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) {
- if (ret_as_reply)
- rep.error = error;
- else
- krb5_free_error_contents(context, &error);
- goto out;
- }
- krb5_free_error_contents(context, &error);
- send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
} else {
_krb5_get_init_creds_opt_set_krb5_error(context,
init_cred_opts,
@@ -1437,6 +1431,8 @@ init_cred_loop(krb5_context context,
}
}
out:
+ if (stctx)
+ krb5_sendto_ctx_free(context, stctx);
krb5_data_free(&ctx->req_buffer);
free_METHOD_DATA(&md);
memset(&md, 0, sizeof(md));
diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h
index be718f6714..a551c42ecd 100644
--- a/source4/heimdal/lib/krb5/krb5-private.h
+++ b/source4/heimdal/lib/krb5/krb5-private.h
@@ -149,6 +149,14 @@ _krb5_kcm_noop (
krb5_context /*context*/,
krb5_ccache /*id*/);
+krb5_error_code
+_krb5_kdc_retry (
+ krb5_context /*context*/,
+ krb5_sendto_ctx /*ctx*/,
+ void */*data*/,
+ const krb5_data */*reply*/,
+ int */*action*/);
+
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_cr_err_reply (
krb5_context /*context*/,
diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h
index e852bffeb1..058496434e 100644
--- a/source4/heimdal/lib/krb5/krb5-protos.h
+++ b/source4/heimdal/lib/krb5/krb5-protos.h
@@ -2244,6 +2244,14 @@ krb5_get_pw_salt (
krb5_salt */*salt*/);
krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_renewed_creds (
+ krb5_context /*context*/,
+ krb5_creds */*creds*/,
+ krb5_const_principal /*client*/,
+ krb5_ccache /*ccache*/,
+ const char */*in_tkt_service*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_get_server_rcache (
krb5_context /*context*/,
const krb5_data */*piece*/,
@@ -2868,6 +2876,12 @@ krb5_parse_name_flags (
int /*flags*/,
krb5_principal */*principal*/);
+krb5_error_code
+krb5_parse_nametype (
+ krb5_context /*context*/,
+ const char */*str*/,
+ int32_t */*nametype*/);
+
const char* KRB5_LIB_FUNCTION
krb5_passwd_result_to_string (
krb5_context /*context*/,
@@ -3071,7 +3085,7 @@ krb5_rd_cred2 (
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_error (
krb5_context /*context*/,
- krb5_data */*msg*/,
+ const krb5_data */*msg*/,
KRB_ERROR */*result*/);
krb5_error_code KRB5_LIB_FUNCTION
@@ -3347,6 +3361,43 @@ krb5_sendto (
krb5_data */*receive*/);
krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_context (
+ krb5_context /*context*/,
+ krb5_sendto_ctx /*ctx*/,
+ const krb5_data */*send_data*/,
+ const krb5_realm /*realm*/,
+ krb5_data */*receive*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_add_flags (
+ krb5_sendto_ctx /*ctx*/,
+ int /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_ctx_alloc (
+ krb5_context /*context*/,
+ krb5_sendto_ctx */*ctx*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_free (
+ krb5_context /*context*/,
+ krb5_sendto_ctx /*ctx*/);
+
+int KRB5_LIB_FUNCTION
+krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_func (
+ krb5_sendto_ctx /*ctx*/,
+ krb5_sendto_ctx_func /*func*/,
+ void */*data*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_type (
+ krb5_sendto_ctx /*ctx*/,
+ int /*type*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_sendto_kdc (
krb5_context /*context*/,
const krb5_data */*send_data*/,
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index eefda81ca9..345fe70764 100644
--- a/source4/heimdal/lib/krb5/krb5.h
+++ b/source4/heimdal/lib/krb5/krb5.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */
+/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */
#ifndef __KRB5_H__
#define __KRB5_H__
@@ -361,6 +361,7 @@ typedef union {
#define KRB5_GC_NO_STORE (1U << 3)
#define KRB5_GC_FORWARDABLE (1U << 4)
#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5)
+#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6)
/* constants for compare_creds (and cc_retrieve_cred) */
#define KRB5_TC_DONT_MATCH_REALM (1U << 31)
@@ -753,9 +754,18 @@ enum {
/* flags for krb5_unparse_name_flags */
enum {
KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
- KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2,
+ KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4
};
+typedef struct krb5_sendto_ctx *krb5_sendto_ctx;
+
+#define KRB5_SENDTO_DONE 0
+#define KRB5_SENDTO_RESTART 1
+#define KRB5_SENDTO_CONTINUE 2
+
+typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *);
+
struct credentials; /* this is to keep the compiler happy */
struct getargs;
struct sockaddr;
diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et
index 785c258ee0..6714401e45 100644
--- a/source4/heimdal/lib/krb5/krb5_err.et
+++ b/source4/heimdal/lib/krb5/krb5_err.et
@@ -3,7 +3,7 @@
#
# This might look like a com_err file, but is not
#
-id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
+id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
error_table krb5
@@ -35,8 +35,10 @@ error_code KEY_EXPIRED, "Password has expired"
error_code PREAUTH_FAILED, "Preauthentication failed"
error_code PREAUTH_REQUIRED, "Additional pre-authentication required"
error_code SERVER_NOMATCH, "Requested server and ticket don't match"
+error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only"
+error_code PATH_NOT_ACCEPTED, "KDC Policy rejects transited path"
+error_code SVC_UNAVAILABLE, "A service is not available"
-# 27-30 are reserved
index 31
prefix KRB5KRB_AP
error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
@@ -108,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo
index 128
prefix
-error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
+error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode"
error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password"
diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c
index 51bf934bfd..69b52dd808 100644
--- a/source4/heimdal/lib/krb5/krbhst.c
+++ b/source4/heimdal/lib/krb5/krbhst.c
@@ -35,7 +35,7 @@
#include <resolve.h>
#include "locate_plugin.h"
-RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $");
+RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $");
static int
string_to_proto(const char *string)
@@ -501,10 +501,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
hostlen = strlen(host);
hi = calloc(1, sizeof(*hi) + hostlen);
- if(hi == NULL) {
- free(host);
+ if(hi == NULL)
return ENOMEM;
- }
hi->proto = krbhst_get_default_proto(kd);
hi->port = hi->def_port = socket_get_port(addr);
diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c
index 0d410b57d2..8050bdb9b4 100644
--- a/source4/heimdal/lib/krb5/misc.c
+++ b/source4/heimdal/lib/krb5/misc.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $");
+RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $");
krb5_error_code KRB5_LIB_FUNCTION
_krb5_s4u2self_to_checksumdata(krb5_context context,
@@ -51,6 +51,7 @@ _krb5_s4u2self_to_checksumdata(krb5_context context,
krb5_clear_error_string(context);
return ENOMEM;
}
+ krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
ret = krb5_store_int32(sp, self->name.name_type);
if (ret)
goto out;
diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c
index 55d4f5ff56..f7a5e83ea3 100644
--- a/source4/heimdal/lib/krb5/pac.c
+++ b/source4/heimdal/lib/krb5/pac.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $");
+RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $");
struct PAC_INFO_BUFFER {
uint32_t type;
@@ -409,6 +409,8 @@ verify_checksum(krb5_context context,
krb5_error_code ret;
Checksum cksum;
+ memset(&cksum, 0, sizeof(cksum));
+
sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
sig->buffersize);
if (sp == NULL) {
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index dd82842084..105cab554d 100755
--- a/source4/heimdal/lib/krb5/pkinit.c
+++ b/source4/heimdal/lib/krb5/pkinit.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $");
+RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $");
struct krb5_dh_moduli {
char *name;
@@ -554,18 +554,13 @@ pk_mk_padata(krb5_context context,
if (ret)
goto out;
- ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(),
- &content_info);
+ ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
krb5_data_free(&sd_buf);
- if (ret)
- goto out;
-
- ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length,
- &content_info, &size, ret);
- if (ret)
+ if (ret) {
+ krb5_set_error_string(context,
+ "ContentInfo wrapping of signedData failed");
goto out;
- if (buf.length != size)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ }
if (ctx->type == COMPAT_WIN2K) {
PA_PK_AS_REQ_Win2k winreq;
@@ -794,6 +789,7 @@ get_reply_key_win(krb5_context context,
if (ret) {
krb5_set_error_string(context, "PKINIT failed copying reply key");
free(*key);
+ *key = NULL;
}
return ret;
@@ -856,6 +852,7 @@ get_reply_key(krb5_context context,
if (ret) {
krb5_set_error_string(context, "PKINIT failed copying reply key");
free(*key);
+ *key = NULL;
}
return ret;
@@ -929,6 +926,7 @@ pk_verify_host(krb5_context context,
if (hi) {
ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert,
ctx->require_hostname_match,
+ HX509_HN_HOSTNAME,
hi->hostname,
hi->ai->ai_addr, hi->ai->ai_addrlen);
@@ -942,7 +940,8 @@ pk_verify_host(krb5_context context,
static krb5_error_code
pk_rd_pa_reply_enckey(krb5_context context,
int type,
- const ContentInfo *rep,
+ const heim_octet_string *indata,
+ const heim_oid *dataType,
const char *realm,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
@@ -954,27 +953,19 @@ pk_rd_pa_reply_enckey(krb5_context context,
{
krb5_error_code ret;
struct krb5_pk_cert *host = NULL;
- size_t size;
- int length;
- void *p;
krb5_data content;
heim_oid contentType = { 0, NULL };
- if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
+ if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
krb5_set_error_string(context, "PKINIT: Invalid content type");
return EINVAL;
}
- if (rep->content == NULL) {
- krb5_set_error_string(context, "PKINIT: No content in reply");
- return EINVAL;
- }
-
ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
ctx->id->certs,
HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
- rep->content->data,
- rep->content->length,
+ indata->data,
+ indata->length,
NULL,
&contentType,
&content);
@@ -983,41 +974,52 @@ pk_rd_pa_reply_enckey(krb5_context context,
"Failed to unenvelope CMS data in PK-INIT reply");
return ret;
}
+ der_free_oid(&contentType);
+
+#if 0 /* windows LH with interesting CMS packets, leaks memory */
+ {
+ size_t ph = 1 + der_length_len (length);
+ unsigned char *ptr = malloc(length + ph);
+ size_t l;
- p = content.data;
- length = content.length;
+ memcpy(ptr + ph, p, length);
+
+ ret = der_put_length_and_tag (ptr + ph - 1, ph, length,
+ ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ if (ret)
+ return ret;
+ ptr += ph - l;
+ length += l;
+ p = ptr;
+ }
+#endif
/* win2k uses ContentInfo */
if (type == COMPAT_WIN2K) {
- ContentInfo ci;
+ heim_oid type;
+ heim_octet_string out;
- ret = decode_ContentInfo(p, length, &ci, &size);
- if (ret) {
- krb5_set_error_string(context,
- "PKINIT: failed decoding ContentInfo: %d",
- ret);
- goto out;
- }
-
- if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
+ ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
+ if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
ret = EINVAL; /* XXX */
krb5_set_error_string(context, "PKINIT: Invalid content type");
+ der_free_oid(&type);
+ der_free_octet_string(&out);
goto out;
}
- if (ci.content == NULL) {
- ret = EINVAL; /* XXX */
- krb5_set_error_string(context, "PKINIT: Invalid content type");
+ der_free_oid(&type);
+ krb5_data_free(&content);
+ ret = krb5_data_copy(&content, out.data, out.length);
+ der_free_octet_string(&out);
+ if (ret) {
+ krb5_set_error_string(context, "PKINIT: out of memory");
goto out;
}
- krb5_data_free(&content);
- content = *ci.content;
- p = ci.content->data;
- length = ci.content->length;
}
ret = _krb5_pk_verify_sign(context,
- p,
- length,
+ content.data,
+ content.length,
ctx->id,
&contentType,
&content,
@@ -1073,7 +1075,8 @@ pk_rd_pa_reply_enckey(krb5_context context,
static krb5_error_code
pk_rd_pa_reply_dh(krb5_context context,
- const ContentInfo *rep,
+ const heim_octet_string *indata,
+ const heim_oid *dataType,
const char *realm,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
@@ -1097,19 +1100,14 @@ pk_rd_pa_reply_dh(krb5_context context,
krb5_data_zero(&content);
memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
- if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
+ if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
krb5_set_error_string(context, "PKINIT: Invalid content type");
return EINVAL;
}
- if (rep->content == NULL) {
- krb5_set_error_string(context, "PKINIT: No content in reply");
- return EINVAL;
- }
-
ret = _krb5_pk_verify_sign(context,
- rep->content->data,
- rep->content->length,
+ indata->data,
+ indata->length,
ctx->id,
&contentType,
&content,
@@ -1261,20 +1259,19 @@ _krb5_pk_rd_pa_reply(krb5_context context,
{
krb5_pk_init_ctx ctx = c;
krb5_error_code ret;
- ContentInfo ci;
size_t size;
/* Check for IETF PK-INIT first */
if (ctx->type == COMPAT_IETF) {
PA_PK_AS_REP rep;
+ heim_octet_string os, data;
+ heim_oid oid;
if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
krb5_set_error_string(context, "PKINIT: wrong padata recv");
return EINVAL;
}
- memset(&rep, 0, sizeof(rep));
-
ret = decode_PA_PK_AS_REP(pa->padata_value.data,
pa->padata_value.length,
&rep,
@@ -1286,49 +1283,42 @@ _krb5_pk_rd_pa_reply(krb5_context context,
switch (rep.element) {
case choice_PA_PK_AS_REP_dhInfo:
- ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data,
- rep.u.dhInfo.dhSignedData.length,
- &ci,
- &size);
- if (ret) {
- krb5_set_error_string(context,
- "PKINIT: decoding failed DH "
- "ContentInfo: %d", ret);
-
- free_PA_PK_AS_REP(&rep);
- break;
- }
- ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi,
- ctx->clientDHNonce,
- rep.u.dhInfo.serverDHNonce,
- nonce, pa, key);
- free_ContentInfo(&ci);
- free_PA_PK_AS_REP(&rep);
-
+ os = rep.u.dhInfo.dhSignedData;
break;
case choice_PA_PK_AS_REP_encKeyPack:
- ret = decode_ContentInfo(rep.u.encKeyPack.data,
- rep.u.encKeyPack.length,
- &ci,
- &size);
- free_PA_PK_AS_REP(&rep);
- if (ret) {
- krb5_set_error_string(context,
- "PKINIT: -25 decoding failed "
- "ContentInfo: %d", ret);
- break;
- }
- ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx,
- etype, hi, nonce, req_buffer, pa, key);
- free_ContentInfo(&ci);
- return ret;
+ os = rep.u.encKeyPack;
+ break;
default:
free_PA_PK_AS_REP(&rep);
krb5_set_error_string(context, "PKINIT: -27 reply "
"invalid content type");
- ret = EINVAL;
+ return EINVAL;
+ }
+
+ ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
+ return ret;
+ }
+
+ switch (rep.element) {
+ case choice_PA_PK_AS_REP_dhInfo:
+ ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
+ ctx->clientDHNonce,
+ rep.u.dhInfo.serverDHNonce,
+ nonce, pa, key);
break;
+ case choice_PA_PK_AS_REP_encKeyPack:
+ ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm,
+ ctx, etype, hi, nonce, req_buffer, pa, key);
+ break;
+ default:
+ krb5_abortx(context, "pk-init as-rep case not possible to happen");
}
+ der_free_octet_string(&data);
+ der_free_oid(&oid);
+ free_PA_PK_AS_REP(&rep);
} else if (ctx->type == COMPAT_WIN2K) {
PA_PK_AS_REP_Win2k w2krep;
@@ -1357,23 +1347,25 @@ _krb5_pk_rd_pa_reply(krb5_context context,
krb5_clear_error_string(context);
switch (w2krep.element) {
- case choice_PA_PK_AS_REP_Win2k_encKeyPack:
- ret = decode_ContentInfo(w2krep.u.encKeyPack.data,
- w2krep.u.encKeyPack.length,
- &ci,
- &size);
+ case choice_PA_PK_AS_REP_Win2k_encKeyPack: {
+ heim_octet_string data;
+ heim_oid oid;
+
+ ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack,
+ &oid, &data, NULL);
free_PA_PK_AS_REP_Win2k(&w2krep);
if (ret) {
- krb5_set_error_string(context,
- "PKINIT: decoding failed "
- "ContentInfo: %d",
- ret);
+ krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
return ret;
}
- ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx,
- etype, hi, nonce, req_buffer, pa, key);
- free_ContentInfo(&ci);
+
+ ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm,
+ ctx, etype, hi, nonce, req_buffer, pa, key);
+ der_free_octet_string(&data);
+ der_free_oid(&oid);
+
break;
+ }
default:
free_PA_PK_AS_REP_Win2k(&w2krep);
krb5_set_error_string(context, "PKINIT: win2k reply invalid "
@@ -1473,8 +1465,7 @@ _krb5_pk_load_id(krb5_context context,
id = calloc(1, sizeof(*id));
if (id == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
- ret = ENOMEM;
- goto out;
+ return ENOMEM;
}
ret = hx509_context_init(&id->hx509ctx);
diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c
index f19464bf3c..68317a12c0 100644
--- a/source4/heimdal/lib/krb5/plugin.c
+++ b/source4/heimdal/lib/krb5/plugin.c
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $");
+RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -96,6 +96,7 @@ loadlib(krb5_context context,
(*e)->dsohandle = dlopen(lib, RTLD_LAZY);
if ((*e)->dsohandle == NULL) {
free(*e);
+ *e = NULL;
krb5_set_error_string(context, "Failed to load %s: %s",
lib, dlerror());
return ENOMEM;
diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c
index ef3f5412db..c1a29d266b 100644
--- a/source4/heimdal/lib/krb5/principal.c
+++ b/source4/heimdal/lib/krb5/principal.c
@@ -41,7 +41,7 @@
#include <fnmatch.h>
#include "resolve.h"
-RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $");
+RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $");
#define princ_num_comp(P) ((P)->name.name_string.len)
#define princ_type(P) ((P)->name.name_type)
@@ -281,15 +281,19 @@ krb5_parse_name(krb5_context context,
static const char quotable_chars[] = " \n\t\b\\/@";
static const char replace_chars[] = " ntb\\/@";
+static const char nq_chars[] = " \\/@";
#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
static size_t
-quote_string(const char *s, char *out, size_t idx, size_t len)
+quote_string(const char *s, char *out, size_t idx, size_t len, int display)
{
const char *p, *q;
for(p = s; *p && idx < len; p++){
- if((q = strchr(quotable_chars, *p))){
+ q = strchr(quotable_chars, *p);
+ if (q && display) {
+ add_char(out, idx, len, replace_chars[q - quotable_chars]);
+ } else if (q) {
add_char(out, idx, len, '\\');
add_char(out, idx, len, replace_chars[q - quotable_chars]);
}else
@@ -312,6 +316,7 @@ unparse_name_fixed(krb5_context context,
int i;
int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
+ int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
if (!no_realm && princ_realm(principal) == NULL) {
krb5_set_error_string(context, "Realm missing from principal, "
@@ -322,7 +327,7 @@ unparse_name_fixed(krb5_context context,
for(i = 0; i < princ_num_comp(principal); i++){
if(i)
add_char(name, idx, len, '/');
- idx = quote_string(princ_ncomp(principal, i), name, idx, len);
+ idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
if(idx == len) {
krb5_set_error_string(context, "Out of space printing principal");
return ERANGE;
@@ -341,7 +346,7 @@ unparse_name_fixed(krb5_context context,
}
if(!short_form && !no_realm) {
add_char(name, idx, len, '@');
- idx = quote_string(princ_realm(principal), name, idx, len);
+ idx = quote_string(princ_realm(principal), name, idx, len, display);
if(idx == len) {
krb5_set_error_string(context,
"Out of space printing realm of principal");
@@ -1213,3 +1218,37 @@ krb5_sname_to_principal (krb5_context context,
krb5_free_host_realm(context, realms);
return ret;
}
+
+static const struct {
+ const char *type;
+ int32_t value;
+} nametypes[] = {
+ { "UNKNOWN", KRB5_NT_UNKNOWN },
+ { "PRINCIPAL", KRB5_NT_PRINCIPAL },
+ { "SRV_INST", KRB5_NT_SRV_INST },
+ { "SRV_HST", KRB5_NT_SRV_HST },
+ { "SRV_XHST", KRB5_NT_SRV_XHST },
+ { "UID", KRB5_NT_UID },
+ { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
+ { "SMTP_NAME", KRB5_NT_SMTP_NAME },
+ { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
+ { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
+ { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
+ { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
+ { NULL }
+};
+
+krb5_error_code
+krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
+{
+ size_t i;
+
+ for(i = 0; nametypes[i].type; i++) {
+ if (strcasecmp(nametypes[i].type, str) == 0) {
+ *nametype = nametypes[i].value;
+ return 0;
+ }
+ }
+ krb5_set_error_string(context, "Failed to find name type %s", str);
+ return KRB5_PARSE_MALFORMED;
+}
diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c
index 89615ee8ac..e7646467af 100644
--- a/source4/heimdal/lib/krb5/rd_error.c
+++ b/source4/heimdal/lib/krb5/rd_error.c
@@ -33,11 +33,11 @@
#include "krb5_locl.h"
-RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $");
+RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_error(krb5_context context,
- krb5_data *msg,
+ const krb5_data *msg,
KRB_ERROR *result)
{
diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c
index 6c70244327..c1a4df2b01 100644
--- a/source4/heimdal/lib/krb5/send_to_kdc.c
+++ b/source4/heimdal/lib/krb5/send_to_kdc.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $");
+RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $");
struct send_to_kdc {
krb5_send_to_kdc_func func;
@@ -413,26 +413,16 @@ krb5_sendto_kdc_flags(krb5_context context,
int flags)
{
krb5_error_code ret;
- krb5_krbhst_handle handle;
- int type;
-
- if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
- type = KRB5_KRBHST_ADMIN;
- else
- type = KRB5_KRBHST_KDC;
+ krb5_sendto_ctx ctx;
- if (send_data->length > context->large_msg_size)
- flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
-
- ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle);
+ ret = krb5_sendto_ctx_alloc(context, &ctx);
if (ret)
return ret;
+ krb5_sendto_ctx_add_flags(ctx, flags);
+ krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL);
- ret = krb5_sendto(context, send_data, handle, receive);
- krb5_krbhst_free(context, handle);
- if (ret == KRB5_KDC_UNREACH)
- krb5_set_error_string(context,
- "unable to reach any KDC in realm %s", *realm);
+ ret = krb5_sendto_context(context, ctx, send_data, *realm, receive);
+ krb5_sendto_ctx_free(context, ctx);
return ret;
}
@@ -458,4 +448,157 @@ krb5_set_send_to_kdc_func(krb5_context context,
return 0;
}
+struct krb5_sendto_ctx {
+ int flags;
+ int type;
+ krb5_sendto_ctx_func func;
+ void *data;
+};
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx)
+{
+ *ctx = calloc(1, sizeof(**ctx));
+ if (*ctx == NULL) {
+ krb5_set_error_string(context, "out of memory");
+ return ENOMEM;
+ }
+ return 0;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags)
+{
+ ctx->flags |= flags;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx)
+{
+ return ctx->flags;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type)
+{
+ ctx->type = type;
+}
+
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx,
+ krb5_sendto_ctx_func func,
+ void *data)
+{
+ ctx->func = func;
+ ctx->data = data;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_context(krb5_context context,
+ krb5_sendto_ctx ctx,
+ const krb5_data *send_data,
+ const krb5_realm realm,
+ krb5_data *receive)
+{
+ krb5_error_code ret;
+ krb5_krbhst_handle handle = NULL;
+ int type, freectx = 0;
+ int action;
+
+ krb5_data_zero(receive);
+
+ if (ctx == NULL) {
+ freectx = 1;
+ ret = krb5_sendto_ctx_alloc(context, &ctx);
+ if (ret)
+ return ret;
+ }
+
+ type = ctx->type;
+ if (type == 0) {
+ if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
+ type = KRB5_KRBHST_ADMIN;
+ else
+ type = KRB5_KRBHST_KDC;
+ }
+
+ if (send_data->length > context->large_msg_size)
+ ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
+
+ /* loop until we get back a appropriate response */
+
+ do {
+ action = KRB5_SENDTO_DONE;
+
+ krb5_data_free(receive);
+
+ if (handle == NULL) {
+ ret = krb5_krbhst_init_flags(context, realm, type,
+ ctx->flags, &handle);
+ if (ret) {
+ if (freectx)
+ krb5_sendto_ctx_free(context, ctx);
+ return ret;
+ }
+ }
+
+ ret = krb5_sendto(context, send_data, handle, receive);
+ if (ret)
+ break;
+ if (ctx->func) {
+ ret = (*ctx->func)(context, ctx, ctx->data, receive, &action);
+ if (ret)
+ break;
+ }
+ if (action != KRB5_SENDTO_CONTINUE) {
+ krb5_krbhst_free(context, handle);
+ handle = NULL;
+ }
+ } while (action != KRB5_SENDTO_DONE);
+ if (handle)
+ krb5_krbhst_free(context, handle);
+ if (ret == KRB5_KDC_UNREACH)
+ krb5_set_error_string(context,
+ "unable to reach any KDC in realm %s", realm);
+ if (ret)
+ krb5_data_free(receive);
+ if (freectx)
+ krb5_sendto_ctx_free(context, ctx);
+ return ret;
+}
+
+krb5_error_code
+_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data,
+ const krb5_data *reply, int *action)
+{
+ krb5_error_code ret;
+ KRB_ERROR error;
+
+ if(krb5_rd_error(context, reply, &error))
+ return 0;
+
+ ret = krb5_error_from_rd_error(context, &error, NULL);
+ krb5_free_error_contents(context, &error);
+
+ switch(ret) {
+ case KRB5KRB_ERR_RESPONSE_TOO_BIG: {
+ if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG)
+ break;
+ krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG);
+ *action = KRB5_SENDTO_RESTART;
+ break;
+ }
+ case KRB5KDC_ERR_SVC_UNAVAILABLE:
+ *action = KRB5_SENDTO_CONTINUE;
+ break;
+ }
+ return 0;
+}
diff --git a/source4/heimdal/lib/ntlm/heimntlm-protos.h b/source4/heimdal/lib/ntlm/heimntlm-protos.h
index 2df32dfa50..438ba2b94d 100644
--- a/source4/heimdal/lib/ntlm/heimntlm-protos.h
+++ b/source4/heimdal/lib/ntlm/heimntlm-protos.h
@@ -34,6 +34,14 @@ heim_ntlm_calculate_ntlm2 (
struct ntlm_buf */*answer*/);
int
+heim_ntlm_calculate_ntlm2_sess (
+ const unsigned char clnt_nonce[8],
+ const unsigned char svr_chal[8],
+ const unsigned char ntlm_hash[16],
+ struct ntlm_buf */*lm*/,
+ struct ntlm_buf */*ntlm*/);
+
+int
heim_ntlm_decode_targetinfo (
struct ntlm_buf */*data*/,
int /*ucs2*/,
diff --git a/source4/heimdal/lib/ntlm/ntlm.c b/source4/heimdal/lib/ntlm/ntlm.c
index af950cc3b5..1961c7fa22 100644
--- a/source4/heimdal/lib/ntlm/ntlm.c
+++ b/source4/heimdal/lib/ntlm/ntlm.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,7 +33,7 @@
#include <config.h>
-RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
+RCSID("$Id: ntlm.c 21317 2007-06-25 19:22:02Z lha $");
#include <stdio.h>
#include <stdlib.h>
@@ -52,6 +52,12 @@ RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
#include <heimntlm.h>
+/*
+ * Source of NTLM information:
+ * http://davenport.sourceforge.net/ntlm.html
+ */
+
+
struct sec_buffer {
uint16_t length;
uint16_t allocated;
@@ -760,6 +766,10 @@ splitandenc(unsigned char *hash,
memset(key, 0, sizeof(key));
}
+/*
+ * String-to-key function for NTLM
+ */
+
int
heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
{
@@ -784,6 +794,10 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
return 0;
}
+/*
+ * Calculate NTLMv1 response hash
+ */
+
int
heim_ntlm_calculate_ntlm1(void *key, size_t len,
unsigned char challange[8],
@@ -809,6 +823,10 @@ heim_ntlm_calculate_ntlm1(void *key, size_t len,
return 0;
}
+/*
+ * Calculate NTLMv1 master key
+ */
+
int
heim_ntlm_build_ntlm1_master(void *key, size_t len,
struct ntlm_buf *session,
@@ -880,8 +898,8 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len,
ascii2ucs2le(username, 1, &buf);
HMAC_Update(&c, buf.data, buf.length);
free(buf.data);
- /* turn target into ucs2-le */
- ascii2ucs2le(target, 0, &buf);
+ /* uppercase target and turn into ucs2-le */
+ ascii2ucs2le(target, 1, &buf);
HMAC_Update(&c, buf.data, buf.length);
free(buf.data);
}
@@ -914,6 +932,10 @@ nt2unixtime(uint64_t t)
}
+/*
+ * Calculate NTLMv2 response
+ */
+
int
heim_ntlm_calculate_ntlm2(const void *key, size_t len,
const char *username,
@@ -948,25 +970,27 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
return ENOMEM;
krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
- CHECK(krb5_store_uint32(sp, 0x01010000), 0);
+ CHECK(krb5_store_uint32(sp, 0x00000101), 0);
CHECK(krb5_store_uint32(sp, 0), 0);
/* timestamp le 64 bit ts */
CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0);
CHECK(krb5_store_uint32(sp, t >> 32), 0);
+
CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
+
+ CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */
CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length),
infotarget->length);
- /* unknown */
- /* CHECK(krb5_store_uint32(sp, 0), 0); */
+ CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */
CHECK(krb5_storage_to_data(sp, &data), 0);
krb5_storage_free(sp);
sp = NULL;
HMAC_CTX_init(&c);
- HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
- HMAC_Update(&c, data.data, data.length);
+ HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
HMAC_Update(&c, serverchallange, 8);
+ HMAC_Update(&c, data.data, data.length);
HMAC_Final(&c, ntlmv2answer, &hmaclen);
HMAC_CTX_cleanup(&c);
@@ -996,6 +1020,10 @@ out:
static const int authtimediff = 3600 * 2; /* 2 hours */
+/*
+ * Verify NTLMv2 response.
+ */
+
int
heim_ntlm_verify_ntlm2(const void *key, size_t len,
const char *username,
@@ -1009,6 +1037,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
krb5_error_code ret;
unsigned int hmaclen;
unsigned char clientanswer[16];
+ unsigned char clientnonce[8];
unsigned char serveranswer[16];
krb5_storage *sp;
HMAC_CTX c;
@@ -1039,7 +1068,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
CHECK(krb5_storage_read(sp, clientanswer, 16), 16);
CHECK(krb5_ret_uint32(sp, &temp), 0);
- CHECK(temp, 0x01010000);
+ CHECK(temp, 0x00000101);
CHECK(krb5_ret_uint32(sp, &temp), 0);
CHECK(temp, 0);
/* timestamp le 64 bit ts */
@@ -1056,9 +1085,12 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
}
/* client challange */
- CHECK(krb5_storage_read(sp, serveranswer, 8), 8);
+ CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
- infotarget->length = answer->length - 40;
+ CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */
+
+ /* should really unparse the infotarget, but lets pick up everything */
+ infotarget->length = answer->length - krb5_storage_seek(sp, 0, SEEK_CUR);
infotarget->data = malloc(infotarget->length);
if (infotarget->data == NULL) {
ret = ENOMEM;
@@ -1066,14 +1098,14 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
}
CHECK(krb5_storage_read(sp, infotarget->data, infotarget->length),
infotarget->length);
- /* XXX remove the unknown uint32_t */
+ /* XXX remove the unknown ?? */
krb5_storage_free(sp);
sp = NULL;
HMAC_CTX_init(&c);
- HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
- HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
+ HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
HMAC_Update(&c, serverchallange, 8);
+ HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
HMAC_Final(&c, serveranswer, &hmaclen);
HMAC_CTX_cleanup(&c);
@@ -1089,3 +1121,52 @@ out:
krb5_storage_free(sp);
return ret;
}
+
+
+/*
+ * Calculate the NTLM2 Session Response
+ */
+
+int
+heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
+ const unsigned char svr_chal[8],
+ const unsigned char ntlm_hash[16],
+ struct ntlm_buf *lm,
+ struct ntlm_buf *ntlm)
+{
+ unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
+ unsigned char res[21], *resp;
+ MD5_CTX md5;
+
+ lm->data = malloc(24);
+ if (lm->data == NULL)
+ return ENOMEM;
+ lm->length = 24;
+
+ ntlm->data = malloc(24);
+ if (ntlm->data == NULL) {
+ free(lm->data);
+ lm->data = NULL;
+ return ENOMEM;
+ }
+ ntlm->length = 24;
+
+ /* first setup the lm resp */
+ memset(lm->data, 0, 24);
+ memcpy(lm->data, clnt_nonce, 8);
+
+ MD5_Init(&md5);
+ MD5_Update(&md5, svr_chal, 8); /* session nonce part 1 */
+ MD5_Update(&md5, clnt_nonce, 8); /* session nonce part 2 */
+ MD5_Final(ntlm2_sess_hash, &md5); /* will only use first 8 bytes */
+
+ memset(res, 0, sizeof(res));
+ memcpy(res, ntlm_hash, 16);
+
+ resp = ntlm->data;
+ splitandenc(&res[0], ntlm2_sess_hash, resp + 0);
+ splitandenc(&res[7], ntlm2_sess_hash, resp + 8);
+ splitandenc(&res[14], ntlm2_sess_hash, resp + 16);
+
+ return 0;
+}
diff --git a/source4/heimdal/lib/roken/roken_gethostby.c b/source4/heimdal/lib/roken/roken_gethostby.c
index 08eed5f8ed..0b25fbdb3d 100644
--- a/source4/heimdal/lib/roken/roken_gethostby.c
+++ b/source4/heimdal/lib/roken/roken_gethostby.c
@@ -33,7 +33,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id: roken_gethostby.c 21005 2007-06-08 01:54:35Z lha $");
+RCSID("$Id: roken_gethostby.c 21157 2007-06-18 22:03:13Z lha $");
#endif
#include <roken.h>
@@ -111,7 +111,7 @@ int ROKEN_LIB_FUNCTION
roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
{
char *proxy_host = NULL;
- int proxy_port;
+ int proxy_port = 0;
char *dns_host, *dns_path;
int dns_port;