Blob Blame History Raw
From 505bc85ec31ad8cfa66be0dc99d19599cd1a9497 Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce@redhat.com>
Date: Fri, 6 Jul 2012 11:15:15 -0400
Subject: [PATCH 50/79] Move code into common krb5 utils

This moves the decoding function that reads the keys from the ber format
into a structure in the common krb5 util code right below the function
that encodes the same data structure into a ber format.
This way the 2 functions are in the same place and can be both used by
all ia components.
---
 daemons/ipa-kdb/ipa_kdb_principals.c | 148 ++--------------------------------
 util/ipa_krb5.c                      | 150 +++++++++++++++++++++++++++++++++++
 util/ipa_krb5.h                      |   2 +
 3 files changed, 159 insertions(+), 141 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index d87d6fe9f82b479db6ab8e6b59a8b5ee580b9a27..6f8b296fa4cb19cbfe5c37536316d6f0e7f83b9c 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -205,152 +205,18 @@ static int ipadb_ldap_attr_to_key_data(LDAP *lcontext, LDAPMessage *le,
                                        krb5_kvno *res_mkvno)
 {
     struct berval **vals;
-    krb5_key_data *keys = NULL;
-    BerElement *be = NULL;
-    void *tmp;
-    int i = 0;
-    int ret = ENOENT;
+    int mkvno;
+    int ret;
 
     vals = ldap_get_values_len(lcontext, le, attrname);
-    if (vals) {
-        ber_tag_t tag;
-        ber_int_t major_vno;
-        ber_int_t minor_vno;
-        ber_int_t kvno;
-        ber_int_t mkvno;
-        ber_int_t type;
-        ber_tag_t seqtag;
-        ber_len_t seqlen;
-        ber_len_t setlen;
-        ber_tag_t retag;
-        ber_tag_t opttag;
-        struct berval tval;
-
-        be = ber_alloc_t(LBER_USE_DER);
-        if (!be) {
-            return ENOMEM;
-        }
-
-        /* reinit the ber element with the new val */
-        ber_init2(be, vals[0], LBER_USE_DER);
-
-        /* fill key_data struct with the data */
-        retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{",
-                          &tag, &major_vno,
-                          &tag, &minor_vno,
-                          &tag, &kvno,
-                          &tag, &mkvno,
-                          &seqtag);
-        if (retag == LBER_ERROR ||
-                major_vno != 1 ||
-                minor_vno != 1 ||
-                seqtag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)) {
-            ret = EINVAL;
-            goto done;
-        }
-
-        retag = ber_skip_tag(be, &seqlen);
-
-        /* sequence of keys */
-        for (i = 0; retag == LBER_SEQUENCE; i++) {
-
-            tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data));
-            if (!tmp) {
-                ret = ENOMEM;
-                goto done;
-            }
-            keys = tmp;
-
-            memset(&keys[i], 0, sizeof(krb5_key_data));
-
-            keys[i].key_data_kvno = kvno;
-
-            /* do we have a salt type ? (optional) */
-            retag = ber_scanf(be, "t", &opttag);
-            if (retag == LBER_ERROR) {
-                ret = EINVAL;
-                goto done;
-            }
-            if (opttag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
-                keys[i].key_data_ver = 2;
-
-                retag = ber_scanf(be, "[l{tl[i]",
-                                  &seqlen, &tag, &setlen, &type);
-                if (tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
-                    ret = EINVAL;
-                    goto done;
-                }
-                keys[i].key_data_type[1] = type;
-
-                /* do we have salt data ? (optional) */
-                if (seqlen > setlen + 2) {
-                    retag = ber_scanf(be, "t[o]", &tag, &tval);
-                    if (retag == LBER_ERROR ||
-                        tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
-                        ret = EINVAL;
-                        goto done;
-                    }
-                    keys[i].key_data_length[1] = tval.bv_len;
-                    keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val;
-                }
-
-                retag = ber_scanf(be, "}]t", &opttag);
-                if (retag == LBER_ERROR) {
-                    ret = EINVAL;
-                    goto done;
-                }
-
-            } else {
-                keys[i].key_data_ver = 1;
-            }
-
-            if (opttag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
-                ret = EINVAL;
-                goto done;
-            }
-
-            /* get the key */
-            retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval);
-            if (retag == LBER_ERROR) {
-                ret = EINVAL;
-                goto done;
-            }
-            keys[i].key_data_type[0] = type;
-            keys[i].key_data_length[0] = tval.bv_len;
-            keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val;
-
-            /* check for sk2params */
-            retag = ber_peek_tag(be, &setlen);
-            if (retag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) {
-                /* not supported yet, skip */
-                retag = ber_scanf(be, "t[x]}");
-            } else {
-                retag = ber_scanf(be, "}");
-            }
-            if (retag == LBER_ERROR) {
-                ret = EINVAL;
-                goto done;
-            }
-
-            retag = ber_skip_tag(be, &seqlen);
-        }
-        *result = keys;
-        *num = i;
-        *res_mkvno = mkvno;
-        ret = 0;
+    if (!vals) {
+        return ENOENT;
     }
 
-done:
-    ber_free(be, 0); /* internal buffer is 'vals[0]' */
+    ret = ber_decode_krb5_key_data(vals[0], &mkvno, num, result);
     ldap_value_free_len(vals);
