[SCM] Samba Shared Repository - branch master updated

Simo Sorce idra at samba.org
Thu Jan 28 17:34:17 MST 2010


The branch, master has been updated
       via  14e0067... s4:kdc remove dead code and comments
       via  7b355d4... s4:kdc Fill in more data fields
       via  3ce54a4... s4:kdc move db functions in their own file
       via  a097527... s4:kdc Use a clearer name for the samba kdc entry
       via  c6865af... s4:kdc Use better db context structure
      from  f387ed8... Fix bug #7069 - smbget does not return an error status after some errors

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 14e006747eb28b473e5c8070ef021600e1adeeca
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jan 28 19:32:38 2010 -0500

    s4:kdc remove dead code and comments

commit 7b355d41b52e9ff0ae705da7a7620f03a1868a19
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jan 28 08:58:44 2010 -0500

    s4:kdc Fill in more data fields

commit 3ce54a4a973d79012e0ea5a1351393d6b006c809
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jan 28 01:27:11 2010 -0500

    s4:kdc move db functions in their own file
    
    Keep all heimdal related plugin code within hdb_samba4.c
    Move interfaces needed by multiple plugins in db-glue.c
    
    Move sequence context in main db context so that we do
    not depend on db->hdb_dbc in the common code.
    
    Remove unnecessary paremeters from function prototypes

commit a097527ab73c781322d643f6f444c0d146d0ce87
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jan 28 00:19:59 2010 -0500

    s4:kdc Use a clearer name for the samba kdc entry
    
    Renames hdb_samba4_private to samba_kdc_entry
    Streamlines members of the entry and the kdc db contextto avoid
    unnecessary duplication.

commit c6865af4450432bec3f5383d6c815934ac89d434
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jan 28 00:08:36 2010 -0500

    s4:kdc Use better db context structure
    
    This allows to use a common structure not tied to hdb_samba4
    Also allows to avoid many casts within hdb_samba4 functions
    
    This is the first step to abstract samba kdc databse functions
    so they can be used by the MIT forthcoming plugin.

-----------------------------------------------------------------------

Summary of changes:
 source4/kdc/config.mk                 |   14 +-
 source4/kdc/db-glue.c                 | 1513 ++++++++++++++++++++++++++++++++
 source4/kdc/db-glue.h                 |   48 +
 source4/kdc/hdb-samba4.c              | 1540 ++-------------------------------
 source4/kdc/hdb-samba4.h              |   37 -
 source4/kdc/kdc.c                     |   30 +-
 source4/kdc/kdc.h                     |   27 +-
 source4/kdc/kpasswdd.c                |    2 +-
 source4/kdc/pac-glue.c                |   12 +-
 source4/kdc/samba_kdc.h               |   44 +
 source4/kdc/wdc-samba4.c              |   10 +-
 source4/libnet/libnet_export_keytab.c |   14 +-
 12 files changed, 1731 insertions(+), 1560 deletions(-)
 create mode 100644 source4/kdc/db-glue.c
 create mode 100644 source4/kdc/db-glue.h
 delete mode 100644 source4/kdc/hdb-samba4.h
 create mode 100644 source4/kdc/samba_kdc.h


Changeset truncated at 500 lines:

diff --git a/source4/kdc/config.mk b/source4/kdc/config.mk
index c3fc550..93f27a3 100644
--- a/source4/kdc/config.mk
+++ b/source4/kdc/config.mk
@@ -19,7 +19,7 @@ KDC_OBJ_FILES = $(addprefix $(kdcsrcdir)/, kdc.o kpasswdd.o)
 CFLAGS = -Iheimdal/kdc -Iheimdal/lib/hdb
 PRIVATE_DEPENDENCIES = \
 		LIBLDB auth_sam auth_sam_reply CREDENTIALS \
