summaryrefslogtreecommitdiff
path: root/source4/heimdal
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-10-26 23:41:01 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:45:18 -0500
commit14a3abd5591a7c310bdd2638e5c06833dc2c8f92 (patch)
tree5c1036f7ece29289ec9d1ede93ceb5a254dbd978 /source4/heimdal
parent22c912329601d141fdba7359eb6dcec7a84dae69 (diff)
downloadsamba-14a3abd5591a7c310bdd2638e5c06833dc2c8f92.tar.gz
samba-14a3abd5591a7c310bdd2638e5c06833dc2c8f92.tar.bz2
samba-14a3abd5591a7c310bdd2638e5c06833dc2c8f92.zip
r11314: Use a patch from lha to have the kerberos libs extract the PAC, rather
than doing ASN.1 parsing in Samba. Also use the API function for getting a client from a ticket, rather than just digging in the structure. Andrew Bartlett (This used to be commit 25d5ea6d724bd2b64a6086ae6e2e1c5148b8ca4a)
Diffstat (limited to 'source4/heimdal')
-rw-r--r--source4/heimdal/lib/krb5/ticket.c158
1 files changed, 148 insertions, 10 deletions
diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c
index 734cd4d4ca..8f4f8fb152 100644
--- a/source4/heimdal/lib/krb5/ticket.c
+++ b/source4/heimdal/lib/krb5/ticket.c
@@ -97,6 +97,141 @@ krb5_ticket_get_server(krb5_context context,
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_ticket_get_authorization_data_type(krb5_context context,
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);
- }
- krb5_set_error_string(context, "Ticket have not authorization "
+ 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 */
+ return ENOENT; /* XXX */
+ }
+ return 0;
}