From 4f8ba5ad6ac9b7153b0e13654e59f47e67b3f608 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 13 Nov 2009 10:51:14 +1100 Subject: s4:heimdal: import lorikeet-heimdal-200911122202 (commit 9291fd2d101f3eecec550178634faa94ead3e9a1) --- source4/heimdal/lib/krb5/auth_context.c | 11 +- source4/heimdal/lib/krb5/build_auth.c | 80 +++---- source4/heimdal/lib/krb5/context.c | 31 +-- source4/heimdal/lib/krb5/crypto.c | 2 +- source4/heimdal/lib/krb5/error_string.c | 102 +++++++- source4/heimdal/lib/krb5/fcache.c | 33 ++- source4/heimdal/lib/krb5/generate_seq_number.c | 24 +- source4/heimdal/lib/krb5/generate_subkey.c | 19 +- source4/heimdal/lib/krb5/get_cred.c | 154 ++++++------ source4/heimdal/lib/krb5/get_for_creds.c | 13 +- source4/heimdal/lib/krb5/krb5_locl.h | 7 +- source4/heimdal/lib/krb5/mk_error.c | 5 +- source4/heimdal/lib/krb5/mk_req_ext.c | 3 +- source4/heimdal/lib/krb5/pkinit.c | 309 ++++++++++++++++--------- source4/heimdal/lib/krb5/principal.c | 167 +++++++++++-- source4/heimdal/lib/krb5/replay.c | 24 +- source4/heimdal/lib/krb5/warn.c | 8 +- 17 files changed, 641 insertions(+), 351 deletions(-) (limited to 'source4/heimdal/lib/krb5') 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); @@ -815,31 +821,6 @@ krb5_get_default_in_tkt_etypes(krb5_context context, return 0; } -/** - * 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. * 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, "", (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_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 +#include /* * 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 #endif +#include + #include #include #include @@ -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= ""; + *arg= ""; } } -- cgit