svn rev #23160: trunk/src/ include/ include/krb5/ kdc/ lib/krb5/ lib/krb5/asn.1/ ...

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Nov 13 23:46:30 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=23160
Commit By: ghudson
Log Message:
ticket: 6580
subject: 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.



Changed Files:
U   trunk/src/include/k5-int.h
U   trunk/src/include/krb5/krb5.hin
U   trunk/src/kdc/do_tgs_req.c
U   trunk/src/kdc/kdc_authdata.c
U   trunk/src/lib/krb5/asn.1/asn1_k_decode.c
U   trunk/src/lib/krb5/asn.1/asn1_k_decode.h
U   trunk/src/lib/krb5/asn.1/asn1_k_encode.c
U   trunk/src/lib/krb5/asn.1/krb5_decode.c
U   trunk/src/lib/krb5/krb/copy_auth.c
U   trunk/src/lib/krb5/krb/kfree.c
U   trunk/src/lib/krb5/libkrb5.exports
U   trunk/src/plugins/authdata/greet_server/greet_auth.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
U   trunk/src/tests/asn.1/krb5_decode_leak.c
U   trunk/src/tests/asn.1/krb5_decode_test.c
U   trunk/src/tests/asn.1/krb5_encode_test.c
U   trunk/src/tests/asn.1/ktest.c
U   trunk/src/tests/asn.1/ktest.h
U   trunk/src/tests/asn.1/ktest_equal.c
U   trunk/src/tests/asn.1/ktest_equal.h
U   trunk/src/tests/asn.1/reference_encode.out
U   trunk/src/tests/asn.1/trval_reference.out
Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/include/k5-int.h	2009-11-14 04:46:30 UTC (rev 23160)
@@ -1075,6 +1075,21 @@
     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 @@
 (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_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_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_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);

Modified: trunk/src/include/krb5/krb5.hin
===================================================================
--- trunk/src/include/krb5/krb5.hin	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/include/krb5/krb5.hin	2009-11-14 04:46:30 UTC (rev 23160)
@@ -647,6 +647,8 @@
 #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 @@
 #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 */
 

Modified: trunk/src/kdc/do_tgs_req.c
===================================================================
--- trunk/src/kdc/do_tgs_req.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/kdc/do_tgs_req.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -103,7 +103,7 @@
     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 @@
     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 @@
 
     reply.padata = 0; /* For cleanup handler */
     reply_encpart.enc_padata = 0;
+    e_data.data = NULL;
 
     session_key.contents = NULL;
 
@@ -391,9 +393,6 @@
 
             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,8 +424,19 @@
         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;
     else
@@ -443,7 +453,7 @@
      * 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 @@
     }
 
     /*
-     * 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 @@
         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 @@
     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 @@
 
             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 @@
         !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 @@
                               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 @@
     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 */

Modified: trunk/src/kdc/kdc_authdata.c
===================================================================
--- trunk/src/kdc/kdc_authdata.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/kdc/kdc_authdata.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -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 <syslog.h>
 
 #include <assert.h>
-#include "../include/krb5/authdata_plugin.h"
+#include <krb5/authdata_plugin.h>
 
 #if TARGET_OS_MAC
 static const char *objdirs[] = { KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR,
@@ -70,7 +70,6 @@
 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 @@
      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 @@
      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 @@
 #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 @@
 } 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 @@
 
     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 @@
         }
     }
 
-    /* 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 @@
     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 @@
         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 @@
         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 @@
 
     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,
@@ -475,6 +648,36 @@
                      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;
     krb5_boolean tgs_req = (request->msg_type == KRB5_TGS_REQ);
@@ -489,12 +692,6 @@
      * 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 @@
     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 @@
                             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 @@
 
     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;
+}

Modified: trunk/src/lib/krb5/asn.1/asn1_k_decode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_decode.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/asn.1/asn1_k_decode.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -1007,6 +1007,45 @@
     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 @@
     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 */
 

Modified: trunk/src/lib/krb5/asn.1/asn1_k_decode.h
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_decode.h	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/asn.1/asn1_k_decode.h	2009-11-14 04:46:30 UTC (rev 23160)
@@ -134,6 +134,9 @@
 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_ptr(asn1buf *buf,
                                              krb5_ad_kdcissued **val);
 
+asn1_error_code asn1_decode_ad_signedpath(asn1buf *buf,
+                                          krb5_ad_signedpath *val);
+
 #endif

Modified: trunk/src/lib/krb5/asn.1/asn1_k_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -97,7 +97,6 @@
              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,8 +1330,60 @@
 
 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_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);
 
 
 

