[Freeipa-devel] [PATCH] 19-21 Use exop instead of kadmin.local

Sumit Bose sbose at redhat.com
Thu Jun 7 10:09:32 UTC 2012


now with patches :-)
On Thu, Jun 07, 2012 at 12:07:13PM +0200, Sumit Bose wrote:
> Hi,
> 
> this patch fixes https://fedorahosted.org/freeipa/ticket/2513 and as a
> consequence makes https://fedorahosted.org/freeipa/ticket/2516 obsolete.
> 
> This first patch is just a minor cleanup which is not related to the
> ticket. The second make create_keys() a public function so the it can be
> called by the ipasam plugin as well. Finally the third patch removes the
> kadmin.local call and calls the KEYTAB_SET_OID extented operation
> instead.
> 
> bye,
> Sumit
-------------- next part --------------
From adf2c4145587b5505a74beb9f3b0893781ae3119 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 20 Dec 2011 13:56:00 +0100
Subject: [PATCH] ipasam: remove unused struct elements

---
 daemons/ipa-sam/ipa_sam.c |   11 -----------
 1 Datei ge?ndert, 11 Zeilen entfernt(-)

diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 3e88050670c5d2bc760d9de0806f9ea1a164c0d3..2627025a8f2f757ca62c58b541c002f46e7c3be1 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -182,17 +182,6 @@ do { \
 #define HAS_KRB_TICKET_POLICY_AUX (1<<9)
 
 struct ipasam_privates {
-	NTSTATUS (*ldapsam_add_sam_account)(struct pdb_methods *,
-					    struct samu *sampass);
-	NTSTATUS (*ldapsam_update_sam_account)(struct pdb_methods *,
-					       struct samu *sampass);
-	NTSTATUS (*ldapsam_create_user)(struct pdb_methods *my_methods,
-					TALLOC_CTX *tmp_ctx, const char *name,
-					uint32_t acb_info, uint32_t *rid);
-	NTSTATUS (*ldapsam_create_dom_group)(struct pdb_methods *my_methods,
-					     TALLOC_CTX *tmp_ctx,
-					     const char *name,
-					     uint32_t *rid);
 	char *realm;
 	char *base_dn;
 	char *trust_dn;
-- 
1.7.10.2

-------------- next part --------------
From 2f2e777838c1258e45e6185f99ec9806163e5dc7 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 13 Mar 2012 10:29:00 +0100
Subject: [PATCH] Move some krb5 keys related functions from ipa-client to
 util

---
 ipa-client/ipa-getkeytab.c |  381 +-------------------------------------------
 util/ipa_krb5.c            |  362 +++++++++++++++++++++++++++++++++++++++++
 util/ipa_krb5.h            |   36 +++++
 3 Dateien ge?ndert, 403 Zeilen hinzugef?gt(+), 376 Zeilen entfernt(-)

diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
index 7d7b971769cccece5dfe36934f6c73e5986df877..ca6e63413d64060afb802b1e807920ffaac2bb31 100644
--- a/ipa-client/ipa-getkeytab.c
+++ b/ipa-client/ipa-getkeytab.c
@@ -41,30 +41,6 @@
 #include "ipa_krb5.h"
 #include "ipa-client-common.h"
 
-/* Salt types */
-#define NO_SALT                        -1
-#define KRB5_KDB_SALTTYPE_NORMAL        0
-#define KRB5_KDB_SALTTYPE_V4            1
-#define KRB5_KDB_SALTTYPE_NOREALM       2
-#define KRB5_KDB_SALTTYPE_ONLYREALM     3
-#define KRB5_KDB_SALTTYPE_SPECIAL       4
-#define KRB5_KDB_SALTTYPE_AFS3          5
-
-#define KEYTAB_SET_OID "2.16.840.1.113730.3.8.10.1"
-#define KEYTAB_RET_OID "2.16.840.1.113730.3.8.10.2"
-
-struct krb_key_salt {
-    krb5_enctype enctype;
-    krb5_int32 salttype;
-    krb5_keyblock key;
-    krb5_data salt;
-};
-
-struct keys_container {
-    krb5_int32 nkeys;
-    struct krb_key_salt *ksdata;
-};
-
 static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
 {
 	sasl_interact_t *in = NULL;
@@ -122,357 +98,6 @@ static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *s
 	return ret;
 }
 
-static void free_keys_contents(krb5_context krbctx, struct keys_container *keys)
-{
-    struct krb_key_salt *ksdata;
-    int i;
-
-    ksdata = keys->ksdata;
-    for (i = 0; i < keys->nkeys; i++) {
-        krb5_free_keyblock_contents(krbctx, &ksdata[i].key);
-        krb5_free_data_contents(krbctx, &ksdata[i].salt);
-    }
-    free(ksdata);
-
-    keys->ksdata = NULL;
-    keys->nkeys = 0;
-}
-
-/* Determines Encryption and Salt types,
- * allocates key_salt data storage,
- * filters out equivalent encodings,
- * returns 0 if no enctypes available, >0 if enctypes are available */
-static int prep_ksdata(krb5_context krbctx, const char *str,
-                       struct keys_container *keys)
-{
-    struct krb_key_salt *ksdata;
-    krb5_error_code krberr;
-    int n, i, j, nkeys;
-
-    if (str == NULL) {
-        krb5_enctype *ktypes;
-
-        krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
-        if (krberr) {
-            fprintf(stderr, _("No system preferred enctypes ?!\n"));
-            return 0;
-        }
-
-        for (n = 0; ktypes[n]; n++) /* count */ ;
-
-        ksdata = calloc(n + 1, sizeof(struct krb_key_salt));
-        if (NULL == ksdata) {
-            fprintf(stderr, _("Out of memory!?\n"));
-            return 0;
-        }
-
-        for (i = 0; i < n; i++) {
-            ksdata[i].enctype = ktypes[i];
-            ksdata[i].salttype = KRB5_KDB_SALTTYPE_NORMAL;
-        }
-
-        ipa_krb5_free_ktypes(krbctx, ktypes);
-
-        nkeys = i;
-
-    } else {
-        char *tmp, *t, *p, *q;
-
-        t = tmp = strdup(str);
-        if (!tmp) {
-            fprintf(stderr, _("Out of memory\n"));
-            return 0;
-        }
-
-        /* count */
-        n = 0;
-        while ((p = strchr(t, ','))) {
-            t = p+1;
-            n++;
-        }
-        n++; /* count the last one that is 0 terminated instead */
-
-        /* at the end we will have at most n entries + 1 terminating */
-        ksdata = calloc(n + 1, sizeof(struct krb_key_salt));
-        if (!ksdata) {
-            fprintf(stderr, _("Out of memory\n"));
-            return 0;
-        }
-
-        for (i = 0, j = 0, t = tmp; i < n; i++) {
-
-            p = strchr(t, ',');
-            if (p) *p = '\0';
-
-            q = strchr(t, ':');
-            if (q) *q++ = '\0';
-
-            krberr = krb5_string_to_enctype(t, &ksdata[j].enctype);
-            if (krberr != 0) {
-                fprintf(stderr,
-                        _("Warning unrecognized encryption type: [%s]\n"), t);
-                if (p) t = p + 1;
-                continue;
-            }
-            if (p) t = p + 1;
-
-            if (!q) {
-                ksdata[j].salttype = KRB5_KDB_SALTTYPE_NORMAL;
-                j++;
-                continue;
-            }
-
-            krberr = krb5_string_to_salttype(q, &ksdata[j].salttype);
-            if (krberr != 0) {
-                fprintf(stderr,
-                        _("Warning unrecognized salt type: [%s]\n"), q);
-                continue;
-            }
-
-            j++;
-        }
-
-        nkeys = j;
-
-        free(tmp);
-    }
-
-    /* Check we don't already have a key with a similar encoding,
-     * it would just produce redundant data and this is what the
-     * MIT code do anyway */
-
-    for (i = 0, n = 0; i < nkeys; i++ ) {
-        krb5_boolean similar = 0;
-
-        for (j = 0; j < i; j++) {
-            krberr = krb5_c_enctype_compare(krbctx,
-                                            ksdata[j].enctype,
-                                            ksdata[i].enctype,
-                                            &similar);
-            if (krberr) {
-                free_keys_contents(krbctx, keys);
-                free(ksdata);
-                fprintf(stderr, _("Enctype comparison failed!\n"));
-                return 0;
-            }
-            if (similar &&
-                (ksdata[j].salttype == ksdata[i].salttype)) {
-                break;
-            }
-        }
-        if (j < i) {
-            /* redundant encoding, remove it, and shift others */
-            int x;
-            for (x = i; x < nkeys-1; x++) {
-                ksdata[x].enctype = ksdata[x+1].enctype;
-                ksdata[x].salttype = ksdata[x+1].salttype;
-            }
-            continue;
-        }
-        /* count only confirmed enc/salt tuples */
-        n++;
-    }
-
-    keys->nkeys = n;
-    keys->ksdata = ksdata;
-
-    return n;
-}
-
-static int create_keys(krb5_context krbctx,
-                       krb5_principal princ,
-                       char *password,
-                       const char *enctypes_string,
-                       struct keys_container *keys)
-{
-    struct krb_key_salt *ksdata;
-    krb5_error_code krberr;
-    krb5_data key_password;
-    krb5_data *realm = NULL;
-    int i, nkeys;
-    int ret;
-
-    ret = prep_ksdata(krbctx, enctypes_string, keys);
-    if (ret == 0) return 0;
-
-    ksdata = keys->ksdata;
-    nkeys = keys->nkeys;
-
-    if (password) {
-        key_password.data = password;
-        key_password.length = strlen(password);
-
-        realm = krb5_princ_realm(krbctx, princ);
-    }
-
-    for (i = 0; i < nkeys; i++) {
-        krb5_data *salt;
-
-        if (!password) {
-            /* cool, random keys */
-            krberr = krb5_c_make_random_key(krbctx,
-                                            ksdata[i].enctype,
-                                            &ksdata[i].key);
-            if (krberr) {
-                fprintf(stderr, _("Failed to create random key!\n"));
-                return 0;
-            }
-            /* set the salt to NO_SALT as the key was random */
-            ksdata[i].salttype = NO_SALT;
-            continue;
-        }
-
-        /* Make keys using password and required salt */
-        switch (ksdata[i].salttype) {
-        case KRB5_KDB_SALTTYPE_ONLYREALM:
-            krberr = krb5_copy_data(krbctx, realm, &salt);
-            if (krberr) {
-                fprintf(stderr, _("Failed to create key!\n"));
-                return 0;
-            }
-
-            ksdata[i].salt.length = salt->length;
-            ksdata[i].salt.data = malloc(salt->length);
-            if (!ksdata[i].salt.data) {
-                fprintf(stderr, _("Out of memory!\n"));
-                return 0;
-            }
-            memcpy(ksdata[i].salt.data, salt->data, salt->length);
-            krb5_free_data(krbctx, salt);
-            break;
-
-        case KRB5_KDB_SALTTYPE_NOREALM:
-            krberr = ipa_krb5_principal2salt_norealm(krbctx, princ, &ksdata[i].salt);
-            if (krberr) {
-                fprintf(stderr, _("Failed to create key!\n"));
-                return 0;
-            }
-            break;
-
-        case KRB5_KDB_SALTTYPE_NORMAL:
-            krberr = krb5_principal2salt(krbctx, princ, &ksdata[i].salt);
-            if (krberr) {
-                fprintf(stderr, _("Failed to create key!\n"));
-                return 0;
-            }
-            break;
-
-        /* no KRB5_KDB_SALTTYPE_V4, we do not support krb v4 */
-
-        case KRB5_KDB_SALTTYPE_AFS3:
-            /* Comment from MIT sources:
-             * * Why do we do this? Well, the afs_mit_string_to_key
-             * * needs to use strlen, and the realm is not NULL
-             * * terminated....
-             */
-            ksdata[i].salt.data = (char *)malloc(realm->length + 1);
-            if (NULL == ksdata[i].salt.data) {
-                fprintf(stderr, _("Out of memory!\n"));
-                return 0;
-            }
-            memcpy((char *)ksdata[i].salt.data,
-                   (char *)realm->data, realm->length);
-            ksdata[i].salt.data[realm->length] = '\0';
-            /* AFS uses a special length (UGLY) */
-            ksdata[i].salt.length = SALT_TYPE_AFS_LENGTH;
-            break;
-
-        default:
-            fprintf(stderr, _("Bad or unsupported salt type (%d)!\n"),
-                ksdata[i].salttype);
-            return 0;
-        }
-
-        krberr = krb5_c_string_to_key(krbctx,
-                                      ksdata[i].enctype,
-                                      &key_password,
-                                      &ksdata[i].salt,
-                                      &ksdata[i].key);
-        if (krberr) {
-            fprintf(stderr, _("Failed to create key!\n"));
-            return 0;
-        }
-
-        /* set back salt length to real value if AFS3 */
-        if (ksdata[i].salttype == KRB5_KDB_SALTTYPE_AFS3) {
-            ksdata[i].salt.length = realm->length;
-        }
-    }
-
-    return nkeys;
-}
-
-static struct berval *create_key_control(struct keys_container *keys,
-                                         const char *principalName)
-{
-    struct krb_key_salt *ksdata;
-    struct berval *bval;
-    BerElement *be;
-    int ret, i;
-
-    be = ber_alloc_t(LBER_USE_DER);
-    if (!be) {
-        return NULL;
-    }
-
-    ret = ber_printf(be, "{s{", principalName);
-    if (ret == -1) {
-        ber_free(be, 1);
-        return NULL;
-    }
-
-    ksdata = keys->ksdata;
-    for (i = 0; i < keys->nkeys; i++) {
-
-        /* we set only the EncryptionKey and salt, no s2kparams */
-
-        ret = ber_printf(be, "{t[{t[i]t[o]}]",
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
-                 (ber_int_t)ksdata[i].enctype,
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
-                 (char *)ksdata[i].key.contents, (ber_len_t)ksdata[i].key.length);
-
-        if (ret == -1) {
-            ber_free(be, 1);
-            return NULL;
-        }
-
-        if (ksdata[i].salttype == NO_SALT) {
-            ret = ber_printf(be, "}");
-            continue;
-        }
-
-        /* we have to pass a salt structure */
-        ret = ber_printf(be, "t[{t[i]t[o]}]}",
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
-                 (ber_int_t)ksdata[i].salttype,
-                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
-                 (char *)ksdata[i].salt.data, (ber_len_t)ksdata[i].salt.length);
-
-        if (ret == -1) {
-            ber_free(be, 1);
-            return NULL;
-        }
-    }
-
-    ret = ber_printf(be, "}}");
-    if (ret == -1) {
-        ber_free(be, 1);
-        return NULL;
-    }
-
-    ret = ber_flatten(be, &bval);
-    if (ret == -1) {
-        ber_free(be, 1);
-        return NULL;
-    }
-
-    ber_free(be, 1);
-    return bval;
-}
-
 int filter_keys(krb5_context krbctx, struct keys_container *keys,
                 ber_int_t *enctypes)
 {
@@ -854,6 +479,7 @@ int main(int argc, const char *argv[])
 	krb5_keytab kt;
 	int kvno;
 	int i, ret;
+	char *err_msg;
 
     ret = init_gettext();
     if (ret) {
@@ -955,8 +581,11 @@ int main(int argc, const char *argv[])
 	}
 
 	/* create key material */
-	ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys);
+	ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys, &err_msg);
 	if (!ret) {
+		if (err_msg != NULL) {
+			fprintf(stderr, "%s", err_msg);
+		}
 		fprintf(stderr, _("Failed to create key material\n"));
 		exit(8);
 	}
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
index 0e82b2380baa5a93ffab1f3eccc8b0597b4ebb83..0240c079ecd38271e5dbb36ec8c6a091001cfce7 100644
--- a/util/ipa_krb5.c
+++ b/util/ipa_krb5.c
@@ -26,6 +26,9 @@
 #include <lber.h>
 #include <errno.h>
 
+#include <libintl.h>
+#define _(STRING) gettext(STRING)
+
 #include "ipa_krb5.h"
 
 /* Salt types */
@@ -530,3 +533,362 @@ krb5_error_code filter_key_salt_tuples(krb5_context context,
     return 0;
 }
 
+struct berval *create_key_control(struct keys_container *keys,
+                                  const char *principalName)
+{
+    struct krb_key_salt *ksdata;
+    struct berval *bval;
+    BerElement *be;
+    int ret, i;
+
+    be = ber_alloc_t(LBER_USE_DER);
+    if (!be) {
+        return NULL;
+    }
+
+    ret = ber_printf(be, "{s{", principalName);
+    if (ret == -1) {
+        ber_free(be, 1);
+        return NULL;
+    }
+
+    ksdata = keys->ksdata;
+    for (i = 0; i < keys->nkeys; i++) {
+
+        /* we set only the EncryptionKey and salt, no s2kparams */
+
+        ret = ber_printf(be, "{t[{t[i]t[o]}]",
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
+                 (ber_int_t)ksdata[i].enctype,
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
+                 (char *)ksdata[i].key.contents, (ber_len_t)ksdata[i].key.length);
+
+        if (ret == -1) {
+            ber_free(be, 1);
+            return NULL;
+        }
+
+        if (ksdata[i].salttype == NO_SALT) {
+            ret = ber_printf(be, "}");
+            continue;
+        }
+
+        /* we have to pass a salt structure */
+        ret = ber_printf(be, "t[{t[i]t[o]}]}",
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
+                 (ber_int_t)ksdata[i].salttype,
+                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
+                 (char *)ksdata[i].salt.data, (ber_len_t)ksdata[i].salt.length);
+
+        if (ret == -1) {
+            ber_free(be, 1);
+            return NULL;
+        }
+    }
+
+    ret = ber_printf(be, "}}");
+    if (ret == -1) {
+        ber_free(be, 1);
+        return NULL;
+    }
+
+    ret = ber_flatten(be, &bval);
+    if (ret == -1) {
+        ber_free(be, 1);
+        return NULL;
+    }
+
+    ber_free(be, 1);
+    return bval;
+}
+
+void free_keys_contents(krb5_context krbctx, struct keys_container *keys)
+{
+    struct krb_key_salt *ksdata;
+    int i;
+
+    ksdata = keys->ksdata;
+    for (i = 0; i < keys->nkeys; i++) {
+        krb5_free_keyblock_contents(krbctx, &ksdata[i].key);
+        krb5_free_data_contents(krbctx, &ksdata[i].salt);
+    }
+    free(ksdata);
+
+    keys->ksdata = NULL;
+    keys->nkeys = 0;
+}
+
+/* Determines Encryption and Salt types,
+ * allocates key_salt data storage,
+ * filters out equivalent encodings,
+ * returns 0 if no enctypes available, >0 if enctypes are available */
+static int prep_ksdata(krb5_context krbctx, const char *str,
+                       struct keys_container *keys,
+                       char **err_msg)
+{
+    struct krb_key_salt *ksdata;
+    krb5_error_code krberr;
+    int n, i, j, nkeys;
+
+    *err_msg = NULL;
+
+    if (str == NULL) {
+        krb5_enctype *ktypes;
+
+        krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
+        if (krberr) {
+            *err_msg = _("No system preferred enctypes ?!\n");
+            return 0;
+        }
+
+        for (n = 0; ktypes[n]; n++) /* count */ ;
+
+        ksdata = calloc(n + 1, sizeof(struct krb_key_salt));
+        if (NULL == ksdata) {
+            *err_msg = _("Out of memory!?\n");
+            return 0;
+        }
+
+        for (i = 0; i < n; i++) {
+            ksdata[i].enctype = ktypes[i];
+            ksdata[i].salttype = KRB5_KDB_SALTTYPE_NORMAL;
+        }
+
+        ipa_krb5_free_ktypes(krbctx, ktypes);
+
+        nkeys = i;
+
+    } else {
+        char *tmp, *t, *p, *q;
+
+        t = tmp = strdup(str);
+        if (!tmp) {
+            *err_msg = _("Out of memory\n");
+            return 0;
+        }
+
+        /* count */
+        n = 0;
+        while ((p = strchr(t, ','))) {
+            t = p+1;
+            n++;
+        }
+        n++; /* count the last one that is 0 terminated instead */
+
+        /* at the end we will have at most n entries + 1 terminating */
+        ksdata = calloc(n + 1, sizeof(struct krb_key_salt));
+        if (!ksdata) {
+            *err_msg = _("Out of memory\n");
+            return 0;
+        }
+
+        for (i = 0, j = 0, t = tmp; i < n; i++) {
+
+            p = strchr(t, ',');
+            if (p) *p = '\0';
+
+            q = strchr(t, ':');
+            if (q) *q++ = '\0';
+
+            krberr = krb5_string_to_enctype(t, &ksdata[j].enctype);
+            if (krberr != 0) {
+                *err_msg = _("Warning unrecognized encryption type.\n");
+                if (p) t = p + 1;
+                continue;
+            }
+            if (p) t = p + 1;
+
+            if (!q) {
+                ksdata[j].salttype = KRB5_KDB_SALTTYPE_NORMAL;
+                j++;
+                continue;
+            }
+
+            krberr = krb5_string_to_salttype(q, &ksdata[j].salttype);
+            if (krberr != 0) {
+                *err_msg = _("Warning unrecognized salt type.\n");
+                continue;
+            }
+
+            j++;
+        }
+
+        nkeys = j;
+
+        free(tmp);
+    }
+
+    /* Check we don't already have a key with a similar encoding,
+     * it would just produce redundant data and this is what the
+     * MIT code do anyway */
+
+    for (i = 0, n = 0; i < nkeys; i++ ) {
+        krb5_boolean similar = 0;
+
+        for (j = 0; j < i; j++) {
+            krberr = krb5_c_enctype_compare(krbctx,
+                                            ksdata[j].enctype,
+                                            ksdata[i].enctype,
+                                            &similar);
+            if (krberr) {
+                free_keys_contents(krbctx, keys);
+                free(ksdata);
+                *err_msg = _("Enctype comparison failed!\n");
+                return 0;
+            }
+            if (similar &&
+                (ksdata[j].salttype == ksdata[i].salttype)) {
+                break;
+            }
+        }
+        if (j < i) {
+            /* redundant encoding, remove it, and shift others */
+            int x;
+            for (x = i; x < nkeys-1; x++) {
+                ksdata[x].enctype = ksdata[x+1].enctype;
+                ksdata[x].salttype = ksdata[x+1].salttype;
+            }
+            continue;
+        }
+        /* count only confirmed enc/salt tuples */
+        n++;
+    }
+
+    keys->nkeys = n;
+    keys->ksdata = ksdata;
+
+    return n;
+}
+
+int create_keys(krb5_context krbctx,
+                krb5_principal princ,
+                char *password,
+                const char *enctypes_string,
+                struct keys_container *keys,
+                char **err_msg)
+{
+    struct krb_key_salt *ksdata;
+    krb5_error_code krberr;
+    krb5_data key_password;
+    krb5_data *realm = NULL;
+    int i, nkeys;
+    int ret;
+
+    *err_msg = NULL;
+
+    ret = prep_ksdata(krbctx, enctypes_string, keys, err_msg);
+    if (ret == 0) return 0;
+
+    ksdata = keys->ksdata;
+    nkeys = keys->nkeys;
+
+    if (password) {
+        key_password.data = password;
+        key_password.length = strlen(password);
+
+        realm = krb5_princ_realm(krbctx, princ);
+    }
+
+    for (i = 0; i < nkeys; i++) {
+        krb5_data *salt;
+
+        if (!password) {
+            /* cool, random keys */
+            krberr = krb5_c_make_random_key(krbctx,
+                                            ksdata[i].enctype,
+                                            &ksdata[i].key);
+            if (krberr) {
+                *err_msg = _("Failed to create random key!\n");
+                return 0;
+            }
+            /* set the salt to NO_SALT as the key was random */
+            ksdata[i].salttype = NO_SALT;
+            continue;
+        }
+
+        /* Make keys using password and required salt */
+        switch (ksdata[i].salttype) {
+        case KRB5_KDB_SALTTYPE_ONLYREALM:
+            krberr = krb5_copy_data(krbctx, realm, &salt);
+            if (krberr) {
+                *err_msg = _("Failed to create key!\n");
+                return 0;
+            }
+
+            ksdata[i].salt.length = salt->length;
+            ksdata[i].salt.data = malloc(salt->length);
+            if (!ksdata[i].salt.data) {
+                *err_msg = _("Out of memory!\n");
+                return 0;
+            }
+            memcpy(ksdata[i].salt.data, salt->data, salt->length);
+            krb5_free_data(krbctx, salt);
+            break;
+
+        case KRB5_KDB_SALTTYPE_NOREALM:
+            krberr = ipa_krb5_principal2salt_norealm(krbctx, princ,
+                                                     &ksdata[i].salt);
+            if (krberr) {
+                *err_msg = _("Failed to create key!\n");
+                return 0;
+            }
+            break;
+
+        case KRB5_KDB_SALTTYPE_NORMAL:
+            krberr = krb5_principal2salt(krbctx, princ, &ksdata[i].salt);
+            if (krberr) {
+                *err_msg = _("Failed to create key!\n");
+                return 0;
+            }
+            break;
+
+        /* no KRB5_KDB_SALTTYPE_V4, we do not support krb v4 */
+
+        case KRB5_KDB_SALTTYPE_AFS3:
+            /* Comment from MIT sources:
+             * * Why do we do this? Well, the afs_mit_string_to_key
+             * * needs to use strlen, and the realm is not NULL
+             * * terminated....
+             */
+            ksdata[i].salt.data = (char *)malloc(realm->length + 1);
+            if (NULL == ksdata[i].salt.data) {
+                *err_msg = _("Out of memory!\n");
+                return 0;
+            }
+            memcpy((char *)ksdata[i].salt.data,
+                   (char *)realm->data, realm->length);
+            ksdata[i].salt.data[realm->length] = '\0';
+            /* AFS uses a special length (UGLY) */
+            ksdata[i].salt.length = SALT_TYPE_AFS_LENGTH;
+            break;
+
+        default:
+            *err_msg = _("Bad or unsupported salt type.\n");
+/* FIXME:
+            fprintf(stderr, _("Bad or unsupported salt type (%d)!\n"),
+                ksdata[i].salttype);
+*/
+            return 0;
+        }
+
+        krberr = krb5_c_string_to_key(krbctx,
+                                      ksdata[i].enctype,
+                                      &key_password,
+                                      &ksdata[i].salt,
+                                      &ksdata[i].key);
+        if (krberr) {
+            *err_msg = _("Failed to create key!\n");
+            return 0;
+        }
+
+        /* set back salt length to real value if AFS3 */
+        if (ksdata[i].salttype == KRB5_KDB_SALTTYPE_AFS3) {
+            ksdata[i].salt.length = realm->length;
+        }
+    }
+
+    return nkeys;
+}
+
diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
index f0513d109d2db9233cfc9b2dc3a6ab421587167a..97ffc47b5017507cd58e130755cfe050a287b30c 100644
--- a/util/ipa_krb5.h
+++ b/util/ipa_krb5.h
@@ -4,6 +4,30 @@
 #include <krb5/krb5.h>
 #include <kdb.h>
 
+struct krb_key_salt {
+    krb5_enctype enctype;
+    krb5_int32 salttype;
+    krb5_keyblock key;
+    krb5_data salt;
+};
+
+struct keys_container {
+    krb5_int32 nkeys;
+    struct krb_key_salt *ksdata;
+};
+
+/* Salt types */
+#define NO_SALT                        -1
+#define KRB5_KDB_SALTTYPE_NORMAL        0
+#define KRB5_KDB_SALTTYPE_V4            1
+#define KRB5_KDB_SALTTYPE_NOREALM       2
+#define KRB5_KDB_SALTTYPE_ONLYREALM     3
+#define KRB5_KDB_SALTTYPE_SPECIAL       4
+#define KRB5_KDB_SALTTYPE_AFS3          5
+
+#define KEYTAB_SET_OID "2.16.840.1.113730.3.8.10.1"
+#define KEYTAB_RET_OID "2.16.840.1.113730.3.8.10.2"
+
 void
 ipa_krb5_free_ktypes(krb5_context context, krb5_enctype *val);
 
@@ -36,4 +60,16 @@ krb5_error_code filter_key_salt_tuples(krb5_context context,
                                        krb5_key_salt_tuple *req, int n_req,
                                        krb5_key_salt_tuple *supp, int n_supp,
                                        krb5_key_salt_tuple **res, int *n_res);
+
+void free_keys_contents(krb5_context krbctx, struct keys_container *keys);
+
+struct berval *create_key_control(struct keys_container *keys,
+                                  const char *principalName);
+
+int create_keys(krb5_context krbctx,
+                krb5_principal princ,
+                char *password,
+                const char *enctypes_string,
+                struct keys_container *keys,
+                char **err_msg);
 #endif /* __IPA_KRB5_H_ */
-- 
1.7.10.2

-------------- next part --------------
From 73eaf78c31bf5e228ba50ce51fc8857454fb4f17 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 13 Mar 2012 14:06:02 +0100
Subject: [PATCH] Use exop instead of kadmin.local

---
 daemons/ipa-sam/Makefile.am      |    6 +++
 daemons/ipa-sam/ipa_sam.c        |  101 ++++++++++++++++++++++++++++----------
 install/updates/60-trusts.update |    4 ++
 3 Dateien ge?ndert, 84 Zeilen hinzugef?gt(+), 27 Zeilen entfernt(-)

diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
index b5b9b0b75b276ac14b01ce35bae63af539e596fc..275cce629385b1719544a7832a00e9ee6664b739 100644
--- a/daemons/ipa-sam/Makefile.am
+++ b/daemons/ipa-sam/Makefile.am
@@ -7,6 +7,9 @@ SAMBA40EXTRA_LIBS = $(SAMBA40EXTRA_LIBPATH)	\
 			-lsmbconf		\
 			$(NULL)
 
+KRB5_UTIL_DIR=../../util
+KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
+
 INCLUDES =						\
 	-I.						\
 	-I$(srcdir)					\
@@ -18,6 +21,7 @@ INCLUDES =						\
 	-DDATADIR=\""$(datadir)"\"			\
 	-DLDAPIDIR=\""$(localstatedir)/run"\"		\
 	-DHAVE_LDAP					\
+	-I $(KRB5_UTIL_DIR)				\
 	$(AM_CFLAGS)					\
 	$(LDAP_CFLAGS)					\
 	$(KRB5_CFLAGS)					\
@@ -34,6 +38,7 @@ plugin_LTLIBRARIES = 		\
 
 ipasam_la_SOURCES = 		\
 	ipa_sam.c		\
+	$(KRB5_UTIL_SRCS)	\
 	$(NULL)
 
 ipasam_la_LDFLAGS = 		\
@@ -43,6 +48,7 @@ ipasam_la_LDFLAGS = 		\
 
 ipasam_la_LIBADD = 		\
 	$(LDAP_LIBS)		\
+	$(KRB5_LIBS)		\
 	$(TALLOC_LIBS)		\
 	$(SAMBAUTIL_LIBS)	\
 	$(NDR_LIBS)		\
diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 2627025a8f2f757ca62c58b541c002f46e7c3be1..851df8c62f0ffb159610ce0ac311463233eea497 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -9,6 +9,7 @@
 #include <pwd.h>
 #include <errno.h>
 #include <ldap.h>
+#include <krb5/krb5.h>
 
 #include <talloc.h>
 
@@ -28,17 +29,7 @@
 
 #include <sasl/sasl.h>
 #include <krb5/krb5.h>
-#include <time.h>
-
-/* TODO: remove if smbrunsecret() is removed */
-typedef struct connection_structi {} connection_struct;
-struct current_user {
-	connection_struct *conn;
-	uint16_t vuid;
-	struct security_unix_token ut;
-	struct security_token *nt_user_token;
-};
-extern struct current_user current_user;
+#include "ipa_krb5.h"
 
 /* from drsblobs.h */
 struct AuthInfoNone {
@@ -104,7 +95,6 @@ char *sid_string_talloc(TALLOC_CTX *mem_ctx, const struct dom_sid *sid); /* avai
 char *sid_string_dbg(const struct dom_sid *sid); /* available in libsmbconf.so */
 bool is_null_sid(const struct dom_sid *sid); /* available in libsecurity.so */
 bool strnequal(const char *s1,const char *s2,size_t n); /* available in libutil_str.so */
-int smbrunsecret(const char *cmd, const char *secret); /* available in libsmbconf.so */
 bool trim_char(char *s,char cfront,char cback); /* available in libutil_str.so */
 bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32_t *rid); /* available in libsecurity.so */
 char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s); /* available in libsmbconf.so */
