summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/krb5
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-11-13 10:51:14 +1100
committerAndrew Bartlett <abartlet@samba.org>2009-11-13 23:19:05 +1100
commit4f8ba5ad6ac9b7153b0e13654e59f47e67b3f608 (patch)
treeca189d440b0a298cdcb3769d994828508dcd2e76 /source4/heimdal/lib/krb5
parent5bc87c14a1f5b45ed86e7ff9663f5f0aa2f70094 (diff)
downloadsamba-4f8ba5ad6ac9b7153b0e13654e59f47e67b3f608.tar.gz
samba-4f8ba5ad6ac9b7153b0e13654e59f47e67b3f608.tar.bz2
samba-4f8ba5ad6ac9b7153b0e13654e59f47e67b3f608.zip
s4:heimdal: import lorikeet-heimdal-200911122202 (commit 9291fd2d101f3eecec550178634faa94ead3e9a1)
Diffstat (limited to 'source4/heimdal/lib/krb5')
-rw-r--r--source4/heimdal/lib/krb5/auth_context.c11
-rw-r--r--source4/heimdal/lib/krb5/build_auth.c80
-rw-r--r--source4/heimdal/lib/krb5/context.c31
-rw-r--r--source4/heimdal/lib/krb5/crypto.c2
-rw-r--r--source4/heimdal/lib/krb5/error_string.c102
-rw-r--r--source4/heimdal/lib/krb5/fcache.c33
-rw-r--r--source4/heimdal/lib/krb5/generate_seq_number.c24
-rw-r--r--source4/heimdal/lib/krb5/generate_subkey.c19
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c154
-rw-r--r--source4/heimdal/lib/krb5/get_for_creds.c13
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h7
-rw-r--r--source4/heimdal/lib/krb5/mk_error.c5
-rw-r--r--source4/heimdal/lib/krb5/mk_req_ext.c3
-rw-r--r--source4/heimdal/lib/krb5/pkinit.c309
-rw-r--r--source4/heimdal/lib/krb5/principal.c167
-rw-r--r--source4/heimdal/lib/krb5/replay.c24
-rw-r--r--source4/heimdal/lib/krb5/warn.c8
17 files changed, 641 insertions, 351 deletions
diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c
index bfc183d168..dfb9f6a0e3 100644
--- a/source4/heimdal/lib/krb5/auth_context.c
+++ b/source4/heimdal/lib/krb5/auth_context.c
@@ -171,10 +171,10 @@ krb5_auth_con_genaddrs(krb5_context context,
if (auth_context->local_address == NULL) {
len = sizeof(ss_local);
if(getsockname(fd, local, &len) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret,
- "getsockname: %s",
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "getsockname: %s", buf);
goto out;
}
ret = krb5_sockaddr2address (context, local, &local_k_address);
@@ -189,9 +189,10 @@ krb5_auth_con_genaddrs(krb5_context context,
if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
len = sizeof(ss_remote);
if(getpeername(fd, remote, &len) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret,
- "getpeername: %s", strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "getpeername: %s", buf);
goto out;
}
ret = krb5_sockaddr2address (context, remote, &remote_k_address);
diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c
index bf77fd4e77..a845e0ac33 100644
--- a/source4/heimdal/lib/krb5/build_auth.c
+++ b/source4/heimdal/lib/krb5/build_auth.c
@@ -100,35 +100,30 @@ make_etypelist(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
-krb5_build_authenticator (krb5_context context,
+_krb5_build_authenticator(krb5_context context,
krb5_auth_context auth_context,
krb5_enctype enctype,
krb5_creds *cred,
Checksum *cksum,
- Authenticator **auth_result,
krb5_data *result,
krb5_key_usage usage)
{
- Authenticator *auth;
+ Authenticator auth;
u_char *buf = NULL;
size_t buf_size;
size_t len;
krb5_error_code ret;
krb5_crypto crypto;
- auth = calloc(1, sizeof(*auth));
- if (auth == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
+ memset(&auth, 0, sizeof(auth));
- auth->authenticator_vno = 5;
- copy_Realm(&cred->client->realm, &auth->crealm);
- copy_PrincipalName(&cred->client->name, &auth->cname);
+ auth.authenticator_vno = 5;
+ copy_Realm(&cred->client->realm, &auth.crealm);
+ copy_PrincipalName(&cred->client->name, &auth.cname);
- krb5_us_timeofday (context, &auth->ctime, &auth->cusec);
+ krb5_us_timeofday (context, &auth.ctime, &auth.cusec);
- ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
+ ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth.subkey);
if(ret)
goto fail;
@@ -137,33 +132,43 @@ krb5_build_authenticator (krb5_context context,
krb5_generate_seq_number (context,
&cred->session,
&auth_context->local_seqnumber);
- ALLOC(auth->seq_number, 1);
- if(auth->seq_number == NULL) {
+ ALLOC(auth.seq_number, 1);
+ if(auth.seq_number == NULL) {
ret = ENOMEM;
goto fail;
}
- *auth->seq_number = auth_context->local_seqnumber;
+ *auth.seq_number = auth_context->local_seqnumber;
} else
- auth->seq_number = NULL;
- auth->authorization_data = NULL;
- auth->cksum = cksum;
-
- if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) {
- /*
- * This is not GSS-API specific, we only enable it for
- * GSS for now
- */
- ret = make_etypelist(context, &auth->authorization_data);
+ auth.seq_number = NULL;
+ auth.authorization_data = NULL;
+
+ if (cksum) {
+ ALLOC(auth.cksum, 1);
+ if (auth.cksum == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ ret = copy_Checksum(cksum, auth.cksum);
if (ret)
goto fail;
+
+ if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) {
+ /*
+ * This is not GSS-API specific, we only enable it for
+ * GSS for now
+ */
+ ret = make_etypelist(context, &auth.authorization_data);
+ if (ret)
+ goto fail;
+ }
}
/* XXX - Copy more to auth_context? */
- auth_context->authenticator->ctime = auth->ctime;
- auth_context->authenticator->cusec = auth->cusec;
+ auth_context->authenticator->ctime = auth.ctime;
+ auth_context->authenticator->cusec = auth.cusec;
- ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret);
+ ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret);
if (ret)
goto fail;
if(buf_size != len)
@@ -175,7 +180,7 @@ krb5_build_authenticator (krb5_context context,
ret = krb5_encrypt (context,
crypto,
usage /* KRB5_KU_AP_REQ_AUTH */,
- buf + buf_size - len,
+ buf,
len,
result);
krb5_crypto_destroy(context, crypto);
@@ -183,20 +188,9 @@ krb5_build_authenticator (krb5_context context,
if (ret)
goto fail;
+ fail:
+ free_Authenticator (&auth);
free (buf);
- if (auth_result)
- *auth_result = auth;
- else {
- /* Don't free the `cksum', it's allocated by the caller */
- auth->cksum = NULL;
- free_Authenticator (auth);
- free (auth);
- }
- return ret;
- fail:
- free_Authenticator (auth);
- free (auth);
- free (buf);
return ret;
}
diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c
index 8bf8b79022..79e1000fd0 100644
--- a/source4/heimdal/lib/krb5/context.c
+++ b/source4/heimdal/lib/krb5/context.c
@@ -304,6 +304,12 @@ krb5_init_context(krb5_context *context)
cc_ops_register(p);
kt_ops_register(p);
+#ifdef PKINIT
+ ret = hx509_context_init(&p->hx509ctx);
+ if (ret)
+ goto out;
+#endif
+
out:
if(ret) {
krb5_free_context(p);
@@ -816,31 +822,6 @@ krb5_get_default_in_tkt_etypes(krb5_context context,
}
/**
- * Return the error string for the error code. The caller must not
- * free the string.
- *
- * @param context Kerberos 5 context.
- * @param code Kerberos error code.
- *
- * @return the error message matching code
- *
- * @ingroup krb5
- */
-
-const char* KRB5_LIB_FUNCTION
-krb5_get_err_text(krb5_context context, krb5_error_code code)
-{
- const char *p = NULL;
- if(context != NULL)
- p = com_right(context->et_list, code);
- if(p == NULL)
- p = strerror(code);
- if (p == NULL)
- p = "Unknown error";
- return p;
-}
-
-/**
* Init the built-in ets in the Kerberos library.
*
* @param context kerberos context to add the ets too
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c
index bdcdb2ea0a..68233c290d 100644
--- a/source4/heimdal/lib/krb5/crypto.c
+++ b/source4/heimdal/lib/krb5/crypto.c
@@ -2058,7 +2058,7 @@ evp_encrypt(krb5_context context,
return 0;
}
-static const char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
+static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
static krb5_error_code
evp_encrypt_cts(krb5_context context,
diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c
index 829c080a55..d2661dcaf5 100644
--- a/source4/heimdal/lib/krb5/error_string.c
+++ b/source4/heimdal/lib/krb5/error_string.c
@@ -104,6 +104,68 @@ krb5_vset_error_message (krb5_context context, krb5_error_code ret,
HEIMDAL_MUTEX_unlock(context->mutex);
}
+/**
+ * Prepend the context full error string for a specific error code.
+ * The error that is stored should be internationalized.
+ *
+ * @param context Kerberos 5 context
+ * @param ret The error code
+ * @param fmt Error string for the error code
+ * @param ... printf(3) style parameters.
+ *
+ * @ingroup krb5_error
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_prepend_error_message(krb5_context context, krb5_error_code ret,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)))
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ krb5_vset_error_message (context, ret, fmt, ap);
+ va_end(ap);
+}
+
+/**
+ * Prepend the contexts's full error string for a specific error code.
+ *
+ * @param context Kerberos 5 context
+ * @param ret The error code
+ * @param fmt Error string for the error code
+ * @param args printf(3) style parameters.
+ *
+ * @ingroup krb5_error
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_vprepend_error_message (krb5_context context, krb5_error_code ret,
+ const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)))
+{
+ char *str, *str2;
+ HEIMDAL_MUTEX_lock(context->mutex);
+ if (context->error_code != ret) {
+ HEIMDAL_MUTEX_unlock(context->mutex);
+ return;
+ }
+ vasprintf(&str, fmt, args);
+ if (context->error_string) {
+ int e;
+
+ e = asprintf(&str2, "%s: %s", str, context->error_string);
+ free(context->error_string);
+ if (e < 0)
+ context->error_string = NULL;
+ else
+ context->error_string = str2;
+ free(str);
+ } else
+ context->error_string = str;
+ HEIMDAL_MUTEX_unlock(context->mutex);
+}
+
/**
* Return the error message in context. On error or no error string,
@@ -155,7 +217,6 @@ krb5_have_error_string(krb5_context context)
const char * KRB5_LIB_FUNCTION
krb5_get_error_message(krb5_context context, krb5_error_code code)
{
- const char *cstr;
char *str;
HEIMDAL_MUTEX_lock(context->mutex);
@@ -172,10 +233,13 @@ krb5_get_error_message(krb5_context context, krb5_error_code code)
if (code == 0)
return strdup("Success");
-
- cstr = krb5_get_err_text(context, code);
- if (cstr)
- return strdup(cstr);
+ {
+ const char *msg;
+ char buf[128];
+ msg = com_right_r(context->et_list, code, buf, sizeof(buf));
+ if (msg)
+ return strdup(msg);
+ }
if (asprintf(&str, "<unknown error: %d>", (int)code) == -1)
return NULL;
@@ -199,3 +263,31 @@ krb5_free_error_message(krb5_context context, const char *msg)
{
free(rk_UNCONST(msg));
}
+
+
+/**
+ * Return the error string for the error code. The caller must not
+ * free the string.
+ *
+ * This function is deprecated since its not threadsafe.
+ *
+ * @param context Kerberos 5 context.
+ * @param code Kerberos error code.
+ *
+ * @return the error message matching code
+ *
+ * @ingroup krb5
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_get_err_text(krb5_context context, krb5_error_code code) KRB5_DEPRECATED
+{
+ const char *p = NULL;
+ if(context != NULL)
+ p = com_right(context->et_list, code);
+ if(p == NULL)
+ p = strerror(code);
+ if (p == NULL)
+ p = "Unknown error";
+ return p;
+}
diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c
index f8e74f1ddc..cda15e483b 100644
--- a/source4/heimdal/lib/krb5/fcache.c
+++ b/source4/heimdal/lib/krb5/fcache.c
@@ -95,13 +95,15 @@ _krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive,
N_("timed out locking cache file %s", "file"),
filename);
break;
- default:
+ default: {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
N_("error locking cache file %s: %s",
- "file, error"),
- filename, strerror(ret));
+ "file, error"), filename, buf);
break;
}
+ }
return ret;
}
@@ -127,12 +129,14 @@ _krb5_xunlock(krb5_context context, int fd)
case EINVAL: /* filesystem doesn't support locking, let the user have it */
ret = 0;
break;
- default:
+ default: {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
- N_("Failed to unlock file: %s", ""),
- strerror(ret));
+ N_("Failed to unlock file: %s", ""), buf);
break;
}
+ }
return ret;
}
@@ -369,9 +373,11 @@ fcc_open(krb5_context context,
int fd;
fd = open(filename, flags, mode);
if(fd < 0) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret, N_("open(%s): %s", "file, error"),
- filename, strerror(ret));
+ filename, buf);
return ret;
}
rk_cloexec(fd);
@@ -431,9 +437,11 @@ fcc_initialize(krb5_context context,
fcc_unlock(context, fd);
if (close(fd) < 0)
if (ret == 0) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message (context, ret, N_("close %s: %s", ""),
- FILENAME(id), strerror(ret));
+ FILENAME(id), buf);
}
return ret;
}
@@ -485,9 +493,11 @@ fcc_store_cred(krb5_context context,
fcc_unlock(context, fd);
if (close(fd) < 0) {
if (ret == 0) {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
ret = errno;
krb5_set_error_message (context, ret, N_("close %s: %s", ""),
- FILENAME(id), strerror(ret));
+ FILENAME(id), buf);
}
}
return ret;
@@ -875,12 +885,13 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
ret = rename(FILENAME(from), FILENAME(to));
if (ret && errno != EXDEV) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
N_("Rename of file from %s "
"to %s failed: %s", ""),
- FILENAME(from), FILENAME(to),
- strerror(ret));
+ FILENAME(from), FILENAME(to), buf);
return ret;
} else if (ret && errno == EXDEV) {
/* make a copy and delete the orignal */
diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c
index 2764f1a914..b7bd8b99f8 100644
--- a/source4/heimdal/lib/krb5/generate_seq_number.c
+++ b/source4/heimdal/lib/krb5/generate_seq_number.c
@@ -38,23 +38,11 @@ krb5_generate_seq_number(krb5_context context,
const krb5_keyblock *key,
uint32_t *seqno)
{
- krb5_error_code ret;
- krb5_keyblock *subkey;
- uint32_t q;
- u_char *p;
- int i;
-
- ret = krb5_generate_subkey (context, key, &subkey);
- if (ret)
- return ret;
-
- q = 0;
- for (p = (u_char *)subkey->keyvalue.data, i = 0;
- i < subkey->keyvalue.length;
- ++i, ++p)
- q = (q << 8) | *p;
- q &= 0xffffffff;
- *seqno = q;
- krb5_free_keyblock (context, subkey);
+ if (RAND_bytes((void *)seqno, sizeof(*seqno)) != 1)
+ krb5_abortx(context, "Failed to generate random block");
+ /* MIT used signed numbers, lets not stomp into that space directly */
+ *seqno &= 0x3fffffff;
+ if (*seqno == 0)
+ *seqno = 1;
return 0;
}
diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c
index efb6cce288..003a66ac01 100644
--- a/source4/heimdal/lib/krb5/generate_subkey.c
+++ b/source4/heimdal/lib/krb5/generate_subkey.c
@@ -33,13 +33,18 @@
#include <krb5_locl.h>
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_generate_subkey(krb5_context context,
- const krb5_keyblock *key,
- krb5_keyblock **subkey)
-{
- return krb5_generate_subkey_extended(context, key, key->keytype, subkey);
-}
+/**
+ * Generate subkey, from keyblock
+ *
+ * @param context kerberos context
+ * @param key session key
+ * @param etype encryption type of subkey, if ETYPE_NULL, use key's enctype
+ * @param subkey returned new, free with krb5_free_keyblock().
+ *
+ * @return 0 on success or a Kerberos 5 error code
+ *
+* @ingroup krb5_crypto
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey_extended(krb5_context context,
diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c
index 10417f1a52..63152bbfa6 100644
--- a/source4/heimdal/lib/krb5/get_cred.c
+++ b/source4/heimdal/lib/krb5/get_cred.c
@@ -32,6 +32,7 @@
*/
#include <krb5_locl.h>
+#include <assert.h>
/*
* Take the `body' and encode it into `padata' using the credentials
@@ -79,7 +80,7 @@ static krb5_error_code
set_auth_data (krb5_context context,
KDC_REQ_BODY *req_body,
krb5_authdata *authdata,
- krb5_keyblock *key)
+ krb5_keyblock *subkey)
{
if(authdata->len) {
size_t len, buf_size;
@@ -101,7 +102,7 @@ set_auth_data (krb5_context context,
N_("malloc: out of memory", ""));
return ENOMEM;
}
- ret = krb5_crypto_init(context, key, 0, &crypto);
+ ret = krb5_crypto_init(context, subkey, 0, &crypto);
if (ret) {
free (buf);
free (req_body->enc_authorization_data);
@@ -111,7 +112,6 @@ set_auth_data (krb5_context context,
krb5_encrypt_EncryptedData(context,
crypto,
KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
- /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */
buf,
len,
0,
@@ -143,7 +143,9 @@ init_tgs_req (krb5_context context,
krb5_keyblock **subkey,
TGS_REQ *t)
{
+ krb5_auth_context ac = NULL;
krb5_error_code ret = 0;
+ krb5_keyblock *key = NULL;
memset(t, 0, sizeof(*t));
t->pvno = 5;
@@ -238,60 +240,39 @@ init_tgs_req (krb5_context context,
}
}
- {
- krb5_auth_context ac;
- krb5_keyblock *key = NULL;
-
- ret = krb5_auth_con_init(context, &ac);
- if(ret)
- goto fail;
-
- if (krb5_config_get_bool_default(context, NULL, FALSE,
- "realms",
- krbtgt->server->realm,
- "tgs_require_subkey",
- NULL))
- {
- ret = krb5_generate_subkey (context, &krbtgt->session, &key);
- if (ret) {
- krb5_auth_con_free (context, ac);
- goto fail;
- }
-
- ret = krb5_auth_con_setlocalsubkey(context, ac, key);
- if (ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free (context, ac);
- goto fail;
- }
- }
-
- ret = set_auth_data (context, &t->req_body, &in_creds->authdata,
- key ? key : &krbtgt->session);
- if (ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free (context, ac);
- goto fail;
- }
+ ret = krb5_auth_con_init(context, &ac);
+ if(ret)
+ goto fail;
+
+ ret = krb5_generate_subkey_extended(context, &krbtgt->session,
+ ETYPE_NULL, &key);
+ if (ret)
+ goto fail;
+
+ ret = krb5_auth_con_setlocalsubkey(context, ac, key);
+ if (ret)
+ goto fail;
+
+ ret = set_auth_data (context, &t->req_body, &in_creds->authdata, key);
+ if (ret)
+ goto fail;
+
+ ret = make_pa_tgs_req(context,
+ ac,
+ &t->req_body,
+ &t->padata->val[0],
+ krbtgt);
+ if(ret)
+ goto fail;
- ret = make_pa_tgs_req(context,
- ac,
- &t->req_body,
- &t->padata->val[0],
- krbtgt);
- if(ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free(context, ac);
- goto fail;
- }
- *subkey = key;
-
- krb5_auth_con_free(context, ac);
- }
+ *subkey = key;
+ key = NULL;
+
fail:
+ if (key)
+ krb5_free_keyblock (context, key);
+ if (ac)
+ krb5_auth_con_free(context, ac);
if (ret) {
t->req_body.addresses = NULL;
free_TGS_REQ (t);
@@ -349,17 +330,12 @@ decrypt_tkt_with_subkey (krb5_context context,
size_t size;
krb5_crypto crypto;
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret)
- return ret;
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- usage,
- &dec_rep->kdc_rep.enc_part,
- &data);
- krb5_crypto_destroy(context, crypto);
- if(ret && subkey){
- /* DCE compat -- try to decrypt with subkey */
+ assert(usage == 0);
+
+ /*
+ * start out with trying with subkey if we have one
+ */
+ if (subkey) {
ret = krb5_crypto_init(context, subkey, 0, &crypto);
if (ret)
return ret;
@@ -370,6 +346,17 @@ decrypt_tkt_with_subkey (krb5_context context,
&data);
krb5_crypto_destroy(context, crypto);
}
+ if (subkey == NULL || ret) {
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+ ret = krb5_decrypt_EncryptedData (context,
+ crypto,
+ KRB5_KU_TGS_REP_ENC_PART_SESSION,
+ &dec_rep->kdc_rep.enc_part,
+ &data);
+ krb5_crypto_destroy(context, crypto);
+ }
if (ret)
return ret;
@@ -549,7 +536,7 @@ get_cred_kdc(krb5_context context,
out_creds,
&krbtgt->session,
NULL,
- KRB5_KU_TGS_REP_ENC_PART_SESSION,
+ 0,
&krbtgt->addresses,
nonce,
eflags,
@@ -574,10 +561,8 @@ out:
free_METHOD_DATA(&padata);
krb5_data_free(&resp);
krb5_data_free(&enc);
- if(subkey){
- krb5_free_keyblock_contents(context, subkey);
- free(subkey);
- }
+ if(subkey)
+ krb5_free_keyblock(context, subkey);
return ret;
}
@@ -898,6 +883,12 @@ get_cred_kdc_referral(krb5_context context,
int loop = 0;
int ok_as_delegate = 1;
+ if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
+ N_("Name too short to do referals, skipping", ""));
+ return KRB5KDC_ERR_PATH_NOT_ACCEPTED;
+ }
+
memset(&tgt, 0, sizeof(tgt));
memset(&ticket, 0, sizeof(ticket));
@@ -1087,6 +1078,12 @@ krb5_get_credentials_with_flags(krb5_context context,
krb5_creds *res_creds;
int i;
+ if (in_creds->session.keytype) {
+ ret = krb5_enctype_valid(context, in_creds->session.keytype);
+ if (ret)
+ return ret;
+ }
+
*out_creds = NULL;
res_creds = calloc(1, sizeof(*res_creds));
if (res_creds == NULL) {
@@ -1282,6 +1279,12 @@ krb5_get_creds(krb5_context context,
krb5_creds *res_creds;
int i;
+ if (opt && opt->enctype) {
+ ret = krb5_enctype_valid(context, opt->enctype);
+ if (ret)
+ return ret;
+ }
+
memset(&in_creds, 0, sizeof(in_creds));
in_creds.server = rk_UNCONST(inprinc);
@@ -1289,7 +1292,10 @@ krb5_get_creds(krb5_context context,
if (ret)
return ret;
- options = opt->options;
+ if (opt)
+ options = opt->options;
+ else
+ options = 0;
flags.i = 0;
*out_creds = NULL;
@@ -1301,7 +1307,7 @@ krb5_get_creds(krb5_context context,
return ENOMEM;
}
- if (opt->enctype) {
+ if (opt && opt->enctype) {
in_creds.session.keytype = opt->enctype;
options |= KRB5_TC_MATCH_KEYTYPE;
}
@@ -1312,7 +1318,7 @@ krb5_get_creds(krb5_context context,
*/
ret = krb5_cc_retrieve_cred(context,
ccache,
- opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0,
+ options & KRB5_TC_MATCH_KEYTYPE,
&in_creds, res_creds);
/*
* If we got a credential, check if credential is expired before
diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c
index 19e48173df..8c58dae187 100644
--- a/source4/heimdal/lib/krb5/get_for_creds.c
+++ b/source4/heimdal/lib/krb5/get_for_creds.c
@@ -137,13 +137,12 @@ krb5_fwd_tgt_creds (krb5_context context,
memset (&creds, 0, sizeof(creds));
creds.client = client;
- ret = krb5_build_principal(context,
- &creds.server,
- strlen(client_realm),
- client_realm,
- KRB5_TGS_NAME,
- client_realm,
- NULL);
+ ret = krb5_make_principal(context,
+ &creds.server,
+ client_realm,
+ KRB5_TGS_NAME,
+ client_realm,
+ NULL);
if (ret)
return ret;
diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h
index 71dc1327c6..d436215769 100644
--- a/source4/heimdal/lib/krb5/krb5_locl.h
+++ b/source4/heimdal/lib/krb5/krb5_locl.h
@@ -136,6 +136,8 @@ struct sockaddr_dl;
#include <door.h>
#endif
+#include <com_err.h>
+
#include <roken.h>
#include <parse_time.h>
#include <base64.h>
@@ -151,6 +153,7 @@ struct sockaddr_dl;
struct send_to_kdc;
/* XXX glue for pkinit */
+struct hx509_certs_data;
struct krb5_pk_identity;
struct krb5_pk_cert;
struct ContentInfo;
@@ -265,6 +268,9 @@ typedef struct krb5_context_data {
#define KRB5_CTX_F_CHECK_PAC 2
#define KRB5_CTX_F_HOMEDIR_ACCESS 4
struct send_to_kdc *send_to_kdc;
+#ifdef PKINIT
+ hx509_context hx509ctx;
+#endif
} krb5_context_data;
#define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}"
@@ -295,7 +301,6 @@ typedef struct krb5_context_data {
#ifdef PKINIT
struct krb5_pk_identity {
- hx509_context hx509ctx;
hx509_verify_ctx verify_ctx;
hx509_certs certs;
hx509_cert cert;
diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c
index f623fc495b..0de30e4ddb 100644
--- a/source4/heimdal/lib/krb5/mk_error.c
+++ b/source4/heimdal/lib/krb5/mk_error.c
@@ -44,6 +44,7 @@ krb5_mk_error(krb5_context context,
int *client_usec,
krb5_data *reply)
{
+ const char *e_text2 = NULL;
KRB_ERROR msg;
krb5_timestamp sec;
int32_t usec;
@@ -62,7 +63,7 @@ krb5_mk_error(krb5_context context,
/* Make sure we only send `protocol' error codes */
if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) {
if(e_text == NULL)
- e_text = krb5_get_err_text(context, error_code);
+ e_text = e_text2 = krb5_get_error_message(context, error_code);
error_code = KRB5KRB_ERR_GENERIC;
}
msg.error_code = error_code - KRB5KDC_ERR_NONE;
@@ -82,6 +83,8 @@ krb5_mk_error(krb5_context context,
}
ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
+ if (e_text2)
+ krb5_free_error_message(context, e_text2);
if (ret)
return ret;
if(reply->length != len)
diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c
index d130272aa1..03fc93b02f 100644
--- a/source4/heimdal/lib/krb5/mk_req_ext.c
+++ b/source4/heimdal/lib/krb5/mk_req_ext.c
@@ -123,12 +123,11 @@ _krb5_mk_req_internal(krb5_context context,
if (ret)
goto out;
- ret = krb5_build_authenticator (context,
+ ret = _krb5_build_authenticator(context,
ac,
ac->keyblock->keytype,
in_creds,
c_opt,
- NULL,
&authenticator,
encrypt_usage);
if (c_opt)
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index 2f6d7854a5..f6457aa5c9 100644
--- a/source4/heimdal/lib/krb5/pkinit.c
+++ b/source4/heimdal/lib/krb5/pkinit.c
@@ -74,6 +74,7 @@ struct krb5_pk_init_ctx_data {
unsigned int require_krbtgt_otherName:1;
unsigned int require_hostname_match:1;
unsigned int trustedCertifiers:1;
+ unsigned int anonymous:1;
};
static void
@@ -193,15 +194,15 @@ find_cert(krb5_context context, struct krb5_pk_identity *id,
for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) {
ret = hx509_query_match_eku(q, cf[i].oid);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed setting %s OID", cf[i].type);
return ret;
}
- ret = hx509_certs_find(id->hx509ctx, id->certs, q, cert);
+ ret = hx509_certs_find(context->hx509ctx, id->certs, q, cert);
if (ret == 0)
break;
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed finding certificate with %s OID", cf[i].type);
}
return ret;
@@ -221,7 +222,7 @@ create_signature(krb5_context context,
if (id->cert == NULL)
flags |= HX509_CMS_SIGNATURE_NO_SIGNER;
- ret = hx509_cms_create_signed_1(id->hx509ctx,
+ ret = hx509_cms_create_signed_1(context->hx509ctx,
flags,
eContentType,
eContent->data,
@@ -233,7 +234,7 @@ create_signature(krb5_context context,
id->certs,
sd_data);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Create CMS signedData");
return ret;
}
@@ -596,7 +597,7 @@ build_auth_pack(krb5_context context,
if (a->supportedCMSTypes == NULL)
return ENOMEM;
- ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL,
+ ret = hx509_crypto_available(context->hx509ctx, HX509_SELECT_ALL, NULL,
&a->supportedCMSTypes->val,
&a->supportedCMSTypes->len);
if (ret)
@@ -756,7 +757,7 @@ pk_mk_padata(krb5_context context,
free_PA_PK_AS_REQ(&req);
goto out;
}
- ret = build_edi(context, ctx->id->hx509ctx,
+ ret = build_edi(context, context->hx509ctx,
ctx->id->anchors, req.trustedCertifiers);
if (ret) {
krb5_set_error_message(context, ret,
@@ -806,6 +807,12 @@ _krb5_pk_mk_padata(krb5_context context,
krb5_pk_init_ctx ctx = c;
int win2k_compat;
+ if (ctx->id->certs == NULL && ctx->anonymous == 0) {
+ krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
+ N_("PKINIT: No user certificate given", ""));
+ return HEIM_PKINIT_NO_PRIVATE_KEY;
+ }
+
win2k_compat = krb5_config_get_bool_default(context, NULL,
FALSE,
"realms",
@@ -873,7 +880,7 @@ pk_verify_sign(krb5_context context,
*signer = NULL;
- ret = hx509_cms_verify_signed(id->hx509ctx,
+ ret = hx509_cms_verify_signed(context->hx509ctx,
id->verify_ctx,
HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH|HX509_CMS_VS_NO_KU_CHECK,
data,
@@ -884,7 +891,7 @@ pk_verify_sign(krb5_context context,
content,
&signer_certs);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"CMS verify signed failed");
return ret;
}
@@ -896,9 +903,9 @@ pk_verify_sign(krb5_context context,
goto out;
}
- ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert);
+ ret = hx509_get_one_cert(context->hx509ctx, signer_certs, &(*signer)->cert);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to get on of the signer certs");
goto out;
}
@@ -1040,7 +1047,7 @@ pk_verify_host(krb5_context context,
krb5_error_code ret = 0;
if (ctx->require_eku) {
- ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
+ ret = hx509_cert_check_eku(context->hx509ctx, host->cert,
&asn1_oid_id_pkkdcekuoid, 0);
if (ret) {
krb5_set_error_message(context, ret,
@@ -1052,7 +1059,7 @@ pk_verify_host(krb5_context context,
hx509_octet_string_list list;
int i;
- ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx,
+ ret = hx509_cert_find_subjectAltName_otherName(context->hx509ctx,
host->cert,
&asn1_oid_id_pkinit_san,
&list);
@@ -1102,7 +1109,7 @@ pk_verify_host(krb5_context context,
return ret;
if (hi) {
- ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert,
+ ret = hx509_verify_hostname(context->hx509ctx, host->cert,
ctx->require_hostname_match,
HX509_HN_HOSTNAME,
hi->hostname,
@@ -1145,7 +1152,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
if (ctx->type == PKINIT_WIN2K)
flags |= HX509_CMS_UE_ALLOW_WEAK;
- ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
+ ret = hx509_cms_unenvelope(context->hx509ctx,
ctx->id->certs,
flags,
indata->data,
@@ -1155,7 +1162,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
&contentType,
&content);
if (ret) {
- pk_copy_error(context, ctx->id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to unenvelope CMS data in PK-INIT reply");
return ret;
}
@@ -1167,8 +1174,26 @@ pk_rd_pa_reply_enckey(krb5_context context,
heim_octet_string out;
ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
- if (ret)
- goto out;
+ if (ret) {
+ /* windows LH with interesting CMS packets */
+ size_t ph = 1 + der_length_len(content.length);
+ unsigned char *ptr = malloc(content.length + ph);
+ size_t l;
+
+ memcpy(ptr + ph, content.data, content.length);
+
+ ret = der_put_length_and_tag (ptr + ph - 1, ph, content.length,
+ ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ if (ret)
+ return ret;
+ free(content.data);
+ content.data = ptr;
+ content.length += ph;
+
+ ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
+ if (ret)
+ goto out;
+ }
if (der_heim_oid_cmp(&type, &asn1_oid_id_pkcs7_signedData)) {
ret = EINVAL; /* XXX */
krb5_set_error_message(context, ret,
@@ -1700,10 +1725,44 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter)
return 0;
}
+static krb5_error_code
+_krb5_pk_set_user_id(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ struct hx509_certs_data *certs)
+{
+ hx509_certs c = hx509_certs_ref(certs);
+ hx509_query *q = NULL;
+ int ret;
+
+ if (ctx->id->certs)
+ hx509_certs_free(&ctx->id->certs);
+ if (ctx->id->cert) {
+ hx509_cert_free(ctx->id->cert);
+ ctx->id->cert = NULL;
+ }
+
+ ctx->id->certs = c;
+ ctx->anonymous = 0;
+
+ ret = hx509_query_alloc(context->hx509ctx, &q);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Allocate query to find signing certificate");
+ return ret;
+ }
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+
+ ret = find_cert(context, ctx->id, q, &ctx->id->cert);
+ hx509_query_free(context->hx509ctx, q);
+
+ return ret;
+}
+
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_load_id(krb5_context context,
struct krb5_pk_identity **ret_id,
- int flags,
const char *user_id,
const char *anchor_id,
char * const *chain_list,
@@ -1713,7 +1772,6 @@ _krb5_pk_load_id(krb5_context context,
char *password)
{
struct krb5_pk_identity *id = NULL;
- hx509_lock lock = NULL;
struct prompter p;
int ret;
@@ -1725,12 +1783,6 @@ _krb5_pk_load_id(krb5_context context,
return HEIM_PKINIT_NO_VALID_CA;
}
- if (user_id == NULL && (flags & 4) == 0) {
- krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
- N_("PKINIT: No user certificate given", ""));
- return HEIM_PKINIT_NO_PRIVATE_KEY;
- }
-
/* load cert */
id = calloc(1, sizeof(*id));
@@ -1740,33 +1792,34 @@ _krb5_pk_load_id(krb5_context context,
return ENOMEM;
}
- ret = hx509_context_init(&id->hx509ctx);
- if (ret)
- goto out;
-
- ret = hx509_lock_init(id->hx509ctx, &lock);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret, "Failed init lock");
- goto out;
- }
-
- if (password && password[0])
- hx509_lock_add_password(lock, password);
-
- if (prompter) {
- p.context = context;
- p.prompter = prompter;
- p.prompter_data = prompter_data;
+ if (user_id) {
+ hx509_lock lock;
- ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
- if (ret)
+ ret = hx509_lock_init(context->hx509ctx, &lock);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret, "Failed init lock");
goto out;
- }
+ }
+
+ if (password && password[0])
+ hx509_lock_add_password(lock, password);
+
+ if (prompter) {
+ p.context = context;
+ p.prompter = prompter;
+ p.prompter_data = prompter_data;
+
+ ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
+ if (ret) {
+ hx509_lock_free(lock);
+ goto out;
+ }
+ }
- if (user_id) {
- ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
+ ret = hx509_certs_init(context->hx509ctx, user_id, 0, lock, &id->certs);
+ hx509_lock_free(lock);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init cert certs");
goto out;
}
@@ -1774,26 +1827,26 @@ _krb5_pk_load_id(krb5_context context,
id->certs = NULL;
}
- ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
+ ret = hx509_certs_init(context->hx509ctx, anchor_id, 0, NULL, &id->anchors);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init anchors");
goto out;
}
- ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain",
+ ret = hx509_certs_init(context->hx509ctx, "MEMORY:pkinit-cert-chain",
0, NULL, &id->certpool);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init chain");
goto out;
}
while (chain_list && *chain_list) {
- ret = hx509_certs_append(id->hx509ctx, id->certpool,
+ ret = hx509_certs_append(context->hx509ctx, id->certpool,
NULL, *chain_list);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to laod chain %s",
*chain_list);
goto out;
@@ -1802,30 +1855,30 @@ _krb5_pk_load_id(krb5_context context,
}
if (revoke_list) {
- ret = hx509_revoke_init(id->hx509ctx, &id->revokectx);
+ ret = hx509_revoke_init(context->hx509ctx, &id->revokectx);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed init revoke list");
goto out;
}
while (*revoke_list) {
- ret = hx509_revoke_add_crl(id->hx509ctx,
+ ret = hx509_revoke_add_crl(context->hx509ctx,
id->revokectx,
*revoke_list);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed load revoke list");
goto out;
}
revoke_list++;
}
} else
- hx509_context_set_missing_revoke(id->hx509ctx, 1);
+ hx509_context_set_missing_revoke(context->hx509ctx, 1);
- ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx);
+ ret = hx509_verify_init_ctx(context->hx509ctx, &id->verify_ctx);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed init verify context");
goto out;
}
@@ -1840,14 +1893,11 @@ _krb5_pk_load_id(krb5_context context,
hx509_certs_free(&id->anchors);
hx509_certs_free(&id->certpool);
hx509_revoke_free(&id->revokectx);
- hx509_context_free(&id->hx509ctx);
+ hx509_context_free(&context->hx509ctx);
free(id);
} else
*ret_id = id;
- if (lock)
- hx509_lock_free(lock);
-
return ret;
}
@@ -2204,7 +2254,6 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
hx509_cert_free(ctx->id->cert);
hx509_certs_free(&ctx->id->anchors);
hx509_certs_free(&ctx->id->certpool);
- hx509_context_free(&ctx->id->hx509ctx);
if (ctx->clientDHNonce) {
krb5_free_data(NULL, ctx->clientDHNonce);
@@ -2275,9 +2324,11 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
x509_anchors = anchors;
}
+ if (flags & 4)
+ opt->opt_private->pk_init_ctx->anonymous = 1;
+
ret = _krb5_pk_load_id(context,
&opt->opt_private->pk_init_ctx->id,
- flags,
user_id,
x509_anchors,
pool,
@@ -2292,31 +2343,14 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
}
if (opt->opt_private->pk_init_ctx->id->certs) {
- hx509_query *q = NULL;
- hx509_cert cert = NULL;
- hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
-
- ret = hx509_query_alloc(hx509ctx, &q);
- if (ret) {
- pk_copy_error(context, hx509ctx, ret,
- "Allocate query to find signing certificate");
- return ret;
- }
-
- hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
-
- ret = find_cert(context, opt->opt_private->pk_init_ctx->id, q, &cert);
- hx509_query_free(hx509ctx, q);
- if (ret)
- return ret;
-
- opt->opt_private->pk_init_ctx->id->cert = cert;
+ _krb5_pk_set_user_id(context,
+ opt->opt_private->pk_init_ctx,
+ opt->opt_private->pk_init_ctx->id->certs);
} else
opt->opt_private->pk_init_ctx->id->cert = NULL;
if ((flags & 2) == 0) {
- hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
+ hx509_context hx509ctx = context->hx509ctx;
hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;
opt->opt_private->pk_init_ctx->keyex = USE_DH;
@@ -2353,6 +2387,33 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
#endif
}
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ struct hx509_certs_data *certs)
+{
+#ifdef PKINIT
+ if (opt->opt_private == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: on non extendable opt", ""));
+ return EINVAL;
+ }
+ if (opt->opt_private->pk_init_ctx == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: on pkinit context", ""));
+ return EINVAL;
+ }
+
+ _krb5_pk_set_user_id(context, opt->opt_private->pk_init_ctx, certs);
+
+ return 0;
+#else
+ krb5_set_error_message(context, EINVAL,
+ N_("no support for PKINIT compiled in", ""));
+ return EINVAL;
+#endif
+}
+
#ifdef PKINIT
static int
@@ -2404,34 +2465,35 @@ krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_enterprise_cert(krb5_context context,
const char *user_id,
krb5_const_realm realm,
- krb5_principal *principal)
+ krb5_principal *principal,
+ struct hx509_certs_data **res)
{
#ifdef PKINIT
krb5_error_code ret;
- hx509_context hx509ctx;
hx509_certs certs, result;
hx509_cert cert;
hx509_query *q;
char *name;
*principal = NULL;
+ if (res)
+ *res = NULL;
- if (user_id == NULL)
+ if (user_id == NULL) {
+ krb5_clear_error_message(context);
return ENOENT;
+ }
- ret = hx509_context_init(&hx509ctx);
- if (ret)
- return ret;
-
- ret = hx509_certs_init(hx509ctx, user_id, 0, NULL, &certs);
+ ret = hx509_certs_init(context->hx509ctx, user_id, 0, NULL, &certs);
if (ret) {
- pk_copy_error(context, hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init cert certs");
return ret;
}
- ret = hx509_query_alloc(hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret) {
+ krb5_set_error_message(context, ret, "out of memory");
hx509_certs_free(&certs);
return ret;
}
@@ -2441,29 +2503,54 @@ _krb5_pk_enterprise_cert(krb5_context context,
hx509_query_match_eku(q, &asn1_oid_id_pkinit_ms_eku);
hx509_query_match_cmp_func(q, find_ms_san, NULL);
- ret = hx509_certs_filter(hx509ctx, certs, q, &result);
- hx509_query_free(hx509ctx, q);
+ ret = hx509_certs_filter(context->hx509ctx, certs, q, &result);
+ hx509_query_free(context->hx509ctx, q);
hx509_certs_free(&certs);
- if (ret)
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to find PKINIT certificate");
return ret;
+ }
- ret = hx509_get_one_cert(hx509ctx, result, &cert);
+ ret = hx509_get_one_cert(context->hx509ctx, result, &cert);
hx509_certs_free(&result);
- if (ret)
- return ret;
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to get one cert");
+ goto out;
+ }
- ret = get_ms_san(hx509ctx, cert, &name);
- if (ret)
- return ret;
+ ret = get_ms_san(context->hx509ctx, cert, &name);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to get MS SAN");
+ goto out;
+ }
ret = krb5_make_principal(context, principal, realm, name, NULL);
free(name);
- hx509_context_free(&hx509ctx);
if (ret)
- return ret;
+ goto out;
krb5_principal_set_type(context, *principal, KRB5_NT_ENTERPRISE_PRINCIPAL);
-
+
+ if (res) {
+ ret = hx509_certs_init(context->hx509ctx, "MEMORY:", 0, NULL, res);
+ if (ret) {
+ hx509_cert_free(cert);
+ goto out;
+ }
+
+ ret = hx509_certs_add(context->hx509ctx, *res, cert);
+ if (ret) {
+ hx509_certs_free(res);
+ goto out;
+ }
+ }
+
+ out:
+ hx509_cert_free(cert);
+
return ret;
#else
krb5_set_error_message(context, EINVAL,
diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c
index 1483d59f9d..d854113a43 100644
--- a/source4/heimdal/lib/krb5/principal.c
+++ b/source4/heimdal/lib/krb5/principal.c
@@ -106,6 +106,17 @@ krb5_principal_set_type(krb5_context context,
princ_type(principal) = type;
}
+/**
+ * Get the type of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to get the type for
+ *
+ * @return the type of principal
+ *
+ * @ingroup krb5_principal
+ */
+
int KRB5_LIB_FUNCTION
krb5_principal_get_type(krb5_context context,
krb5_const_principal principal)
@@ -113,6 +124,17 @@ krb5_principal_get_type(krb5_context context,
return princ_type(principal);
}
+/**
+ * Get the realm of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to get the realm for
+ *
+ * @return realm of the principal, don't free or use after krb5_principal is freed
+ *
+ * @ingroup krb5_principal
+ */
+
const char* KRB5_LIB_FUNCTION
krb5_principal_get_realm(krb5_context context,
krb5_const_principal principal)
@@ -148,6 +170,19 @@ krb5_principal_get_num_comp(krb5_context context,
return princ_num_comp(principal);
}
+/**
+ * Parse a name into a krb5_principal structure, flags controls the behavior.
+ *
+ * @param context Kerberos 5 context
+ * @param name name to parse into a Kerberos principal
+ * @param flags flags to control the behavior
+ * @param principal returned principal, free with krb5_free_principal().
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_parse_name_flags(krb5_context context,
const char *name,
@@ -337,6 +372,18 @@ exit:
return ret;
}
+/**
+ * Parse a name into a krb5_principal structure
+ *
+ * @param context Kerberos 5 context
+ * @param name name to parse into a Kerberos principal
+ * @param principal returned principal, free with krb5_free_principal().
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_parse_name(krb5_context context,
const char *name,
@@ -630,6 +677,20 @@ krb5_principal_set_realm(krb5_context context,
return 0;
}
+#ifndef HEIMDAL_SMALLER
+/**
+ * Build a principal using vararg style building
+ *
+ * @param context A Kerberos context.
+ * @param principal returned principal
+ * @param rlen length of realm
+ * @param realm realm name
+ * @param ... a list of components ended with NULL.
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal(krb5_context context,
@@ -645,6 +706,43 @@ krb5_build_principal(krb5_context context,
va_end(ap);
return ret;
}
+#endif
+
+/**
+ * Build a principal using vararg style building
+ *
+ * @param context A Kerberos context.
+ * @param principal returned principal
+ * @param realm realm name
+ * @param ... a list of components ended with NULL.
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_principal(krb5_context context,
+ krb5_principal *principal,
+ krb5_const_realm realm,
+ ...)
+{
+ krb5_error_code ret;
+ krb5_realm r = NULL;
+ va_list ap;
+ if(realm == NULL) {
+ ret = krb5_get_default_realm(context, &r);
+ if(ret)
+ return ret;
+ realm = r;
+ }
+ va_start(ap, realm);
+ ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
+ va_end(ap);
+ if(r)
+ free(r);
+ return ret;
+}
static krb5_error_code
append_component(krb5_context context, krb5_principal p,
@@ -730,28 +828,6 @@ build_principal(krb5_context context,
return 0;
}
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_make_principal(krb5_context context,
- krb5_principal *principal,
- krb5_const_realm realm,
- ...)
-{
- krb5_error_code ret;
- krb5_realm r = NULL;
- va_list ap;
- if(realm == NULL) {
- ret = krb5_get_default_realm(context, &r);
- if(ret)
- return ret;
- realm = r;
- }
- va_start(ap, realm);
- ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
- va_end(ap);
- if(r)
- free(r);
- return ret;
-}
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal_va(krb5_context context,
@@ -789,6 +865,18 @@ krb5_build_principal_ext(krb5_context context,
return ret;
}
+/**
+ * Copy a principal
+ *
+ * @param context A Kerberos context.
+ * @param inprinc principal to copy
+ * @param outprinc copied principal, free with krb5_free_principal()
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_principal(krb5_context context,
@@ -821,6 +909,8 @@ krb5_copy_principal(krb5_context context,
* @return non zero if equal, 0 if not
*
* @ingroup krb5_principal
+ * @see krb5_principal_compare()
+ * @see krb5_realm_compare()
*/
krb5_boolean KRB5_LIB_FUNCTION
@@ -854,6 +944,19 @@ _krb5_principal_compare_PrincipalName(krb5_context context,
}
+/**
+ * Compares the two principals, including realm of the principals and returns
+ * TRUE if they are the same and FALSE if not.
+ *
+ * @param context Kerberos 5 context
+ * @param princ1 first principal to compare
+ * @param princ2 second principal to compare
+ *
+ * @ingroup krb5_principal
+ * @see krb5_principal_compare_any_realm()
+ * @see krb5_realm_compare()
+ */
+
/*
* return TRUE iff princ1 == princ2
*/
@@ -868,8 +971,16 @@ krb5_principal_compare(krb5_context context,
return krb5_principal_compare_any_realm(context, princ1, princ2);
}
-/*
+/**
* return TRUE iff realm(princ1) == realm(princ2)
+ *
+ * @param context Kerberos 5 context
+ * @param princ1 first principal to compare
+ * @param princ2 second principal to compare
+ *
+ * @ingroup krb5_principal
+ * @see krb5_principal_compare_any_realm()
+ * @see krb5_principal_compare()
*/
krb5_boolean KRB5_LIB_FUNCTION
@@ -880,8 +991,10 @@ krb5_realm_compare(krb5_context context,
return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
}
-/*
+/**
* return TRUE iff princ matches pattern
+ *
+ * @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
@@ -1418,6 +1531,12 @@ static const struct {
{ NULL }
};
+/**
+ * Parse nametype string and return a nametype integer
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code
krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
{
diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c
index be484c29dc..0cad91e437 100644
--- a/source4/heimdal/lib/krb5/replay.c
+++ b/source4/heimdal/lib/krb5/replay.c
@@ -133,9 +133,10 @@ krb5_rc_initialize(krb5_context context,
int ret;
if(f == NULL) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "open(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf);
return ret;
}
tmp.stamp = auth_lifespan;
@@ -158,9 +159,10 @@ krb5_rc_destroy(krb5_context context,
int ret;
if(remove(id->name) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "remove(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "remove(%s): %s", id->name, buf);
return ret;
}
return krb5_rc_close(context, id);
@@ -208,9 +210,10 @@ krb5_rc_store(krb5_context context,
checksum_authenticator(rep, ent.data);
f = fopen(id->name, "r");
if(f == NULL) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "open(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf);
return ret;
}
rk_cloexec_file(f);
@@ -226,18 +229,21 @@ krb5_rc_store(krb5_context context,
}
}
if(ferror(f)){
+ char buf[128];
ret = errno;
fclose(f);
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret, "%s: %s",
- id->name, strerror(ret));
+ id->name, buf);
return ret;
}
fclose(f);
f = fopen(id->name, "a");
if(f == NULL) {
+ char buf[128];
+ strerror_r(errno, buf, sizeof(buf));
krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
- "open(%s): %s", id->name,
- strerror(errno));
+ "open(%s): %s", id->name, buf);
return KRB5_RC_IO_UNKNOWN;
}
fwrite(&ent, 1, sizeof(ent), f);
diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c
index 05239186ec..886a1fe981 100644
--- a/source4/heimdal/lib/krb5/warn.c
+++ b/source4/heimdal/lib/krb5/warn.c
@@ -59,19 +59,13 @@ _warnerr(krb5_context context, int do_errtext,
*arg++ = msg;
}
if(context && do_errtext){
- const char *err_msg;
-
strlcat(xfmt, "%s", sizeof(xfmt));
err_str = krb5_get_error_message(context, code);
if (err_str != NULL) {
*arg = err_str;
} else {
- err_msg = krb5_get_err_text(context, code);
- if (err_msg)
- *arg = err_msg;
- else
- *arg= "<unknown error>";
+ *arg= "<unknown error>";
}
}