summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-07-03 08:00:08 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:58:59 -0500
commitec0035c9b8e0690f3bc21f3de089c39eae660916 (patch)
tree183dddce1bc0704f0c137df03e611d255fb68e11 /source4/heimdal/lib/krb5
parent74b35321dc043188386d0305508b5276a5290d0d (diff)
downloadsamba-ec0035c9b8e0690f3bc21f3de089c39eae660916.tar.gz
samba-ec0035c9b8e0690f3bc21f3de089c39eae660916.tar.bz2
samba-ec0035c9b8e0690f3bc21f3de089c39eae660916.zip
r23678: Update to current lorikeet-heimdal (-r 767), which should fix the
panics on hosts without /dev/random. Andrew Bartlett (This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f)
Diffstat (limited to 'source4/heimdal/lib/krb5')
-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
15 files changed, 481 insertions, 175 deletions
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;
+}