Modified: trunk/src/lib/krb5/asn.1/krb5_decode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/krb5_decode.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/asn.1/krb5_decode.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -1192,6 +1192,42 @@
     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)

Modified: trunk/src/lib/krb5/krb/copy_auth.c
===================================================================
--- trunk/src/lib/krb5/krb/copy_auth.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/krb/copy_auth.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -223,34 +223,47 @@
 
 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 @@
     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 @@
     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 @@
     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);

Modified: trunk/src/lib/krb5/krb/kfree.c
===================================================================
--- trunk/src/lib/krb5/krb/kfree.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/krb/kfree.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -909,3 +909,20 @@
     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);
+}

Modified: trunk/src/lib/krb5/libkrb5.exports
===================================================================
--- trunk/src/lib/krb5/libkrb5.exports	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/lib/krb5/libkrb5.exports	2009-11-14 04:46:30 UTC (rev 23160)
@@ -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_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_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_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

Modified: trunk/src/plugins/authdata/greet_server/greet_auth.c
===================================================================
--- trunk/src/plugins/authdata/greet_server/greet_auth.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/authdata/greet_server/greet_auth.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -69,7 +69,7 @@
                                  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 @@
     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 @@
         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 @@
     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);
 

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -75,6 +75,40 @@
     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 @@
     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;
     }

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif	2009-11-14 04:46:30 UTC (rev 23160)
@@ -662,6 +662,15 @@
                 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 @@
 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.

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema	2009-11-14 04:46:30 UTC (rev 23160)
@@ -533,6 +533,13 @@
                 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 @@
                 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.

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -2085,6 +2085,43 @@
 	}
     }
 
+    /* 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;

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -61,6 +61,7 @@
 				     "krbLastPwdChange",
 				     "krbExtraData",
 				     "krbObjectReferences",
+				     "krbAllowedToDelegateTo",
 				     NULL };
 
 /* Must match KDB_*_ATTR macros in ldap_principal.h.  */

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -1082,7 +1082,8 @@
 		    || 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 @@
 			|| 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;

Modified: trunk/src/tests/asn.1/krb5_decode_leak.c
===================================================================
--- trunk/src/tests/asn.1/krb5_decode_leak.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/krb5_decode_leak.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -680,6 +680,30 @@
                   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;
 }

Modified: trunk/src/tests/asn.1/krb5_decode_test.c
===================================================================
--- trunk/src/tests/asn.1/krb5_decode_test.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/krb5_decode_test.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -907,6 +907,14 @@
 	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 */
     {

Modified: trunk/src/tests/asn.1/krb5_encode_test.c
===================================================================
--- trunk/src/tests/asn.1/krb5_encode_test.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/krb5_encode_test.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -717,6 +717,28 @@
 		   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;

Modified: trunk/src/tests/asn.1/ktest.c
===================================================================
--- trunk/src/tests/asn.1/ktest.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/ktest.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -855,6 +855,42 @@
     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 @@
     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;

Modified: trunk/src/tests/asn.1/ktest.h
===================================================================
--- trunk/src/tests/asn.1/ktest.h	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/ktest.h	2009-11-14 04:46:30 UTC (rev 23160)
@@ -107,6 +107,8 @@
 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_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);

Modified: trunk/src/tests/asn.1/ktest_equal.c
===================================================================
--- trunk/src/tests/asn.1/ktest_equal.c	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/ktest_equal.c	2009-11-14 04:46:30 UTC (rev 23160)
@@ -570,6 +570,35 @@
     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 @@
     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;

Modified: trunk/src/tests/asn.1/ktest_equal.h
===================================================================
--- trunk/src/tests/asn.1/ktest_equal.h	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/ktest_equal.h	2009-11-14 04:46:30 UTC (rev 23160)
@@ -69,6 +69,8 @@
 	(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_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);

Modified: trunk/src/tests/asn.1/reference_encode.out
===================================================================
--- trunk/src/tests/asn.1/reference_encode.out	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/reference_encode.out	2009-11-14 04:46:30 UTC (rev 23160)
@@ -58,3 +58,5 @@
 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

Modified: trunk/src/tests/asn.1/trval_reference.out
===================================================================
--- trunk/src/tests/asn.1/trval_reference.out	2009-11-14 01:08:10 UTC (rev 23159)
+++ trunk/src/tests/asn.1/trval_reference.out	2009-11-14 04:46:30 UTC (rev 23160)
@@ -1283,3 +1283,52 @@
 .  .  .  [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"
+




More information about the cvs-krb5 mailing list