s4-kdc: Introduce a simple sdb_kdb shim layer
authorGünther Deschner <gd@samba.org>
Fri, 9 May 2014 11:45:19 +0000 (13:45 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 17 Mar 2016 03:32:27 +0000 (04:32 +0100)
Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/kdc/sdb_to_kdb.c [new file with mode: 0644]
source4/kdc/wscript_build

diff --git a/source4/kdc/sdb_to_kdb.c b/source4/kdc/sdb_to_kdb.c
new file mode 100644 (file)
index 0000000..9e0950c
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Database Glue between Samba and the KDC
+
+   Copyright (C) Guenther Deschner <gd@samba.org> 2014
+   Copyright (C) Andreas Schneider <asn@samba.org> 2014
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <kdb.h>
+#include "sdb.h"
+#include "sdb_kdb.h"
+#include "kdc/samba_kdc.h"
+#include "lib/krb5_wrap/krb5_samba.h"
+
+static int SDBFlags_to_kflags(const struct SDBFlags *s,
+                             krb5_flags *k)
+{
+       *k = 0;
+
+       if (s->initial) {
+               *k |= KRB5_KDB_DISALLOW_TGT_BASED;
+       }
+       if (!s->forwardable) {
+               *k |= KRB5_KDB_DISALLOW_FORWARDABLE;
+       }
+       if (!s->proxiable) {
+               *k |= KRB5_KDB_DISALLOW_PROXIABLE;
+       }
+       if (!s->renewable) {
+               *k |= KRB5_KDB_DISALLOW_RENEWABLE;
+       }
+       if (!s->postdate) {
+               *k |= KRB5_KDB_DISALLOW_POSTDATED;
+       }
+       if (!s->server) {
+               *k |= KRB5_KDB_DISALLOW_SVR;
+       }
+       if (s->client) {
+               ;
+       }
+       if (s->invalid) {
+               *k |= KRB5_KDB_DISALLOW_ALL_TIX;
+       }
+       if (s->require_preauth) {
+               *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
+       }
+       if (s->change_pw) {
+               *k |= KRB5_KDB_PWCHANGE_SERVICE;
+       }
+       if (s->require_hwauth) {
+               *k |= KRB5_KDB_REQUIRES_HW_AUTH;
+       }
+       if (s->ok_as_delegate) {
+               *k |= KRB5_KDB_OK_AS_DELEGATE;
+       }
+       if (s->user_to_user) {
+               ;
+       }
+       if (s->immutable) {
+               ;
+       }
+       if (s->trusted_for_delegation) {
+               *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
+       }
+       if (s->allow_kerberos4) {
+               ;
+       }
+       if (s->allow_digest) {
+               ;
+       }
+
+       return 0;
+}
+
+static int sdb_event_to_kmod(krb5_context context,
+                            const struct sdb_event *s,
+                            krb5_db_entry *k)
+{
+       krb5_error_code ret;
+       krb5_principal principal = NULL;
+
+       if (s->principal != NULL) {
+               ret = krb5_copy_principal(context,
+                                         s->principal,
+                                         &principal);
+               if (ret != 0) {
+                       return ret;
+               }
+       }
+
+       ret = krb5_dbe_update_mod_princ_data(context,
+                                            k, s->time,
+                                            principal);
+
+       krb5_free_principal(context, principal);
+
+       return ret;
+}
+
+/* sets up salt on the 2nd array position */
+
+static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
+                                    krb5_key_data *k)
+{
+       switch (s->type) {
+#if 0
+       /* for now use the special mechanism where the MIT KDC creates the salt
+        * on its own */
+       case 3: /* FIXME KRB5_PW_SALT */
+               k->key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL;
+               break;
+       /*
+       case hdb_afs3_salt:
+               k->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
+               break;
+       */
+#endif
+       default:
+               k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
+               break;
+       }
+
+       k->key_data_contents[1] = malloc(s->salt.length);
+       if (k->key_data_contents[1] == NULL) {
+               return ENOMEM;
+       }
+       memcpy(k->key_data_contents[1],
+              s->salt.data,
+              s->salt.length);
+       k->key_data_length[1] = s->salt.length;
+
+       return 0;
+}
+
+static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
+                                   int kvno,
+                                   krb5_key_data *k)
+{
+       int ret = 0;
+
+       ZERO_STRUCTP(k);
+
+       k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
+       k->key_data_kvno = kvno;
+
+       k->key_data_type[0] = KRB5_KEY_TYPE(&s->key);
+       k->key_data_length[0] = KRB5_KEY_LENGTH(&s->key);
+       k->key_data_contents[0] = malloc(k->key_data_length[0]);
+       if (k->key_data_contents[0] == NULL) {
+               return ENOMEM;
+       }
+
+       memcpy(k->key_data_contents[0],
+              KRB5_KEY_DATA(&s->key),
+              k->key_data_length[0]);
+
+       if (s->salt != NULL) {
+               ret = sdb_salt_to_krb5_key_data(s->salt, k);
+               if (ret) {
+                       memset(k->key_data_contents[0], 0, k->key_data_length[0]);
+                       free(k->key_data_contents[0]);
+               }
+       }
+
+       return ret;
+}
+
+static void free_krb5_db_entry(krb5_context context,
+                              krb5_db_entry *k)
+{
+       krb5_tl_data *tl_data_next = NULL;
+       krb5_tl_data *tl_data = NULL;
+       int i, j;
+
+       if (k == NULL) {
+               return;
+       }
+
+       krb5_free_principal(context, k->princ);
+
+       for (tl_data = k->tl_data; tl_data; tl_data = tl_data_next) {
+               tl_data_next = tl_data->tl_data_next;
+               if (tl_data->tl_data_contents != NULL) {
+                       free(tl_data->tl_data_contents);
+               }
+               free(tl_data);
+       }
+
+       if (k->key_data != NULL) {
+               for (i = 0; i < k->n_key_data; i++) {
+                       for (j = 0; j < k->key_data[i].key_data_ver; j++) {
+                               if (k->key_data[i].key_data_length[j] != 0) {
+                                       if (k->key_data[i].key_data_contents[j] != NULL) {
+                                               memset(k->key_data[i].key_data_contents[j], 0, k->key_data[i].key_data_length[j]);
+                                               free(k->key_data[i].key_data_contents[j]);
+                                       }
+                               }
+                               k->key_data[i].key_data_contents[j] = NULL;
+                               k->key_data[i].key_data_length[j] = 0;
+                               k->key_data[i].key_data_type[j] = 0;
+                       }
+               }
+               free(k->key_data);
+       }
+
+       ZERO_STRUCTP(k);
+}
+
+static int sdb_entry_ex_to_krb5_db_entry(krb5_context context,
+                                        const struct sdb_entry *s,
+                                        krb5_db_entry *k)
+{
+       krb5_error_code ret;
+       int i;
+
+       k->magic = KRB5_KDB_MAGIC_NUMBER;
+       k->len = KRB5_KDB_V1_BASE_LENGTH;
+
+       ret = krb5_copy_principal(context,
+                                 s->principal,
+                                 &k->princ);
+       if (ret) {
+               free_krb5_db_entry(context, k);
+               return ret;
+       }
+
+       ret = SDBFlags_to_kflags(&s->flags,
+                                &k->attributes);
+       if (ret) {
+               free_krb5_db_entry(context, k);
+               return ret;
+       }
+
+       if (s->max_life != NULL) {
+               k->max_life = *s->max_life;
+       }
+       if (s->max_renew != NULL) {
+               k->max_renewable_life = *s->max_renew;
+       }
+       if (s->valid_end != NULL) {
+               k->expiration = *s->valid_end;
+       }
+       if (s->pw_end != NULL) {
+               k->pw_expiration = *s->pw_end;
+       }
+
+       /* last_success */
+       /* last_failed */
+       /* fail_auth_count */
+       /* n_tl_data */
+
+       ret = sdb_event_to_kmod(context,
+                               s->modified_by ? s->modified_by : &s->created_by,
+                               k);
+       if (ret) {
+               free_krb5_db_entry(context, k);
+               return ret;
+       }
+
+       /* FIXME: TODO HDB Extensions */
+
+
+       k->key_data = malloc(s->keys.len * sizeof(krb5_key_data));
+       if (k->key_data == NULL) {
+               free_krb5_db_entry(context, k);
+               return ret;
+       }
+
+       for (i=0; i < s->keys.len; i++) {
+
+               ret = sdb_key_to_krb5_key_data(&s->keys.val[i],
+                                              s->kvno,
+                                              &k->key_data[i]);
+               if (ret) {
+                       free_krb5_db_entry(context, k);
+                       return ret;
+               }
+
+               k->n_key_data++;
+       }
+
+       return 0;
+}
+
+static int samba_kdc_kdb_entry_destructor(struct samba_kdc_entry *p)
+{
+       krb5_db_entry *entry_ex = p->entry_ex;
+       krb5_error_code ret;
+       krb5_context context;
+
+       ret = krb5_init_context(&context);
+       if (ret) {
+               return ret;
+       }
+
+       free_krb5_db_entry(context, entry_ex);
+       krb5_free_context(context);
+
+       return 0;
+}
+
+
+int sdb_entry_ex_to_kdb_entry_ex(krb5_context context,
+                                const struct sdb_entry_ex *s,
+                                krb5_db_entry *k)
+{
+       struct samba_kdc_entry *skdc_entry;
+
+       ZERO_STRUCTP(k);
+
+       skdc_entry = talloc_get_type(s->ctx, struct samba_kdc_entry);
+
+       k->e_data       = (void *)skdc_entry;
+
+       talloc_set_destructor(skdc_entry, samba_kdc_kdb_entry_destructor);
+
+       return sdb_entry_ex_to_krb5_db_entry(context, &s->entry, k);
+}
index 2abafa637c2ee4b7b3732883b3422f9ccccc9f7a..ea27e37e7d567fb9bb51218626f368dfbef8a74d 100755 (executable)
@@ -72,6 +72,14 @@ bld.SAMBA_SUBSYSTEM('sdb_hdb',
        enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')
        )
 
+bld.SAMBA_SUBSYSTEM('sdb_kdb',
+       source='sdb_to_kdb.c',
+       includes=kdc_include,
+       deps='sdb kdb5',
+       autoproto='sdb_kdb.h',
+       enabled=bld.CONFIG_SET('HAVE_KDB_H')
+       )
+
 bld.SAMBA_SUBSYSTEM('PAC_GLUE',
        source='pac-glue.c',
         includes=kdc_include,