diff options
Diffstat (limited to 'source4/heimdal/lib/krb5')
-rw-r--r-- | source4/heimdal/lib/krb5/crypto.c | 7 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/get_cred.c | 89 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/init_creds_pw.c | 28 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krb5-private.h | 8 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krb5-protos.h | 53 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krb5.h | 14 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krb5_err.et | 8 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krbhst.c | 6 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/misc.c | 3 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/pac.c | 4 | ||||
-rwxr-xr-x | source4/heimdal/lib/krb5/pkinit.c | 203 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/plugin.c | 3 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/principal.c | 49 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/rd_error.c | 4 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/send_to_kdc.c | 177 |
15 files changed, 481 insertions, 175 deletions
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 93f3e44ba1..12f75d0bcd 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $"); +RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -3162,8 +3162,9 @@ decrypt_internal_derived(krb5_context context, unsigned long l; checksum_sz = CHECKSUMSIZE(et->keyed_checksum); - if (len < checksum_sz) { - krb5_set_error_string(context, "Encrypted data shorter then checksum"); + if (len < checksum_sz + et->confoundersize) { + krb5_set_error_string(context, "Encrypted data shorter then " + "checksum + confunder"); return KRB5_BAD_MSIZE; } diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 761224b82c..8a0af23e40 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -411,7 +411,6 @@ get_cred_kdc_usage(krb5_context context, krb5_keyblock *subkey = NULL; size_t len; Ticket second_ticket_data; - int send_to_kdc_flags = 0; METHOD_DATA padata; krb5_data_zero(&resp); @@ -511,11 +510,18 @@ get_cred_kdc_usage(krb5_context context, /* * Send and receive */ -again: - ret = krb5_sendto_kdc_flags (context, &enc, - &krbtgt->server->name.name_string.val[1], - &resp, - send_to_kdc_flags); + { + krb5_sendto_ctx stctx; + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + return ret; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + + ret = krb5_sendto_context (context, stctx, &enc, + krbtgt->server->name.name_string.val[1], + &resp); + krb5_sendto_ctx_free(context, stctx); + } if(ret) goto out; @@ -550,12 +556,6 @@ again: } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); krb5_free_error_contents(context, &error); - - if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) { - send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; - krb5_data_free(&resp); - goto again; - } } else if(resp.data && ((char*)resp.data)[0] == 4) { ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_clear_error_string(context); @@ -1191,6 +1191,10 @@ krb5_get_creds(krb5_context context, flags.b.forwardable = 1; if (options & KRB5_GC_NO_TRANSIT_CHECK) flags.b.disable_transited_check = 1; + if (options & KRB5_GC_CONSTRAINED_DELEGATION) { + flags.b.request_anonymous = 1; /* XXX ARGH confusion */ + flags.b.constrained_delegation = 1; + } tgts = NULL; ret = get_cred_from_kdc_flags(context, flags, ccache, @@ -1206,3 +1210,62 @@ krb5_get_creds(krb5_context context, krb5_cc_store_cred(context, ccache, *out_creds); return ret; } + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds(krb5_context context, + krb5_creds *creds, + krb5_const_principal client, + krb5_ccache ccache, + const char *in_tkt_service) +{ + krb5_error_code ret; + krb5_kdc_flags flags; + krb5_creds in, *template; + + memset(&in, 0, sizeof(in)); + + ret = krb5_copy_principal(context, client, &in.client); + if (ret) + return ret; + + if (in_tkt_service) { + ret = krb5_parse_name(context, in_tkt_service, &in.server); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } else { + const char *realm = krb5_principal_get_realm(context, client); + + ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME, + realm, NULL); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } + + flags.i = 0; + flags.b.renewable = flags.b.renew = 1; + + /* + * Get template from old credential cache for the same entry, if + * this failes, no worries. + */ + ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template); + if (ret == 0) { + flags.b.forwardable = template->flags.b.forwardable; + flags.b.proxiable = template->flags.b.proxiable; + krb5_free_creds (context, template); + } + + ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds); + krb5_free_principal(context, in.client); + krb5_free_principal(context, in.server); + + return ret; +} diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index a58435a9ea..1676da3bd6 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $"); +RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -1221,8 +1221,8 @@ init_cred_loop(krb5_context context, krb5_data resp; size_t len; size_t size; - int send_to_kdc_flags = 0; krb5_krbhst_info *hi = NULL; + krb5_sendto_ctx stctx = NULL; memset(&md, 0, sizeof(md)); @@ -1238,6 +1238,11 @@ init_cred_loop(krb5_context context, if (ret) return ret; + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + goto out; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + /* Set a new nonce. */ krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce)); ctx->nonce &= 0xffffffff; @@ -1281,10 +1286,9 @@ init_cred_loop(krb5_context context, if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); - ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer, - &creds->client->realm, &resp, - send_to_kdc_flags); - if (ret) + ret = krb5_sendto_context (context, stctx, &ctx->req_buffer, + creds->client->realm, &resp); + if (ret) goto out; memset (&rep, 0, sizeof(rep)); @@ -1329,16 +1333,6 @@ init_cred_loop(krb5_context context, krb5_free_error_contents(context, &error); if (ret) goto out; - } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) { - if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) { - if (ret_as_reply) - rep.error = error; - else - krb5_free_error_contents(context, &error); - goto out; - } - krb5_free_error_contents(context, &error); - send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; } else { _krb5_get_init_creds_opt_set_krb5_error(context, init_cred_opts, @@ -1437,6 +1431,8 @@ init_cred_loop(krb5_context context, } } out: + if (stctx) + krb5_sendto_ctx_free(context, stctx); krb5_data_free(&ctx->req_buffer); free_METHOD_DATA(&md); memset(&md, 0, sizeof(md)); diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index be718f6714..a551c42ecd 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -149,6 +149,14 @@ _krb5_kcm_noop ( krb5_context /*context*/, krb5_ccache /*id*/); +krb5_error_code +_krb5_kdc_retry ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + void */*data*/, + const krb5_data */*reply*/, + int */*action*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_cr_err_reply ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index e852bffeb1..058496434e 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -2244,6 +2244,14 @@ krb5_get_pw_salt ( krb5_salt */*salt*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_const_principal /*client*/, + krb5_ccache /*ccache*/, + const char */*in_tkt_service*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_get_server_rcache ( krb5_context /*context*/, const krb5_data */*piece*/, @@ -2868,6 +2876,12 @@ krb5_parse_name_flags ( int /*flags*/, krb5_principal */*principal*/); +krb5_error_code +krb5_parse_nametype ( + krb5_context /*context*/, + const char */*str*/, + int32_t */*nametype*/); + const char* KRB5_LIB_FUNCTION krb5_passwd_result_to_string ( krb5_context /*context*/, @@ -3071,7 +3085,7 @@ krb5_rd_cred2 ( krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error ( krb5_context /*context*/, - krb5_data */*msg*/, + const krb5_data */*msg*/, KRB_ERROR */*result*/); krb5_error_code KRB5_LIB_FUNCTION @@ -3347,6 +3361,43 @@ krb5_sendto ( krb5_data */*receive*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + const krb5_data */*send_data*/, + const krb5_realm /*realm*/, + krb5_data */*receive*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags ( + krb5_sendto_ctx /*ctx*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc ( + krb5_context /*context*/, + krb5_sendto_ctx */*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/); + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func ( + krb5_sendto_ctx /*ctx*/, + krb5_sendto_ctx_func /*func*/, + void */*data*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type ( + krb5_sendto_ctx /*ctx*/, + int /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_sendto_kdc ( krb5_context /*context*/, const krb5_data */*send_data*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index eefda81ca9..345fe70764 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */ +/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -361,6 +361,7 @@ typedef union { #define KRB5_GC_NO_STORE (1U << 3) #define KRB5_GC_FORWARDABLE (1U << 4) #define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) +#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) @@ -753,9 +754,18 @@ enum { /* flags for krb5_unparse_name_flags */ enum { KRB5_PRINCIPAL_UNPARSE_SHORT = 1, - KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2 + KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2, + KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 }; +typedef struct krb5_sendto_ctx *krb5_sendto_ctx; + +#define KRB5_SENDTO_DONE 0 +#define KRB5_SENDTO_RESTART 1 +#define KRB5_SENDTO_CONTINUE 2 + +typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *); + struct credentials; /* this is to keep the compiler happy */ struct getargs; struct sockaddr; diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index 785c258ee0..6714401e45 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" +id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" error_table krb5 @@ -35,8 +35,10 @@ error_code KEY_EXPIRED, "Password has expired" error_code PREAUTH_FAILED, "Preauthentication failed" error_code PREAUTH_REQUIRED, "Additional pre-authentication required" error_code SERVER_NOMATCH, "Requested server and ticket don't match" +error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only" +error_code PATH_NOT_ACCEPTED, "KDC Policy rejects transited path" +error_code SVC_UNAVAILABLE, "A service is not available" -# 27-30 are reserved index 31 prefix KRB5KRB_AP error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed" @@ -108,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 51bf934bfd..69b52dd808 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include <resolve.h> #include "locate_plugin.h" -RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $"); +RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $"); static int string_to_proto(const char *string) @@ -501,10 +501,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr) hostlen = strlen(host); hi = calloc(1, sizeof(*hi) + hostlen); - if(hi == NULL) { - free(host); + if(hi == NULL) return ENOMEM; - } hi->proto = krbhst_get_default_proto(kd); hi->port = hi->def_port = socket_get_port(addr); diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index 0d410b57d2..8050bdb9b4 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $"); +RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_s4u2self_to_checksumdata(krb5_context context, @@ -51,6 +51,7 @@ _krb5_s4u2self_to_checksumdata(krb5_context context, krb5_clear_error_string(context); return ENOMEM; } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); ret = krb5_store_int32(sp, self->name.name_type); if (ret) goto out; diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 55d4f5ff56..f7a5e83ea3 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $"); +RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -409,6 +409,8 @@ verify_checksum(krb5_context context, krb5_error_code ret; Checksum cksum; + memset(&cksum, 0, sizeof(cksum)); + sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, sig->buffersize); if (sp == NULL) { diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index dd82842084..105cab554d 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $"); struct krb5_dh_moduli { char *name; @@ -554,18 +554,13 @@ pk_mk_padata(krb5_context context, if (ret) goto out; - ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(), - &content_info); + ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf); krb5_data_free(&sd_buf); - if (ret) - goto out; - - ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length, - &content_info, &size, ret); - if (ret) + if (ret) { + krb5_set_error_string(context, + "ContentInfo wrapping of signedData failed"); goto out; - if (buf.length != size) - krb5_abortx(context, "Internal ASN1 encoder error"); + } if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REQ_Win2k winreq; @@ -794,6 +789,7 @@ get_reply_key_win(krb5_context context, if (ret) { krb5_set_error_string(context, "PKINIT failed copying reply key"); free(*key); + *key = NULL; } return ret; @@ -856,6 +852,7 @@ get_reply_key(krb5_context context, if (ret) { krb5_set_error_string(context, "PKINIT failed copying reply key"); free(*key); + *key = NULL; } return ret; @@ -929,6 +926,7 @@ pk_verify_host(krb5_context context, if (hi) { ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert, ctx->require_hostname_match, + HX509_HN_HOSTNAME, hi->hostname, hi->ai->ai_addr, hi->ai->ai_addrlen); @@ -942,7 +940,8 @@ pk_verify_host(krb5_context context, static krb5_error_code pk_rd_pa_reply_enckey(krb5_context context, int type, - const ContentInfo *rep, + const heim_octet_string *indata, + const heim_oid *dataType, const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, @@ -954,27 +953,19 @@ pk_rd_pa_reply_enckey(krb5_context context, { krb5_error_code ret; struct krb5_pk_cert *host = NULL; - size_t size; - int length; - void *p; krb5_data content; heim_oid contentType = { 0, NULL }; - if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } - if (rep->content == NULL) { - krb5_set_error_string(context, "PKINIT: No content in reply"); - return EINVAL; - } - ret = hx509_cms_unenvelope(ctx->id->hx509ctx, ctx->id->certs, HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT, - rep->content->data, - rep->content->length, + indata->data, + indata->length, NULL, &contentType, &content); @@ -983,41 +974,52 @@ pk_rd_pa_reply_enckey(krb5_context context, "Failed to unenvelope CMS data in PK-INIT reply"); return ret; } + der_free_oid(&contentType); + +#if 0 /* windows LH with interesting CMS packets, leaks memory */ + { + size_t ph = 1 + der_length_len (length); + unsigned char *ptr = malloc(length + ph); + size_t l; - p = content.data; - length = content.length; + memcpy(ptr + ph, p, length); + + ret = der_put_length_and_tag (ptr + ph - 1, ph, length, + ASN1_C_UNIV, CONS, UT_Sequence, &l); + if (ret) + return ret; + ptr += ph - l; + length += l; + p = ptr; + } +#endif /* win2k uses ContentInfo */ if (type == COMPAT_WIN2K) { - ContentInfo ci; + heim_oid type; + heim_octet_string out; - ret = decode_ContentInfo(p, length, &ci, &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: failed decoding ContentInfo: %d", - ret); - goto out; - } - - if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { + ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL); + if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) { ret = EINVAL; /* XXX */ krb5_set_error_string(context, "PKINIT: Invalid content type"); + der_free_oid(&type); + der_free_octet_string(&out); goto out; } - if (ci.content == NULL) { - ret = EINVAL; /* XXX */ - krb5_set_error_string(context, "PKINIT: Invalid content type"); + der_free_oid(&type); + krb5_data_free(&content); + ret = krb5_data_copy(&content, out.data, out.length); + der_free_octet_string(&out); + if (ret) { + krb5_set_error_string(context, "PKINIT: out of memory"); goto out; } - krb5_data_free(&content); - content = *ci.content; - p = ci.content->data; - length = ci.content->length; } ret = _krb5_pk_verify_sign(context, - p, - length, + content.data, + content.length, ctx->id, &contentType, &content, @@ -1073,7 +1075,8 @@ pk_rd_pa_reply_enckey(krb5_context context, static krb5_error_code pk_rd_pa_reply_dh(krb5_context context, - const ContentInfo *rep, + const heim_octet_string *indata, + const heim_oid *dataType, const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, @@ -1097,19 +1100,14 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); - if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } - if (rep->content == NULL) { - krb5_set_error_string(context, "PKINIT: No content in reply"); - return EINVAL; - } - ret = _krb5_pk_verify_sign(context, - rep->content->data, - rep->content->length, + indata->data, + indata->length, ctx->id, &contentType, &content, @@ -1261,20 +1259,19 @@ _krb5_pk_rd_pa_reply(krb5_context context, { krb5_pk_init_ctx ctx = c; krb5_error_code ret; - ContentInfo ci; size_t size; /* Check for IETF PK-INIT first */ if (ctx->type == COMPAT_IETF) { PA_PK_AS_REP rep; + heim_octet_string os, data; + heim_oid oid; if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { krb5_set_error_string(context, "PKINIT: wrong padata recv"); return EINVAL; } - memset(&rep, 0, sizeof(rep)); - ret = decode_PA_PK_AS_REP(pa->padata_value.data, pa->padata_value.length, &rep, @@ -1286,49 +1283,42 @@ _krb5_pk_rd_pa_reply(krb5_context context, switch (rep.element) { case choice_PA_PK_AS_REP_dhInfo: - ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data, - rep.u.dhInfo.dhSignedData.length, - &ci, - &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed DH " - "ContentInfo: %d", ret); - - free_PA_PK_AS_REP(&rep); - break; - } - ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi, - ctx->clientDHNonce, - rep.u.dhInfo.serverDHNonce, - nonce, pa, key); - free_ContentInfo(&ci); - free_PA_PK_AS_REP(&rep); - + os = rep.u.dhInfo.dhSignedData; break; case choice_PA_PK_AS_REP_encKeyPack: - ret = decode_ContentInfo(rep.u.encKeyPack.data, - rep.u.encKeyPack.length, - &ci, - &size); - free_PA_PK_AS_REP(&rep); - if (ret) { - krb5_set_error_string(context, - "PKINIT: -25 decoding failed " - "ContentInfo: %d", ret); - break; - } - ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx, - etype, hi, nonce, req_buffer, pa, key); - free_ContentInfo(&ci); - return ret; + os = rep.u.encKeyPack; + break; default: free_PA_PK_AS_REP(&rep); krb5_set_error_string(context, "PKINIT: -27 reply " "invalid content type"); - ret = EINVAL; + return EINVAL; + } + + ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL); + if (ret) { + free_PA_PK_AS_REP(&rep); + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + return ret; + } + + switch (rep.element) { + case choice_PA_PK_AS_REP_dhInfo: + ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi, + ctx->clientDHNonce, + rep.u.dhInfo.serverDHNonce, + nonce, pa, key); break; + case choice_PA_PK_AS_REP_encKeyPack: + ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + break; + default: + krb5_abortx(context, "pk-init as-rep case not possible to happen"); } + der_free_octet_string(&data); + der_free_oid(&oid); + free_PA_PK_AS_REP(&rep); } else if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REP_Win2k w2krep; @@ -1357,23 +1347,25 @@ _krb5_pk_rd_pa_reply(krb5_context context, krb5_clear_error_string(context); switch (w2krep.element) { - case choice_PA_PK_AS_REP_Win2k_encKeyPack: - ret = decode_ContentInfo(w2krep.u.encKeyPack.data, - w2krep.u.encKeyPack.length, - &ci, - &size); + case choice_PA_PK_AS_REP_Win2k_encKeyPack: { + heim_octet_string data; + heim_oid oid; + + ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack, + &oid, &data, NULL); free_PA_PK_AS_REP_Win2k(&w2krep); if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed " - "ContentInfo: %d", - ret); + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); return ret; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx, - etype, hi, nonce, req_buffer, pa, key); - free_ContentInfo(&ci); + + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + der_free_octet_string(&data); + der_free_oid(&oid); + break; + } default: free_PA_PK_AS_REP_Win2k(&w2krep); krb5_set_error_string(context, "PKINIT: win2k reply invalid " @@ -1473,8 +1465,7 @@ _krb5_pk_load_id(krb5_context context, id = calloc(1, sizeof(*id)); if (id == NULL) { krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; + return ENOMEM; } ret = hx509_context_init(&id->hx509ctx); diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index f19464bf3c..68317a12c0 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $"); +RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> #endif @@ -96,6 +96,7 @@ loadlib(krb5_context context, (*e)->dsohandle = dlopen(lib, RTLD_LAZY); if ((*e)->dsohandle == NULL) { free(*e); + *e = NULL; krb5_set_error_string(context, "Failed to load %s: %s", lib, dlerror()); return ENOMEM; diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index ef3f5412db..c1a29d266b 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include <fnmatch.h> #include "resolve.h" -RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $"); +RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -281,15 +281,19 @@ krb5_parse_name(krb5_context context, static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; +static const char nq_chars[] = " \\/@"; #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); static size_t -quote_string(const char *s, char *out, size_t idx, size_t len) +quote_string(const char *s, char *out, size_t idx, size_t len, int display) { const char *p, *q; for(p = s; *p && idx < len; p++){ - if((q = strchr(quotable_chars, *p))){ + q = strchr(quotable_chars, *p); + if (q && display) { + add_char(out, idx, len, replace_chars[q - quotable_chars]); + } else if (q) { add_char(out, idx, len, '\\'); add_char(out, idx, len, replace_chars[q - quotable_chars]); }else @@ -312,6 +316,7 @@ unparse_name_fixed(krb5_context context, int i; int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; + int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; if (!no_realm && princ_realm(principal) == NULL) { krb5_set_error_string(context, "Realm missing from principal, " @@ -322,7 +327,7 @@ unparse_name_fixed(krb5_context context, for(i = 0; i < princ_num_comp(principal); i++){ if(i) add_char(name, idx, len, '/'); - idx = quote_string(princ_ncomp(principal, i), name, idx, len); + idx = quote_string(princ_ncomp(principal, i), name, idx, len, display); if(idx == len) { krb5_set_error_string(context, "Out of space printing principal"); return ERANGE; @@ -341,7 +346,7 @@ unparse_name_fixed(krb5_context context, } if(!short_form && !no_realm) { add_char(name, idx, len, '@'); - idx = quote_string(princ_realm(principal), name, idx, len); + idx = quote_string(princ_realm(principal), name, idx, len, display); if(idx == len) { krb5_set_error_string(context, "Out of space printing realm of principal"); @@ -1213,3 +1218,37 @@ krb5_sname_to_principal (krb5_context context, krb5_free_host_realm(context, realms); return ret; } + +static const struct { + const char *type; + int32_t value; +} nametypes[] = { + { "UNKNOWN", KRB5_NT_UNKNOWN }, + { "PRINCIPAL", KRB5_NT_PRINCIPAL }, + { "SRV_INST", KRB5_NT_SRV_INST }, + { "SRV_HST", KRB5_NT_SRV_HST }, + { "SRV_XHST", KRB5_NT_SRV_XHST }, + { "UID", KRB5_NT_UID }, + { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL }, + { "SMTP_NAME", KRB5_NT_SMTP_NAME }, + { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL }, + { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID }, + { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL }, + { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID }, + { NULL } +}; + +krb5_error_code +krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) +{ + size_t i; + + for(i = 0; nametypes[i].type; i++) { + if (strcasecmp(nametypes[i].type, str) == 0) { + *nametype = nametypes[i].value; + return 0; + } + } + krb5_set_error_string(context, "Failed to find name type %s", str); + return KRB5_PARSE_MALFORMED; +} diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c index 89615ee8ac..e7646467af 100644 --- a/source4/heimdal/lib/krb5/rd_error.c +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -33,11 +33,11 @@ #include "krb5_locl.h" -RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $"); +RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error(krb5_context context, - krb5_data *msg, + const krb5_data *msg, KRB_ERROR *result) { diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 6c70244327..c1a4df2b01 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $"); +RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -413,26 +413,16 @@ krb5_sendto_kdc_flags(krb5_context context, int flags) { krb5_error_code ret; - krb5_krbhst_handle handle; - int type; - - if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) - type = KRB5_KRBHST_ADMIN; - else - type = KRB5_KRBHST_KDC; + krb5_sendto_ctx ctx; - if (send_data->length > context->large_msg_size) - flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; - - ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle); + ret = krb5_sendto_ctx_alloc(context, &ctx); if (ret) return ret; + krb5_sendto_ctx_add_flags(ctx, flags); + krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL); - ret = krb5_sendto(context, send_data, handle, receive); - krb5_krbhst_free(context, handle); - if (ret == KRB5_KDC_UNREACH) - krb5_set_error_string(context, - "unable to reach any KDC in realm %s", *realm); + ret = krb5_sendto_context(context, ctx, send_data, *realm, receive); + krb5_sendto_ctx_free(context, ctx); return ret; } @@ -458,4 +448,157 @@ krb5_set_send_to_kdc_func(krb5_context context, return 0; } +struct krb5_sendto_ctx { + int flags; + int type; + krb5_sendto_ctx_func func; + void *data; +}; +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags) +{ + ctx->flags |= flags; +} + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx) +{ + return ctx->flags; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type) +{ + ctx->type = type; +} + + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx, + krb5_sendto_ctx_func func, + void *data) +{ + ctx->func = func; + ctx->data = data; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context(krb5_context context, + krb5_sendto_ctx ctx, + const krb5_data *send_data, + const krb5_realm realm, + krb5_data *receive) +{ + krb5_error_code ret; + krb5_krbhst_handle handle = NULL; + int type, freectx = 0; + int action; + + krb5_data_zero(receive); + + if (ctx == NULL) { + freectx = 1; + ret = krb5_sendto_ctx_alloc(context, &ctx); + if (ret) + return ret; + } + + type = ctx->type; + if (type == 0) { + if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) + type = KRB5_KRBHST_ADMIN; + else + type = KRB5_KRBHST_KDC; + } + + if (send_data->length > context->large_msg_size) + ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + + /* loop until we get back a appropriate response */ + + do { + action = KRB5_SENDTO_DONE; + + krb5_data_free(receive); + + if (handle == NULL) { + ret = krb5_krbhst_init_flags(context, realm, type, + ctx->flags, &handle); + if (ret) { + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; + } + } + + ret = krb5_sendto(context, send_data, handle, receive); + if (ret) + break; + if (ctx->func) { + ret = (*ctx->func)(context, ctx, ctx->data, receive, &action); + if (ret) + break; + } + if (action != KRB5_SENDTO_CONTINUE) { + krb5_krbhst_free(context, handle); + handle = NULL; + } + } while (action != KRB5_SENDTO_DONE); + if (handle) + krb5_krbhst_free(context, handle); + if (ret == KRB5_KDC_UNREACH) + krb5_set_error_string(context, + "unable to reach any KDC in realm %s", realm); + if (ret) + krb5_data_free(receive); + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; +} + +krb5_error_code +_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data, + const krb5_data *reply, int *action) +{ + krb5_error_code ret; + KRB_ERROR error; + + if(krb5_rd_error(context, reply, &error)) + return 0; + + ret = krb5_error_from_rd_error(context, &error, NULL); + krb5_free_error_contents(context, &error); + + switch(ret) { + case KRB5KRB_ERR_RESPONSE_TOO_BIG: { + if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG) + break; + krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG); + *action = KRB5_SENDTO_RESTART; + break; + } + case KRB5KDC_ERR_SVC_UNAVAILABLE: + *action = KRB5_SENDTO_CONTINUE; + break; + } + return 0; +} |