-		HEIMDAL_HDB LIBSAMBA-HOSTCONFIG
+		HEIMDAL_HDB DB_GLUE LIBSAMBA-HOSTCONFIG
 # End SUBSYSTEM HDB
 #######################
 
@@ -48,3 +48,15 @@ PRIVATE_DEPENDENCIES = \
 #######################
 
 PAC_GLUE_OBJ_FILES = $(addprefix $(kdcsrcdir)/, pac-glue.o)
+
+#######################
+# Start SUBSYSTEM KDC
+[SUBSYSTEM::DB_GLUE]
+CFLAGS = -Iheimdal/kdc -Iheimdal/lib/hdb
+PRIVATE_DEPENDENCIES = \
+		LIBLDB auth_sam auth_sam_reply CREDENTIALS \
+		HEIMDAL_HDB LIBSAMBA-HOSTCONFIG
+# End SUBSYSTEM KDC
+#######################
+
+DB_GLUE_OBJ_FILES = $(addprefix $(kdcsrcdir)/, db-glue.o)
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
new file mode 100644
index 0000000..c434ccb
--- /dev/null
+++ b/source4/kdc/db-glue.c
@@ -0,0 +1,1513 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Database Glue between Samba and the KDC
+
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005-2009
+   Copyright (C) Simo Sorce <idra at samba.org> 2010
+
+   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 "system/time.h"
+#include "../libds/common/flags.h"
+#include "lib/ldb/include/ldb.h"
+#include "librpc/gen_ndr/netlogon.h"
+#include "libcli/security/security.h"
+#include "auth/auth.h"
+#include "auth/credentials/credentials.h"
+#include "auth/auth_sam.h"
+#include "../lib/util/util_ldb.h"
+#include "dsdb/samdb/samdb.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "librpc/gen_ndr/lsa.h"
+#include "libcli/auth/libcli_auth.h"
+#include "param/param.h"
+#include "../lib/crypto/md4.h"
+#include "system/kerberos.h"
+#include <hdb.h>
+#include "kdc/samba_kdc.h"
+#include "kdc/db-glue.h"
+
+enum samba_kdc_ent_type
+{ SAMBA_KDC_ENT_TYPE_CLIENT, SAMBA_KDC_ENT_TYPE_SERVER,
+  SAMBA_KDC_ENT_TYPE_KRBTGT, SAMBA_KDC_ENT_TYPE_TRUST, SAMBA_KDC_ENT_TYPE_ANY };
+
+enum trust_direction {
+	UNKNOWN = 0,
+	INBOUND = LSA_TRUST_DIRECTION_INBOUND,
+	OUTBOUND = LSA_TRUST_DIRECTION_OUTBOUND
+};
+
+static const char *trust_attrs[] = {
+	"trustPartner",
+	"trustAuthIncoming",
+	"trustAuthOutgoing",
+	"whenCreated",
+	"msDS-SupportedEncryptionTypes",
+	"trustAttributes",
+	"trustDirection",
+	"trustType",
+	NULL
+};
+
+static KerberosTime ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, KerberosTime default_val)
+{
+    const char *tmp;
+    const char *gentime;
+    struct tm tm;
+
+    gentime = ldb_msg_find_attr_as_string(msg, attr, NULL);
+    if (!gentime)
+	return default_val;
+
+    tmp = strptime(gentime, "%Y%m%d%H%M%SZ", &tm);
+    if (tmp == NULL) {
+	    return default_val;
+    }
+
+    return timegm(&tm);
+}
+
+static HDBFlags uf2HDBFlags(krb5_context context, int userAccountControl, enum samba_kdc_ent_type ent_type)
+{
+	HDBFlags flags = int2HDBFlags(0);
+
+	/* we don't allow kadmin deletes */
+	flags.immutable = 1;
+
+	/* mark the principal as invalid to start with */
+	flags.invalid = 1;
+
+	flags.renewable = 1;
+
+	/* All accounts are servers, but this may be disabled again in the caller */
+	flags.server = 1;
+
+	/* Account types - clear the invalid bit if it turns out to be valid */
+	if (userAccountControl & UF_NORMAL_ACCOUNT) {
+		if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
+			flags.client = 1;
+		}
+		flags.invalid = 0;
+	}
+
+	if (userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
+		if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
+			flags.client = 1;
+		}
+		flags.invalid = 0;
+	}
+	if (userAccountControl & UF_WORKSTATION_TRUST_ACCOUNT) {
+		if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
+			flags.client = 1;
+		}
+		flags.invalid = 0;
+	}
+	if (userAccountControl & UF_SERVER_TRUST_ACCOUNT) {
+		if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
+			flags.client = 1;
+		}
+		flags.invalid = 0;
+	}
+
+	/* Not permitted to act as a client if disabled */
+	if (userAccountControl & UF_ACCOUNTDISABLE) {
+		flags.client = 0;
+	}
+	if (userAccountControl & UF_LOCKOUT) {
+		flags.invalid = 1;
+	}
+/*
+	if (userAccountControl & UF_PASSWORD_NOTREQD) {
+		flags.invalid = 1;
+	}
+*/
+/*
+	UF_PASSWORD_CANT_CHANGE and UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED are irrelevent
+*/
+	if (userAccountControl & UF_TEMP_DUPLICATE_ACCOUNT) {
+		flags.invalid = 1;
+	}
+
+/* UF_DONT_EXPIRE_PASSWD and UF_USE_DES_KEY_ONLY handled in samba_kdc_message2entry() */
+
+/*
+	if (userAccountControl & UF_MNS_LOGON_ACCOUNT) {
+		flags.invalid = 1;
+	}
+*/
+	if (userAccountControl & UF_SMARTCARD_REQUIRED) {
+		flags.require_hwauth = 1;
+	}
+	if (userAccountControl & UF_TRUSTED_FOR_DELEGATION) {
+		flags.ok_as_delegate = 1;
+	}
+	if (!(userAccountControl & UF_NOT_DELEGATED)) {
+		flags.forwardable = 1;
+		flags.proxiable = 1;
+	}
+
+	if (userAccountControl & UF_DONT_REQUIRE_PREAUTH) {
+		flags.require_preauth = 0;
+	} else {
+		flags.require_preauth = 1;
+
+	}
+	return flags;
+}
+
+static int samba_kdc_entry_destructor(struct samba_kdc_entry *p)
+{
+    hdb_entry_ex *entry_ex = p->entry_ex;
+    free_hdb_entry(&entry_ex->entry);
+    return 0;
+}
+
+static void samba_kdc_free_entry(krb5_context context, hdb_entry_ex *entry_ex)
+{
+	talloc_free(entry_ex->ctx);
+}
+
+static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
+					      struct smb_iconv_convenience *iconv_convenience,
+					      TALLOC_CTX *mem_ctx,
+					      struct ldb_message *msg,
+					      unsigned int userAccountControl,
+					      hdb_entry_ex *entry_ex)
+{
+	krb5_error_code ret = 0;
+	enum ndr_err_code ndr_err;
+	struct samr_Password *hash;
+	const struct ldb_val *sc_val;
+	struct supplementalCredentialsBlob scb;
+	struct supplementalCredentialsPackage *scpk = NULL;
+	bool newer_keys = false;
+	struct package_PrimaryKerberosBlob _pkb;
+	struct package_PrimaryKerberosCtr3 *pkb3 = NULL;
+	struct package_PrimaryKerberosCtr4 *pkb4 = NULL;
+	uint32_t i;
+	uint32_t allocated_keys = 0;
+
+	entry_ex->entry.keys.val = NULL;
+	entry_ex->entry.keys.len = 0;
+
+	entry_ex->entry.kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
+
+	/* Get keys from the db */
+
+	hash = samdb_result_hash(mem_ctx, msg, "unicodePwd");
+	sc_val = ldb_msg_find_ldb_val(msg, "supplementalCredentials");
+
+	/* unicodePwd for enctype 0x17 (23) if present */
+	if (hash) {
+		allocated_keys++;
+	}
+
+	/* supplementalCredentials if present */
+	if (sc_val) {
+		ndr_err = ndr_pull_struct_blob_all(sc_val, mem_ctx, iconv_convenience, &scb,
+						   (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			dump_data(0, sc_val->data, sc_val->length);
+			ret = EINVAL;
+			goto out;
+		}
+
+		if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
+			NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
+			ret = EINVAL;
+			goto out;
+		}
+
+		for (i=0; i < scb.sub.num_packages; i++) {
+			if (strcmp("Primary:Kerberos-Newer-Keys", scb.sub.packages[i].name) == 0) {
+				scpk = &scb.sub.packages[i];
+				if (!scpk->data || !scpk->data[0]) {
+					scpk = NULL;
+					continue;
+				}
+				newer_keys = true;
+				break;
+			} else if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) == 0) {
+				scpk = &scb.sub.packages[i];
+				if (!scpk->data || !scpk->data[0]) {
+					scpk = NULL;
+				}
+				/*
+				 * we don't break here in hope to find
+				 * a Kerberos-Newer-Keys package
+				 */
+			}
+		}
+	}
+	/*
+	 * Primary:Kerberos-Newer-Keys or Primary:Kerberos element
+	 * of supplementalCredentials
+	 */
+	if (scpk) {
+		DATA_BLOB blob;
+
+		blob = strhex_to_data_blob(mem_ctx, scpk->data);
+		if (!blob.data) {
+			ret = ENOMEM;
+			goto out;
+		}
+
+		/* we cannot use ndr_pull_struct_blob_all() here, as w2k and w2k3 add padding bytes */
+		ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, iconv_convenience, &_pkb,
+					       (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			ret = EINVAL;
+			krb5_set_error_message(context, ret, "samba_kdc_message2entry_keys: could not parse package_PrimaryKerberosBlob");
+			krb5_warnx(context, "samba_kdc_message2entry_keys: could not parse package_PrimaryKerberosBlob");
+			goto out;
+		}
+
+		if (newer_keys && _pkb.version != 4) {
+			ret = EINVAL;
+			krb5_set_error_message(context, ret, "samba_kdc_message2entry_keys: Primary:Kerberos-Newer-Keys not version 4");
+			krb5_warnx(context, "samba_kdc_message2entry_keys: Primary:Kerberos-Newer-Keys not version 4");
+			goto out;
+		}
+
+		if (!newer_keys && _pkb.version != 3) {
+			ret = EINVAL;
+			krb5_set_error_message(context, ret, "samba_kdc_message2entry_keys: could not parse Primary:Kerberos not version 3");
+			krb5_warnx(context, "samba_kdc_message2entry_keys: could not parse Primary:Kerberos not version 3");
+			goto out;
+		}
+
+		if (_pkb.version == 4) {
+			pkb4 = &_pkb.ctr.ctr4;
+			allocated_keys += pkb4->num_keys;
+		} else if (_pkb.version == 3) {
+			pkb3 = &_pkb.ctr.ctr3;
+			allocated_keys += pkb3->num_keys;
+		}
+	}
+
+	if (allocated_keys == 0) {
+		/* oh, no password.  Apparently (comment in
+		 * hdb-ldap.c) this violates the ASN.1, but this
+		 * allows an entry with no keys (yet). */
+		return 0;
+	}
+
+	/* allocate space to decode into */
+	entry_ex->entry.keys.len = 0;
+	entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(Key));
+	if (entry_ex->entry.keys.val == NULL) {
+		ret = ENOMEM;
+		goto out;
+	}
+
+	if (hash && !(userAccountControl & UF_USE_DES_KEY_ONLY)) {
+		Key key;
+
+		key.mkvno = 0;
+		key.salt = NULL; /* No salt for this enc type */
+
+		ret = krb5_keyblock_init(context,
+					 ENCTYPE_ARCFOUR_HMAC,
+					 hash->hash, sizeof(hash->hash),
+					 &key.key);
+		if (ret) {
+			goto out;
+		}
+
+		entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
+		entry_ex->entry.keys.len++;
+	}
+
+	if (pkb4) {
+		for (i=0; i < pkb4->num_keys; i++) {
+			bool use = true;
+			Key key;
+
+			if (!pkb4->keys[i].value) continue;
+
+			if (userAccountControl & UF_USE_DES_KEY_ONLY) {
+				switch (pkb4->keys[i].keytype) {
+				case ENCTYPE_DES_CBC_CRC:
+				case ENCTYPE_DES_CBC_MD5:
+					break;
+				default:
+					use = false;
+					break;
+				}
+			}
+
+			if (!use) continue;
+
+			key.mkvno = 0;
+			key.salt = NULL;
+
+			if (pkb4->salt.string) {
+				DATA_BLOB salt;
+
+				salt = data_blob_string_const(pkb4->salt.string);
+
+				key.salt = calloc(1, sizeof(*key.salt));
+				if (key.salt == NULL) {
+					ret = ENOMEM;
+					goto out;
+				}
+
+				key.salt->type = hdb_pw_salt;
+
+				ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length);
+				if (ret) {
+					free(key.salt);
+					key.salt = NULL;
+					goto out;
+				}
+			}
+
+			/* TODO: maybe pass the iteration_count somehow... */
+
+			ret = krb5_keyblock_init(context,
+						 pkb4->keys[i].keytype,
+						 pkb4->keys[i].value->data,
+						 pkb4->keys[i].value->length,
+						 &key.key);
+			if (ret == KRB5_PROG_ETYPE_NOSUPP) {
+				DEBUG(2,("Unsupported keytype ignored - type %u\n",
+					 pkb4->keys[i].keytype));
+				ret = 0;
+				continue;
+			}
+			if (ret) {
+				if (key.salt) {
+					free_Salt(key.salt);
+					free(key.salt);
+					key.salt = NULL;
+				}
+				goto out;
+			}
+
+			entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
+			entry_ex->entry.keys.len++;
+		}
+	} else if (pkb3) {
+		for (i=0; i < pkb3->num_keys; i++) {
+			bool use = true;
+			Key key;
+
+			if (!pkb3->keys[i].value) continue;
+
+			if (userAccountControl & UF_USE_DES_KEY_ONLY) {
+				switch (pkb3->keys[i].keytype) {
+				case ENCTYPE_DES_CBC_CRC:
+				case ENCTYPE_DES_CBC_MD5:
+					break;
+				default:
+					use = false;
+					break;
+				}
+			}
+
+			if (!use) continue;
+
+			key.mkvno = 0;
+			key.salt = NULL;
+
+			if (pkb3->salt.string) {
+				DATA_BLOB salt;
+
+				salt = data_blob_string_const(pkb3->salt.string);
+
+				key.salt = calloc(1, sizeof(*key.salt));
+				if (key.salt == NULL) {
+					ret = ENOMEM;
+					goto out;
+				}
+
+				key.salt->type = hdb_pw_salt;
+
+				ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length);
+				if (ret) {
+					free(key.salt);
+					key.salt = NULL;
+					goto out;
+				}
+			}
+
+			ret = krb5_keyblock_init(context,
+						 pkb3->keys[i].keytype,
+						 pkb3->keys[i].value->data,
+						 pkb3->keys[i].value->length,
+						 &key.key);
+			if (ret) {
+				if (key.salt) {
+					free_Salt(key.salt);
+					free(key.salt);
+					key.salt = NULL;
+				}
+				goto out;
+			}
+
+			entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
+			entry_ex->entry.keys.len++;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list