Author: abartlet
Date: 2005-10-26 23:59:45 +0000 (Wed, 26 Oct 2005)
New Revision: 482

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=lorikeet&rev=482

Log:
Merge patch from lha (just commited to Samba4) to make the kerberos
libs parse the auth_data (and therefore find the PAC, inside the
AD-IFRELEVENT structure).

I've  only tested the  AD-IFRELEVENT branch,  as I  don't know  how to
generate the KDC-ISSUED branch.

Andrew Bartlett

Modified:
   trunk/heimdal/lib/krb5/ticket.c


Changeset:
Modified: trunk/heimdal/lib/krb5/ticket.c
===================================================================
--- trunk/heimdal/lib/krb5/ticket.c     2005-10-23 23:12:08 UTC (rev 481)
+++ trunk/heimdal/lib/krb5/ticket.c     2005-10-26 23:59:45 UTC (rev 482)
@@ -97,6 +97,141 @@
     return krb5_copy_principal(context, ticket->server, server);
 }
 
+static int
+find_type_in_ad(krb5_context context,
+               int type, 
+               krb5_data *data,
+               int *found,
+               int failp,
+               krb5_keyblock *sessionkey,
+               const AuthorizationData *ad,
+               int level)
+{
+    krb5_error_code ret = ENOENT;
+    int i;
+
+    if (level > 9) {
+       krb5_set_error_string(context, "Authorization data nested deeper "
+                             "then %d levels, stop searching", level);
+       ret = ENOENT; /* XXX */
+       goto out;
+    }
+
+    /*
+     * Only copy out the element the first time we get to it, we need
+     * to run over the whole authorization data fields to check if
+     * there are any container clases we need to care about.
+     */
+    for (i = 0; i < ad->len; i++) {
+       if (!*found && ad->val[i].ad_type == type) {
+           ret = copy_octet_string(&ad->val[i].ad_data, data);
+           if (ret) {
+               krb5_set_error_string(context, "malloc - out of memory");
+               goto out;
+           }
+           *found = 1;
+           continue;
+       }
+       switch (ad->val[i].ad_type) {
+       case KRB5_AUTHDATA_IF_RELEVANT: {
+           AuthorizationData child;
+           ret = decode_AuthorizationData(ad->val[i].ad_data.data,
+                                          ad->val[i].ad_data.length,
+                                          &child,
+                                          NULL);
+           if (ret) {
+               krb5_set_error_string(context, "Failed to decode "
+                                     "IF_RELEVANT with %d", ret);
+               goto out;
+           }
+           ret = find_type_in_ad(context, type, data, found, 0, sessionkey,
+                                 &child, level + 1);
+           free_AuthorizationData(&child);
+           if (ret)
+               goto out;
+           break;
+       }
+       case KRB5_AUTHDATA_KDC_ISSUED: {
+           AD_KDCIssued child;
+
+           ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
+                                     ad->val[i].ad_data.length,
+                                     &child,
+                                     NULL);
+           if (ret) {
+               krb5_set_error_string(context, "Failed to decode "
+                                     "AD_KDCIssued with %d", ret);
+               goto out;
+           }
+           if (failp) {
+               krb5_boolean valid;
+               krb5_data buf;
+               size_t len;
+
+               ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length, 
+                                  &child.elements, &len, ret);
+               if (ret) {
+                   free_AD_KDCIssued(&child);
+                   krb5_clear_error_string(context);
+                   goto out;
+               }
+               if(buf.length != len)
+                   krb5_abortx(context, "internal error in ASN.1 encoder");
+
+               ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
+                                            &child.ad_checksum, &valid);
+               krb5_data_free(&buf);
+               if (ret) {
+                   free_AD_KDCIssued(&child);
+                   goto out;
+               }
+               if (!valid) {
+                   krb5_clear_error_string(context);
+                   ret = ENOENT;
+                   free_AD_KDCIssued(&child);
+                   goto out;
+               }
+           }
+           ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
+                                 &child.elements, level + 1);
+           free_AD_KDCIssued(&child);
+           if (ret)
+               goto out;
+           break;
+       }
+       case KRB5_AUTHDATA_AND_OR:
+           if (!failp)
+               break;
+           krb5_set_error_string(context, "Authorization data contains "
+                                 "AND-OR element that is unknown to the "
+                                 "application");
+           ret = ENOENT; /* XXX */
+           goto out;
+       default:
+           if (!failp)
+               break;
+           krb5_set_error_string(context, "Authorization data contains "
+                                 "unknown type (%d) ", ad->val[i].ad_type);
+           ret = ENOENT; /* XXX */
+           goto out;
+       }
+    }
+out:
+    if (ret) {
+       if (*found) {
+           krb5_data_free(data);
+           *found = 0;
+       }
+    }
+    return ret;
+}
+
+/*
+ * Extract the authorization data type of `type' from the
+ * 'ticket'. Store the field in `data'. This function is to use for
+ * kerberos applications
+ */
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_ticket_get_authorization_data_type(krb5_context context,
                                        krb5_ticket *ticket,
@@ -104,22 +239,25 @@
                                        krb5_data *data)
 {
     AuthorizationData *ad;
-    int i;
+    krb5_error_code ret;
+    int found = 0;
 
-    data->length = 0;
-    data->data = NULL;
+    krb5_data_zero(data);
 
     ad = ticket->ticket.authorization_data;
-    if (ad == NULL) {
+    if (ticket->ticket.authorization_data == NULL) {
        krb5_set_error_string(context, "Ticket have not authorization data");
        return ENOENT; /* XXX */
     }
 
-    for (i = 0; i < ad->len; i++) {
-       if (ad->val[i].ad_type == type)
-           return copy_octet_string(&ad->val[i].ad_data, data);
+    ret = find_type_in_ad(context, type, data, &found, 1, &ticket->ticket.key,
+                         ticket->ticket.authorization_data, 0);
+    if (ret)
+       return ret;
+    if (!found) {
+       krb5_set_error_string(context, "Ticket have not authorization "
+                         "data of type %d", type);
+       return ENOENT; /* XXX */
     }
-    krb5_set_error_string(context, "Ticket have not authorization "
-                         "data of type %d", type);
-    return ENOENT; /* XXX */
+    return 0;
 }

Reply via email to