-    if (ret) {
-        for (i -= 1; keys && i >= 0; i--) {
-            free(keys[i].key_data_contents[0]);
-            free(keys[i].key_data_contents[1]);
-        }
-        free(keys);
-        *result = NULL;
-        *num = 0;
+    if (ret == 0) {
+        *res_mkvno = mkvno;
     }
     return ret;
 }
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
index 0240c079ecd38271e5dbb36ec8c6a091001cfce7..934fd27d80cdd846f4de631b2dd587b0ad0f325c 100644
--- a/util/ipa_krb5.c
+++ b/util/ipa_krb5.c
@@ -427,6 +427,156 @@ done:
     return ret;
 }
 
+int ber_decode_krb5_key_data(struct berval *encoded, int *m_kvno,
+                             int *numk, krb5_key_data **data)
+{
+    krb5_key_data *keys = NULL;
+    BerElement *be = NULL;
+    void *tmp;
+    int i = 0;
+    ber_tag_t tag;
+    ber_int_t major_vno;
+    ber_int_t minor_vno;
+    ber_int_t kvno;
+    ber_int_t mkvno;
+    ber_int_t type;
+    ber_tag_t seqtag;
+    ber_len_t seqlen;
+    ber_len_t setlen;
+    ber_tag_t retag;
+    ber_tag_t opttag;
+    struct berval tval;
+    int ret;
+
+    be = ber_alloc_t(LBER_USE_DER);
+    if (!be) {
+        return ENOMEM;
+    }
+
+    /* reinit the ber element with the new val */
+    ber_init2(be, encoded, LBER_USE_DER);
+
+    /* fill key_data struct with the data */
+    retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{",
+                      &tag, &major_vno,
+                      &tag, &minor_vno,
+                      &tag, &kvno,
+                      &tag, &mkvno,
+                      &seqtag);
+    if (retag == LBER_ERROR ||
+            major_vno != 1 ||
+            minor_vno != 1 ||
+            seqtag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)) {
+        ret = EINVAL;
+        goto done;
+    }
+
+    retag = ber_skip_tag(be, &seqlen);
+
+    /* sequence of keys */
+    for (i = 0; retag == LBER_SEQUENCE; i++) {
+
+        tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data));
+        if (!tmp) {
+            ret = ENOMEM;
+            goto done;
+        }
+        keys = tmp;
+
+        memset(&keys[i], 0, sizeof(krb5_key_data));
+
+        keys[i].key_data_kvno = kvno;
+
+        /* do we have a salt type ? (optional) */
+        retag = ber_scanf(be, "t", &opttag);
+        if (retag == LBER_ERROR) {
+            ret = EINVAL;
+            goto done;
+        }
+        if (opttag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
+            keys[i].key_data_ver = 2;
+
+            retag = ber_scanf(be, "[l{tl[i]",
+                              &seqlen, &tag, &setlen, &type);
+            if (tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
+                ret = EINVAL;
+                goto done;
+            }
+            keys[i].key_data_type[1] = type;
+
+            /* do we have salt data ? (optional) */
+            if (seqlen > setlen + 2) {
+                retag = ber_scanf(be, "t[o]", &tag, &tval);
+                if (retag == LBER_ERROR ||
+                    tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
+                    ret = EINVAL;
+                    goto done;
+                }
+                keys[i].key_data_length[1] = tval.bv_len;
+                keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val;
+            }
+
+            retag = ber_scanf(be, "}]t", &opttag);
+            if (retag == LBER_ERROR) {
+                ret = EINVAL;
+                goto done;
+            }
+
+        } else {
+            keys[i].key_data_ver = 1;
+        }
+
+        if (opttag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
+            ret = EINVAL;
+            goto done;
+        }
+
+        /* get the key */
+        retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval);
+        if (retag == LBER_ERROR) {
+            ret = EINVAL;
+            goto done;
+        }
+        keys[i].key_data_type[0] = type;
+        keys[i].key_data_length[0] = tval.bv_len;
+        keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val;
+
+        /* check for sk2params */
+        retag = ber_peek_tag(be, &setlen);
+        if (retag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) {
+            /* not supported yet, skip */
+            retag = ber_scanf(be, "t[x]}");
+        } else {
+            retag = ber_scanf(be, "}");
+        }
+        if (retag == LBER_ERROR) {
+            ret = EINVAL;
+            goto done;
+        }
+
+        retag = ber_skip_tag(be, &seqlen);
+    }
+
+    ret = 0;
+
+done:
+    ber_free(be, 0); /* internal buffer is 'encoded' */
+    if (ret) {
+        for (i -= 1; keys && i >= 0; i--) {
+            free(keys[i].key_data_contents[0]);
+            free(keys[i].key_data_contents[1]);
+        }
+        free(keys);
+        keys = NULL;
+        mkvno = 0;
+    }
+    *m_kvno = mkvno;
+    *numk = i;
+    *data = keys;
+    return ret;
+}
+
+
 krb5_error_code parse_bval_key_salt_tuples(krb5_context kcontext,
                                            const char * const *vals,
                                            int n_vals,
diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
index 97ffc47b5017507cd58e130755cfe050a287b30c..7fb0355724e3c4f522097df417d2686b85619319 100644
--- a/util/ipa_krb5.h
+++ b/util/ipa_krb5.h
@@ -49,6 +49,8 @@ void ipa_krb5_free_key_data(krb5_key_data *keys, int num_keys);
 int ber_encode_krb5_key_data(krb5_key_data *data,
                              int numk, int mkvno,
                              struct berval **encoded);
+int ber_decode_krb5_key_data(struct berval *encoded, int *m_kvno,
+                             int *numk, krb5_key_data **data);
 
 krb5_error_code parse_bval_key_salt_tuples(krb5_context kcontext,
                                            const char * const *vals,
-- 
1.7.11.2