@@ -1382,6 +1372,76 @@ static bool search_krb_princ(struct ldapsam_privates *ldap_state,
 	return true;
 }
 
+static int set_cross_realm_pw(struct ldapsam_privates *ldap_state,
+			      TALLOC_CTX *mem_ctx,
+			      const char *princ, const char *pwd,
+			      const char *base_dn)
+{
+	int ret;
+	krb5_error_code krberr;
+	krb5_context krbctx;
+	krb5_principal service_princ;
+	struct keys_container keys;
+	char *err_msg;
+	struct berval *reqdata = NULL;
+	struct berval *retdata = NULL;
+        char *retoid;
+
+	krberr = krb5_init_context(&krbctx);
+	if (krberr != 0) {
+		DEBUG(1, ("krb5_init_context failed.\n"));
+		ret = krberr;
+		goto done;
+	}
+
+	krberr = krb5_parse_name(krbctx, princ, &service_princ);
+	if (krberr != 0) {
+		DEBUG(1, ("Invalid Service Principal Name [%s]\n", princ));
+		ret = krberr;
+		goto done;
+	}
+
+	ret = create_keys(krbctx, service_princ, discard_const(pwd), NULL, &keys, &err_msg);
+	if (!ret) {
+		if (err_msg != NULL) {
+			DEBUG(1, ("create_keys returned [%s]\n", err_msg));
+		}
+		goto done;
+	}
+
+	reqdata = create_key_control(&keys, princ);
+	if (reqdata == NULL) {
+		DEBUG(1, ("Failed to create reqdata!\n"));
+		ret= ENOMEM;
+		goto done;
+	}
+
+	ret = smbldap_extended_operation(ldap_state->smbldap_state,
+					 KEYTAB_SET_OID, reqdata, NULL, NULL,
+					 &retoid, &retdata);
+	if (ret != LDAP_SUCCESS) {
+		DEBUG(1, ("smbldap_extended_operation failed!\n"));
+		goto done;
+	}
+
+	/* So far we do not care abot the result */
+	ldap_memfree(retoid);
+	if (retdata != NULL) {
+		ber_bvfree(retdata);
+	}
+
+	ret = 0;
+done:
+	if (reqdata != NULL) {
+	    ber_bvfree(reqdata);
+	}
+	free_keys_contents(krbctx, &keys);
+	krb5_free_principal(krbctx, service_princ);
+	krb5_free_context(krbctx);
+
+	return ret;
+}
+
 static bool set_krb_princ(struct ldapsam_privates *ldap_state,
 			  TALLOC_CTX *mem_ctx,
 			  const char *princ, const char *pwd,
@@ -1450,22 +1510,9 @@ static bool set_krb_princ(struct ldapsam_privates *ldap_state,
 		return false;
 	}
 
-	/* TODO: Call the appropriate expo if ipasam is part of the FreeIPA
-	 * source tree */
-	inp = talloc_asprintf(mem_ctx, "change_password -pw %s %s", pwd, princ);
-	if (inp == NULL) {
-		return false;
-	}
-
-	uid_t save_uid = current_user.ut.uid;
-	gid_t save_gid = current_user.ut.gid;
-	current_user.ut.uid = 0;
-	current_user.ut.gid = 0;
-	ret = smbrunsecret("kadmin.local", inp);
-	current_user.ut.uid = save_uid;
-	current_user.ut.gid = save_gid;
+	ret = set_cross_realm_pw(ldap_state, mem_ctx, princ, pwd, base_dn);
 	if (ret != 0) {
-		DEBUG(1, ("calling kadmin.local failed.\n"));
+		DEBUG(1, ("set_cross_realm_pw failed.\n"));
 		return false;
 	}
 
diff --git a/install/updates/60-trusts.update b/install/updates/60-trusts.update
index cfd1ad7e5f83bd64c5934d270090754bbe9e9e36..a05f89cc83e3683b5d2deab59fdb930486a20e86 100644
--- a/install/updates/60-trusts.update
+++ b/install/updates/60-trusts.update
@@ -60,3 +60,7 @@ add:aci: '(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType ||
 # Samba user should be able to read NT passwords to authenticate
 dn: $SUFFIX
 add:aci: '(targetattr = "ipaNTHash")(version 3.0; acl "Samba system principals can read NT passwords"; allow (read) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)'
+
+# Samba user should be able to create cross domain principals
+dn: cn=trusts,$SUFFIX
+add:aci: '(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "krbPrincipalName || krbLastPwdChange || krbTicketFlags || krbLoginFailedCount || krbExtraData || krbPrincipalKey")(version 3.0;acl "Allow trust system user to create cross domain principals"; allow (read,write,add,delete) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)'
-- 
1.7.10.2



More information about the Freeipa-devel mailing list