From: Greg Hudson Date: Sat, 14 Nov 2009 04:46:30 +0000 (+0000) Subject: Constrained delegation without PAC support X-Git-Tag: krb5-1.8-alpha1~187 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0524889196c42d81dcc4c74277522b46f987cabb;p=krb5.git Constrained delegation without PAC support Merge Luke's users/lhoward/s4u2proxy branch to trunk. Implements a Heimdal-compatible mechanism for allowing constrained delegation without back-end support for PACs. Back-end support exists in LDAP only (via a new krbAllowedToDelegateTo attribute), not DB2. ticket: 6580 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23160 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 6a85a398e..a9769234c 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1075,6 +1075,21 @@ typedef struct _krb5_ad_kdcissued { krb5_authdata **elements; } krb5_ad_kdcissued; +typedef struct _krb5_ad_signedpath_data { + krb5_principal client; + krb5_timestamp authtime; + krb5_principal *delegated; + krb5_pa_data **method_data; + krb5_authdata **authorization_data; +} krb5_ad_signedpath_data; + +typedef struct _krb5_ad_signedpath { + krb5_enctype enctype; + krb5_checksum checksum; + krb5_principal *delegated; + krb5_pa_data **method_data; +} krb5_ad_signedpath; + typedef krb5_error_code (*krb5_preauth_obtain_proc) (krb5_context, krb5_pa_data *, @@ -1386,6 +1401,8 @@ void KRB5_CALLCONV krb5_free_fast_response (krb5_context, krb5_fast_response *); void KRB5_CALLCONV krb5_free_ad_kdcissued (krb5_context, krb5_ad_kdcissued *); +void KRB5_CALLCONV krb5_free_ad_signedpath +(krb5_context, krb5_ad_signedpath *); /* #include "krb5/wordsize.h" -- comes in through base-defs.h. */ #include "com_err.h" @@ -1810,6 +1827,10 @@ krb5_error_code encode_krb5_fast_response krb5_error_code encode_krb5_ad_kdcissued (const krb5_ad_kdcissued *, krb5_data **); +krb5_error_code encode_krb5_ad_signedpath +(const krb5_ad_signedpath *, krb5_data **); +krb5_error_code encode_krb5_ad_signedpath_data +(const krb5_ad_signedpath_data *, krb5_data **); /************************************************************************* * End of prototypes for krb5_encode.c @@ -1989,6 +2010,9 @@ krb5_error_code decode_krb5_fast_response krb5_error_code decode_krb5_ad_kdcissued (const krb5_data *, krb5_ad_kdcissued **); +krb5_error_code decode_krb5_ad_signedpath +(const krb5_data *, krb5_ad_signedpath **); + struct _krb5_key_data; /* kdb.h */ struct ldap_seqof_key_data { @@ -3008,6 +3032,12 @@ krb5_get_credentials_for_proxy(krb5_context context, krb5_ticket *evidence_tkt, krb5_creds **out_creds); +krb5_error_code KRB5_CALLCONV +krb5int_get_authdata_containee_types(krb5_context context, + const krb5_authdata *container, + unsigned int *nad_types, + krb5_authdatatype **ad_types); + krb5_error_code krb5int_parse_enctype_list(krb5_context context, char *profstr, krb5_enctype *default_list, krb5_enctype **result); diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index 464f3fa30..1b03451f6 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -647,6 +647,8 @@ krb5_error_code KRB5_CALLCONV #define KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST 26 /* XXX note conflict with above */ #define KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY 27 /* XXX note conflict with above */ +#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21 + /* define in draft-ietf-krb-wg-preauth-framework*/ #define KRB5_KEYUSAGE_FAST_REQ_CHKSUM 50 #define KRB5_KEYUSAGE_FAST_ENC 51 @@ -1092,6 +1094,7 @@ krb5_error_code KRB5_CALLCONV krb5_verify_checksum #define KRB5_AUTHDATA_SESAME 65 #define KRB5_AUTHDATA_WIN2K_PAC 128 #define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /* RFC 4537 */ +#define KRB5_AUTHDATA_SIGNTICKET 142 #define KRB5_AUTHDATA_FX_ARMOR 71 /* password change constants */ diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index a6ec43b76..dab1513d6 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -103,7 +103,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, krb5_keyblock encrypting_key; int nprincs = 0; krb5_boolean more; - krb5_timestamp kdc_time, authtime=0; + krb5_timestamp kdc_time, authtime = 0; krb5_keyblock session_key; krb5_timestamp rtime; krb5_keyblock *reply_key = NULL; @@ -116,7 +116,8 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, register int i; int firstpass = 1; const char *status = 0; - krb5_enc_tkt_part *header_enc_tkt = NULL; /* TG or evidence ticket */ + krb5_enc_tkt_part *header_enc_tkt = NULL; /* TGT */ + krb5_enc_tkt_part *subject_tkt = NULL; /* TGT or evidence ticket */ krb5_db_entry client, krbtgt; int c_nprincs = 0, k_nprincs = 0; krb5_pa_s4u_x509_user *s4u_x509_user = NULL; /* protocol transition request */ @@ -135,6 +136,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, reply.padata = 0; /* For cleanup handler */ reply_encpart.enc_padata = 0; + e_data.data = NULL; session_key.contents = NULL; @@ -391,9 +393,6 @@ tgt_again: assert(krb5_is_tgs_principal(header_ticket->server)); - /* From now on, use evidence ticket as header ticket */ - header_enc_tkt = request->second_ticket[st_idx]->enc_part2; - assert(c_nprincs == 0); /* assured by kdc_process_s4u2self_req() */ client = st_client; @@ -425,7 +424,18 @@ tgt_again: goto cleanup; } - authtime = header_enc_tkt->times.authtime; + /* + * subject_tkt will refer to the evidence ticket (for constrained + * delegation) or the TGT. The distinction from header_enc_tkt is + * necessary because the TGS signature only protects some fields: + * the others could be forged by a malicious server. + */ + + if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + subject_tkt = request->second_ticket[st_idx]->enc_part2; + else + subject_tkt = header_enc_tkt; + authtime = subject_tkt->times.authtime; if (is_referral) ticket_reply.server = server.princ; @@ -443,7 +453,7 @@ tgt_again: * authtime's value. */ if (!(header_enc_tkt->times.starttime)) - header_enc_tkt->times.starttime = header_enc_tkt->times.authtime; + header_enc_tkt->times.starttime = authtime; /* don't use new addresses unless forwarded, see below */ @@ -584,9 +594,9 @@ tgt_again: } /* - * Set authtime to be the same as header_ticket's + * Set authtime to be the same as header or evidence ticket's */ - enc_tkt_reply.times.authtime = header_enc_tkt->times.authtime; + enc_tkt_reply.times.authtime = authtime; /* * Propagate the preauthentication flags through to the returned ticket. @@ -606,7 +616,7 @@ tgt_again: errcode = krb5_unparse_name(kdc_context, s4u_x509_user->user_id.user, &s4u_name); } else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { - errcode = krb5_unparse_name(kdc_context, header_enc_tkt->client, + errcode = krb5_unparse_name(kdc_context, subject_tkt->client, &s4u_name); } else { errcode = 0; @@ -676,15 +686,13 @@ tgt_again: if (isflagset(server.attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED) == 0) { /* * If we are not doing protocol transition/constrained delegation - * and there was no authorization data included, try to lookup - * the client principal as it may be mapped to a local account. + * try to lookup the client principal so plugins can add additional + * authorization information. * * Always validate authorization data for constrained delegation * because we must validate the KDC signatures. */ - if (!isflagset(c_flags, KRB5_KDB_FLAGS_S4U) && - header_enc_tkt->authorization_data == NULL) { - + if (!isflagset(c_flags, KRB5_KDB_FLAGS_S4U)) { /* Generate authorization data so we can include it in ticket */ setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); /* Map principals from foreign (possibly non-AD) realms */ @@ -694,7 +702,7 @@ tgt_again: c_nprincs = 1; errcode = krb5_db_get_principal_ext(kdc_context, - header_enc_tkt->client, + subject_tkt->client, c_flags, &client, &c_nprincs, @@ -720,7 +728,7 @@ tgt_again: !isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM)) enc_tkt_reply.client = s4u_x509_user->user_id.user; else - enc_tkt_reply.client = header_enc_tkt->client; + enc_tkt_reply.client = subject_tkt->client; enc_tkt_reply.session = &session_key; enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; @@ -739,7 +747,7 @@ tgt_again: request, s4u_x509_user ? s4u_x509_user->user_id.user : NULL, - header_enc_tkt, + subject_tkt, &enc_tkt_reply); if (errcode) { krb5_klog_syslog(LOG_INFO, "TGS_REQ : handle_authdata (%d)", errcode); @@ -913,10 +921,8 @@ tgt_again: reply_encpart.session = &session_key; reply_encpart.nonce = request->nonce; - /* copy the time fields EXCEPT for authtime; its location - is used for ktime */ + /* copy the time fields */ reply_encpart.times = enc_tkt_reply.times; - reply_encpart.times.authtime = header_enc_tkt->times.authtime; /* starttime is optional, and treated as authtime if not present. so we can nuke it if it matches */ diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c index 3cef2d714..aa55ef455 100644 --- a/src/kdc/kdc_authdata.c +++ b/src/kdc/kdc_authdata.c @@ -3,7 +3,7 @@ * kdc/kdc_authdata.c * * Copyright (C) 2007 Apple Inc. All Rights Reserved. - * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * Copyright (C) 2008, 2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. @@ -36,7 +36,7 @@ #include #include -#include "../include/krb5/authdata_plugin.h" +#include #if TARGET_OS_MAC static const char *objdirs[] = { KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR, @@ -70,7 +70,6 @@ typedef krb5_error_code (*init_proc) typedef void (*fini_proc) (krb5_context, void *); -/* Internal authdata system for copying TGS-REQ authdata to ticket */ static krb5_error_code handle_request_authdata (krb5_context context, unsigned int flags, @@ -86,7 +85,6 @@ static krb5_error_code handle_request_authdata krb5_enc_tkt_part *enc_tkt_request, krb5_enc_tkt_part *enc_tkt_reply); -/* Internal authdata system for handling KDC-issued authdata */ static krb5_error_code handle_tgt_authdata (krb5_context context, unsigned int flags, @@ -102,6 +100,27 @@ static krb5_error_code handle_tgt_authdata krb5_enc_tkt_part *enc_tkt_request, krb5_enc_tkt_part *enc_tkt_reply); +static krb5_error_code +handle_kdb_authdata(krb5_context context, unsigned int flags, + krb5_db_entry *client, krb5_db_entry *server, + krb5_db_entry *krbtgt, krb5_keyblock *client_key, + krb5_keyblock *server_key, krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); + +static krb5_error_code +handle_signedpath_authdata(krb5_context context, unsigned int flags, + krb5_db_entry *client, krb5_db_entry *server, + krb5_db_entry *krbtgt, krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); + typedef struct _krb5_authdata_systems { const char *name; #define AUTHDATA_SYSTEM_UNKNOWN -1 @@ -109,6 +128,7 @@ typedef struct _krb5_authdata_systems { #define AUTHDATA_SYSTEM_V2 2 int type; #define AUTHDATA_FLAG_CRITICAL 0x1 +#define AUTHDATA_FLAG_PRE_PLUGIN 0x2 int flags; void *plugin_context; init_proc init; @@ -120,10 +140,46 @@ typedef struct _krb5_authdata_systems { } krb5_authdata_systems; static krb5_authdata_systems static_authdata_systems[] = { - { "tgs_req", AUTHDATA_SYSTEM_V2, AUTHDATA_FLAG_CRITICAL, - NULL, NULL, NULL, { handle_request_authdata } }, - { "tgt", AUTHDATA_SYSTEM_V2, AUTHDATA_FLAG_CRITICAL, - NULL, NULL, NULL, { handle_tgt_authdata } }, + { + /* Propagate client-submitted authdata */ + "tgs_req", + AUTHDATA_SYSTEM_V2, + AUTHDATA_FLAG_CRITICAL | AUTHDATA_FLAG_PRE_PLUGIN, + NULL, + NULL, + NULL, + { handle_request_authdata } + }, + { + /* Propagate TGT authdata */ + "tgt", + AUTHDATA_SYSTEM_V2, + AUTHDATA_FLAG_CRITICAL, + NULL, + NULL, + NULL, + { handle_tgt_authdata } + }, + { + /* Verify and issue KDB issued authdata */ + "kdb", + AUTHDATA_SYSTEM_V2, + AUTHDATA_FLAG_CRITICAL, + NULL, + NULL, + NULL, + { handle_kdb_authdata } + }, + { + /* Verify and issue signed delegation path */ + "signedpath", + AUTHDATA_SYSTEM_V2, + AUTHDATA_FLAG_CRITICAL, + NULL, + NULL, + NULL, + { handle_signedpath_authdata } + } }; static krb5_authdata_systems *authdata_systems; @@ -204,6 +260,19 @@ load_authdata_plugins(krb5_context context) k = 0; + /* + * Special case to ensure that handle_request_authdata is + * first in the list, to make unenc_authdata available to + * plugins. + */ + for (i = 0; i < (sizeof(static_authdata_systems) / + sizeof(static_authdata_systems[0])); i++) { + if ((static_authdata_systems[i].flags & AUTHDATA_FLAG_PRE_PLUGIN) == 0) + continue; + assert(static_authdata_systems[i].init == NULL); + authdata_systems[k++] = static_authdata_systems[i]; + } + /* Add dynamically loaded V2 plugins */ if (authdata_plugins_ftables_v2 != NULL) { struct krb5plugin_authdata_server_ftable_v2 *ftable; @@ -280,20 +349,13 @@ load_authdata_plugins(krb5_context context) } } - /* Add the locally-supplied mechanisms to the dynamic list first. */ for (i = 0; i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]); i++) { - authdata_systems[k] = static_authdata_systems[i]; - /* Try to initialize the authdata system. If it fails, we'll remove it - * from the list of systems we'll be using. */ - server_init_proc = static_authdata_systems[i].init; - if ((server_init_proc != NULL) && - ((*server_init_proc)(context, &authdata_systems[k].plugin_context) != 0)) { - memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + if (static_authdata_systems[i].flags & AUTHDATA_FLAG_PRE_PLUGIN) continue; - } - k++; + assert(static_authdata_systems[i].init == NULL); + authdata_systems[k++] = static_authdata_systems[i]; } n_authdata_systems = k; @@ -331,12 +393,106 @@ unload_authdata_plugins(krb5_context context) return 0; } -/* Merge authdata. If copy == 0, in_authdata is invalid on return */ +/* + * Returns TRUE if authdata should be filtered when copying from + * untrusted authdata. + */ +static krb5_boolean +is_kdc_issued_authdatum (krb5_context context, + krb5_authdata *authdata, + krb5_authdatatype desired_type) +{ + krb5_boolean ret = FALSE; + krb5_authdatatype ad_type; + unsigned int i, count = 0; + krb5_authdatatype *ad_types = NULL; + + if (authdata->ad_type == KRB5_AUTHDATA_IF_RELEVANT) { + if (krb5int_get_authdata_containee_types(context, + authdata, + &count, + &ad_types) != 0) + goto cleanup; + } else { + ad_type = authdata->ad_type; + count = 1; + ad_types = &ad_type; + } + + for (i = 0; i < count; i++) { + switch (ad_types[i]) { + case KRB5_AUTHDATA_SIGNTICKET: + case KRB5_AUTHDATA_KDC_ISSUED: + case KRB5_AUTHDATA_WIN2K_PAC: + ret = desired_type ? (desired_type == ad_types[i]) : TRUE; + break; + default: + ret = FALSE; + break; + } + if (ret) + break; + } + +cleanup: + if (authdata->ad_type == KRB5_AUTHDATA_IF_RELEVANT && + ad_types != NULL) + free(ad_types); + + return ret; +} + +static krb5_boolean +has_kdc_issued_authdata (krb5_context context, + krb5_authdata **authdata, + krb5_authdatatype desired_type) +{ + int i; + krb5_boolean ret = FALSE; + + if (authdata != NULL) { + for (i = 0; authdata[i] != NULL; i++) { + if (is_kdc_issued_authdatum(context, authdata[i], desired_type)) { + ret = TRUE; + break; + } + } + } + + return ret; +} + +static krb5_boolean +has_mandatory_for_kdc_authdata (krb5_context context, + krb5_authdata **authdata) +{ + int i; + krb5_boolean ret = FALSE; + + if (authdata != NULL) { + for (i = 0; authdata[i] != NULL; i++) { + if (authdata[0]->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC) { + ret = TRUE; + break; + } + } + } + + return ret; +} + +/* + * Merge authdata. + * + * If copy is FALSE, in_authdata is invalid on successful return. + * If ignore_kdc_issued is TRUE, KDC-issued authdata is not copied. + */ static krb5_error_code merge_authdata (krb5_context context, krb5_authdata **in_authdata, krb5_authdata ***out_authdata, - krb5_boolean copy) + krb5_boolean copy, + krb5_boolean ignore_kdc_issued) { size_t i, nadata = 0; krb5_authdata **authdata = *out_authdata; @@ -356,7 +512,7 @@ merge_authdata (krb5_context context, authdata = (krb5_authdata **)calloc(i + 1, sizeof(krb5_authdata *)); } else { authdata = (krb5_authdata **)realloc(authdata, - ((nadata + i + 1) * sizeof(krb5_authdata *))); + ((nadata + i + 1) * sizeof(krb5_authdata *))); } if (authdata == NULL) return ENOMEM; @@ -372,13 +528,24 @@ merge_authdata (krb5_context context, in_authdata = tmp; } - for (i = 0; in_authdata[i] != NULL; i++) - authdata[nadata + i] = in_authdata[i]; + for (i = 0; in_authdata[i] != NULL; i++) { + if (ignore_kdc_issued && + is_kdc_issued_authdatum(context, in_authdata[i], 0)) { + free(in_authdata[i]->contents); + free(in_authdata[i]); + } else + authdata[nadata + i] = in_authdata[i]; + } authdata[nadata + i] = NULL; free(in_authdata); + if (authdata[0] == NULL) { + free(authdata); + authdata = NULL; + } + *out_authdata = authdata; return 0; @@ -453,13 +620,19 @@ handle_request_authdata (krb5_context context, free(scratch.data); - code = merge_authdata(context, request->unenc_authdata, - &enc_tkt_reply->authorization_data, TRUE /* copy */); + if (has_mandatory_for_kdc_authdata(context, request->unenc_authdata)) + return KRB5KDC_ERR_POLICY; + + code = merge_authdata(context, + request->unenc_authdata, + &enc_tkt_reply->authorization_data, + TRUE, /* copy */ + TRUE); /* ignore_kdc_issued */ return code; } -/* Handle backend-managed authorization data */ +/* Handle copying TGT authorization data into reply */ static krb5_error_code handle_tgt_authdata (krb5_context context, unsigned int flags, @@ -474,6 +647,36 @@ handle_tgt_authdata (krb5_context context, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_request, krb5_enc_tkt_part *enc_tkt_reply) +{ + if (request->msg_type != KRB5_TGS_REQ) + return 0; + + if (has_mandatory_for_kdc_authdata(context, + enc_tkt_request->authorization_data)) + return KRB5KDC_ERR_POLICY; + + return merge_authdata(context, + enc_tkt_request->authorization_data, + &enc_tkt_reply->authorization_data, + TRUE, /* copy */ + TRUE); /* ignore_kdc_issued */ +} + +/* Handle backend-managed authorization data */ +static krb5_error_code +handle_kdb_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) { krb5_error_code code; krb5_authdata **db_authdata = NULL; @@ -489,12 +692,6 @@ handle_tgt_authdata (krb5_context context, * or protocol transition/constrained delegation was used, or, in * the AS-REQ case, if the pre-auth data indicated the PAC should * be present. - * - * We permit sign_authorization_data() to return a krb5_db_entry - * representing the principal associated with the authorization - * data, in case that principal is not local to our realm and we - * need to perform additional checks (such as disabling delegation - * for cross-realm protocol transition below). */ if (tgs_req) { assert(enc_tkt_request != NULL); @@ -522,16 +719,6 @@ handle_tgt_authdata (krb5_context context, else actual_client = enc_tkt_reply->client; - /* - * If the backend does not implement the sign authdata method, then - * just copy the TGT authorization data into the reply, except for - * the constrained delegation case (which requires special handling - * because it will promote untrusted auth data to KDC issued auth - * data; this requires backend-specific code) - * - * Presently this interface does not support using request auth data - * to influence (eg. possibly restrict) the reply auth data. - */ code = sign_db_authdata(context, flags, actual_client, @@ -545,26 +732,16 @@ handle_tgt_authdata (krb5_context context, tgs_req ? enc_tkt_request->authorization_data : NULL, enc_tkt_reply->session, &db_authdata); - if (code == KRB5_KDB_DBTYPE_NOSUP) { - assert(db_authdata == NULL); - - if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) - return KRB5KDC_ERR_POLICY; - - if (tgs_req) - return merge_authdata(context, enc_tkt_request->authorization_data, - &enc_tkt_reply->authorization_data, TRUE); - else - return 0; - } - - if (db_authdata != NULL) { - code = merge_authdata(context, db_authdata, + if (code == 0) { + code = merge_authdata(context, + db_authdata, &enc_tkt_reply->authorization_data, - FALSE); + FALSE, /* !copy */ + FALSE); /* !ignore_kdc_issued */ if (code != 0) krb5_free_authdata(context, db_authdata); - } + } else if (code == KRB5_KDB_DBTYPE_NOSUP) + code = 0; return code; } @@ -627,3 +804,392 @@ handle_authdata (krb5_context context, return code; } + +static krb5_error_code +make_ad_signedpath_data(krb5_context context, + krb5_const_principal client, + krb5_timestamp authtime, + krb5_principal *deleg_path, + krb5_pa_data **method_data, + krb5_authdata **authdata, + krb5_data **data) +{ + krb5_ad_signedpath_data sp_data; + krb5_authdata **sign_authdata = NULL; + int i, j; + krb5_error_code code; + + memset(&sp_data, 0, sizeof(sp_data)); + + if (authdata != NULL) { + for (i = 0; authdata[i] != NULL; i++) + ; + } else + i = 0; + + if (i != 0) { + sign_authdata = k5alloc((i + 1) * sizeof(krb5_authdata *), &code); + if (code != 0) + return code; + + for (i = 0, j = 0; authdata[i] != NULL; i++) { + if (is_kdc_issued_authdatum(context, authdata[i], + KRB5_AUTHDATA_SIGNTICKET)) + continue; + + sign_authdata[j++] = authdata[i]; + } + + sign_authdata[j] = NULL; + } + + sp_data.client = (krb5_principal)client; + sp_data.authtime = authtime; + sp_data.delegated = deleg_path; + sp_data.method_data = method_data; + sp_data.authorization_data = sign_authdata; + + code = encode_krb5_ad_signedpath_data(&sp_data, data); + + if (sign_authdata != NULL) + free(sign_authdata); + + return code; +} + +static krb5_error_code +verify_ad_signedpath_checksum(krb5_context context, + const krb5_db_entry *krbtgt, + krb5_keyblock *krbtgt_key, + krb5_enc_tkt_part *enc_tkt_part, + krb5_principal *deleg_path, + krb5_pa_data **method_data, + krb5_checksum *cksum, + krb5_boolean *valid) +{ + krb5_error_code code; + krb5_data *data; + + *valid = FALSE; + + if (!krb5_c_is_keyed_cksum(cksum->checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + + code = make_ad_signedpath_data(context, + enc_tkt_part->client, + enc_tkt_part->times.authtime, + deleg_path, + method_data, + enc_tkt_part->authorization_data, + &data); + if (code != 0) + return code; + + code = krb5_c_verify_checksum(context, + krbtgt_key, + KRB5_KEYUSAGE_AD_SIGNEDPATH, + data, + cksum, + valid); + + krb5_free_data(context, data); + + if (code == 0 && *valid == FALSE) + code = KRB5KRB_AP_ERR_MODIFIED; + + return code; +} + + +static krb5_error_code +verify_ad_signedpath(krb5_context context, + krb5_db_entry *krbtgt, + krb5_keyblock *krbtgt_key, + krb5_enc_tkt_part *enc_tkt_part, + krb5_principal **pdelegated, + krb5_boolean *path_is_signed) +{ + krb5_error_code code; + krb5_ad_signedpath *sp = NULL; + krb5_authdata **sp_authdata = NULL; + krb5_data enc_sp; + + *pdelegated = NULL; + *path_is_signed = FALSE; + + code = krb5int_find_authdata(context, + enc_tkt_part->authorization_data, + NULL, + KRB5_AUTHDATA_SIGNTICKET, + &sp_authdata); + if (code != 0) + goto cleanup; + + if (sp_authdata == NULL || + sp_authdata[0]->ad_type != KRB5_AUTHDATA_SIGNTICKET || + sp_authdata[1] != NULL) + goto cleanup; + + enc_sp.data = (char *)sp_authdata[0]->contents; + enc_sp.length = sp_authdata[0]->length; + + code = decode_krb5_ad_signedpath(&enc_sp, &sp); + if (code != 0) + goto cleanup; + + code = verify_ad_signedpath_checksum(context, + krbtgt, + krbtgt_key, + enc_tkt_part, + sp->delegated, + sp->method_data, + &sp->checksum, + path_is_signed); + if (code != 0) + goto cleanup; + + *pdelegated = sp->delegated; + sp->delegated = NULL; + +cleanup: + krb5_free_ad_signedpath(context, sp); + krb5_free_authdata(context, sp_authdata); + + return code; +} + +static krb5_error_code +make_ad_signedpath_checksum(krb5_context context, + krb5_const_principal for_user_princ, + const krb5_db_entry *krbtgt, + krb5_keyblock *krbtgt_key, + krb5_enc_tkt_part *enc_tkt_part, + krb5_principal *deleg_path, + krb5_pa_data **method_data, + krb5_checksum *cksum) +{ + krb5_error_code code; + krb5_data *data; + krb5_cksumtype cksumtype; + krb5_const_principal client; + + if (for_user_princ != NULL) + client = for_user_princ; + else + client = enc_tkt_part->client; + + code = make_ad_signedpath_data(context, + client, + enc_tkt_part->times.authtime, + deleg_path, + method_data, + enc_tkt_part->authorization_data, + &data); + if (code != 0) + return code; + + code = krb5int_c_mandatory_cksumtype(context, + krbtgt_key->enctype, + &cksumtype); + if (code != 0) { + krb5_free_data(context, data); + return code; + } + + if (!krb5_c_is_keyed_cksum(cksumtype)) { + krb5_free_data(context, data); + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + code = krb5_c_make_checksum(context, cksumtype, krbtgt_key, + KRB5_KEYUSAGE_AD_SIGNEDPATH, data, + cksum); + + krb5_free_data(context, data); + + return code; +} + +static krb5_error_code +make_ad_signedpath(krb5_context context, + krb5_const_principal for_user_princ, + krb5_principal server, + const krb5_db_entry *krbtgt, + krb5_keyblock *krbtgt_key, + krb5_principal *deleg_path, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code code; + krb5_ad_signedpath sp; + int i; + krb5_data *data = NULL; + krb5_authdata ad_datum, *ad_data[2]; + krb5_authdata **if_relevant = NULL; + + memset(&sp, 0, sizeof(sp)); + + sp.enctype = krbtgt_key->enctype; + + if (deleg_path != NULL) { + for (i = 0; deleg_path[i] != NULL; i++) + ; + } else + i = 0; + + sp.delegated = k5alloc((i + (server ? 1 : 0) + 1) * + sizeof(krb5_principal), &code); + if (code != 0) + goto cleanup; + + /* Combine existing and new transited services, if any */ + if (deleg_path != NULL) + memcpy(sp.delegated, deleg_path, i * sizeof(krb5_principal)); + if (server != NULL) + sp.delegated[i++] = server; + sp.delegated[i] = NULL; + sp.method_data = NULL; + + code = make_ad_signedpath_checksum(context, + for_user_princ, + krbtgt, + krbtgt_key, + enc_tkt_reply, + sp.delegated, + sp.method_data, + &sp.checksum); + if (code != 0) { + if (code == KRB5KRB_AP_ERR_INAPP_CKSUM) { + /* + * In the hopefully unlikely case the TGS key enctype + * has an unkeyed mandatory checksum type, do not fail + * so we do not prevent the KDC from servicing requests. + */ + code = 0; + } + goto cleanup; + } + + code = encode_krb5_ad_signedpath(&sp, &data); + if (code != 0) + goto cleanup; + + ad_datum.ad_type = KRB5_AUTHDATA_SIGNTICKET; + ad_datum.contents = (krb5_octet *)data->data; + ad_datum.length = data->length; + + ad_data[0] = &ad_datum; + ad_data[1] = NULL; + + code = krb5_encode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + ad_data, + &if_relevant); + if (code != 0) + goto cleanup; + + code = merge_authdata(context, + if_relevant, + &enc_tkt_reply->authorization_data, + FALSE, /* !copy */ + FALSE); /* !ignore_kdc_issued */ + if (code != 0) + goto cleanup; + + if_relevant = NULL; /* merge_authdata() freed */ + +cleanup: + if (sp.delegated != NULL) + free(sp.delegated); + krb5_free_authdata(context, if_relevant); + krb5_free_data(context, data); + krb5_free_checksum_contents(context, &sp.checksum); + krb5_free_pa_data(context, sp.method_data); + + return code; +} + +static void +free_deleg_path(krb5_context context, krb5_principal *deleg_path) +{ + if (deleg_path != NULL) { + int i; + + for (i = 0; deleg_path[i] != NULL; i++) + krb5_free_principal(context, deleg_path[i]); + free(deleg_path); + } +} + +/* + * Returns TRUE if the Windows 2000 PAC is the only element in the + * supplied authorization data. + */ +static krb5_boolean +only_pac_p(krb5_context context, krb5_authdata **authdata) +{ + return has_kdc_issued_authdata(context, + authdata, KRB5_AUTHDATA_WIN2K_PAC) && + (authdata[1] == NULL); +} + +static krb5_error_code +handle_signedpath_authdata (krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code code = 0; + krb5_principal *deleg_path = NULL; + krb5_boolean signed_path = FALSE; + krb5_boolean s4u2proxy; + + s4u2proxy = isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); + + /* + * The Windows PAC fulfils the same role as the signed path + * if it is the only authorization data element. + */ + if (request->msg_type == KRB5_TGS_REQ && + !only_pac_p(context, enc_tkt_request->authorization_data)) { + code = verify_ad_signedpath(context, + krbtgt, + krbtgt_key, + enc_tkt_request, + &deleg_path, + &signed_path); + if (code != 0) + goto cleanup; + + if (s4u2proxy && signed_path == FALSE) { + code = KRB5KDC_ERR_BADOPTION; + goto cleanup; + } + } + + if (!isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM) && + !only_pac_p(context, enc_tkt_reply->authorization_data)) { + code = make_ad_signedpath(context, + for_user_princ, + s4u2proxy ? client->princ : NULL, + krbtgt, + krbtgt_key, + deleg_path, + enc_tkt_reply); + if (code != 0) + goto cleanup; + } + +cleanup: + free_deleg_path(context, deleg_path); + + return code; +} diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index 76539904e..dd1a2ae98 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -1007,6 +1007,45 @@ error_out: return retval; } +static asn1_error_code asn1_peek_authdata_elt(asn1buf *buf, krb5_authdatatype *val) +{ + setup(); + *val = 0; + { begin_structure(); + get_field(*val, 0, asn1_decode_authdatatype); + end_structure(); + } + return 0; +error_out: + return retval; +} + +asn1_error_code asn1_peek_authorization_data +(asn1buf *buf, unsigned int *num, krb5_authdatatype **val) +{ + int size = 0; + krb5_authdatatype *array = NULL, *new_array; + + asn1_error_code retval; + { sequence_of(buf); + while (asn1buf_remains(&seqbuf,seqofindef) > 0) { + size++; + new_array = realloc(array,size*sizeof(krb5_authdatatype)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_peek_authdata_elt(&seqbuf,&array[size-1]); + if (retval) clean_return(retval); + } + end_sequence_of(buf); + } + *num = size; + *val = array; + return 0; +error_out: + free(array); + return retval; +} + asn1_error_code asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr) { @@ -1812,6 +1851,51 @@ error_out: return retval; } +static asn1_error_code asn1_decode_princ_plus_realm +(asn1buf *buf, krb5_principal *valptr) +{ + setup(); + alloc_principal((*valptr)); + { begin_structure(); + get_field((*valptr), 0, asn1_decode_principal_name); + get_field((*valptr), 1, asn1_decode_realm); + end_structure(); + } + return 0; +error_out: + krb5_free_principal(NULL, *valptr); + *valptr = NULL; + return retval; +} + +static asn1_error_code asn1_decode_sequence_of_princ_plus_realm +(asn1buf *buf, krb5_principal **val) +{ + decode_array_body(krb5_principal_data,asn1_decode_princ_plus_realm,krb5_free_principal); +} + +asn1_error_code asn1_decode_ad_signedpath +(asn1buf *buf, krb5_ad_signedpath *val) +{ + setup(); + val->enctype = ENCTYPE_NULL; + val->checksum.contents = NULL; + val->delegated = NULL; + { + begin_structure(); + get_field(val->enctype, 0, asn1_decode_enctype); + get_field(val->checksum, 1, asn1_decode_checksum); + opt_field(val->delegated, 2, asn1_decode_sequence_of_princ_plus_realm, + NULL); + opt_field(val->method_data, 3, asn1_decode_sequence_of_pa_data, NULL); + end_structure(); + } + return 0; +error_out: + krb5_free_checksum_contents(NULL, &val->checksum); + return retval; +} + #ifndef DISABLE_PKINIT /* PKINIT */ diff --git a/src/lib/krb5/asn.1/asn1_k_decode.h b/src/lib/krb5/asn.1/asn1_k_decode.h index 8041535e6..1b0aa750b 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -134,6 +134,9 @@ asn1_error_code asn1_decode_last_req_entry_ptr(asn1buf *buf, asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val); asn1_error_code asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr); +asn1_error_code asn1_peek_authorization_data(asn1buf *buf, + unsigned int *num, + krb5_authdatatype **val); asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val); asn1_error_code asn1_decode_krb_cred_info_ptr(asn1buf *buf, krb5_cred_info **valptr); @@ -265,4 +268,7 @@ asn1_error_code asn1_decode_ad_kdcissued(asn1buf *buf, krb5_ad_kdcissued *val); asn1_error_code asn1_decode_ad_kdcissued_ptr(asn1buf *buf, krb5_ad_kdcissued **val); +asn1_error_code asn1_decode_ad_signedpath(asn1buf *buf, + krb5_ad_signedpath *val); + #endif diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index d0371f53f..22ebae32a 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -97,7 +97,6 @@ DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1)); DEFPTRTYPE(realm_of_principal, realm_of_principal_data); - static const struct field_info princname_fields[] = { FIELDOF_NORM(krb5_principal_data, int32, type, 0), FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, 1), @@ -1331,7 +1330,59 @@ ad_kdcissued_optional(const void *p) DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields, ad_kdcissued_optional); +static const struct field_info princ_plus_realm_fields[] = { + FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 0), + FIELDOF_ENCODEAS(krb5_principal_data, realm_of_principal_data, 1), +}; + +DEFSEQTYPE(princ_plus_realm_data, krb5_principal_data, princ_plus_realm_fields, 0); +DEFPTRTYPE(princ_plus_realm, princ_plus_realm_data); + +DEFNULLTERMSEQOFTYPE(seq_of_princ_plus_realm, princ_plus_realm); +DEFPTRTYPE(ptr_seq_of_princ_plus_realm, seq_of_princ_plus_realm); + +static const struct field_info ad_signedpath_data_fields[] = { + FIELDOF_NORM(krb5_ad_signedpath_data, princ_plus_realm, client, 0), + FIELDOF_NORM(krb5_ad_signedpath_data, kerberos_time, authtime, 1), + FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seq_of_princ_plus_realm, delegated, 2, 2), + FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seqof_pa_data, method_data, 3, 3), + FIELDOF_OPT(krb5_ad_signedpath_data, auth_data_ptr, authorization_data, 4, 4), +}; + +static unsigned int ad_signedpath_data_optional(const void *p) +{ + unsigned int optional = 0; + const krb5_ad_signedpath_data *val = p; + if (val->delegated && val->delegated[0]) + optional |= (1u << 2); + if (val->method_data && val->method_data[0]) + optional |= (1u << 3); + if (val->authorization_data && val->authorization_data[0]) + optional |= (1u << 4); + return optional; +} + +DEFSEQTYPE(ad_signedpath_data, krb5_ad_signedpath_data, ad_signedpath_data_fields, ad_signedpath_data_optional); + +static const struct field_info ad_signedpath_fields[] = { + FIELDOF_NORM(krb5_ad_signedpath, int32, enctype, 0), + FIELDOF_NORM(krb5_ad_signedpath, checksum, checksum, 1), + FIELDOF_OPT(krb5_ad_signedpath, ptr_seq_of_princ_plus_realm, delegated, 2, 2), + FIELDOF_OPT(krb5_ad_signedpath, ptr_seqof_pa_data, method_data, 3, 3), +}; + +static unsigned int ad_signedpath_optional(const void *p) +{ + unsigned int optional = 0; + const krb5_ad_signedpath *val = p; + if (val->delegated && val->delegated[0]) + optional |= (1u << 2); + if (val->method_data && val->method_data[0]) + optional |= (1u << 3); + return optional; +} +DEFSEQTYPE(ad_signedpath, krb5_ad_signedpath, ad_signedpath_fields, ad_signedpath_optional); /* Exported complete encoders -- these produce a krb5_data with the encoding in the correct byte order. */ @@ -1407,6 +1458,8 @@ MAKE_FULL_ENCODER( encode_krb5_pa_fx_fast_reply, pa_fx_fast_reply); MAKE_FULL_ENCODER(encode_krb5_fast_response, fast_response); MAKE_FULL_ENCODER(encode_krb5_ad_kdcissued, ad_kdc_issued); +MAKE_FULL_ENCODER(encode_krb5_ad_signedpath_data, ad_signedpath_data); +MAKE_FULL_ENCODER(encode_krb5_ad_signedpath, ad_signedpath); diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index fa835feba..0daa32efd 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -1192,6 +1192,42 @@ krb5_error_code decode_krb5_ad_kdcissued cleanup(free); } +krb5_error_code decode_krb5_ad_signedpath +(const krb5_data *code, krb5_ad_signedpath **repptr) +{ + setup_buf_only(krb5_ad_signedpath *); + alloc_field(rep); + + retval = asn1_decode_ad_signedpath(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +krb5int_get_authdata_containee_types(krb5_context context, + const krb5_authdata *authdata, + unsigned int *num, + krb5_authdatatype **repptr) +{ + krb5_data data, *code = &data; + + data.data = (char *)authdata->contents; + data.length = authdata->length; + + *num = 0; + + { + setup_buf_only(krb5_authdatatype *); + + retval = asn1_peek_authorization_data(&buf, num, &rep); + if (retval) clean_return(retval); + + cleanup_none(); + } + assert(0); /* NOTREACHED */ +} + #ifndef DISABLE_PKINIT krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **repptr) diff --git a/src/lib/krb5/krb/copy_auth.c b/src/lib/krb5/krb/copy_auth.c index 0262fe5bb..d4c270078 100644 --- a/src/lib/krb5/krb/copy_auth.c +++ b/src/lib/krb5/krb/copy_auth.c @@ -223,34 +223,47 @@ grow_find_authdata(krb5_context context, struct find_authdata_context *fctx, static krb5_error_code find_authdata_1(krb5_context context, krb5_authdata *const *in_authdat, - krb5_authdatatype ad_type, struct find_authdata_context *fctx) + krb5_authdatatype ad_type, struct find_authdata_context *fctx, + int from_ap_req) { int i = 0; - krb5_error_code retval=0; + krb5_error_code retval = 0; for (i = 0; in_authdat[i]; i++) { krb5_authdata *ad = in_authdat[i]; - if (ad->ad_type == ad_type && retval ==0) - retval = grow_find_authdata(context, fctx, ad); - else switch (ad->ad_type) { - krb5_authdata **decoded_container; - case KRB5_AUTHDATA_IF_RELEVANT: - if (retval == 0) - retval = krb5_decode_authdata_container( context, ad->ad_type, ad, &decoded_container); - if (retval == 0) { - retval = find_authdata_1(context, - decoded_container, ad_type, fctx); - krb5_free_authdata(context, decoded_container); - } - break; - default: - break; + krb5_authdata **decoded_container; + + switch (ad->ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: + if (retval == 0) + retval = krb5_decode_authdata_container(context, + ad->ad_type, + ad, + &decoded_container); + if (retval == 0) { + retval = find_authdata_1(context, + decoded_container, + ad_type, + fctx, + from_ap_req); + krb5_free_authdata(context, decoded_container); } + break; + case KRB5_AUTHDATA_SIGNTICKET: + case KRB5_AUTHDATA_KDC_ISSUED: + case KRB5_AUTHDATA_WIN2K_PAC: + if (from_ap_req) + continue; + default: + if (ad->ad_type == ad_type && retval == 0) + retval = grow_find_authdata(context, fctx, ad); + break; + } } + return retval; } - krb5_error_code krb5int_find_authdata(krb5_context context, krb5_authdata *const *ticket_authdata, @@ -266,9 +279,9 @@ krb5int_find_authdata(krb5_context context, if (fctx.out == NULL) return ENOMEM; if (ticket_authdata) - retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx); + retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx, 0); if ((retval==0) && ap_req_authdata) - retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx); + retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx, 1); if ((retval== 0) && fctx.length) *results = fctx.out; else krb5_free_authdata(context, fctx.out); @@ -300,6 +313,9 @@ krb5_make_authdata_kdc_issued(krb5_context context, if (code != 0) return code; + if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + code = encode_krb5_authdata(ad_kdci.elements, &data); if (code != 0) return code; @@ -361,6 +377,11 @@ krb5_verify_authdata_kdc_issued(krb5_context context, if (code != 0) return code; + if (!krb5_c_is_keyed_cksum(ad_kdci->ad_checksum.checksum_type)) { + krb5_free_ad_kdcissued(context, ad_kdci); + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + code = encode_krb5_authdata(ad_kdci->elements, &data2); if (code != 0) { krb5_free_ad_kdcissued(context, ad_kdci); diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index c372e70b6..02906a1e0 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -909,3 +909,20 @@ krb5_free_ad_kdcissued(krb5_context context, krb5_ad_kdcissued *val) krb5_free_authdata(context, val->elements); free(val); } + +void KRB5_CALLCONV +krb5_free_ad_signedpath(krb5_context context, krb5_ad_signedpath *val) +{ + int i; + + if (val == NULL) + return; + + krb5_free_checksum_contents(context, &val->checksum); + if (val->delegated != NULL) { + for (i = 0; val->delegated[i] != NULL; i++) + krb5_free_principal(context, val->delegated[i]); + free(val->delegated); + } + krb5_free_pa_data(context, val->method_data); +} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 2735c9f98..8ef3a9dc0 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -1,5 +1,6 @@ _krb5_conf_boolean decode_krb5_ad_kdcissued +decode_krb5_ad_signedpath decode_krb5_alt_method decode_krb5_ap_rep decode_krb5_ap_rep_enc_part @@ -42,6 +43,8 @@ decode_krb5_tgs_req decode_krb5_ticket decode_krb5_typed_data encode_krb5_ad_kdcissued +encode_krb5_ad_signedpath_data +encode_krb5_ad_signedpath encode_krb5_alt_method encode_krb5_ap_rep encode_krb5_ap_rep_enc_part @@ -220,6 +223,7 @@ krb5_externalize_opaque krb5_fcc_ops krb5_find_serializer krb5_free_ad_kdcissued +krb5_free_ad_signedpath krb5_free_address krb5_free_addresses krb5_free_alt_method @@ -554,6 +558,7 @@ krb5int_find_pa_data krb5int_foreach_localaddr krb5int_free_addrlist krb5int_free_data_list +krb5int_get_authdata_containee_types krb5int_get_domain_realm_mapping krb5int_init_context_kdc krb5int_initialize_library diff --git a/src/plugins/authdata/greet_server/greet_auth.c b/src/plugins/authdata/greet_server/greet_auth.c index 9a0533286..fad044a55 100644 --- a/src/plugins/authdata/greet_server/greet_auth.c +++ b/src/plugins/authdata/greet_server/greet_auth.c @@ -69,7 +69,7 @@ greet_kdc_verify(krb5_context context, NULL, KRB5_AUTHDATA_KDC_ISSUED, &tgt_authdata); - if (code != 0) + if (code != 0 || tgt_authdata == NULL) return 0; code = krb5_verify_authdata_kdc_issued(context, @@ -113,6 +113,7 @@ greet_kdc_sign(krb5_context context, krb5_error_code code; krb5_authdata ad_datum, *ad_data[2], **kdc_issued = NULL; krb5_authdata **if_relevant = NULL; + krb5_authdata **tkt_authdata; ad_datum.ad_type = -42; ad_datum.contents = (krb5_octet *)greeting->data; @@ -138,13 +139,20 @@ greet_kdc_sign(krb5_context context, return code; } - /* this isn't very friendly to other plugins... */ - krb5_free_authdata(context, enc_tkt_reply->authorization_data); - enc_tkt_reply->authorization_data = if_relevant; + code = krb5_merge_authdata(context, + if_relevant, + enc_tkt_reply->authorization_data, + &tkt_authdata); + if (code == 0) { + krb5_free_authdata(context, enc_tkt_reply->authorization_data); + enc_tkt_reply->authorization_data = tkt_authdata; + } else { + krb5_free_authdata(context, if_relevant); + } krb5_free_authdata(context, kdc_issued); - return 0; + return code; } static krb5_error_code @@ -165,17 +173,12 @@ greet_authdata(krb5_context context, krb5_error_code code; krb5_data *greeting = NULL; - if (request->msg_type == KRB5_TGS_REQ) { - code = greet_kdc_verify(context, enc_tkt_request, &greeting); - if (code != 0) - return code; - } + if (request->msg_type != KRB5_TGS_REQ) + return 0; - if (greeting == NULL) { - code = greet_hello(context, &greeting); - if (code != 0) - return code; - } + code = greet_hello(context, &greeting); + if (code != 0) + return code; code = greet_kdc_sign(context, enc_tkt_reply, tgs->princ, greeting); diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c index 717daee22..27f094f82 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c @@ -75,6 +75,40 @@ krb5_ldap_audit_as(krb5_context context, return code; } +static krb5_error_code +krb5_ldap_check_allowed_to_delegate(krb5_context context, + unsigned int method, + const krb5_data *request, + krb5_data *response) +{ + const kdb_check_allowed_to_delegate_req *req; + krb5_error_code code; + krb5_tl_data *tlp; + + req = (const kdb_check_allowed_to_delegate_req *)request->data; + + code = KRB5KDC_ERR_POLICY; + + for (tlp = req->server->tl_data; tlp != NULL; tlp = tlp->tl_data_next) { + krb5_principal acl; + + if (tlp->tl_data_type != KRB5_TL_CONSTRAINED_DELEGATION_ACL) + continue; + + if (krb5_parse_name(context, (char *)tlp->tl_data_contents, &acl) != 0) + continue; + + if (krb5_principal_compare(context, req->proxy, acl)) { + code = 0; + krb5_free_principal(context, acl); + break; + } + krb5_free_principal(context, acl); + } + + return code; +} + krb5_error_code krb5_ldap_invoke(krb5_context context, unsigned int method, @@ -90,6 +124,9 @@ krb5_ldap_invoke(krb5_context context, case KRB5_KDB_METHOD_AUDIT_AS: code = krb5_ldap_audit_as(context, method, req, rep); break; + case KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE: + code = krb5_ldap_check_allowed_to_delegate(context, method, req, rep); + break; default: break; } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif index fd226b13d..886f8b435 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif +++ b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif @@ -662,6 +662,15 @@ attributetypes: ( 2.16.840.1.113719.1.301.4.53.1 EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) +##### A list of services to which a service principal can delegate. +dn: cn=schema +changetype: modify +add: attributetypes +attributetype: ( 1.3.6.1.4.1.5322.21.2.4 + NAME 'krbAllowedToDelegateTo' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) ######################################################################## ######################################################################## @@ -745,7 +754,7 @@ add: objectclasses objectClasses: ( 2.16.840.1.113719.1.301.6.8.1 NAME 'krbPrincipalAux' AUXILIARY - MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData ) ) + MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData $ krbAllowedToDelegateTo ) ) ###### This class is used to create additional principals and stand alone principals. diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema index 9525e60d6..65e07d6cd 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema +++ b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema @@ -533,6 +533,13 @@ attributetype ( 2.16.840.1.113719.1.301.4.53.1 EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) +##### A list of services to which a service principal can delegate. +attributetype ( 1.3.6.1.4.1.5322.21.2.4 + NAME 'krbAllowedToDelegateTo' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) + ######################################################################## ######################################################################## # Object Class Definitions # @@ -602,7 +609,7 @@ objectclass ( 2.16.840.1.113719.1.301.6.8.1 NAME 'krbPrincipalAux' SUP top AUXILIARY - MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData ) ) + MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData $ krbAllowedToDelegateTo ) ) ###### This class is used to create additional principals and stand alone principals. diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c index 8625984d8..a5ab6598a 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c @@ -2085,6 +2085,43 @@ populate_krb5_db_entry (krb5_context context, } } + /* ALLOWED TO DELEGATE TO */ + { + char **a2d2 = NULL; + int i; + krb5_tl_data **tlp; + + st = krb5_ldap_get_strings(ld, ent, "krbAllowedToDelegateTo", + &a2d2, &attr_present); + if (st != 0) + goto cleanup; + + if (attr_present == TRUE) { + for (tlp = &entry->tl_data; *tlp; tlp = &(*tlp)->tl_data_next) + ; + for (i = 0; a2d2[i] != NULL; i++) { + krb5_tl_data *tl = k5alloc(sizeof(*tl), &st); + if (st != 0) { + ldap_value_free(a2d2); + goto cleanup; + } + tl->tl_data_type = KRB5_TL_CONSTRAINED_DELEGATION_ACL; + tl->tl_data_length = strlen(a2d2[i]); + tl->tl_data_contents = (krb5_octet *)strdup(a2d2[i]); + if (tl->tl_data_contents == NULL) { + st = ENOMEM; + ldap_value_free(a2d2); + free(tl); + goto cleanup; + } + tl->tl_data_next = NULL; + *tlp = tl; + tlp = &tl->tl_data_next; + } + ldap_value_free(a2d2); + } + } + /* KRBOBJECTREFERENCES */ { int i=0; diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c index ecc4d3c8a..c59944406 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c @@ -61,6 +61,7 @@ char *principal_attributes[] = { "krbprincipalname", "krbLastPwdChange", "krbExtraData", "krbObjectReferences", + "krbAllowedToDelegateTo", NULL }; /* Must match KDB_*_ATTR macros in ldap_principal.h. */ diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c index 42a76859a..3474b7cda 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c @@ -1082,7 +1082,8 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) || ptr->tl_data_type == KRB5_TL_DB_ARGS #endif || ptr->tl_data_type == KRB5_TL_KADM_DATA - || ptr->tl_data_type == KDB_TL_USER_INFO) + || ptr->tl_data_type == KDB_TL_USER_INFO + || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL) continue; count++; } @@ -1102,7 +1103,8 @@ krb5_ldap_put_principal(context, entries, nentries, db_args) || ptr->tl_data_type == KRB5_TL_DB_ARGS #endif || ptr->tl_data_type == KRB5_TL_KADM_DATA - || ptr->tl_data_type == KDB_TL_USER_INFO) + || ptr->tl_data_type == KDB_TL_USER_INFO + || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL) continue; if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0) break; diff --git a/src/tests/asn.1/krb5_decode_leak.c b/src/tests/asn.1/krb5_decode_leak.c index 1b90bf769..9f68fb085 100644 --- a/src/tests/asn.1/krb5_decode_leak.c +++ b/src/tests/asn.1/krb5_decode_leak.c @@ -680,6 +680,30 @@ main(int argc, char **argv) krb5_free_ad_kdcissued); ktest_empty_ad_kdcissued(&kdci); } +#if 0 + /****************************************************************/ + /* encode_krb5_ad_signedpath_data */ + { + krb5_ad_signedpath_data spd, *tmp; + setup(spd, "ad_signedpath_data", + ktest_make_sample_ad_signedpath_data); + leak_test(spd, encode_krb5_ad_signedpath_data, + decode_krb5_ad_signedpath_data, + NULL); + ktest_empty_ad_signedpath_data(&spd); + } +#endif + /****************************************************************/ + /* encode_krb5_ad_signedpath */ + { + krb5_ad_signedpath sp, *tmp; + setup(sp, "ad_signedpath", + ktest_make_sample_ad_signedpath); + leak_test(sp, encode_krb5_ad_signedpath, + decode_krb5_ad_signedpath, + krb5_free_ad_signedpath); + ktest_empty_ad_signedpath(&sp); + } krb5_free_context(test_context); return 0; } diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c index 903697292..d99698180 100644 --- a/src/tests/asn.1/krb5_decode_test.c +++ b/src/tests/asn.1/krb5_decode_test.c @@ -907,6 +907,14 @@ int main(argc, argv) ktest_empty_ad_kdcissued(&ref); } + /****************************************************************/ + /* decode_ad_signedpath */ + { + setup(krb5_ad_signedpath,"krb5_ad_signedpath",ktest_make_sample_ad_signedpath); + decode_run("ad_signedpath","","30 3E A0 03 02 01 01 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61",decode_krb5_ad_signedpath,ktest_equal_ad_signedpath,krb5_free_ad_signedpath); + ktest_empty_ad_signedpath(&ref); + } + #ifdef ENABLE_LDAP /* ldap sequence_of_keys */ { diff --git a/src/tests/asn.1/krb5_encode_test.c b/src/tests/asn.1/krb5_encode_test.c index db99f1080..3716eb477 100644 --- a/src/tests/asn.1/krb5_encode_test.c +++ b/src/tests/asn.1/krb5_encode_test.c @@ -717,6 +717,28 @@ main(argc, argv) encode_krb5_ad_kdcissued); ktest_empty_ad_kdcissued(&kdci); } + /****************************************************************/ + /* encode_krb5_ad_signedpath_data */ + { + krb5_ad_signedpath_data spd; + setup(spd,krb5_ad_signedpath_data,"ad_signedpath_data", + ktest_make_sample_ad_signedpath_data); + encode_run(spd,krb5_ad_signedpath_data, + "ad_signedpath_data","", + encode_krb5_ad_signedpath_data); + ktest_empty_ad_signedpath_data(&spd); + } + /****************************************************************/ + /* encode_krb5_ad_signedpath */ + { + krb5_ad_signedpath sp; + setup(sp,krb5_ad_signedpath,"ad_signedpath", + ktest_make_sample_ad_signedpath); + encode_run(sp,krb5_ad_signedpath, + "ad_signedpath","", + encode_krb5_ad_signedpath); + ktest_empty_ad_signedpath(&sp); + } #ifdef ENABLE_LDAP { ldap_seqof_key_data skd; diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c index 6ca9652ab..64c4fbdba 100644 --- a/src/tests/asn.1/ktest.c +++ b/src/tests/asn.1/ktest.c @@ -855,6 +855,42 @@ krb5_error_code ktest_make_sample_ad_kdcissued(p) return retval; } +krb5_error_code ktest_make_sample_ad_signedpath_data(p) + krb5_ad_signedpath_data *p; +{ + krb5_error_code retval; + retval = ktest_make_sample_principal(&p->client); + if (retval) return retval; + p->authtime = SAMPLE_TIME; + p->delegated = k5alloc((2 * sizeof(krb5_principal)), &retval); + if (retval) return retval; + retval = ktest_make_sample_principal(&p->delegated[0]); + if (retval) return retval; + p->delegated[1] = NULL; + retval = ktest_make_sample_principal(&p->client); + if (retval) return retval; + retval = ktest_make_sample_authorization_data(&p->authorization_data); + if (retval) return retval; + retval = ktest_make_sample_pa_data_array(&p->method_data); + if (retval) return retval; + return retval; +} + +krb5_error_code ktest_make_sample_ad_signedpath(p) + krb5_ad_signedpath*p; +{ + krb5_error_code retval; + p->enctype = 1; + retval = ktest_make_sample_checksum(&p->checksum); + if (retval) return retval; + p->delegated = k5alloc((2 * sizeof(krb5_principal)), &retval); + if (retval) return retval; + p->delegated[1] = NULL; + retval = ktest_make_sample_pa_data_array(&p->method_data); + if (retval) return retval; + return retval; +} + #ifdef ENABLE_LDAP static krb5_error_code ktest_make_sample_key_data(krb5_key_data *p, int i) { @@ -1466,6 +1502,37 @@ void ktest_empty_ad_kdcissued(p) ktest_destroy_authorization_data(&p->elements); } +void ktest_empty_ad_signedpath_data(p) + krb5_ad_signedpath_data *p; +{ + int i; + ktest_destroy_principal(&p->client); + if (p->delegated != NULL) { + for (i = 0; p->delegated[i] != NULL; i++) { + krb5_principal princ = p->delegated[i]; + ktest_destroy_principal(&princ); + } + free(p->delegated); + } + ktest_destroy_pa_data_array(&p->method_data); + ktest_destroy_authorization_data(&p->authorization_data); +} + +void ktest_empty_ad_signedpath(p) + krb5_ad_signedpath *p; +{ + int i; + if (p->checksum.contents) free(p->checksum.contents); + if (p->delegated != NULL) { + for (i = 0; p->delegated[i] != NULL; i++) { + krb5_principal princ = p->delegated[i]; + ktest_destroy_principal(&princ); + } + free(p->delegated); + } + ktest_destroy_pa_data_array(&p->method_data); +} + #ifdef ENABLE_LDAP void ktest_empty_ldap_seqof_key_data(ctx, p) krb5_context ctx; diff --git a/src/tests/asn.1/ktest.h b/src/tests/asn.1/ktest.h index fa33ceffd..5f9b5ca38 100644 --- a/src/tests/asn.1/ktest.h +++ b/src/tests/asn.1/ktest.h @@ -107,6 +107,8 @@ krb5_error_code ktest_make_sample_predicted_sam_response(krb5_predicted_sam_resp krb5_error_code ktest_make_sample_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p); krb5_error_code ktest_make_sample_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p); krb5_error_code ktest_make_sample_ad_kdcissued(krb5_ad_kdcissued *p); +krb5_error_code ktest_make_sample_ad_signedpath_data(krb5_ad_signedpath_data *p); +krb5_error_code ktest_make_sample_ad_signedpath(krb5_ad_signedpath *p); #ifdef ENABLE_LDAP krb5_error_code ktest_make_sample_ldap_seqof_key_data(ldap_seqof_key_data * p); @@ -217,6 +219,8 @@ void ktest_empty_sam_response_2(krb5_sam_response_2 *p); void ktest_empty_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p); void ktest_empty_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p); void ktest_empty_ad_kdcissued(krb5_ad_kdcissued *p); +void ktest_empty_ad_signedpath_data(krb5_ad_signedpath_data *p); +void ktest_empty_ad_signedpath(krb5_ad_signedpath *p); #ifdef ENABLE_LDAP void ktest_empty_ldap_seqof_key_data(krb5_context, ldap_seqof_key_data *p); diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c index 5479f8047..67c8d7e4f 100644 --- a/src/tests/asn.1/ktest_equal.c +++ b/src/tests/asn.1/ktest_equal.c @@ -570,6 +570,35 @@ int ktest_equal_ad_kdcissued(ref, var) return p; } +int ktest_equal_ad_signedpath_data(ref, var) + krb5_ad_signedpath_data *ref; + krb5_ad_signedpath_data *var; +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p=p&&ptr_equal(client,ktest_equal_principal_data); + p=p&&scalar_equal(authtime); + p=p&&ptr_equal(delegated,ktest_equal_sequence_of_principal); + p=p&&ptr_equal(method_data,ktest_equal_sequence_of_pa_data); + p=p&&ptr_equal(authorization_data,ktest_equal_authorization_data); + return p; +} + +int ktest_equal_ad_signedpath(ref, var) + krb5_ad_signedpath* ref; + krb5_ad_signedpath* var; +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p=p&&scalar_equal(enctype); + p=p&&struct_equal(checksum,ktest_equal_checksum); + p=p&&ptr_equal(delegated,ktest_equal_sequence_of_principal); + p=p&&ptr_equal(method_data,ktest_equal_sequence_of_pa_data); + return p; +} + #ifdef ENABLE_LDAP static int equal_key_data(ref, var) krb5_key_data *ref; @@ -721,6 +750,13 @@ int ktest_equal_sequence_of_cred_info(ref, var) array_compare(ktest_equal_cred_info); } +int ktest_equal_sequence_of_principal(ref, var) + krb5_principal * ref; + krb5_principal * var; +{ + array_compare(ktest_equal_principal_data); +} + int ktest_equal_array_of_passwd_phrase_element(ref, var) passwd_phrase_element ** ref; passwd_phrase_element ** var; diff --git a/src/tests/asn.1/ktest_equal.h b/src/tests/asn.1/ktest_equal.h index 1464ebb50..80c38b639 100644 --- a/src/tests/asn.1/ktest_equal.h +++ b/src/tests/asn.1/ktest_equal.h @@ -69,6 +69,8 @@ int ktest_equal_sequence_of_pa_data (krb5_pa_data **ref, krb5_pa_data **var); int ktest_equal_sequence_of_cred_info (krb5_cred_info **ref, krb5_cred_info **var); +int ktest_equal_sequence_of_principal + (krb5_principal *ref, krb5_principal *var); len_array(ktest_equal_array_of_enctype,krb5_enctype); len_array(ktest_equal_array_of_data,krb5_data); @@ -98,6 +100,12 @@ int ktest_equal_pa_s4u_x509_user int ktest_equal_ad_kdcissued (krb5_ad_kdcissued *ref, krb5_ad_kdcissued *var); +int ktest_equal_ad_signedpath_data + (krb5_ad_signedpath_data *ref, + krb5_ad_signedpath_data *var); +int ktest_equal_ad_signedpath + (krb5_ad_signedpath *ref, + krb5_ad_signedpath *var); int ktest_equal_ldap_sequence_of_keys(ldap_seqof_key_data *ref, ldap_seqof_key_data *var); diff --git a/src/tests/asn.1/reference_encode.out b/src/tests/asn.1/reference_encode.out index 952e69c77..c6bcf619c 100644 --- a/src/tests/asn.1/reference_encode.out +++ b/src/tests/asn.1/reference_encode.out @@ -58,3 +58,5 @@ encode_krb5_sam_response_2: 30 42 A0 03 02 01 2B A1 07 03 05 00 80 00 00 00 A2 0 encode_krb5_enc_sam_response_enc_2: 30 1F A0 03 02 01 58 A1 18 04 16 65 6E 63 5F 73 61 6D 5F 72 65 73 70 6F 6E 73 65 5F 65 6E 63 5F 32 encode_krb5_pa_s4u_x509_user: 30 68 A0 55 30 53 A0 06 02 04 00 CA 14 9A A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 12 04 10 70 61 5F 73 34 75 5F 78 35 30 39 5F 75 73 65 72 A4 07 03 05 00 80 00 00 00 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 encode_krb5_ad_kdcissued: 30 65 A0 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_ad_signedpath_data: 30 81 C7 A0 30 30 2E A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 32 30 30 30 2E A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_ad_signedpath: 30 3E A0 03 02 01 01 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 diff --git a/src/tests/asn.1/trval_reference.out b/src/tests/asn.1/trval_reference.out index b19ca747e..38e5b99ad 100644 --- a/src/tests/asn.1/trval_reference.out +++ b/src/tests/asn.1/trval_reference.out @@ -1283,3 +1283,52 @@ encode_krb5_ad_kdcissued: . . . [0] [Integer] 1 . . . [1] [Octet String] "foobar" +encode_krb5_ad_signedpath_data: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [1] [General string] "ATHENA.MIT.EDU" +. [1] [Generalized Time] "19940610060317Z" +. [2] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . . [1] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [1] [General string] "ATHENA.MIT.EDU" +. [3] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. [4] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "foobar" +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "foobar" + +encode_krb5_ad_signedpath: + +[Sequence/Sequence Of] +. [0] [Integer] 1 +. [1] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" +. [3] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +