[PATCHSET] Samba AD with MIT Kerberos

Andreas Schneider asn at samba.org
Mon Apr 24 12:36:21 UTC 2017


On Monday, 24 April 2017 13:44:27 CEST Andrew Bartlett via samba-technical 
wrote:
> On Thu, 2017-04-20 at 16:13 +0200, Andreas Schneider via samba-
> 
> technical wrote:
> > On Wednesday, 19 April 2017 11:26:29 CEST Andrew Bartlett wrote:
> > > The configure --help output does not explain the changed behaviour,
> > > it
> > > still says:
> > > 
> > >   --with-system-mitkrb5
> > >             enable system MIT krb5 build (includes Samba 4 client
> > > and
> > > Samba 3 code base).You may specify list of paths where Kerberos is
> > > installed (e.g. /usr/local
> > >             /usr/kerberos) to search krb5-config
> > 
> > Fixed, and also changed the test of the --without-ad-dc option. We
> > need to 
> > stop referring to Samba4 and Samba3 and use Samba AD and Samba FS!
> 
> It still fails for me with:
> 
> Checking for
> gssapi                                                               : yes 
> ERROR: MIT krb5 build requires at least 1.15.1. 1.14.4 is found and cannot
> be used ERROR: You may try to build with embedded Heimdal Kerebros by not
> specifying --with-system-mitkrb5

Yes, this looks correct to me.

> This implies to me that you have not restored the behaviour to have --
> without-ad-dc be the default when --with-system-mitkrb5 is set.

Yes, by default the DC should be built, the same way as it is with Heimdal 
too. If you do not want to build the DC you should run configure with:

	--without-ad-dc

That's why we have that option. It should not be the other way around. Else we 
would have to add another option with does the opposite and if we remove it it 
would be confusing twice.

> There are these problems:
>  - It means that builds that worked will now fail, until an extra
> option is specified

It means that we just require a newer version to build Samba with MIT Kerberos 
by default. The option --without-ad-dc is already used by packages which build 
Samba with MIT Kerberos, e.g. SUSE and Fedora.

I've added the following warning to the configure error:

ERROR: If you want to just build Samba FS use the option --without-ad-dc

>  - The AD DC will be built for installations that previously didn't get
> it
>  - Nothing in the error message suggests that --without-ad-dc is a fix
> for this error.

See rebased attached patchset.
 
> Please do as I requested, and again make --with-system-mitkrb5 imply --
> without-ad-dc unless specified otherwise.  Then test that you can
> ./configure --with-system-mitkrb5 on Ubuntu 14.04 and Fedora 25.
> 
> There will be a time when this will also build the AD DC by default,
> but that needs to be later, preferably once we sort out the remaining
> features.

This will be much more confusing when the option set changes later and not now 
when we add it. Distributions building Samba with MIT Kerberos already use --
without-ad-dc.

Also this is not half baked unstable code. This is very well tested code which 
is mature and we want to make progress. This code revealed so many issues in 
Samba AD. Most of the time I fixed bugs in the AD DC which are not MIT 
Kerberos related at all. Just look what Metze and I worked on over the last 
year.

Rewrite of libsmb/cliconnect.c to pass down cli credentials to gensec
A lot of gensec fixes
Trusted domain fixes

> I'm sorry that I can't give you a review quite yet.  Additionally,
> Jeremy's war on talloc_autofree() has broken the patch set against
> master.  It isn't a hard fix, but I know it will be frustrating.

See attached patchset.

I rebase this patchset since several years every few days now! Most of the 
time this patchset had between 70 and 120 patches. We already sent smaller 
junks to get them upstream the last years. This is the final one.


Attached is a rebased patchset on master.


	Andreas

-- 
Andreas Schneider                   GPG-ID: CC014E3D
Samba Team                             asn at samba.org
www.samba.org
-------------- next part --------------
From b184ebf3a53ec06e571def930dce7baa9ec5ccea Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 30 Jul 2015 17:38:34 +0200
Subject: [PATCH 01/50] samba_dnsupdate: Do not rewrite krb5.conf in selftest

The samba_dnsupdate script is responsible to provision the DNS entries.
The private krb5.conf uses dns lookups to find the KDC to acquire a
Kerberos ticket.  Obviously this will fail because currently we are are
in the process of adding the DNS entries for the KDC.

If we are inside of selftest we need to use the krb5.conf created by
selftest itself.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/scripting/bin/samba_dnsupdate | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate
index f9e835bc5c3..d382758168b 100755
--- a/source4/scripting/bin/samba_dnsupdate
+++ b/source4/scripting/bin/samba_dnsupdate
@@ -662,10 +662,13 @@ if opts.update_cache:
 else:
     dns_update_cache = lp.private_path('dns_update_cache')
 
-# use our private krb5.conf to avoid problems with the wrong domain
-# bind9 nsupdate wants the default domain set
-krb5conf = lp.private_path('krb5.conf')
-os.environ['KRB5_CONFIG'] = krb5conf
+krb5conf = None
+# only change the krb5.conf if we are not in selftest
+if 'SOCKET_WRAPPER_DIR' not in os.environ:
+    # use our private krb5.conf to avoid problems with the wrong domain
+    # bind9 nsupdate wants the default domain set
+    krb5conf = lp.private_path('krb5.conf')
+    os.environ['KRB5_CONFIG'] = krb5conf
 
 file = open(dns_update_list, "r")
 
-- 
2.12.2


From fef8f516641dfd31c7c5e5f089a5e582ead05dd9 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 26 Jan 2017 16:54:30 +0100
Subject: [PATCH 02/50] mit-kdb: Zero the db principal when we allocate it

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index f5015840055..8a2bfe9b715 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -188,7 +188,7 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
 	int ret;
 	int sflags = 0;
 
-	kentry = malloc(sizeof(krb5_db_entry));
+	kentry = calloc(1, sizeof(krb5_db_entry));
 	if (kentry == NULL) {
 		return ENOMEM;
 	}
-- 
2.12.2


From c04fb70337efcdb1bfebc182e92fcfa39f86f2bd Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 20 Jan 2017 09:14:03 +0100
Subject: [PATCH 03/50] waf: Require MIT Kerberos 1.15.1 for Samba AD

Are build without AD DC still only requried MIT Kerberos 1.9.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 wscript                          |  4 ++--
 wscript_configure_system_mitkrb5 | 28 +++++++++++++++++++---------
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/wscript b/wscript
index de85591223c..a7c4f4c31b9 100644
--- a/wscript
+++ b/wscript
@@ -48,12 +48,12 @@ def set_options(opt):
     opt.samba_add_onoff_option('pthreadpool', with_name="enable", without_name="disable", default=True)
 
     opt.add_option('--with-system-mitkrb5',
-                   help='enable system MIT krb5 build (includes Samba 4 client and Samba 3 code base).'+
+                   help='build Samba with system MIT Kerberos. ' +
                         'You may specify list of paths where Kerberos is installed (e.g. /usr/local /usr/kerberos) to search krb5-config',
                    action='callback', callback=system_mitkrb5_callback, dest='with_system_mitkrb5', default=False)
 
     opt.add_option('--without-ad-dc',
-                   help='disable AD DC functionality (enables Samba 4 client and Samba 3 code base).',
+                   help='disable AD DC functionality (enables only Samba FS (File Server, Winbind, NMBD) and client utilities.',
                    action='store_true', dest='without_ad_dc', default=False)
 
     opt.add_option('--with-ntvfs-fileserver',
diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
index d3e8ebf0dcd..3e9d4ffb076 100644
--- a/wscript_configure_system_mitkrb5
+++ b/wscript_configure_system_mitkrb5
@@ -3,6 +3,14 @@ import Logs, Options, sys
 # Check for kerberos
 have_gssapi=False
 
+# Requried versions
+krb5_required_version = "1.9"
+if conf.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'):
+    krb5_required_version = "1.15.1"
+
+def parse_version(v):
+    return tuple(map(int, (v.split("."))))
+
 def krb5_define_syslib(conf, lib, deps):
     found = 'FOUND_SYSTEMLIB_' + lib
     if found in conf.env:
@@ -44,19 +52,21 @@ if conf.env.KRB5_CONFIG:
     if conf.env.KRB5_VENDOR != 'heimdal':
         conf.define('USING_SYSTEM_KRB5', 1)
         del conf.env.HEIMDAL_KRB5_CONFIG
-        kversion = conf.cmd_and_log("%(path)s --version" % dict(path=conf.env.KRB5_CONFIG), dict()).strip()
-        kversion_split = kversion.split(' ')[-1].split('.')
+        krb5_conf_version = conf.cmd_and_log("%(path)s --version" % dict(path=conf.env.KRB5_CONFIG), dict()).strip()
+
+        krb5_version = krb5_conf_version.split()[-1]
+
         # drop '-prerelease' suffix
-        if kversion_split[-1].find('-') > 0:
-            last_digit = kversion_split[-1].split('-')[0]
-            kversion_split[-1] = last_digit
-        kversion_check = map(int, kversion_split)
-        if kversion_check < [1, 9]:
-            Logs.error('ERROR: MIT krb5 build requires at least 1.9.0. %s is found and cannot be used' % (kversion))
+        if krb5_version.find('-') > 0:
+            krb5_version = krb5_version.split("-")[0]
+
+        if parse_version(krb5_version) < parse_version(krb5_required_version):
+            Logs.error('ERROR: MIT krb5 build requires at least %s. %s is found and cannot be used' % (krb5_required_version, krb5_version))
+            Logs.error('ERROR: If you want to just build Samba FS use the option --without-ad-dc')
             Logs.error('ERROR: You may try to build with embedded Heimdal Kerebros by not specifying --with-system-mitkrb5')
             sys.exit(1)
         else:
-            Logs.info('%s is detected, MIT krb5 build can proceed' % (kversion))
+            Logs.info('MIT Kerberos %s detected, MIT krb5 build can proceed' % (krb5_version))
 
 conf.CHECK_CFG(args="--cflags --libs", package="com_err", uselib_store="com_err")
 conf.CHECK_FUNCS_IN('_et_list', 'com_err')
-- 
2.12.2


From c4fcdf504782482a22c983e1bd0e8f48e1ae2cee Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 26 Jan 2017 16:52:15 +0100
Subject: [PATCH 04/50] mit-kdb: Update KDB vtable for DAL version 6

This changed between 1.14 and 1.15. Also the 1.15 change removed the
ability that the KDB module can free memory. This caused issues of
serveral projects. It got fixed with 1.15.1.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit-kdb/kdb_samba.c            | 92 +++++++++++++-----------------
 source4/kdc/mit-kdb/kdb_samba.h            |  6 --
 source4/kdc/mit-kdb/kdb_samba_common.c     | 48 ----------------
 source4/kdc/mit-kdb/kdb_samba_principals.c | 33 ++++-------
 source4/kdc/sdb_to_kdb.c                   | 16 ++++--
 5 files changed, 63 insertions(+), 132 deletions(-)

diff --git a/source4/kdc/mit-kdb/kdb_samba.c b/source4/kdc/mit-kdb/kdb_samba.c
index b7f802c8c66..c5157d6ed1b 100644
--- a/source4/kdc/mit-kdb/kdb_samba.c
+++ b/source4/kdc/mit-kdb/kdb_samba.c
@@ -126,60 +126,50 @@ static krb5_error_code kdb_samba_db_unlock(krb5_context context)
 	return 0;
 }
 
-static void *kdb_samba_db_alloc(krb5_context context, void *ptr, size_t size)
+static void kdb_samba_db_free_principal_e_data(krb5_context context,
+					       krb5_octet *e_data)
 {
-	return realloc(ptr, size);
-}
+	struct samba_kdc_entry *skdc_entry;
 
-static void kdb_samba_db_free(krb5_context context, void *ptr)
-{
-	free(ptr);
+	skdc_entry = talloc_get_type_abort(e_data,
+					   struct samba_kdc_entry);
+	talloc_set_destructor(skdc_entry, NULL);
+	TALLOC_FREE(skdc_entry);
 }
 
 kdb_vftabl kdb_function_table = {
-	KRB5_KDB_DAL_MAJOR_VERSION,        /* major version number */
-	0,                                 /* minor version number */
-	kdb_samba_init_library,            /* init_library */
-	kdb_samba_fini_library,            /* fini_library */
-	kdb_samba_init_module,             /* init_module */
-	kdb_samba_fini_module,             /* fini_module */
-
-	kdb_samba_db_create,               /* db_create */
-	kdb_samba_db_destroy,              /* db_destroy */
-	kdb_samba_db_get_age,              /* db_get_age */
-	kdb_samba_db_lock,                 /* db_lock */
-	kdb_samba_db_unlock,               /* db_unlock */
-
-	kdb_samba_db_get_principal,        /* db_get_principal */
-	kdb_samba_db_free_principal,       /* db_free_principal */
-	kdb_samba_db_put_principal,        /* db_put_principal */
-	kdb_samba_db_delete_principal,     /* db_delete_principal */
-	kdb_samba_db_iterate,              /* db_iterate */
-
-	NULL,                              /* create_policy */
-	NULL,                              /* get_policy */
-	NULL,                              /* put_policy */
-	NULL,                              /* iter_policy */
-	NULL,                              /* delete_policy */
-	NULL,                              /* free_policy */
-
-	kdb_samba_db_alloc,                /* db_alloc */
-	kdb_samba_db_free,                 /* db_free */
-
-	kdb_samba_fetch_master_key,        /* fetch_master_key */
-	kdb_samba_fetch_master_key_list,   /* fetch_master_key_list */
-	NULL,                              /* store_master_key_list */
-	NULL,                              /* dbe_search_enctype */
-	kdb_samba_change_pwd,              /* change_pwd */
-	NULL,                              /* promote_db */
-	kdb_samba_dbekd_decrypt_key_data,  /* decrypt_key_data */
-	kdb_samba_dbekd_encrypt_key_data,  /* encrypt_key_data */
-
-	kdb_samba_db_sign_auth_data,       /* sign_authdata */
-	NULL,                              /* check_transited_realms */
-	kdb_samba_db_check_policy_as,      /* check_policy_as */
-	NULL,                              /* check_policy_tgs */
-	kdb_samba_db_audit_as_req,         /* audit_as_req */
-	NULL,                              /* refresh_config */
-	kdb_samba_db_check_allowed_to_delegate
+	.maj_ver                   = KRB5_KDB_DAL_MAJOR_VERSION,
+	.min_ver                   = 1,
+
+	.init_library              = kdb_samba_init_library,
+	.fini_library              = kdb_samba_fini_library,
+	.init_module               = kdb_samba_init_module,
+	.fini_module               = kdb_samba_fini_module,
+
+	.create                    = kdb_samba_db_create,
+	.destroy                   = kdb_samba_db_destroy,
+	.get_age                   = kdb_samba_db_get_age,
+	.lock                      = kdb_samba_db_lock,
+	.unlock                    = kdb_samba_db_unlock,
+
+	.get_principal             = kdb_samba_db_get_principal,
+	.put_principal             = kdb_samba_db_put_principal,
+	.delete_principal          = kdb_samba_db_delete_principal,
+
+	.iterate                   = kdb_samba_db_iterate,
+
+	.fetch_master_key          = kdb_samba_fetch_master_key,
+	.fetch_master_key_list     = kdb_samba_fetch_master_key_list,
+
+	.change_pwd                = kdb_samba_change_pwd,
+
+	.decrypt_key_data          = kdb_samba_dbekd_decrypt_key_data,
+	.encrypt_key_data          = kdb_samba_dbekd_encrypt_key_data,
+
+	.sign_authdata             = kdb_samba_db_sign_auth_data,
+	.check_policy_as           = kdb_samba_db_check_policy_as,
+	.audit_as_req              = kdb_samba_db_audit_as_req,
+	.check_allowed_to_delegate = kdb_samba_db_check_allowed_to_delegate,
+
+	.free_principal_e_data     = kdb_samba_db_free_principal_e_data,
 };
diff --git a/source4/kdc/mit-kdb/kdb_samba.h b/source4/kdc/mit-kdb/kdb_samba.h
index 0258b2d313f..abca2c166ae 100644
--- a/source4/kdc/mit-kdb/kdb_samba.h
+++ b/source4/kdc/mit-kdb/kdb_samba.h
@@ -48,9 +48,6 @@
 
 struct mit_samba_context *ks_get_context(krb5_context kcontext);
 
-void ks_free_krb5_db_entry(krb5_context context,
-			   krb5_db_entry *entry);
-
 bool ks_data_eq_string(krb5_data d, const char *s);
 
 krb5_data ks_make_data(void *data, unsigned int len);
@@ -74,9 +71,6 @@ krb5_error_code kdb_samba_db_get_principal(krb5_context context,
 					   unsigned int kflags,
 					   krb5_db_entry **kentry);
 
-void kdb_samba_db_free_principal(krb5_context context,
-				 krb5_db_entry *entry);
-
 krb5_error_code kdb_samba_db_put_principal(krb5_context context,
 					   krb5_db_entry *entry,
 					   char **db_args);
diff --git a/source4/kdc/mit-kdb/kdb_samba_common.c b/source4/kdc/mit-kdb/kdb_samba_common.c
index 1cd546977b7..e89aed6aeba 100644
--- a/source4/kdc/mit-kdb/kdb_samba_common.c
+++ b/source4/kdc/mit-kdb/kdb_samba_common.c
@@ -43,54 +43,6 @@ struct mit_samba_context *ks_get_context(krb5_context kcontext)
 	return (struct mit_samba_context *)db_ctx;
 }
 
-void ks_free_krb5_db_entry(krb5_context context,
-			   krb5_db_entry *entry)
-{
-	krb5_tl_data *tl_data_next = NULL;
-	krb5_tl_data *tl_data = NULL;
-	int i, j;
-
-	if (entry == NULL) {
-		return;
-	}
-
-#if 0 /* TODO FIXME do we have something to free? */
-	if (entry->e_data != NULL) {
-		/* FREE ME! */
-	}
-#endif
-
-	krb5_free_principal(context, entry->princ);
-
-	for (tl_data = entry->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 (entry->key_data != NULL) {
-		for (i = 0; i < entry->n_key_data; i++) {
-			for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
-				if (entry->key_data[i].key_data_length[j] != 0) {
-					if (entry->key_data[i].key_data_contents[j] != NULL) {
-						memset(entry->key_data[i].key_data_contents[j],
-								0,
-								entry->key_data[i].key_data_length[j]);
-						free(entry->key_data[i].key_data_contents[j]);
-					}
-				}
-				entry->key_data[i].key_data_contents[j] = NULL;
-				entry->key_data[i].key_data_length[j] = 0;
-				entry->key_data[i].key_data_type[j] = 0;
-			}
-		}
-		free(entry->key_data);
-	}
-
-	free(entry);
-}
-
 bool ks_data_eq_string(krb5_data d, const char *s)
 {
 	int rc;
diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c
index 7b6fd6a81e9..1dbb69b561d 100644
--- a/source4/kdc/mit-kdb/kdb_samba_principals.c
+++ b/source4/kdc/mit-kdb/kdb_samba_principals.c
@@ -93,7 +93,7 @@ static krb5_error_code ks_get_master_key_principal(krb5_context context,
 		code = krb5_copy_principal(context, princ, &kentry->princ);
 	}
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -101,7 +101,7 @@ static krb5_error_code ks_get_master_key_principal(krb5_context context,
 
 	code = krb5_dbe_update_mod_princ_data(context, kentry, now, kentry->princ);
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -109,7 +109,7 @@ static krb5_error_code ks_get_master_key_principal(krb5_context context,
 	kentry->n_key_data = 1;
 	kentry->key_data = calloc(1, sizeof(krb5_key_data));
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -119,7 +119,7 @@ static krb5_error_code ks_get_master_key_principal(krb5_context context,
 	key_data->key_data_kvno         = 1;
 	key_data->key_data_type[0]      = ENCTYPE_UNKNOWN;
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -169,7 +169,7 @@ static krb5_error_code ks_create_principal(krb5_context context,
 
 	code = krb5_copy_principal(context, princ, &kentry->princ);
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -177,13 +177,13 @@ static krb5_error_code ks_create_principal(krb5_context context,
 
 	code = krb5_dbe_update_mod_princ_data(context, kentry, now, kentry->princ);
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
 	code = mit_samba_generate_salt(&salt);
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -194,7 +194,7 @@ static krb5_error_code ks_create_principal(krb5_context context,
 		/* create a random password */
 		code = mit_samba_generate_random_password(&pwd);
 		if (code != 0) {
-			ks_free_krb5_db_entry(context, kentry);
+			krb5_db_free_principal(context, kentry);
 			return code;
 		}
 	}
@@ -202,14 +202,14 @@ static krb5_error_code ks_create_principal(krb5_context context,
 	code = krb5_c_string_to_key(context, enctype, &pwd, &salt, &key);
 	SAFE_FREE(pwd.data);
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
 	kentry->n_key_data = 1;
 	kentry->key_data = calloc(1, sizeof(krb5_key_data));
 	if (code != 0) {
-		ks_free_krb5_db_entry(context, kentry);
+		krb5_db_free_principal(context, kentry);
 		return code;
 	}
 
@@ -288,19 +288,6 @@ krb5_error_code kdb_samba_db_get_principal(krb5_context context,
 	return code;
 }
 
-void kdb_samba_db_free_principal(krb5_context context,
-				 krb5_db_entry *entry)
-{
-	struct mit_samba_context *mit_ctx;
-
-	mit_ctx = ks_get_context(context);
-	if (mit_ctx == NULL) {
-		return;
-	}
-
-	ks_free_krb5_db_entry(context, entry);
-}
-
 krb5_error_code kdb_samba_db_put_principal(krb5_context context,
 					   krb5_db_entry *entry,
 					   char **db_args)
diff --git a/source4/kdc/sdb_to_kdb.c b/source4/kdc/sdb_to_kdb.c
index ff50c0cab87..74d882738f8 100644
--- a/source4/kdc/sdb_to_kdb.c
+++ b/source4/kdc/sdb_to_kdb.c
@@ -318,27 +318,35 @@ static int samba_kdc_kdb_entry_destructor(struct samba_kdc_entry *p)
 	krb5_error_code ret;
 	krb5_context context;
 
+	if (entry_ex->e_data != NULL) {
+		struct samba_kdc_entry *skdc_entry;
+
+		skdc_entry = talloc_get_type(entry_ex->e_data,
+					     struct samba_kdc_entry);
+		talloc_set_destructor(skdc_entry, NULL);
+		entry_ex->e_data = NULL;
+	}
+
 	ret = krb5_init_context(&context);
 	if (ret) {
 		return ret;
 	}
 
-	free_krb5_db_entry(context, entry_ex);
+	krb5_db_free_principal(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);
 
 	if (s->ctx != NULL) {
+		struct samba_kdc_entry *skdc_entry;
+
 		skdc_entry = talloc_get_type(s->ctx, struct samba_kdc_entry);
 
 		k->e_data	= (void *)skdc_entry;
-- 
2.12.2


From 3976c02be21cfa20552a9e17edf4ef926419151e Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 23 Jul 2015 13:49:09 +0200
Subject: [PATCH 05/50] waf: Check for MIT KDC binary

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 wscript                          |  5 +++++
 wscript_configure_system_mitkrb5 | 13 +++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/wscript b/wscript
index a7c4f4c31b9..032f2ae5fd2 100644
--- a/wscript
+++ b/wscript
@@ -51,6 +51,11 @@ def set_options(opt):
                    help='build Samba with system MIT Kerberos. ' +
                         'You may specify list of paths where Kerberos is installed (e.g. /usr/local /usr/kerberos) to search krb5-config',
                    action='callback', callback=system_mitkrb5_callback, dest='with_system_mitkrb5', default=False)
+    opt.add_option('--with-system-mitkdc',
+                   help=('Specify the path to the krb5kdc binary from MIT Kerberos'),
+                   type="string",
+                   dest='with_system_mitkdc',
+                   default=None)
 
     opt.add_option('--without-ad-dc',
                    help='disable AD DC functionality (enables only Samba FS (File Server, Winbind, NMBD) and client utilities.',
diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
index 3e9d4ffb076..39924577431 100644
--- a/wscript_configure_system_mitkrb5
+++ b/wscript_configure_system_mitkrb5
@@ -291,3 +291,16 @@ conf.CHECK_CODE('''
     'HAVE_FLAGS_IN_KRB5_CREDS',
     headers='krb5.h', lib='krb5', execute=False,
     msg="Checking whether krb5_creds have flags property")
+
+# Check for MIT KDC
+if conf.CONFIG_SET('AD_DC_BUILD_IS_ENABLED'):
+    Logs.info("Looking for MIT KDC")
+    conf.DEFINE('SAMBA_USES_MITKDC', 1);
+
+    kdc_path_list = [ '/usr/sbin', '/usr/lib/mit/sbin']
+
+    if getattr(Options.options, 'with_system_mitkdc', None):
+        conf.DEFINE('MIT_KDC_PATH', '"' + Options.options.with_system_mitkdc + '"')
+    else:
+        conf.find_program('krb5kdc', path_list=kdc_path_list, var='MIT_KDC_BINARY', mandatory=True)
+        conf.DEFINE('MIT_KDC_PATH', '"' + conf.env.MIT_KDC_BINARY + '"')
-- 
2.12.2


From b8dee3f1e48021a7d8c2893dc8f6dfc6dbfd899e Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 28 Apr 2014 15:22:34 +0200
Subject: [PATCH 06/50] param: Add 'mit kdc command' to change the default.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 docs-xml/smbdotconf/security/mitkdccommand.xml | 15 +++++++++++++++
 lib/param/loadparm.c                           |  5 +++++
 source3/param/loadparm.c                       |  4 ++++
 3 files changed, 24 insertions(+)
 create mode 100644 docs-xml/smbdotconf/security/mitkdccommand.xml

diff --git a/docs-xml/smbdotconf/security/mitkdccommand.xml b/docs-xml/smbdotconf/security/mitkdccommand.xml
new file mode 100644
index 00000000000..2c7601fb5f5
--- /dev/null
+++ b/docs-xml/smbdotconf/security/mitkdccommand.xml
@@ -0,0 +1,15 @@
+<samba:parameter name="mit kdc command"
+                 context="G"
+                 type="list"
+                 advanced="1"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>This option specifies the path to the MIT kdc binary.</para>
+
+    <para>If the KDC is not installed in the default location and wasn't
+    correctly detected during build then you should moify this variable and
+    point it to the correct binary.</para>
+</description>
+
+<value type="example">/opt/mit/sbin/krb5kdc</value>
+</samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index c8a8b6d95c4..860f3e2c96c 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2732,6 +2732,11 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
 	lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
 					"%s/samba_kcc", dyn_SCRIPTSBINDIR);
+#ifdef MIT_KDC_PATH
+	lpcfg_do_global_parameter_var(lp_ctx,
+				      "mit kdc command",
+				      MIT_KDC_PATH);
+#endif
 	lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
 	lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%D/%U");
 
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 3c597ec2f40..91ecba88ad8 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -900,6 +900,10 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.samba_kcc_command = str_list_make_v3_const(NULL, s, NULL);
 	TALLOC_FREE(s);
 
+#ifdef MIT_KDC_PATH
+	Globals.mit_kdc_command = str_list_make_v3_const(NULL, MIT_KDC_PATH, NULL);
+#endif
+
 	s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
 	if (s == NULL) {
 		smb_panic("init_globals: ENOMEM");
-- 
2.12.2


From 7caa22e978f8d03a1cf38a6ae57dd43041d35fe0 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 8 Sep 2016 09:46:52 +0200
Subject: [PATCH 07/50] s4-kdc: Add a MIT Kerberos KDC service

This starts the krb5kdc binary shipped with MIT Kerberos.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/kdc-service-mit.c | 120 ++++++++++++++++++++++++++++++++++++++++++
 source4/kdc/kdc-service-mit.h |  27 ++++++++++
 source4/kdc/wscript_build     |  50 +++++++++++-------
 3 files changed, 179 insertions(+), 18 deletions(-)
 create mode 100644 source4/kdc/kdc-service-mit.c
 create mode 100644 source4/kdc/kdc-service-mit.h

diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c
new file mode 100644
index 00000000000..5ac191d3ba0
--- /dev/null
+++ b/source4/kdc/kdc-service-mit.c
@@ -0,0 +1,120 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   run s3 file server within Samba4
+
+   Copyright (c) 2014      Andreas Schneider <asn at samba.org>
+
+   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 "talloc.h"
+#include "tevent.h"
+#include "system/filesys.h"
+#include "lib/param/param.h"
+#include "lib/util/samba_util.h"
+#include "source4/smbd/service.h"
+#include "source4/smbd/process_model.h"
+#include "kdc/kdc-service-mit.h"
+#include "dynconfig.h"
+#include "libds/common/roles.h"
+
+static void mitkdc_server_done(struct tevent_req *subreq);
+
+/*
+ * Startup a copy of the krb5kdc as a child daemon
+ */
+void mitkdc_task_init(struct task_server *task)
+{
+	struct tevent_req *subreq;
+	const char * const *kdc_cmd;
+
+	task_server_set_title(task, "task[mitkdc_parent]");
+
+	switch (lpcfg_server_role(task->lp_ctx)) {
+	case ROLE_STANDALONE:
+		task_server_terminate(task,
+				      "The KDC is not required in standalone "
+				      "server configuration, terminate!",
+				      false);
+		return;
+	case ROLE_DOMAIN_MEMBER:
+		task_server_terminate(task,
+				      "The KDC is not required in member "
+				      "server configuration",
+				      false);
+		return;
+	case ROLE_ACTIVE_DIRECTORY_DC:
+		/* Yes, we want to start the KDC */
+		break;
+	}
+
+	/* start it as a child process */
+	kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
+
+	subreq = samba_runcmd_send(task,
+				   task->event_ctx,
+				   timeval_zero(),
+				   1, /* stdout log level */
+				   0, /* stderr log level */
+				   kdc_cmd,
+				   "-n", /* Don't go into background */
+#if 0
+				   "-w 2", /* Start two workers */
+#endif
+				   NULL);
+	if (subreq == NULL) {
+		DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
+
+		task_server_terminate(task,
+				      "Failed to startup mitkdc task",
+				      true);
+		return;
+	}
+
+	tevent_req_set_callback(subreq, mitkdc_server_done, task);
+
+	DEBUG(5,("Started krb5kdc process\n"));
+}
+
+/*
+ * This gets called the kdc exits.
+ */
+static void mitkdc_server_done(struct tevent_req *subreq)
+{
+	struct task_server *task =
+		tevent_req_callback_data(subreq,
+		struct task_server);
+	int sys_errno;
+	int ret;
+
+	ret = samba_runcmd_recv(subreq, &sys_errno);
+	if (ret != 0) {
+		DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
+			  sys_errno));
+	} else {
+		DEBUG(0,("The MIT KDC daemon exited normally\n"));
+	}
+
+	task_server_terminate(task, "mitkdc child process exited", true);
+}
+
+/* Called at MIT KRB5 startup - register ourselves as a server service */
+NTSTATUS server_service_mitkdc_init(void);
+
+NTSTATUS server_service_mitkdc_init(void)
+{
+	return register_server_service("kdc", mitkdc_task_init);
+}
diff --git a/source4/kdc/kdc-service-mit.h b/source4/kdc/kdc-service-mit.h
new file mode 100644
index 00000000000..2c06484705e
--- /dev/null
+++ b/source4/kdc/kdc-service-mit.h
@@ -0,0 +1,27 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   run s3 file server within Samba4
+
+   Copyright (C) Andrew Tridgell	2011
+
+   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/>.
+*/
+
+#ifndef _KDC_SERVICE_MIT_H
+#define _KDC_SERVICE_MIT_H
+
+void mitkdc_task_init(struct task_server *task);
+
+#endif /* _KDC_SERVICE_MIT_H */
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index 76efb1f02ca..b700c11ee44 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -6,24 +6,38 @@ if not bld.CONFIG_SET("USING_SYSTEM_KDC"):
 else:
     kdc_include = getattr(bld.env, "CPPPATH_KDC")
 
-bld.SAMBA_MODULE('service_kdc',
-                 source='kdc-heimdal.c',
-                 subsystem='service',
-                 init_function='server_service_kdc_init',
-                 deps='''
-                      kdc
-                      HDB_SAMBA4
-                      WDC_SAMBA4
-                      samba-hostconfig
-                      com_err
-                      samba_server_gensec
-                      PAC_GLUE
-                      KDC-GLUE
-                      KDC-SERVER
-                      KPASSWD-SERVICE
-                      KPASSWD_GLUE
-                 ''',
-                 internal_module=False)
+if bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'):
+    bld.SAMBA_MODULE('service_kdc',
+                     source='kdc-heimdal.c',
+                     subsystem='service',
+                     init_function='server_service_kdc_init',
+                     deps='''
+                          kdc
+                          HDB_SAMBA4
+                          WDC_SAMBA4
+                          samba-hostconfig
+                          com_err
+                          samba_server_gensec
+                          PAC_GLUE
+                          KDC-GLUE
+                          KDC-SERVER
+                          KPASSWD-SERVICE
+                          KPASSWD_GLUE
+                     ''',
+                     internal_module=False)
+
+if bld.CONFIG_GET('SAMBA_USES_MITKDC'):
+    bld.SAMBA_MODULE('service_kdc',
+                     source='kdc-service-mit.c',
+                     subsystem='service',
+                     init_function='server_service_mitkdc_init',
+                     deps='''
+                          samba-hostconfig
+                          service
+                          talloc
+                          UTIL_RUNCMD
+                     ''',
+                     internal_module=False)
 
 bld.SAMBA_LIBRARY('HDB_SAMBA4',
                   source='hdb-samba4.c hdb-samba4-plugin.c',
-- 
2.12.2


From ca1141680dbe8594246bdda94f529ef2b7f968c2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 8 Sep 2016 09:55:41 +0200
Subject: [PATCH 08/50] s4-kdc: Add MIT KRB5 based irpc service for PAC
 validation

Pair-Programmed-With: Guenther Deschner <gd at samba.org>
Signed-off-by: Andreas Schneider <asn at samba.org>
Signed-off-by: Guenther Deschner <gd at samba.org>
---
 source4/kdc/mit_kdc_irpc.c | 190 +++++++++++++++++++++++++++++++++++++++++++++
 source4/kdc/mit_kdc_irpc.h |  20 +++++
 source4/kdc/wscript_build  |  14 ++++
 3 files changed, 224 insertions(+)
 create mode 100644 source4/kdc/mit_kdc_irpc.c
 create mode 100644 source4/kdc/mit_kdc_irpc.h

diff --git a/source4/kdc/mit_kdc_irpc.c b/source4/kdc/mit_kdc_irpc.c
new file mode 100644
index 00000000000..63ae75e578e
--- /dev/null
+++ b/source4/kdc/mit_kdc_irpc.c
@@ -0,0 +1,190 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (c) 2015      Andreas Schneider <asn at samba.org>
+ *
+ * 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/kerberos.h"
+#include "source4/auth/kerberos/kerberos.h"
+#include "auth/kerberos/pac_utils.h"
+
+#include "librpc/gen_ndr/irpc.h"
+#include "lib/messaging/irpc.h"
+#include "source4/librpc/gen_ndr/ndr_irpc.h"
+#include "source4/librpc/gen_ndr/irpc.h"
+
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
+#include "source4/smbd/process_model.h"
+#include "lib/param/param.h"
+
+#include "samba_kdc.h"
+#include "db-glue.h"
+#include "sdb.h"
+#include "mit_kdc_irpc.h"
+
+struct mit_kdc_irpc_context {
+	struct task_server *task;
+	krb5_context krb5_context;
+	struct samba_kdc_db_context *db_ctx;
+};
+
+static NTSTATUS netr_samlogon_generic_logon(struct irpc_message *msg,
+					    struct kdc_check_generic_kerberos *r)
+{
+	struct PAC_Validate pac_validate;
+	DATA_BLOB pac_chksum;
+	struct PAC_SIGNATURE_DATA pac_kdc_sig;
+	struct mit_kdc_irpc_context *mki_ctx =
+		talloc_get_type(msg->private_data,
+				struct mit_kdc_irpc_context);
+	enum ndr_err_code ndr_err;
+	int code;
+	krb5_principal principal;
+	struct sdb_entry_ex sentry = {};
+	struct sdb_keys skeys;
+	unsigned int i;
+
+	/* There is no reply to this request */
+	r->out.generic_reply = data_blob(NULL, 0);
+
+	ndr_err = ndr_pull_struct_blob(&r->in.generic_request,
+				       msg,
+				       &pac_validate,
+				       (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
+		/*
+		 * We don't implement any other message types - such as
+		 * certificate validation - yet
+		 */
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength)
+	    || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength
+	    || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	/* PAC Checksum */
+	pac_chksum = data_blob_const(pac_validate.ChecksumAndSignature.data,
+				     pac_validate.ChecksumLength);
+
+	/* Create the krbtgt principal */
+	code = smb_krb5_make_principal(mki_ctx->krb5_context,
+				      &principal,
+				      lpcfg_realm(mki_ctx->task->lp_ctx),
+				      "krbtgt",
+				      lpcfg_realm(mki_ctx->task->lp_ctx),
+				      NULL);
+	if (code != 0) {
+		DEBUG(0, ("Failed to create krbtgt@%s principal!\n",
+			  lpcfg_realm(mki_ctx->task->lp_ctx)));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* Get the krbtgt from the DB */
+	code = samba_kdc_fetch(mki_ctx->krb5_context,
+			       mki_ctx->db_ctx,
+			       principal,
+			       SDB_F_GET_KRBTGT | SDB_F_DECRYPT,
+			       0,
+			       &sentry);
+	krb5_free_principal(mki_ctx->krb5_context, principal);
+	if (code != 0) {
+		DEBUG(0, ("Failed to fetch krbtgt@%s principal entry!\n",
+			  lpcfg_realm(mki_ctx->task->lp_ctx)));
+		return NT_STATUS_LOGON_FAILURE;
+	}
+
+	/* PAC Signature */
+	pac_kdc_sig.type = pac_validate.SignatureType;
+	pac_kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength],
+					    pac_validate.SignatureLength);
+
+	/*
+	 * Brute force variant because MIT KRB5 doesn't provide a function like
+	 * krb5_checksum_to_enctype().
+	 */
+	skeys = sentry.entry.keys;
+
+	for (i = 0; i < skeys.len; i++) {
+		krb5_keyblock krbtgt_keyblock = skeys.val[i].key;
+
+		code = check_pac_checksum(pac_chksum,
+					  &pac_kdc_sig,
+					  mki_ctx->krb5_context,
+					  &krbtgt_keyblock);
+		if (code == 0) {
+			break;
+		}
+	}
+
+	sdb_free_entry(&sentry);
+
+	if (code != 0) {
+		return NT_STATUS_LOGON_FAILURE;
+	}
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task)
+{
+	struct samba_kdc_base_context base_ctx;
+	struct mit_kdc_irpc_context *mki_ctx;
+	NTSTATUS status;
+	int code;
+
+	mki_ctx = talloc_zero(task, struct mit_kdc_irpc_context);
+	mki_ctx->task = task;
+
+	base_ctx.ev_ctx = task->event_ctx;
+	base_ctx.lp_ctx = task->lp_ctx;
+
+	/* db-glue.h */
+	status = samba_kdc_setup_db_ctx(mki_ctx,
+					&base_ctx,
+					&mki_ctx->db_ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	code = smb_krb5_init_context_basic(mki_ctx,
+					   task->lp_ctx,
+					   &mki_ctx->krb5_context);
+	if (code != 0) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	status = IRPC_REGISTER(task->msg_ctx,
+			       irpc,
+			       KDC_CHECK_GENERIC_KERBEROS,
+			       netr_samlogon_generic_logon,
+			       mki_ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	irpc_add_name(task->msg_ctx, "kdc_server");
+
+	return status;
+}
diff --git a/source4/kdc/mit_kdc_irpc.h b/source4/kdc/mit_kdc_irpc.h
new file mode 100644
index 00000000000..943c76cfb38
--- /dev/null
+++ b/source4/kdc/mit_kdc_irpc.h
@@ -0,0 +1,20 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (c) 2015      Andreas Schneider <asn at samba.org>
+ *
+ * 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/>.
+ */
+
+NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task);
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index b700c11ee44..9d8288129e3 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -143,6 +143,20 @@ bld.SAMBA_SUBSYSTEM('KPASSWD_GLUE',
         includes=kdc_include,
         deps='ldb com_err')
 
+bld.SAMBA_SUBSYSTEM('MIT_KDC_IRPC',
+                    source='mit_kdc_irpc.c',
+                    deps='''
+                    ldb
+                    auth4_sam
+                    samba-credentials
+                    db-glue
+                    samba-hostconfig
+                    com_err
+                    kdb5
+                    ''',
+                    enabled=(bld.CONFIG_SET('SAMBA_USES_MITKDC') and bld.CONFIG_SET('HAVE_KDB_H'))
+                    )
+
 bld.SAMBA_SUBSYSTEM('MIT_SAMBA',
                     source='mit_samba.c',
                     deps='''
-- 
2.12.2


From 5a8b20a41f7ca472e4aa7753fe7d4a1a28ee5ca1 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 8 Sep 2016 09:56:37 +0200
Subject: [PATCH 09/50] s4-kdc: Register the MIT irpc PAC validation service

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/kdc-service-mit.c | 12 ++++++++++++
 source4/kdc/wscript_build     |  1 +
 2 files changed, 13 insertions(+)

diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c
index 5ac191d3ba0..10b9e5f0e82 100644
--- a/source4/kdc/kdc-service-mit.c
+++ b/source4/kdc/kdc-service-mit.c
@@ -31,6 +31,8 @@
 #include "dynconfig.h"
 #include "libds/common/roles.h"
 
+#include "source4/kdc/mit_kdc_irpc.h"
+
 static void mitkdc_server_done(struct tevent_req *subreq);
 
 /*
@@ -40,6 +42,7 @@ void mitkdc_task_init(struct task_server *task)
 {
 	struct tevent_req *subreq;
 	const char * const *kdc_cmd;
+	NTSTATUS status;
 
 	task_server_set_title(task, "task[mitkdc_parent]");
 
@@ -87,6 +90,15 @@ void mitkdc_task_init(struct task_server *task)
 	tevent_req_set_callback(subreq, mitkdc_server_done, task);
 
 	DEBUG(5,("Started krb5kdc process\n"));
+
+	status = samba_setup_mit_kdc_irpc(task);
+	if (!NT_STATUS_IS_OK(status)) {
+		task_server_terminate(task,
+				      "Failed to setup kdc irpc service",
+				      true);
+	}
+
+	DEBUG(5,("Started irpc service for kdc_server\n"));
 }
 
 /*
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index 9d8288129e3..a19932cca50 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -36,6 +36,7 @@ if bld.CONFIG_GET('SAMBA_USES_MITKDC'):
                           service
                           talloc
                           UTIL_RUNCMD
+                          MIT_KDC_IRPC
                      ''',
                      internal_module=False)
 
-- 
2.12.2


From 201bba3306d6a9c18f43fa53ff1e8b24f39bc806 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 7 Oct 2015 14:36:57 +0200
Subject: [PATCH 10/50] param: Add 'mit kdc config' option to smb.conf

This points to the kdc config file created by Samba by default.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 docs-xml/smbdotconf/security/mitkdcconfig.xml | 11 +++++++++++
 source4/kdc/kdc-service-mit.c                 |  7 +++++++
 2 files changed, 18 insertions(+)
 create mode 100644 docs-xml/smbdotconf/security/mitkdcconfig.xml

diff --git a/docs-xml/smbdotconf/security/mitkdcconfig.xml b/docs-xml/smbdotconf/security/mitkdcconfig.xml
new file mode 100644
index 00000000000..013d407fe0b
--- /dev/null
+++ b/docs-xml/smbdotconf/security/mitkdcconfig.xml
@@ -0,0 +1,11 @@
+<samba:parameter name="mit kdc config"
+                 context="G"
+                 type="string"
+                 advanced="1"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>This option specifies the path to the MIT KDC config file.</para>
+</description>
+
+<value type="example">/etc/samba/kdc.conf</value>
+</samba:parameter>
diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c
index 10b9e5f0e82..a1cdd3a4471 100644
--- a/source4/kdc/kdc-service-mit.c
+++ b/source4/kdc/kdc-service-mit.c
@@ -42,6 +42,7 @@ void mitkdc_task_init(struct task_server *task)
 {
 	struct tevent_req *subreq;
 	const char * const *kdc_cmd;
+	const char *kdc_config;
 	NTSTATUS status;
 
 	task_server_set_title(task, "task[mitkdc_parent]");
@@ -64,6 +65,12 @@ void mitkdc_task_init(struct task_server *task)
 		break;
 	}
 
+	kdc_config = lpcfg_mit_kdc_config(task->lp_ctx, task);
+	if (kdc_config != NULL && kdc_config[0] != '\0') {
+		/* Do not overwrite the variable if already set! */
+		setenv("KRB5_KDC_PROFILE", kdc_config, 0);
+	}
+
 	/* start it as a child process */
 	kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
 
-- 
2.12.2


From 09066ee951c50a563d9f6048a904b997213d2b2a Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 4 Dec 2015 08:12:03 +0100
Subject: [PATCH 11/50] waf: Do not disable the ntvfs fileserver when we have
 MIT DC build

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 wscript | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/wscript b/wscript
index 032f2ae5fd2..57b87850896 100644
--- a/wscript
+++ b/wscript
@@ -190,17 +190,15 @@ def configure(conf):
         if Options.options.with_pam:
             conf.RECURSE('lib/pam_wrapper')
         if Options.options.with_ntvfs_fileserver != False:
-            if not (Options.options.without_ad_dc or Options.options.with_system_mitkrb5):
+            if not (Options.options.without_ad_dc):
                 conf.DEFINE('WITH_NTVFS_FILESERVER', 1)
         if Options.options.with_ntvfs_fileserver == False:
-            if not (Options.options.without_ad_dc or Options.options.with_system_mitkrb5):
+            if not (Options.options.without_ad_dc):
                 raise Utils.WafError('--without-ntvfs-fileserver conflicts with --enable-selftest while building the AD DC')
 
     if Options.options.with_ntvfs_fileserver == True:
         if Options.options.without_ad_dc:
             raise Utils.WafError('--with-ntvfs-fileserver conflicts with --without-ad-dc')
-        if Options.options.with_system_mitkrb5:
-            raise Utils.WafError('--with-ntvfs-fileserver conflicts with --with-system-mitkrb5')
         conf.DEFINE('WITH_NTVFS_FILESERVER', 1)
 
     if Options.options.with_pthreadpool:
-- 
2.12.2


From 5594e8d7cf59243c98895456f44a3f951f3b46ac Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 5 May 2014 13:27:58 +0200
Subject: [PATCH 12/50] selftest: Start MIT KDC if Kerberos is from MIT

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/selftest.pl | 6 ++++++
 selftest/wscript     | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index 32fc845bde5..b00ab486e87 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -49,6 +49,7 @@ my @opt_exclude = ();
 my @opt_include = ();
 my $opt_testenv = 0;
 my $opt_list = 0;
+my $opt_mitkrb5 = 0;
 my $ldap = undef;
 my $opt_resetup_env = undef;
 my $opt_load_list = undef;
@@ -246,6 +247,7 @@ my $result = GetOptions (
 		'bindir=s' => \$bindir,
 		'testenv' => \$opt_testenv,
 		'list' => \$opt_list,
+		'mitkrb5' => \$opt_mitkrb5,
 		'ldap:s' => \$ldap,
 		'resetup-environment' => \$opt_resetup_env,
 		'testlist=s' => \@testlists,
@@ -418,6 +420,10 @@ if ($opt_use_dns_faking) {
 my $target;
 my $testenv_default = "none";
 
+if ($opt_mitkrb5 == 1) {
+	$ENV{MITKRB5} = $opt_mitkrb5;
+}
+
 # After this many seconds, the server will self-terminate.  All tests
 # must terminate in this time, and testenv will only stay alive this
 # long
diff --git a/selftest/wscript b/selftest/wscript
index f35efa8e7a3..34dd7a0d1f9 100644
--- a/selftest/wscript
+++ b/selftest/wscript
@@ -230,6 +230,9 @@ def cmd_testonly(opt):
     # FIXME REMOVE ME!
     env.OPTIONS += " --use-dns-faking"
 
+    if CONFIG_GET(opt, 'USING_SYSTEM_KRB5') and CONFIG_GET(opt, 'MIT_KDC_PATH'):
+        env.OPTIONS += " --mitkrb5"
+
     if not CONFIG_GET(opt, 'HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X'):
         # older MIT krb5 libraries (< 1.14) don't have
         # GSS_KRB5_CRED_NO_CI_FLAGS_X
-- 
2.12.2


From 0bff00851605c7d7f4c797bcc2929da333fee431 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 20 Sep 2016 12:43:38 +0200
Subject: [PATCH 13/50] selftest: Disable RODC tests with MIT KDC

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/skip_mit_kdc | 3 +++
 selftest/wscript      | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 selftest/skip_mit_kdc

diff --git a/selftest/skip_mit_kdc b/selftest/skip_mit_kdc
new file mode 100644
index 00000000000..b0c901514d5
--- /dev/null
+++ b/selftest/skip_mit_kdc
@@ -0,0 +1,3 @@
+# We do not support RODC yet
+.*rodc
+.*RODC
diff --git a/selftest/wscript b/selftest/wscript
index 34dd7a0d1f9..2299195428f 100644
--- a/selftest/wscript
+++ b/selftest/wscript
@@ -231,7 +231,7 @@ def cmd_testonly(opt):
     env.OPTIONS += " --use-dns-faking"
 
     if CONFIG_GET(opt, 'USING_SYSTEM_KRB5') and CONFIG_GET(opt, 'MIT_KDC_PATH'):
-        env.OPTIONS += " --mitkrb5"
+        env.OPTIONS += " --mitkrb5 --exclude=${srcdir}/selftest/skip_mit_kdc"
 
     if not CONFIG_GET(opt, 'HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X'):
         # older MIT krb5 libraries (< 1.14) don't have
-- 
2.12.2


From 52c62016d005e12ceb2f62b6914fe4a4a7e178c4 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 30 Apr 2014 09:32:49 +0200
Subject: [PATCH 14/50] selftest: Setup configs for MIT KDC

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/target/Samba.pm  | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 selftest/target/Samba4.pm |  8 ++++++++
 2 files changed, 57 insertions(+)

diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index e53d8dc4e9e..3e5a7c3aa97 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -274,6 +274,55 @@ sub mk_realms_stanza($$$$)
         return $realms_stanza;
 }
 
+sub mk_mitkdc_conf($$)
+{
+	# samba_kdb_dir is the path to mit_samba.so
+	my ($ctx, $samba_kdb_dir) = @_;
+
+	unless (open(KDCCONF, ">$ctx->{mitkdc_conf}")) {
+	        warn("can't open $ctx->{mitkdc_conf}$?");
+		return undef;
+	}
+
+	print KDCCONF "
+# Generated kdc.conf for $ctx->{realm}
+
+[kdcdefaults]
+	kdc_ports = 88
+	kdc_tcp_ports = 88
+
+[realms]
+	$ctx->{realm} = {
+	}
+
+	$ctx->{dnsname} = {
+	}
+
+	$ctx->{domain} = {
+	}
+
+[dbmodules]
+	db_module_dir = $samba_kdb_dir
+
+	$ctx->{realm} = {
+		db_library = samba
+	}
+
+	$ctx->{dnsname} = {
+		db_library = samba
+	}
+
+	$ctx->{domain} = {
+		db_library = samba
+	}
+
+[logging]
+	kdc = FILE:$ctx->{logdir}/mit_kdc.log
+";
+
+	close(KDCCONF);
+}
+
 sub get_interface($)
 {
     my ($netbiosname) = @_;
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 30bb2552997..0d75c471de5 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -123,6 +123,9 @@ sub check_or_start($$$)
 
 		$ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG};
 		$ENV{KRB5CCNAME} = "$env_vars->{KRB5_CCACHE}.samba";
+		if (defined($ENV{MITKRB5})) {
+			$ENV{KRB5_KDC_PROFILE} = $env_vars->{MITKDC_CONFIG};
+		}
 		$ENV{SELFTEST_WINBINDD_SOCKET_DIR} = $env_vars->{SELFTEST_WINBINDD_SOCKET_DIR};
 		$ENV{NMBD_SOCKET_DIR} = $env_vars->{NMBD_SOCKET_DIR};
 
@@ -440,6 +443,7 @@ sub provision_raw_prepare($$$$$$$$$$$)
 	$ctx->{smb_conf} = "$ctx->{etcdir}/smb.conf";
 	$ctx->{krb5_conf} = "$ctx->{etcdir}/krb5.conf";
 	$ctx->{krb5_ccache} = "$prefix_abs/krb5_ccache";
+	$ctx->{mitkdc_conf} = "$ctx->{etcdir}/mitkdc.conf";
 	$ctx->{privatedir} = "$prefix_abs/private";
 	$ctx->{ncalrpcdir} = "$prefix_abs/ncalrpc";
 	$ctx->{lockdir} = "$prefix_abs/lockdir";
@@ -617,6 +621,7 @@ sub provision_raw_step1($$)
 	}
 
 	Samba::mk_krb5_conf($ctx);
+	Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared")));
 
 	open(PWD, ">$ctx->{nsswrap_passwd}");
 	if ($ctx->{unix_uid} != 0) {
@@ -680,6 +685,7 @@ nogroup:x:65534:nobody
 	my $ret = {
 		KRB5_CONFIG => $ctx->{krb5_conf},
 		KRB5_CCACHE => $ctx->{krb5_ccache},
+		MITKDC_CONFIG => $ctx->{mitkdc_conf},
 		PIDDIR => $ctx->{piddir},
 		SERVER => $ctx->{hostname},
 		SERVER_IP => $ctx->{ipv4},
@@ -1367,6 +1373,7 @@ sub provision_subdom_dc($$$)
 	}
 
 	Samba::mk_krb5_conf($ctx);
+	Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared")));
 
 	my $samba_tool =  Samba::bindir_path($self, "samba-tool");
 	my $cmd = "";
@@ -1675,6 +1682,7 @@ sub provision_rodc($$$)
 	$ctx->{kdc_ipv4} = $ret->{SERVER_IP};
 	$ctx->{kdc_ipv6} = $ret->{SERVER_IPV6};
 	Samba::mk_krb5_conf($ctx);
+	Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared")));
 
 	$ret->{RODC_DC_SERVER} = $ret->{SERVER};
 	$ret->{RODC_DC_SERVER_IP} = $ret->{SERVER_IP};
-- 
2.12.2


From a7c6719358df28210a4a2db0c8e7f91578a7ac0d Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 26 Sep 2016 18:51:33 +0200
Subject: [PATCH 15/50] selftest: Set clockskew grace time to 5 seconds

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/target/Samba.pm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index 3e5a7c3aa97..8b2e4a664b3 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -201,6 +201,10 @@ sub mk_krb5_conf($$)
  ticket_lifetime = 24h
  forwardable = yes
  allow_weak_crypto = yes
+ # Set the grace clocskew to 5 seconds
+ # This is especially required by samba3.raw.session krb5 and
+ # reauth tests
+ clockskew = 5
 
 ";
 
-- 
2.12.2


From a16c0c7f6d0386d4eb84adc1c201c12037da8516 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd at samba.org>
Date: Sat, 7 Feb 2015 12:48:54 +0100
Subject: [PATCH 16/50] s4-torture: disable s4u2self/proxy remote pac tests for
 MIT build for now.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Guenther

Signed-off-by: G√ľnther Deschner <gd at samba.org>
---
 source4/torture/rpc/remote_pac.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c
index 091309874fe..9fca10f1b08 100644
--- a/source4/torture/rpc/remote_pac.c
+++ b/source4/torture/rpc/remote_pac.c
@@ -616,6 +616,7 @@ static bool test_PACVerify_workstation_des(struct torture_context *tctx,
 
 
 /* Check various ways to get the PAC, in particular check the group membership and other details between the PAC from a normal kinit, S2U4Self and a SamLogon */
+#ifdef SAMBA4_USES_HEIMDAL
 static bool test_S2U4Self(struct torture_context *tctx,
 			  struct dcerpc_pipe *p1,
 			  struct cli_credentials *credentials,
@@ -929,6 +930,7 @@ static bool test_S2U4Self_workstation_aes(struct torture_context *tctx,
 			     TEST_MACHINE_NAME_S2U4SELF_WKSTA,
 			     NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
 }
+#endif
 
 struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
 {
@@ -954,7 +956,7 @@ struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
 	tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netlogon-member-des",
 								      &ndr_table_netlogon, TEST_MACHINE_NAME_WKSTA_DES);
 	torture_rpc_tcase_add_test_join(tcase, "verify-sig", test_PACVerify_workstation_des);
-
+#ifdef SAMBA4_USES_HEIMDAL
 	tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netr-bdc-arcfour",
 							      &ndr_table_netlogon, TEST_MACHINE_NAME_S2U4SELF_BDC);
 	torture_rpc_tcase_add_test_creds(tcase, "s2u4self-arcfour", test_S2U4Self_bdc_arcfour);
@@ -970,6 +972,6 @@ struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
 	tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-aes",
 								      &ndr_table_netlogon, TEST_MACHINE_NAME_S2U4SELF_WKSTA);
 	torture_rpc_tcase_add_test_creds(tcase, "s2u4self-aes", test_S2U4Self_workstation_aes);
-
+#endif
 	return suite;
 }
-- 
2.12.2


From 8656629ffd7d3b428ce87891203c7e2ef787a249 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 22 Apr 2015 15:19:10 +0200
Subject: [PATCH 17/50] testprogs: Fix test_chgdcpass blackbox test with MIT

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 testprogs/blackbox/test_chgdcpass.sh | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/testprogs/blackbox/test_chgdcpass.sh b/testprogs/blackbox/test_chgdcpass.sh
index 120f0024cff..3830cb4e31d 100755
--- a/testprogs/blackbox/test_chgdcpass.sh
+++ b/testprogs/blackbox/test_chgdcpass.sh
@@ -25,7 +25,9 @@ samba4bindir="$BINDIR"
 samba4srcdir="$SRCDIR/source4"
 
 samba4kinit=kinit
+heimdal=0
 if test -x $BINDIR/samba4kinit; then
+	heimdal=1
 	samba4kinit=bin/samba4kinit
 fi
 
@@ -59,7 +61,12 @@ enctype="-e $ENCTYPE"
 KRB5CCNAME="$PREFIX/tmpccache"
 export KRB5CCNAME
 rm -f $KRB5CCNAME
-testit "kinit with keytab" $samba4kinit $enctype -t $PROVDIR/private/secrets.keytab --use-keytab $USERNAME   || failed=`expr $failed + 1`
+
+if [ $heimdal -eq 1 ]; then
+	testit "kinit with keytab" $samba4kinit $enctype -t $PROVDIR/private/secrets.keytab --use-keytab $USERNAME   || failed=`expr $failed + 1`
+else
+	testit "kinit with keytab" $samba4kinit -k -t $PROVDIR/private/secrets.keytab $USERNAME || failed=`expr $failed + 1`
+fi
 
 #This is important because it puts the ticket for the old KVNO and password into a local ccache
 test_smbclient "Test login with kerberos ccache before password change" 'ls' "$unc" -k yes || failed=`expr $failed + 1`
@@ -94,8 +101,13 @@ test_drs bind "Test drs bind after 2nd password change" || failed=`expr $failed
 test_drs options "Test drs options after 2nd password change" || failed=`expr $failed + 1`
 
 #This confirms that the DC password is valid for a kinit too
-testit "kinit with keytab" $samba4kinit $enctype -t $PROVDIR/private/secrets.keytab --use-keytab $USERNAME   || failed=`expr $failed + 1`
+if [ $heimdal -eq 1 ]; then
+	testit "kinit with keytab" $samba4kinit $enctype -t $PROVDIR/private/secrets.keytab --use-keytab $USERNAME   || failed=`expr $failed + 1`
+else
+	testit "kinit with keytab" $samba4kinit -k -t $PROVDIR/private/secrets.keytab $USERNAME || failed=`expr $failed + 1`
+fi
 test_smbclient "Test login with kerberos ccache with fresh kinit" 'ls' "$unc" -k yes || failed=`expr $failed + 1`
+
 rm -f $KRB5CCNAME
 
 rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache tmpkpasswdscript
-- 
2.12.2


From 4317d6a3bdd01e6eafa92ac05c0a608f7f7a235f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 22 Apr 2015 15:39:45 +0200
Subject: [PATCH 18/50] testprogs: Fix usage printout of bogus blackbox test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 testprogs/blackbox/bogus.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testprogs/blackbox/bogus.sh b/testprogs/blackbox/bogus.sh
index be67e1992e7..3056b538aee 100755
--- a/testprogs/blackbox/bogus.sh
+++ b/testprogs/blackbox/bogus.sh
@@ -2,7 +2,7 @@
 
 if [ $# -lt 1 ]; then
 cat <<EOF
-Usage: blackbox_newuser.sh PREFIX
+Usage: bogus.sh SERVER SHARE USER PASSWORD DC_USER DC_PASSWORD SMBCLIENT
 EOF
 exit 1;
 fi
-- 
2.12.2


From a0e2cb27cae4354a68a05be03553aef35c5c8631 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 22 Apr 2015 12:00:21 +0200
Subject: [PATCH 19/50] s4-torture: Fix kinit of samba4.blackbox.locktest

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/tests/test_locktest.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/torture/tests/test_locktest.sh b/source4/torture/tests/test_locktest.sh
index c4368363536..95fc7ffc275 100755
--- a/source4/torture/tests/test_locktest.sh
+++ b/source4/torture/tests/test_locktest.sh
@@ -23,6 +23,6 @@ locktest="$samba4bindir/locktest"
 
 . `dirname $0`/../../../testprogs/blackbox/subunit.sh
 
-testit "locktest" $VALGRIND $locktest //$SERVER/test1 //$SERVER/test2 --num-ops=100  -W "$DOMAIN" -U"$USERNAME%$PASSWORD" $@ || failed=`expr $failed + 1`
+testit "locktest" $VALGRIND $locktest //$SERVER/test1 //$SERVER/test2 --num-ops=100  -W "$DOMAIN" -U"$DOMAIN\\$USERNAME%$PASSWORD" $@ || failed=`expr $failed + 1`
 
 exit $failed
-- 
2.12.2


From 8b74761d1480c579553d508ed23d8666db137241 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 14 Jan 2016 16:41:36 +0100
Subject: [PATCH 20/50] testprogs: Add test_kinit_mit.sh test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/selftest/tests.py            |   4 +
 testprogs/blackbox/test_kinit_mit.sh | 310 +++++++++++++++++++++++++++++++++++
 2 files changed, 314 insertions(+)
 create mode 100755 testprogs/blackbox/test_kinit_mit.sh

diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 8312f4886e9..798ec62bd89 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -397,6 +397,10 @@ if have_heimdal_support:
     plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external", "arcfour-hmac-md5"])
     plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4])
     plantestsuite("samba4.blackbox.kpasswd(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"])
+else:
+    plantestsuite("samba4.blackbox.kinit(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
+    plantestsuite("samba4.blackbox.kinit(fl2000dc:local)", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
+    plantestsuite("samba4.blackbox.kinit(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
 
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'forest', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2003dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'external', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
diff --git a/testprogs/blackbox/test_kinit_mit.sh b/testprogs/blackbox/test_kinit_mit.sh
new file mode 100755
index 00000000000..3e07281b8c7
--- /dev/null
+++ b/testprogs/blackbox/test_kinit_mit.sh
@@ -0,0 +1,310 @@
+#!/bin/sh
+# Blackbox tests for kinit and kerberos integration with smbclient etc
+# Copyright (c) 2015-2016 Andreas Schneider <asn at samba.org>
+
+if [ $# -lt 5 ]; then
+cat <<EOF
+Usage: test_kinit.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+PASSWORD=$3
+REALM=$4
+DOMAIN=$5
+PREFIX=$6
+smbclient=$7
+shift 7
+failed=0
+
+samba_bindir="$BINDIR"
+samba_srcdir="$SRCDIR/source4"
+samba_kinit=kinit
+samba_kdestroy=kdestroy
+samba_kpasswd=kpasswd
+
+samba_tool="$samba_bindir/samba-tool"
+samba_texpect="$samba_bindir/texpect"
+
+samba_enableaccount="$samba_tool user enable"
+machineaccountccache="$samba_srcdir/scripting/bin/machineaccountccache"
+
+ldbmodify="ldbmodify"
+if [ -x "$samba4bindir/ldbmodify" ]; then
+	ldbmodify="$samba4bindir/ldbmodify"
+fi
+
+ldbsearch="ldbsearch"
+if [ -x "$samba4bindir/ldbsearch" ]; then
+	ldbsearch="$samba4bindir/ldbsearch"
+fi
+
+. `dirname $0`/subunit.sh
+
+test_smbclient() {
+	name="$1"
+	cmd="$2"
+	shift
+	shift
+	echo "test: $name"
+	$VALGRIND $smbclient $CONFIGURATION //$SERVER/tmp -c "$cmd" $@
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "success: $name"
+	else
+		echo "failure: $name"
+	fi
+	return $status
+}
+
+ADMIN_LDBMODIFY_CONFIG="-H ldap://$SERVER -U$USERNAME%$PASSWORD"
+export ADMIN_LDBMODIFY_CONFIG
+
+KRB5CCNAME_PATH="$PREFIX/tmpccache"
+KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
+ADMIN_KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
+export KRB5CCNAME
+rm -rf $KRB5CCNAME_PATH
+
+testit "reset password policies beside of minimum password age of 0 days" $VALGRIND $samba_tool domain passwordsettings $ADMIN_LDBMODIFY_CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=0 --max-pwd-age=default || failed=`expr $failed + 1`
+
+cat > $PREFIX/tmpkinitscript <<EOF
+expect Password for
+send ${PASSWORD}\n
+EOF
+
+###########################################################
+### Test kinit defaults
+###########################################################
+
+testit "kinit with password" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit $USERNAME@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+testit "kinit renew ticket" $samba_kinit -R   || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### Test kinit with enterprice principal
+###########################################################
+
+testit "kinit with password (enterprise style)" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit -E $USERNAME@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+# This does not work with MIT Kerberos 1.14 or older
+testit "kinit renew ticket (enterprise style)" $samba_kinit -R   || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### Tests with kinit default again
+###########################################################
+
+testit "kinit with password" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit $USERNAME@$REALM   || failed=`expr $failed + 1`
+testit "check time with kerberos ccache" $VALGRIND $samba_tool time $SERVER $CONFIGURATION -k yes $@ || failed=`expr $failed + 1`
+
+USERPASS="testPass at 12%"
+
+testit "add user with kerberos ccache" $VALGRIND $samba_tool user create nettestuser $USERPASS $CONFIGURATION  -k yes $@ || failed=`expr $failed + 1`
+
+echo "Getting defaultNamingContext"
+BASEDN=`$ldbsearch $options --basedn='' -H ldap://$SERVER -s base DUMMY=x defaultNamingContext | grep defaultNamingContext | awk '{print $2}'`
+
+cat > $PREFIX/tmpldbmodify <<EOF
+dn: cn=nettestuser,cn=users,$BASEDN
+changetype: modify
+add: servicePrincipalName
+servicePrincipalName: host/nettestuser
+replace: userPrincipalName
+userPrincipalName: nettest@$REALM
+EOF
+
+testit "modify servicePrincipalName and userPrincpalName" $VALGRIND $ldbmodify -H ldap://$SERVER $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1`
+
+testit "set user password with kerberos ccache" $VALGRIND $samba_tool user setpassword nettestuser --newpassword=$USERPASS $CONFIGURATION  -k yes $@ || failed=`expr $failed + 1`
+
+testit "enable user with kerberos cache" $VALGRIND $samba_enableaccount nettestuser -H ldap://$SERVER -k yes $@ || failed=`expr $failed + 1`
+
+###########################################################
+### Test kinit with user credentials
+###########################################################
+
+KRB5CCNAME_PATH="$PREFIX/tmpuserccache"
+KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
+export KRB5CCNAME
+
+rm -f $KRB5CCNAME_PATH
+
+cat > $PREFIX/tmpkinituserpassscript <<EOF
+expect Password for
+send ${USERPASS}\n
+EOF
+
+testit "kinit with user password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+### Change password
+
+NEWUSERPASS="testPaSS at 34%"
+testit "change user password with 'samba-tool user password' (rpc)" $VALGRIND $samba_tool user password -W$DOMAIN -Unettestuser%$USERPASS $CONFIGURATION -k no --newpassword=$NEWUSERPASS $@ || failed=`expr $failed + 1`
+
+cat > $PREFIX/tmpkinituserpassscript <<EOF
+expect Password for
+send ${NEWUSERPASS}\n
+EOF
+
+testit "kinit with new user password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### Test kinit with user credentials in special formats
+###########################################################
+
+testit "kinit with new (NT-Principal style) using UPN" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettest@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache from NT UPN" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+testit "kinit with new (enterprise style) using UPN" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit -E nettest@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache from enterprise UPN" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### Test kinit with user credentials and changed realm
+###########################################################
+
+cat > $PREFIX/tmpldbmodify <<EOF
+dn: cn=nettestuser,cn=users,$BASEDN
+changetype: modify
+replace: userPrincipalName
+userPrincipalName: nettest@$REALM.org
+EOF
+
+testit "modify userPrincipalName to be a different domain" $VALGRIND $ldbmodify $ADMIN_LDBMODIFY_CONFIG $PREFIX/tmpldbmodify $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1`
+
+testit "kinit with new (enterprise style) using UPN" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit -E nettest@$REALM.org   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache from enterprise UPN" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### Test password change with kpasswd
+###########################################################
+
+testit "kinit with user password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+USERPASS=$NEWUSERPASS
+NEWUSERPASS=testPaSS at 56%
+
+cat > $PREFIX/tmpkpasswdscript <<EOF
+expect Password for
+password ${USERPASS}\n
+expect Enter new password
+send ${NEWUSERPASS}\n
+expect Enter it again
+send ${NEWUSERPASS}\n
+expect Password changed
+EOF
+
+testit "change user password with kpasswd" $samba_texpect $PREFIX/tmpkpasswdscript $samba_kpasswd nettestuser@$REALM || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+USERPASS=$NEWUSERPASS
+cat > $PREFIX/tmpkinituserpassscript <<EOF
+expect Password for
+send ${USERPASS}\n
+EOF
+
+testit "kinit with user password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+###########################################################
+### TODO Test set password with kpasswd
+###########################################################
+
+# This is not implemented in kpasswd
+
+###########################################################
+### Test password expiry
+###########################################################
+
+cat > $PREFIX/tmpldbmodify <<EOF
+dn: cn=nettestuser,cn=users,$BASEDN
+changetype: modify
+replace: pwdLastSet
+pwdLastSet: 0
+EOF
+
+USERPASS=$NEWUSERPASS
+NEWUSERPASS=testPaSS at 911%
+
+testit "modify pwdLastSet" $VALGRIND $ldbmodify $ADMIN_LDBMODIFY_CONFIG $PREFIX/tmpldbmodify $PREFIX/tmpldbmodify -k yes $@ || failed=`expr $failed + 1`
+
+cat > $PREFIX/tmpkinituserpassscript <<EOF
+expect Password for
+send ${USERPASS}\n
+expect Password expired.  You must change it now.
+expect Enter new password
+send ${NEWUSERPASS}\n
+expect Enter it again
+send ${NEWUSERPASS}\n
+EOF
+
+testit "kinit (MIT) with user password for expired password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+USERPASS=$NEWUSERPASS
+cat > $PREFIX/tmpkinituserpassscript <<EOF
+expect Password for
+send ${USERPASS}\n
+EOF
+
+testit "kinit with user password" $samba_texpect $PREFIX/tmpkinituserpassscript $samba_kinit nettestuser@$REALM   || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+###########################################################
+### Test login with lowercase realm
+###########################################################
+
+KRB5CCNAME_PATH="$PREFIX/tmpccache"
+KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
+export KRB5CCNAME
+
+rm -rf $KRB5CCNAME_PATH
+
+lowerrealm=$(echo $REALM | tr '[A-Z]' '[a-z]')
+test_smbclient "Test login with user kerberos lowercase realm" 'ls' -k yes -Unettestuser@$lowerrealm%$NEWUSERPASS || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos lowercase realm 2" 'ls' -k yes -Unettestuser@$REALM%$NEWUSERPASS --realm=$lowerrealm || failed=`expr $failed + 1`
+
+testit "del user with kerberos ccache" $VALGRIND $samba_tool user delete nettestuser $CONFIGURATION -k yes $@ || failed=`expr $failed + 1`
+
+###########################################################
+### Test login with machine account
+###########################################################
+
+rm -f $KRB5CCNAME_PATH
+testit "kinit with machineaccountccache script" $machineaccountccache $CONFIGURATION $KRB5CCNAME || failed=`expr $failed + 1`
+test_smbclient "Test machine account login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+testit "reset password policies" $VALGRIND $samba_tool domain passwordsettings $ADMIN_LDBMODIFY_CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1`
+
+### Cleanup
+
+$samba_kdestroy
+
+rm -f $KRB5CCNAME_PATH
+rm -f $PREFIX/tmpkinituserpassscript
+rm -f $PREFIX/tmpkinitscript
+
+exit $failed
-- 
2.12.2


From 21d99ee7bacb7a1e32a0f2f0eb1bb4495d19649c Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 15 Feb 2016 08:22:58 +0100
Subject: [PATCH 21/50] testprogs: Add a kinit trust test for MIT KDC

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/selftest/tests.py                   |   3 +
 testprogs/blackbox/test_kinit_trusts_mit.sh | 139 ++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+)
 create mode 100755 testprogs/blackbox/test_kinit_trusts_mit.sh

diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 798ec62bd89..b94d1edc4ce 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -401,11 +401,14 @@ else:
     plantestsuite("samba4.blackbox.kinit(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
     plantestsuite("samba4.blackbox.kinit(fl2000dc:local)", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
     plantestsuite("samba4.blackbox.kinit(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
+    plantestsuite("samba4.blackbox.kinit_trust(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
+    plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
 
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'forest', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2003dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'external', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
 plantestsuite("samba4.blackbox.trust_ntlm", "ad_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
 plantestsuite("samba4.blackbox.trust_ntlm", "nt4_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$DOMAIN', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
+
 plantestsuite("samba4.blackbox.trust_utils(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
 plantestsuite("samba4.blackbox.trust_utils(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
 plantestsuite("samba4.blackbox.ktpass(ad_dc_ntvfs)", "ad_dc_ntvfs", [os.path.join(bbdir, "test_ktpass.sh"), '$PREFIX/ad_dc_ntvfs'])
diff --git a/testprogs/blackbox/test_kinit_trusts_mit.sh b/testprogs/blackbox/test_kinit_trusts_mit.sh
new file mode 100755
index 00000000000..6696f441363
--- /dev/null
+++ b/testprogs/blackbox/test_kinit_trusts_mit.sh
@@ -0,0 +1,139 @@
+#!/bin/sh
+# Blackbox tests for kinit and trust validation
+# Copyright (c) 2015 Stefan Metzmacher <metze at samba.org>
+# Copyright (c) 2016 Andreas Schneider <asn at samba.org>
+
+if [ $# -lt 5 ]; then
+cat <<EOF
+Usage: test_kinit_trusts.sh SERVER USERNAME PASSWORD REALM DOMAIN TRUST_USERNAME TRUST_PASSWORD TRUST_REALM TRUST_DOMAIN PREFIX TYPE
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+PASSWORD=$3
+REALM=$4
+DOMAIN=$5
+shift 5
+TRUST_SERVER=$1
+TRUST_USERNAME=$2
+TRUST_PASSWORD=$3
+TRUST_REALM=$4
+TRUST_DOMAIN=$5
+shift 5
+PREFIX=$1
+TYPE=$2
+shift 2
+
+failed=0
+
+samba_bindir="$BINDIR"
+samba_srcdir="$SRCDIR/source4"
+samba_kinit=kinit
+samba_kdestroy=kdestroy
+samba_kpasswd=kpasswd
+
+samba_tool="$samba_bindir/samba-tool"
+samba_texpect="$samba_bindir/texpect"
+
+smbclient="$samba_bindir/smbclient"
+wbinfo="$samba_bindir/wbinfo"
+rpcclient="$samba_bindir/rpcclient"
+
+SMBCLIENT_UNC="//$SERVER.$REALM/tmp"
+
+. `dirname $0`/subunit.sh
+
+test_smbclient() {
+	name="$1"
+	cmd="$2"
+	shift
+	shift
+	echo "test: $name"
+	$VALGRIND $smbclient $CONFIGURATION $SMBCLIENT_UNC -c "$cmd" $@
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "success: $name"
+	else
+		echo "failure: $name"
+	fi
+	return $status
+}
+
+KRB5CCNAME_PATH="$PREFIX/test_kinit_trusts_ccache"
+KRB5CCNAME="FILE:$KRB5CCNAME_PATH"
+export KRB5CCNAME
+rm -rf $KRB5CCNAME_PATH
+
+cat > $PREFIX/tmpkinitscript <<EOF
+expect Password for
+send ${TRUST_PASSWORD}\n
+EOF
+
+###########################################################
+### Test incoming trust direction
+###########################################################
+
+testit "kinit with password" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+$samba_kdestroy
+
+smbclient="$samba_bindir/smbclient4"
+
+testit "kinit with password" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache (smbclient4)" 'ls' -k yes || failed=`expr $failed + 1`
+$samba_kdestroy
+
+smbclient="$samba_bindir/smbclient"
+
+testit "kinit with password (enterprise)" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit -E $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+if test x"${TYPE}" = x"forest" ;then
+    testit "kinit with password (enterprise UPN)" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit -E testdenied_upn@${TRUST_REALM}.upn || failed=`expr $failed + 1`
+    test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+fi
+
+$samba_kdestroy
+
+testit "kinit with password (enterprise)" $samba_texpect $PREFIX/tmpkinitscript $samba_kinit -E $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+testit "kinit renew ticket" $samba_kinit -R
+test_smbclient "Test login with kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+
+testit "check time with kerberos ccache" $VALGRIND $samba_tool time $SERVER.$REALM $CONFIGURATION -k yes $@ || failed=`expr $failed + 1`
+
+$samba_kdestroy
+
+lowerrealm=$(echo $TRUST_REALM | tr '[A-Z]' '[a-z]')
+test_smbclient "Test login with user kerberos lowercase realm" 'ls' -k yes -d5 -U$TRUST_USERNAME@$lowerrealm%$TRUST_PASSWORD || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos lowercase realm 2" 'ls' -k yes -U$TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD --realm=$lowerrealm || failed=`expr $failed + 1`
+
+###########################################################
+### Test outgoing trust direction
+###########################################################
+
+SMBCLIENT_UNC="//$TRUST_SERVER.$TRUST_REALM/tmp"
+test_smbclient "Test user login with the first outgoing secret" 'ls' -k yes -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1`
+
+testit_expect_failure "setpassword should not work" $VALGRIND $samba_tool user setpassword "${TRUST_DOMAIN}\$" --random-password || failed=`expr $failed + 1`
+
+testit "wbinfo ping dc" $VALGRIND $wbinfo --ping-dc --domain=$TRUST_DOMAIN || failed=`expr $failed + 1`
+testit "wbinfo change outgoing trust pw" $VALGRIND $wbinfo --change-secret --domain=$TRUST_DOMAIN || failed=`expr $failed + 1`
+testit "wbinfo check outgoing trust pw" $VALGRIND $wbinfo --check-secret --domain=$TRUST_DOMAIN || failed=`expr $failed + 1`
+
+test_smbclient "Test user login with the changed outgoing secret" 'ls' -k yes -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1`
+
+### Cleanup
+
+$samba_kdestroy
+
+rm -f $KRB5CCNAME_PATH
+rm -f $PREFIX/tmpkinituserpassscript
+rm -f $PREFIX/tmpkinitscript
+
+exit $failed
-- 
2.12.2


From 737eb5b7cfe714997f3ec7ad9fdaa8485ee2811d Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 10 Mar 2016 14:35:23 +0100
Subject: [PATCH 22/50] testprogs: Add test with exported keytab from
 samba-tool

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/selftest/tests.py                    |   1 +
 testprogs/blackbox/test_export_keytab_mit.sh | 127 +++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)
 create mode 100755 testprogs/blackbox/test_export_keytab_mit.sh

diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index b94d1edc4ce..b7ac0c5f5f7 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -403,6 +403,7 @@ else:
     plantestsuite("samba4.blackbox.kinit(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration])
     plantestsuite("samba4.blackbox.kinit_trust(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
     plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
+    plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_mit.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4])
 
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'forest', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2003dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'external', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
diff --git a/testprogs/blackbox/test_export_keytab_mit.sh b/testprogs/blackbox/test_export_keytab_mit.sh
new file mode 100755
index 00000000000..b972cd8f1c4
--- /dev/null
+++ b/testprogs/blackbox/test_export_keytab_mit.sh
@@ -0,0 +1,127 @@
+#!/bin/sh
+#
+# Blackbox tests for an exported keytab with kinit
+#
+# Copyright (C) 2006-2007 Jelmer Vernooij <jelmer at samba.org>
+# Copyright (C) 2006-2008 Andrew Bartlett <abartlet at samba.org>
+# Copyright (C) 2016      Andreas Schneider <asn at cryptomilk.org>
+
+if [ $# -lt 5 ]; then
+cat <<EOF
+Usage: test_extract_keytab.sh SERVER USERNAME REALM DOMAIN PREFIX SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+REALM=$3
+DOMAIN=$4
+PREFIX=$5
+smbclient=$6
+shift 6
+failed=0
+
+samba_bindir="$BINDIR"
+samba_tool="$samba_bindir/samba-tool"
+samba_newuser="$samba_tool user create"
+samba_texpect="$samba_bindir/texpect"
+samba_ktutil="$BINDIR/samba4ktutil"
+
+samba_kinit=kinit
+samba_kdestroy=kdestroy
+
+SERVER_FQDN="$SERVER.$(echo $REALM | tr '[:upper:]' '[:lower:]')"
+
+source `dirname $0`/subunit.sh
+
+test_smbclient() {
+	name="$1"
+	cmd="$2"
+	shift
+	shift
+	echo "test: $name"
+	$VALGRIND $smbclient //$SERVER/tmp -c "$cmd" $@
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "success: $name"
+	else
+		echo "failure: $name"
+	fi
+	return $status
+}
+
+test_keytab() {
+	testname="$1"
+	keytab="$2"
+	principal="$3"
+	expected_nkeys="$4"
+
+	echo "test: $testname"
+
+	NKEYS=$($VALGRIND $samba_ktutil $keytab | grep -i "$principal" | egrep -c "DES|AES|ArcFour")
+	status=$?
+	if [ x$status != x0 ]; then
+		echo "failure: $testname"
+		return $status
+	fi
+
+	if [ x$NKEYS != x$expected_nkeys ] ; then
+		echo "failure: $testname"
+		return 1
+	fi
+	echo "success: $testname"
+	return 0
+}
+
+TEST_USER=nettestuser
+TEST_PASSWORD=testPaSS at 01%
+
+testit "create local user $TEST_USER" $VALGRIND $samba_newuser $TEST_USER $TEST_PASSWORD $@ || failed=`expr $failed + 1`
+
+testit "dump keytab from domain" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-all $@ || failed=`expr $failed + 1`
+test_keytab "read keytab from domain" "$PREFIX/tmpkeytab-all" "$SERVER\\\$" 5
+
+testit "dump keytab from domain (2nd time)" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-all $@ || failed=`expr $failed + 1`
+test_keytab "read keytab from domain (2nd time)" "$PREFIX/tmpkeytab-all" "$SERVER\\\$" 5
+
+testit "dump keytab from domain for cifs service principal" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-server --principal=cifs/$SERVER_FQDN $@ || failed=`expr $failed + 1`
+test_keytab "read keytab from domain for cifs service principal" "$PREFIX/tmpkeytab-server" "cifs/$SERVER_FQDN" 5
+testit "dump keytab from domain for cifs service principal (2nd time)" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-server --principal=cifs/$SERVER_FQDN $@ || failed=`expr $failed + 1`
+test_keytab "read keytab from domain for cifs service principal (2nd time)" "$PREFIX/tmpkeytab-server" "cifs/$SERVER_FQDN" 5
+
+testit "dump keytab from domain for user principal" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-user-princ --principal=$TEST_USER $@ || failed=`expr $failed + 1`
+test_keytab "dump keytab from domain for user principal" "$PREFIX/tmpkeytab-user-princ" "$TEST_USER@$REALM" 5
+testit "dump keytab from domain for user principal (2nd time)" $VALGRIND $samba_tool domain exportkeytab $PREFIX/tmpkeytab-user-princ --principal=$TEST_USER@$REALM $@ || failed=`expr $failed + 1`
+test_keytab "dump keytab from domain for user principal (2nd time)" "$PREFIX/tmpkeytab-user-princ" "$TEST_USER@$REALM" 5
+
+KRB5CCNAME="$PREFIX/tmpuserccache"
+export KRB5CCNAME
+
+testit "kinit with keytab as user" $VALGRIND $samba_kinit -k -t $PREFIX/tmpkeytab-all $TEST_USER@$REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
+$samba_kdestroy
+
+testit "kinit with keytab as user (one princ)" $VALGRIND $samba_kinit -k -t $PREFIX/tmpkeytab-user-princ $TEST_USER@$REALM || failed=`expr $failed + 1`
+test_smbclient "Test login with user kerberos ccache (one princ)" 'ls' -k yes || failed=`expr $failed + 1`
+$samba_kdestroy
+
+KRB5CCNAME="$PREFIX/tmpadminccache"
+export KRB5CCNAME
+
+testit "kinit with keytab as $USERNAME" $VALGRIND $samba_kinit -k -t $PREFIX/tmpkeytab-all $USERNAME@$REALM || failed=`expr $failed + 1`
+
+KRB5CCNAME="$PREFIX/tmpserverccache"
+export KRB5CCNAME
+echo "$samba_kinit -k -t $PREFIX/tmpkeytab-server cifs/$SERVER_FQDN"
+testit "kinit with SPN from keytab" $VALGRIND $samba_kinit -k -t $PREFIX/tmpkeytab-server cifs/$SERVER_FQDN || failed=`expr $failed + 1`
+
+exit 0
+
+# cleanup
+testit "delete user $TEST_USER" $VALGRIND $samba_tool user delete nettestuser -k yes $@ || failed=`expr $failed + 1`
+
+$samba_kdestroy
+rm -f $PREFIX/tmpadminccache $PREFIX/tmpuserccache $PREFIX/tmpkeytab $PREFIX/tmpkeytab-2 $PREFIX/tmpkeytab-server
+
+exit $failed
-- 
2.12.2


From c133824b27bce3a97f1abec64082e01c8093746f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 13 May 2016 09:36:34 +0200
Subject: [PATCH 23/50] s4-torture: Add KDC test harness and first test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/krb5/kdc-mit.c | 347 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 343 insertions(+), 4 deletions(-)

diff --git a/source4/torture/krb5/kdc-mit.c b/source4/torture/krb5/kdc-mit.c
index 882627eb6f3..dfb32019ceb 100644
--- a/source4/torture/krb5/kdc-mit.c
+++ b/source4/torture/krb5/kdc-mit.c
@@ -1,4 +1,3 @@
-
 /*
    Unix SMB/CIFS implementation.
 
@@ -31,13 +30,339 @@
 #include "source4/auth/kerberos/kerberos_util.h"
 #include "lib/util/util_net.h"
 
-static bool test_skip(struct torture_context *tctx)
+#define krb5_is_app_tag(dat,tag)                          \
+	((dat != NULL) && (dat)->length &&                \
+	 ((((dat)->data[0] & ~0x20) == ((tag) | 0x40))))
+
+#define krb5_is_as_req(dat)                   krb5_is_app_tag(dat, 10)
+#define krb5_is_as_rep(dat)                   krb5_is_app_tag(dat, 11)
+#define krb5_is_krb_error(dat)                krb5_is_app_tag(dat, 30)
+
+enum torture_krb5_test {
+	TORTURE_KRB5_TEST_PLAIN,
+	TORTURE_KRB5_TEST_PAC_REQUEST,
+	TORTURE_KRB5_TEST_BREAK_PW,
+	TORTURE_KRB5_TEST_CLOCK_SKEW,
+};
+
+struct torture_krb5_context {
+	struct torture_context *tctx;
+	krb5_context krb5_context;
+	enum torture_krb5_test test;
+	int recv_packet_count;
+	krb5_kdc_req *as_req;
+	krb5_kdc_rep *as_rep;
+};
+
+krb5_error_code decode_krb5_error(const krb5_data *output, krb5_error **rep);
+
+krb5_error_code decode_krb5_as_req(const krb5_data *output, krb5_kdc_req **req);
+krb5_error_code decode_krb5_as_rep(const krb5_data *output, krb5_kdc_rep **rep);
+
+void krb5_free_kdc_req(krb5_context ctx, krb5_kdc_req *req);
+void krb5_free_kdc_rep(krb5_context ctx, krb5_kdc_rep *rep);
+
+static bool torture_check_krb5_as_req(struct torture_krb5_context *test_context,
+				      krb5_context context,
+				      const krb5_data *message)
+{
+	krb5_error_code code;
+	int nktypes;
+
+	code = decode_krb5_as_req(message, &test_context->as_req);
+	torture_assert_int_equal(test_context->tctx,
+				 code, 0,
+				 "decode_as_req failed");
+	torture_assert_int_equal(test_context->tctx,
+				 test_context->as_req->msg_type,
+				 KRB5_AS_REQ,
+				 "Not a AS REQ");
+
+	nktypes = test_context->as_req->nktypes;
+	torture_assert_int_not_equal(test_context->tctx,
+				     nktypes, 0,
+				     "No keytypes");
+
+	return true;
+}
+
+static krb5_error_code torture_krb5_pre_send_test(krb5_context context,
+						  void *data,
+						  const krb5_data *realm,
+						  const krb5_data *message,
+						  krb5_data **new_message_out,
+						  krb5_data **new_reply_out)
+{
+	bool ok;
+	struct torture_krb5_context *test_context =
+		(struct torture_krb5_context *)data;
+
+	switch (test_context->test)
+	{
+	case TORTURE_KRB5_TEST_PLAIN:
+	case TORTURE_KRB5_TEST_PAC_REQUEST:
+	case TORTURE_KRB5_TEST_BREAK_PW:
+	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		ok = torture_check_krb5_as_req(test_context,
+					       context,
+					       message);
+		if (!ok) {
+			return KRB5KDC_ERR_BADOPTION;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * We need these function to validate packets because our torture macros
+ * do a 'return false' on error.
+ */
+static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
+				     krb5_context context,
+				     const krb5_data *reply,
+				     krb5_error_code error_code)
+
 {
-	torture_skip(tctx, "Skip kdc tests with MIT Kerberos");
+	krb5_error *krb_error;
+	krb5_error_code code;
+
+	code = decode_krb5_error(reply, &krb_error);
+	torture_assert_int_equal(test_context->tctx,
+				 code,
+				 0,
+				 "decode_krb5_error failed");
+
+	torture_assert_int_equal(test_context->tctx,
+				 krb_error->error,
+				 error_code - KRB5KDC_ERR_NONE,
+				 "Got wrong error code");
+
+	krb5_free_error(context, krb_error);
 
 	return true;
 }
 
+static bool torture_check_krb5_as_rep(struct torture_krb5_context *test_context,
+				      krb5_context context,
+				      const krb5_data *reply)
+{
+	krb5_error_code code;
+	bool ok;
+
+	code = decode_krb5_as_rep(reply, &test_context->as_rep);
+	torture_assert_int_equal(test_context->tctx,
+				 code,
+				 0,
+				 "decode_krb5_as_rep failed");
+
+	torture_assert(test_context->tctx,
+		       test_context->as_rep->ticket->enc_part.kvno,
+		       "No KVNO set");
+
+	ok = torture_setting_bool(test_context->tctx,
+				  "expect_cached_at_rodc",
+				  false);
+	if (ok) {
+		torture_assert_int_not_equal(test_context->tctx,
+					     test_context->as_rep->ticket->enc_part.kvno & 0xFFFF0000,
+					     0,
+					     "Did not get a RODC number in the KVNO");
+	} else {
+		torture_assert_int_equal(test_context->tctx,
+					 test_context->as_rep->ticket->enc_part.kvno & 0xFFFF0000,
+					 0,
+					 "Unexpecedly got a RODC number in the KVNO");
+	}
+
+	return true;
+}
+
+static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
+						   void *data,
+						   krb5_error_code kdc_code,
+						   const krb5_data *realm,
+						   const krb5_data *message,
+						   const krb5_data *reply,
+						   krb5_data **new_reply_out)
+{
+	struct torture_krb5_context *test_context =
+		(struct torture_krb5_context *)data;
+	krb5_error_code code;
+	bool ok = true;
+
+	torture_comment(test_context->tctx,
+			"PACKET COUNT = %d\n",
+			test_context->recv_packet_count);
+
+	torture_comment(test_context->tctx,
+			"KRB5_AS_REP = %d\n",
+			krb5_is_as_req(reply));
+
+	torture_comment(test_context->tctx,
+			"KRB5_ERROR = %d\n",
+			krb5_is_krb_error(reply));
+
+	torture_comment(test_context->tctx,
+			"KDC ERROR CODE = %d\n",
+			kdc_code);
+
+	switch (test_context->test)
+	{
+	case TORTURE_KRB5_TEST_PLAIN:
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		} else {
+			ok = torture_check_krb5_as_rep(test_context,
+						       context,
+						       reply);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_as_rep failed");
+		}
+
+		torture_assert_goto(test_context->tctx,
+				    test_context->recv_packet_count < 2,
+				    ok,
+				    out,
+				    "Too many packets");
+
+		break;
+	case TORTURE_KRB5_TEST_PAC_REQUEST:
+	case TORTURE_KRB5_TEST_BREAK_PW:
+	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		break;
+	}
+
+	code = kdc_code;
+out:
+	if (!ok) {
+		code = EINVAL;
+	}
+
+	/* Cleanup */
+	krb5_free_kdc_req(test_context->krb5_context, test_context->as_req);
+	krb5_free_kdc_rep(test_context->krb5_context, test_context->as_rep);
+
+	test_context->recv_packet_count++;
+
+	return code;
+}
+
+static bool torture_krb5_init_context(struct torture_context *tctx,
+				      enum torture_krb5_test test,
+				      struct smb_krb5_context **smb_krb5_context)
+{
+	krb5_error_code code;
+
+	struct torture_krb5_context *test_context = talloc_zero(tctx,
+								struct torture_krb5_context);
+	torture_assert(tctx, test_context != NULL, "Failed to allocate");
+
+	test_context->test = test;
+	test_context->tctx = tctx;
+
+	code = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context);
+	torture_assert_int_equal(tctx, code, 0, "smb_krb5_init_context failed");
+
+	test_context->krb5_context = (*smb_krb5_context)->krb5_context;
+
+	krb5_set_kdc_send_hook((*smb_krb5_context)->krb5_context,
+			       torture_krb5_pre_send_test,
+			       test_context);
+
+	krb5_set_kdc_recv_hook((*smb_krb5_context)->krb5_context,
+			       torture_krb5_post_recv_test,
+			       test_context);
+
+	return true;
+}
+static bool torture_krb5_as_req_creds(struct torture_context *tctx,
+				      struct cli_credentials *credentials,
+				      enum torture_krb5_test test)
+{
+	krb5_get_init_creds_opt *krb_options = NULL;
+	struct smb_krb5_context *smb_krb5_context;
+	enum credentials_obtained obtained;
+	const char *error_string;
+	const char *password;
+	krb5_principal principal;
+	krb5_error_code code;
+	krb5_creds my_creds;
+	bool ok;
+
+	ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
+	torture_assert(tctx, ok, "torture_krb5_init_context failed");
+
+	code = principal_from_credentials(tctx,
+					  credentials,
+					  smb_krb5_context,
+					  &principal,
+					  &obtained,
+					  &error_string);
+	torture_assert_int_equal(tctx, code, 0, error_string);
+
+	switch (test)
+	{
+	case TORTURE_KRB5_TEST_PLAIN:
+	case TORTURE_KRB5_TEST_PAC_REQUEST:
+	case TORTURE_KRB5_TEST_BREAK_PW:
+	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		break;
+	}
+
+	password = cli_credentials_get_password(credentials);
+
+	code = krb5_get_init_creds_password(smb_krb5_context->krb5_context,
+					    &my_creds,
+					    principal,
+					    password,
+					    NULL,
+					    NULL,
+					    0,
+					    NULL,
+					    krb_options);
+	krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context,
+				     krb_options);
+
+	switch (test)
+	{
+	case TORTURE_KRB5_TEST_PLAIN:
+	case TORTURE_KRB5_TEST_PAC_REQUEST:
+		torture_assert_int_equal(tctx,
+					 code,
+					 0,
+					 "krb5_get_init_creds_password failed");
+		break;
+	case TORTURE_KRB5_TEST_BREAK_PW:
+	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		break;
+	}
+
+	krb5_free_cred_contents(smb_krb5_context->krb5_context,
+				&my_creds);
+
+	return true;
+}
+
+static bool torture_krb5_as_req_cmdline(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_PLAIN);
+}
+
 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite =
@@ -46,8 +371,22 @@ NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 	suite->description = talloc_strdup(suite, "Kerberos tests");
 	kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests");
 
-	torture_suite_add_simple_test(kdc_suite, "skip", test_skip);
+	torture_suite_add_simple_test(kdc_suite,
+				      "as-req-cmdline",
+				      torture_krb5_as_req_cmdline);
+
+#if 0
+	torture_suite_add_simple_test(kdc_suite, "as-req-pac-request",
+				      torture_krb5_as_req_pac_request);
+
+	torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
+				      torture_krb5_as_req_break_pw);
+
+	torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
+				      torture_krb5_as_req_clock_skew);
 
+	torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
+#endif
 	torture_suite_add_suite(suite, kdc_suite);
 
 	torture_register_suite(suite);
-- 
2.12.2


From 5865fed2cb22a88884dacdd9b74f7856adae867a Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 4 Jul 2016 11:35:19 +0200
Subject: [PATCH 24/50] s4-torture: Add TORTURE_KRB5_TEST_PAC_REQUEST test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/krb5/kdc-mit.c | 84 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/source4/torture/krb5/kdc-mit.c b/source4/torture/krb5/kdc-mit.c
index dfb32019ceb..073d5c69380 100644
--- a/source4/torture/krb5/kdc-mit.c
+++ b/source4/torture/krb5/kdc-mit.c
@@ -240,6 +240,53 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 
 		break;
 	case TORTURE_KRB5_TEST_PAC_REQUEST:
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KRB_ERR_RESPONSE_TOO_BIG);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		} else if (test_context->recv_packet_count == 1) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		} else if (krb5_is_krb_error(reply)) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KRB_ERR_RESPONSE_TOO_BIG);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		} else {
+			ok = torture_check_krb5_as_rep(test_context,
+						       context,
+						       reply);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_as_rep failed");
+		}
+
+		torture_assert_goto(test_context->tctx,
+				    test_context->recv_packet_count < 3,
+				    ok,
+				    out,
+				    "Too many packets");
+		break;
 	case TORTURE_KRB5_TEST_BREAK_PW:
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
 		break;
@@ -316,7 +363,23 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 	switch (test)
 	{
 	case TORTURE_KRB5_TEST_PLAIN:
+		break;
 	case TORTURE_KRB5_TEST_PAC_REQUEST:
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
+		code = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
+						     &krb_options);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_get_init_creds_opt_alloc failed");
+
+		code = krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context,
+							       krb_options,
+							       1);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_get_init_creds_opt_set_pac_request failed");
+#endif
+		break;
 	case TORTURE_KRB5_TEST_BREAK_PW:
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
 		break;
@@ -363,6 +426,22 @@ static bool torture_krb5_as_req_cmdline(struct torture_context *tctx)
 					 TORTURE_KRB5_TEST_PLAIN);
 }
 
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
+static bool torture_krb5_as_req_pac_request(struct torture_context *tctx)
+{
+	bool ok;
+
+	ok = torture_setting_bool(tctx, "expect_rodc", false);
+	if (ok) {
+		torture_skip(tctx,
+			     "This test needs further investigation in the "
+			     "RODC case against a Windows DC, in particular "
+			     "with non-cached users");
+	}
+	return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PAC_REQUEST);
+}
+#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST */
+
 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite =
@@ -375,10 +454,13 @@ NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 				      "as-req-cmdline",
 				      torture_krb5_as_req_cmdline);
 
-#if 0
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
+	/* Only available with MIT Kerveros 1.15 and newer */
 	torture_suite_add_simple_test(kdc_suite, "as-req-pac-request",
 				      torture_krb5_as_req_pac_request);
+#endif
 
+#if 0
 	torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
 				      torture_krb5_as_req_break_pw);
 
-- 
2.12.2


From 86ea69adfb24258429b4dbb2de479ca7066356d6 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 4 Jul 2016 16:37:08 +0200
Subject: [PATCH 25/50] s4-torture: Add TORTURE_KRB5_TEST_BREAK_PW test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/krb5/kdc-mit.c | 100 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 92 insertions(+), 8 deletions(-)

diff --git a/source4/torture/krb5/kdc-mit.c b/source4/torture/krb5/kdc-mit.c
index 073d5c69380..1e12a17b3cf 100644
--- a/source4/torture/krb5/kdc-mit.c
+++ b/source4/torture/krb5/kdc-mit.c
@@ -59,8 +59,11 @@ krb5_error_code decode_krb5_error(const krb5_data *output, krb5_error **rep);
 krb5_error_code decode_krb5_as_req(const krb5_data *output, krb5_kdc_req **req);
 krb5_error_code decode_krb5_as_rep(const krb5_data *output, krb5_kdc_rep **rep);
 
+krb5_error_code decode_krb5_padata_sequence(const krb5_data *output, krb5_pa_data ***rep);
+
 void krb5_free_kdc_req(krb5_context ctx, krb5_kdc_req *req);
 void krb5_free_kdc_rep(krb5_context ctx, krb5_kdc_rep *rep);
+void krb5_free_pa_data(krb5_context ctx, krb5_pa_data **data);
 
 static bool torture_check_krb5_as_req(struct torture_krb5_context *test_context,
 				      krb5_context context,
@@ -122,7 +125,8 @@ static krb5_error_code torture_krb5_pre_send_test(krb5_context context,
 static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
 				     krb5_context context,
 				     const krb5_data *reply,
-				     krb5_error_code error_code)
+				     krb5_error_code error_code,
+				     bool check_pa_data)
 
 {
 	krb5_error *krb_error;
@@ -139,6 +143,34 @@ static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
 				 error_code - KRB5KDC_ERR_NONE,
 				 "Got wrong error code");
 
+	if (check_pa_data) {
+		krb5_pa_data **d, **pa_data = NULL;
+		bool timestamp_found = false;
+
+		torture_assert_int_not_equal(test_context->tctx,
+					     krb_error->e_data.length, 0,
+					     "No e-data returned");
+
+		code = decode_krb5_padata_sequence(&krb_error->e_data,
+						   &pa_data);
+		torture_assert_int_equal(test_context->tctx,
+					 code,
+					 0,
+					 "decode_krb5_padata_sequence failed");
+
+		for (d = pa_data; d != NULL; d++) {
+			if ((*d)->pa_type == KRB5_PADATA_ENC_TIMESTAMP) {
+				timestamp_found = true;
+				break;
+			}
+		}
+		torture_assert(test_context->tctx,
+			       timestamp_found,
+			       "Encrypted timestamp not found");
+
+		krb5_free_pa_data(context, pa_data);
+	}
+
 	krb5_free_error(context, krb_error);
 
 	return true;
@@ -215,7 +247,8 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 			ok = torture_check_krb5_error(test_context,
 						      context,
 						      reply,
-						      KRB5KDC_ERR_PREAUTH_REQUIRED);
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
 			torture_assert_goto(test_context->tctx,
 					    ok,
 					    ok,
@@ -244,7 +277,8 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 			ok = torture_check_krb5_error(test_context,
 						      context,
 						      reply,
-						      KRB5KRB_ERR_RESPONSE_TOO_BIG);
+						      KRB5KRB_ERR_RESPONSE_TOO_BIG,
+						      false);
 			torture_assert_goto(test_context->tctx,
 					    ok,
 					    ok,
@@ -254,7 +288,8 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 			ok = torture_check_krb5_error(test_context,
 						      context,
 						      reply,
-						      KRB5KDC_ERR_PREAUTH_REQUIRED);
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
 			torture_assert_goto(test_context->tctx,
 					    ok,
 					    ok,
@@ -264,7 +299,8 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 			ok = torture_check_krb5_error(test_context,
 						      context,
 						      reply,
-						      KRB5KRB_ERR_RESPONSE_TOO_BIG);
+						      KRB5KRB_ERR_RESPONSE_TOO_BIG,
+						      false);
 			torture_assert_goto(test_context->tctx,
 					    ok,
 					    ok,
@@ -288,6 +324,39 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 				    "Too many packets");
 		break;
 	case TORTURE_KRB5_TEST_BREAK_PW:
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+			if (!ok) {
+				goto out;
+			}
+		} else if (test_context->recv_packet_count == 1) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_FAILED,
+						      true);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		}
+
+		torture_assert_goto(test_context->tctx,
+				    test_context->recv_packet_count < 2,
+				    ok,
+				    out,
+				    "Too many packets");
+		break;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
 		break;
 	}
@@ -360,6 +429,8 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 					  &error_string);
 	torture_assert_int_equal(tctx, code, 0, error_string);
 
+	password = cli_credentials_get_password(credentials);
+
 	switch (test)
 	{
 	case TORTURE_KRB5_TEST_PLAIN:
@@ -381,12 +452,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 #endif
 		break;
 	case TORTURE_KRB5_TEST_BREAK_PW:
+		password = "NOT the password";
+		break;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
 		break;
 	}
 
-	password = cli_credentials_get_password(credentials);
-
 	code = krb5_get_init_creds_password(smb_krb5_context->krb5_context,
 					    &my_creds,
 					    principal,
@@ -409,6 +480,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 					 "krb5_get_init_creds_password failed");
 		break;
 	case TORTURE_KRB5_TEST_BREAK_PW:
+		torture_assert_int_equal(tctx,
+					 code,
+					 KRB5KDC_ERR_PREAUTH_FAILED,
+					 "krb5_get_init_creds_password should "
+					 "have failed");
+		return true;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
 		break;
 	}
@@ -442,6 +519,13 @@ static bool torture_krb5_as_req_pac_request(struct torture_context *tctx)
 }
 #endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST */
 
+static bool torture_krb5_as_req_break_pw(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_BREAK_PW);
+}
+
 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite =
@@ -460,10 +544,10 @@ NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 				      torture_krb5_as_req_pac_request);
 #endif
 
-#if 0
 	torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
 				      torture_krb5_as_req_break_pw);
 
+#if 0
 	torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
 				      torture_krb5_as_req_clock_skew);
 
-- 
2.12.2


From b3e3551331cbdfd3273a379b51ccc208a50defc6 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 5 Jul 2016 16:16:17 +0200
Subject: [PATCH 26/50] s4-torture: Add TORTURE_KRB5_TEST_CLOCK_SKEW test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/target/Samba.pm       |  3 ++
 source4/torture/krb5/kdc-mit.c | 62 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index 8b2e4a664b3..1600ed8066a 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -205,6 +205,9 @@ sub mk_krb5_conf($$)
  # This is especially required by samba3.raw.session krb5 and
  # reauth tests
  clockskew = 5
+ # We are running on the same machine, do not correct
+ # system clock differences
+ kdc_timesync = 0
 
 ";
 
diff --git a/source4/torture/krb5/kdc-mit.c b/source4/torture/krb5/kdc-mit.c
index 1e12a17b3cf..8037ba3c9fa 100644
--- a/source4/torture/krb5/kdc-mit.c
+++ b/source4/torture/krb5/kdc-mit.c
@@ -21,6 +21,7 @@
 
 #include "includes.h"
 #include "system/kerberos.h"
+#include "system/time.h"
 #include "torture/smbtorture.h"
 #include "torture/winbind/proto.h"
 #include "torture/krb5/proto.h"
@@ -358,6 +359,44 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 				    "Too many packets");
 		break;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+			if (!ok) {
+				goto out;
+			}
+		} else if (test_context->recv_packet_count == 1) {
+			/*
+			 * This only works if kdc_timesync 0 is set in krb5.conf
+			 *
+			 * See commit 5f39a4438eafd693a3eb8366bbc3901efe62e538
+			 * in the MIT Kerberos source tree.
+			 */
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KRB_AP_ERR_SKEW,
+						      false);
+			torture_assert_goto(test_context->tctx,
+					    ok,
+					    ok,
+					    out,
+					    "torture_check_krb5_error failed");
+		}
+
+		torture_assert_goto(test_context->tctx,
+				    test_context->recv_packet_count < 2,
+				    ok,
+				    out,
+				    "Too many packets");
 		break;
 	}
 
@@ -455,6 +494,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 		password = "NOT the password";
 		break;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+		code = krb5_set_real_time(smb_krb5_context->krb5_context,
+					  time(NULL) + 3600,
+					  0);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_set_real_time failed");
 		break;
 	}
 
@@ -487,7 +532,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 					 "have failed");
 		return true;
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
-		break;
+		torture_assert_int_equal(tctx,
+					 code,
+					 KRB5KRB_AP_ERR_SKEW,
+					 "krb5_get_init_creds_password should "
+					 "have failed");
+		return true;
 	}
 
 	krb5_free_cred_contents(smb_krb5_context->krb5_context,
@@ -526,6 +576,13 @@ static bool torture_krb5_as_req_break_pw(struct torture_context *tctx)
 					 TORTURE_KRB5_TEST_BREAK_PW);
 }
 
+static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_CLOCK_SKEW);
+}
+
 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite =
@@ -547,10 +604,11 @@ NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 	torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
 				      torture_krb5_as_req_break_pw);
 
-#if 0
+	/* This only works if kdc_timesync 0 is set in krb5.conf */
 	torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
 				      torture_krb5_as_req_clock_skew);
 
+#if 0
 	torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
 #endif
 	torture_suite_add_suite(suite, kdc_suite);
-- 
2.12.2


From ea1fbe45b8e537fd3236bbde81258098b8844d64 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 1 Jul 2016 12:33:45 +0200
Subject: [PATCH 27/50] s4-torture: Add AES and RC4 enctype checks

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/krb5/kdc-mit.c | 175 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)

diff --git a/source4/torture/krb5/kdc-mit.c b/source4/torture/krb5/kdc-mit.c
index 8037ba3c9fa..29cb93d9e62 100644
--- a/source4/torture/krb5/kdc-mit.c
+++ b/source4/torture/krb5/kdc-mit.c
@@ -44,6 +44,9 @@ enum torture_krb5_test {
 	TORTURE_KRB5_TEST_PAC_REQUEST,
 	TORTURE_KRB5_TEST_BREAK_PW,
 	TORTURE_KRB5_TEST_CLOCK_SKEW,
+	TORTURE_KRB5_TEST_AES,
+	TORTURE_KRB5_TEST_RC4,
+	TORTURE_KRB5_TEST_AES_RC4,
 };
 
 struct torture_krb5_context {
@@ -107,6 +110,9 @@ static krb5_error_code torture_krb5_pre_send_test(krb5_context context,
 	case TORTURE_KRB5_TEST_PAC_REQUEST:
 	case TORTURE_KRB5_TEST_BREAK_PW:
 	case TORTURE_KRB5_TEST_CLOCK_SKEW:
+	case TORTURE_KRB5_TEST_AES:
+	case TORTURE_KRB5_TEST_RC4:
+	case TORTURE_KRB5_TEST_AES_RC4:
 		ok = torture_check_krb5_as_req(test_context,
 					       context,
 					       message);
@@ -212,6 +218,30 @@ static bool torture_check_krb5_as_rep(struct torture_krb5_context *test_context,
 	return true;
 }
 
+static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context,
+					      krb5_context context,
+					      const krb5_data *reply,
+					      krb5_enctype expected_enctype)
+{
+	krb5_enctype reply_enctype;
+	bool ok;
+
+	ok = torture_check_krb5_as_rep(test_context,
+				       context,
+				       reply);
+	if (!ok) {
+		return false;
+	}
+
+	reply_enctype = test_context->as_rep->enc_part.enctype;
+
+	torture_assert_int_equal(test_context->tctx,
+				 reply_enctype, expected_enctype,
+				 "Ticket encrypted with invalid algorithm");
+
+	return true;
+}
+
 static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 						   void *data,
 						   krb5_error_code kdc_code,
@@ -398,6 +428,72 @@ static krb5_error_code torture_krb5_post_recv_test(krb5_context context,
 				    out,
 				    "Too many packets");
 		break;
+	case TORTURE_KRB5_TEST_AES:
+		torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES\n");
+
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
+			if (!ok) {
+				goto out;
+			}
+		} else {
+			ok = torture_check_krb5_as_rep_enctype(test_context,
+							       context,
+							       reply,
+							       ENCTYPE_AES256_CTS_HMAC_SHA1_96);
+			if (!ok) {
+				goto out;
+			}
+		}
+		break;
+	case TORTURE_KRB5_TEST_RC4:
+		torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_RC4\n");
+
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
+			if (!ok) {
+				goto out;
+			}
+		} else {
+			ok = torture_check_krb5_as_rep_enctype(test_context,
+							       context,
+							       reply,
+							       ENCTYPE_ARCFOUR_HMAC);
+			if (!ok) {
+				goto out;
+			}
+		}
+		break;
+	case TORTURE_KRB5_TEST_AES_RC4:
+		torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES_RC4\n");
+
+		if (test_context->recv_packet_count == 0) {
+			ok = torture_check_krb5_error(test_context,
+						      context,
+						      reply,
+						      KRB5KDC_ERR_PREAUTH_REQUIRED,
+						      false);
+			if (!ok) {
+				goto out;
+			}
+		} else {
+			ok = torture_check_krb5_as_rep_enctype(test_context,
+							       context,
+							       reply,
+							       ENCTYPE_AES256_CTS_HMAC_SHA1_96);
+			if (!ok) {
+				goto out;
+			}
+		}
+		break;
 	}
 
 	code = kdc_code;
@@ -501,6 +597,49 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 					 code, 0,
 					 "krb5_set_real_time failed");
 		break;
+	case TORTURE_KRB5_TEST_AES: {
+		krb5_enctype etype[] = { ENCTYPE_AES256_CTS_HMAC_SHA1_96 };
+
+		code = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
+						     &krb_options);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_get_init_creds_opt_alloc failed");
+
+		krb5_get_init_creds_opt_set_etype_list(krb_options,
+						       etype,
+						       1);
+		break;
+	}
+	case TORTURE_KRB5_TEST_RC4: {
+		krb5_enctype etype[] = { ENCTYPE_ARCFOUR_HMAC };
+
+		code = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
+						     &krb_options);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_get_init_creds_opt_alloc failed");
+
+		krb5_get_init_creds_opt_set_etype_list(krb_options,
+						       etype,
+						       1);
+		break;
+	}
+	case TORTURE_KRB5_TEST_AES_RC4: {
+		krb5_enctype etype[] = { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_ARCFOUR_HMAC };
+
+		code = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
+						     &krb_options);
+		torture_assert_int_equal(tctx,
+					 code, 0,
+					 "krb5_get_init_creds_opt_alloc failed");
+
+
+		krb5_get_init_creds_opt_set_etype_list(krb_options,
+						       etype,
+						       2);
+		break;
+	}
 	}
 
 	code = krb5_get_init_creds_password(smb_krb5_context->krb5_context,
@@ -519,6 +658,9 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
 	{
 	case TORTURE_KRB5_TEST_PLAIN:
 	case TORTURE_KRB5_TEST_PAC_REQUEST:
+	case TORTURE_KRB5_TEST_AES:
+	case TORTURE_KRB5_TEST_RC4:
+	case TORTURE_KRB5_TEST_AES_RC4:
 		torture_assert_int_equal(tctx,
 					 code,
 					 0,
@@ -583,6 +725,27 @@ static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx)
 					 TORTURE_KRB5_TEST_CLOCK_SKEW);
 }
 
+static bool torture_krb5_as_req_aes(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_AES);
+}
+
+static bool torture_krb5_as_req_rc4(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_RC4);
+}
+
+static bool torture_krb5_as_req_aes_rc4(struct torture_context *tctx)
+{
+	return torture_krb5_as_req_creds(tctx,
+					 cmdline_credentials,
+					 TORTURE_KRB5_TEST_AES_RC4);
+}
+
 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite =
@@ -611,6 +774,18 @@ NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
 #if 0
 	torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
 #endif
+	torture_suite_add_simple_test(kdc_suite,
+				      "as-req-aes",
+				      torture_krb5_as_req_aes);
+
+	torture_suite_add_simple_test(kdc_suite,
+				      "as-req-rc4",
+				      torture_krb5_as_req_rc4);
+
+	torture_suite_add_simple_test(kdc_suite,
+				      "as-req-aes-rc4",
+				      torture_krb5_as_req_aes_rc4);
+
 	torture_suite_add_suite(suite, kdc_suite);
 
 	torture_register_suite(suite);
-- 
2.12.2


From 81348c30cf9417ed61f7967bf7fe9e3c65078531 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 7 Sep 2016 12:32:50 +0200
Subject: [PATCH 28/50] s4-kdc: Add MIT Kerberos specific kpasswd code

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/kpasswd-service-mit.c | 300 ++++++++++++++++++++++++++++++++++++++
 source4/kdc/wscript_build         |   3 +-
 2 files changed, 301 insertions(+), 2 deletions(-)
 create mode 100644 source4/kdc/kpasswd-service-mit.c

diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c
new file mode 100644
index 00000000000..eb3a098eb76
--- /dev/null
+++ b/source4/kdc/kpasswd-service-mit.c
@@ -0,0 +1,300 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Samba kpasswd implementation
+
+   Copyright (c) 2016      Andreas Schneider <asn at samba.org>
+
+   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 "smbd/service_task.h"
+#include "param/param.h"
+#include "auth/auth.h"
+#include "auth/gensec/gensec.h"
+#include "kdc/kdc-server.h"
+#include "kdc/kpasswd_glue.h"
+#include "kdc/kpasswd-service.h"
+#include "kdc/kpasswd-helper.h"
+
+#define RFC3244_VERSION 0xff80
+
+krb5_error_code decode_krb5_setpw_req(const krb5_data *code,
+				      krb5_data **password_out,
+				      krb5_principal *target_out);
+
+static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
+					       TALLOC_CTX *mem_ctx,
+					       struct auth_session_info *session_info,
+					       DATA_BLOB *password,
+					       DATA_BLOB *kpasswd_reply,
+					       const char **error_string)
+{
+	NTSTATUS status;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+	enum samPwdChangeReason reject_reason;
+	const char *reject_string = NULL;
+	struct samr_DomInfo1 *dominfo;
+	bool ok;
+
+	status = samdb_kpasswd_change_password(mem_ctx,
+					       kdc->task->lp_ctx,
+					       kdc->task->event_ctx,
+					       kdc->samdb,
+					       session_info,
+					       password,
+					       &reject_reason,
+					       &dominfo,
+					       &reject_string,
+					       &result);
+	if (!NT_STATUS_IS_OK(status)) {
+		ok = kpasswd_make_error_reply(mem_ctx,
+					      KRB5_KPASSWD_ACCESSDENIED,
+					      reject_string,
+					      kpasswd_reply);
+		if (!ok) {
+			*error_string = "Failed to create reply";
+			return KRB5_KPASSWD_HARDERROR;
+		}
+		/* We want to send an an authenticated packet. */
+		return 0;
+	}
+
+	ok = kpasswd_make_pwchange_reply(mem_ctx,
+					 result,
+					 reject_reason,
+					 dominfo,
+					 kpasswd_reply);
+	if (!ok) {
+		*error_string = "Failed to create reply";
+		return KRB5_KPASSWD_HARDERROR;
+	}
+
+	return 0;
+}
+
+static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
+					    TALLOC_CTX *mem_ctx,
+					    struct auth_session_info *session_info,
+					    DATA_BLOB *decoded_data,
+					    DATA_BLOB *kpasswd_reply,
+					    const char **error_string)
+{
+	krb5_context context = kdc->smb_krb5_context->krb5_context;
+	krb5_data k_dec_data;
+	krb5_data *k_clear_data;
+	krb5_principal target_principal;
+	krb5_error_code code;
+	DATA_BLOB password;
+	char *target_realm = NULL;
+	char *target_name = NULL;
+	char *target_principal_string = NULL;
+	bool is_service_principal = false;
+	bool ok;
+	size_t num_components;
+	enum samPwdChangeReason reject_reason = SAM_PWD_CHANGE_NO_ERROR;
+	struct samr_DomInfo1 *dominfo = NULL;
+	NTSTATUS status;
+
+	k_dec_data.length = decoded_data->length;
+	k_dec_data.data   = (char *)decoded_data->data;
+
+	code = decode_krb5_setpw_req(&k_dec_data, &k_clear_data, &target_principal);
+	if (code != 0) {
+		DBG_WARNING("decode_krb5_setpw_req failed: %s\n",
+			    error_message(code));
+		ok = kpasswd_make_error_reply(mem_ctx,
+					      KRB5_KPASSWD_MALFORMED,
+					      "Failed to decode packet",
+					      kpasswd_reply);
+		if (!ok) {
+			*error_string = "Failed to create reply";
+			return KRB5_KPASSWD_HARDERROR;
+		}
+		return 0;
+	}
+
+	ok = convert_string_talloc_handle(mem_ctx,
+					  lpcfg_iconv_handle(kdc->task->lp_ctx),
+					  CH_UTF8,
+					  CH_UTF16,
+					  (const char *)k_clear_data->data,
+					  k_clear_data->length,
+					  (void **)&password.data,
+					  &password.length);
+	krb5_free_data(context, k_clear_data);
+	if (!ok) {
+		DBG_WARNING("String conversion failed\n");
+		*error_string = "String conversion failed";
+		return KRB5_KPASSWD_HARDERROR;
+	}
+
+	target_realm = smb_krb5_principal_get_realm(context, target_principal);
+	code = krb5_unparse_name_flags(context,
+				       target_principal,
+				       KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+				       &target_name);
+	if (code != 0) {
+		DBG_WARNING("Failed to parse principal\n");
+		*error_string = "String conversion failed";
+		return KRB5_KPASSWD_HARDERROR;
+	}
+
+	if ((target_name != NULL && target_realm == NULL) ||
+	    (target_name == NULL && target_realm != NULL)) {
+		krb5_free_principal(context, target_principal);
+		SAFE_FREE(target_realm);
+		SAFE_FREE(target_name);
+
+		ok = kpasswd_make_error_reply(mem_ctx,
+					      KRB5_KPASSWD_MALFORMED,
+					      "Realm and principal must be "
+					      "both present, or neither present",
+					      kpasswd_reply);
+		if (!ok) {
+			*error_string = "Failed to create reply";
+			return KRB5_KPASSWD_HARDERROR;
+		}
+		return 0;
+	}
+
+	if (target_name != NULL && target_realm != NULL) {
+		SAFE_FREE(target_realm);
+		SAFE_FREE(target_name);
+	} else {
+		krb5_free_principal(context, target_principal);
+		SAFE_FREE(target_realm);
+		SAFE_FREE(target_name);
+
+		return kpasswd_change_password(kdc,
+					       mem_ctx,
+					       session_info,
+					       &password,
+					       kpasswd_reply,
+					       error_string);
+	}
+
+	num_components = krb5_princ_size(context, target_principal);
+	if (num_components >= 2) {
+		is_service_principal = true;
+		code = krb5_unparse_name_flags(context,
+					       target_principal,
+					       KRB5_PRINCIPAL_UNPARSE_SHORT,
+					       &target_principal_string);
+	} else {
+		code = krb5_unparse_name(context,
+					 target_principal,
+					 &target_principal_string);
+	}
+	krb5_free_principal(context, target_principal);
+	if (code != 0) {
+		ok = kpasswd_make_error_reply(mem_ctx,
+					      KRB5_KPASSWD_MALFORMED,
+					      "Failed to parse principal",
+					      kpasswd_reply);
+		if (!ok) {
+			*error_string = "Failed to create reply";
+			return KRB5_KPASSWD_HARDERROR;
+		}
+	}
+
+	status = kpasswd_samdb_set_password(mem_ctx,
+					    kdc->task->event_ctx,
+					    kdc->task->lp_ctx,
+					    session_info,
+					    is_service_principal,
+					    target_principal_string,
+					    &password,
+					    &reject_reason,
+					    &dominfo);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("kpasswd_samdb_set_password failed - %s\n",
+			nt_errstr(status));
+	}
+
+	ok = kpasswd_make_pwchange_reply(mem_ctx,
+					 status,
+					 reject_reason,
+					 dominfo,
+					 kpasswd_reply);
+	if (!ok) {
+		*error_string = "Failed to create reply";
+		return KRB5_KPASSWD_HARDERROR;
+	}
+
+	return 0;
+}
+
+krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
+				       TALLOC_CTX *mem_ctx,
+				       struct gensec_security *gensec_security,
+				       uint16_t verno,
+				       DATA_BLOB *decoded_data,
+				       DATA_BLOB *kpasswd_reply,
+				       const char **error_string)
+{
+	struct auth_session_info *session_info;
+	NTSTATUS status;
+
+	status = gensec_session_info(gensec_security,
+				     mem_ctx,
+				     &session_info);
+	if (!NT_STATUS_IS_OK(status)) {
+		*error_string = talloc_asprintf(mem_ctx,
+						"gensec_session_info failed - %s",
+						nt_errstr(status));
+		return KRB5_KPASSWD_HARDERROR;
+	}
+
+	switch(verno) {
+	case 1: {
+		DATA_BLOB password;
+		bool ok;
+
+		ok = convert_string_talloc_handle(mem_ctx,
+						  lpcfg_iconv_handle(kdc->task->lp_ctx),
+						  CH_UTF8,
+						  CH_UTF16,
+						  (const char *)decoded_data->data,
+						  decoded_data->length,
+						  (void **)&password.data,
+						  &password.length);
+		if (!ok) {
+			*error_string = "String conversion failed!";
+			DBG_WARNING("%s\n", *error_string);
+			return KRB5_KPASSWD_HARDERROR;
+		}
+
+		return kpasswd_change_password(kdc,
+					       mem_ctx,
+					       session_info,
+					       &password,
+					       kpasswd_reply,
+					       error_string);
+	}
+	case RFC3244_VERSION: {
+		return kpasswd_set_password(kdc,
+					    mem_ctx,
+					    session_info,
+					    decoded_data,
+					    kpasswd_reply,
+					    error_string);
+	}
+	default:
+		return KRB5_KPASSWD_BAD_VERSION;
+	}
+
+	return 0;
+}
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index a19932cca50..5e50142dadd 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -67,8 +67,7 @@ bld.SAMBA_SUBSYSTEM('KDC-SERVER',
                          ldb
                          LIBTSOCKET
                          LIBSAMBA_TSOCKET
-                    ''',
-                    enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'))
+                    ''')
 
 kpasswd_flavor_src = 'kpasswd-service.c kpasswd-helper.c'
 if bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'):
-- 
2.12.2


From 3565c715f2599da9176a6366cf2dba25dfa85cb7 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 7 Sep 2016 12:29:18 +0200
Subject: [PATCH 29/50] waf: Search for MIT kadm-server library

This is needed for plugin registration in the KDC.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 wscript_configure_system_mitkrb5 | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
index 39924577431..41cc2dd0ed8 100644
--- a/wscript_configure_system_mitkrb5
+++ b/wscript_configure_system_mitkrb5
@@ -34,6 +34,10 @@ if conf.env.KRB5_CONFIG:
     krb5_define_syslib(conf, "krb5", conf.env['LIB_KRB5'])
 
     conf.CHECK_CFG(path=conf.env.KRB5_CONFIG, args="--cflags --libs",
+                   package="kadm-server", uselib_store="KADM-SERVER")
+    conf.CHECK_FUNCS_IN('kadm5_init', 'kadm5srv_mit')
+
+    conf.CHECK_CFG(path=conf.env.KRB5_CONFIG, args="--cflags --libs",
                    package="kdb", uselib_store="KDB5")
     krb5_define_syslib(conf, "kdb5", conf.env['LIB_KDB5'])
 
-- 
2.12.2


From 8a1bebcb09790283e7fc3b5ca37160e77ad6a1ae Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 8 Sep 2016 09:58:44 +0200
Subject: [PATCH 30/50] s4-kdc: Start the kpasswd service with MIT KDC

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/kdc-service-mit.c | 217 ++++++++++++++++++++++++++++++++++++++++++
 source4/kdc/wscript_build     |   7 ++
 2 files changed, 224 insertions(+)

diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c
index a1cdd3a4471..780822b7fb0 100644
--- a/source4/kdc/kdc-service-mit.c
+++ b/source4/kdc/kdc-service-mit.c
@@ -30,11 +30,114 @@
 #include "kdc/kdc-service-mit.h"
 #include "dynconfig.h"
 #include "libds/common/roles.h"
+#include "lib/socket/netif.h"
+#include "samba/session.h"
+#include "dsdb/samdb/samdb.h"
+#include "kdc/samba_kdc.h"
+#include "kdc/kdc-server.h"
+#include "kdc/kpasswd-service.h"
+#include <kadm5/admin.h>
+#include <kdb.h>
 
 #include "source4/kdc/mit_kdc_irpc.h"
 
+/* PROTOTYPES */
 static void mitkdc_server_done(struct tevent_req *subreq);
 
+static int kdc_server_destroy(struct kdc_server *kdc)
+{
+	if (kdc->private_data != NULL) {
+		kadm5_destroy(kdc->private_data);
+	}
+
+	return 0;
+}
+
+static NTSTATUS startup_kpasswd_server(TALLOC_CTX *mem_ctx,
+				       struct kdc_server *kdc,
+				       struct loadparm_context *lp_ctx,
+				       struct interface *ifaces)
+{
+	const struct model_ops *model_ops;
+	int num_interfaces;
+	int i;
+	TALLOC_CTX *tmp_ctx;
+	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	uint16_t kpasswd_port;
+	bool done_wildcard = false;
+	bool ok;
+
+	kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
+	if (kpasswd_port == 0) {
+		return NT_STATUS_OK;
+	}
+
+	model_ops = process_model_startup("single");
+	if (model_ops == NULL) {
+		DBG_ERR("Can't find 'single' process model_ops\n");
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	tmp_ctx = talloc_new(mem_ctx);
+	if (tmp_ctx == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	num_interfaces = iface_list_count(ifaces);
+
+	ok = lpcfg_bind_interfaces_only(lp_ctx);
+	if (!ok) {
+		int num_binds = 0;
+		char **wcard;
+
+		wcard = iface_list_wildcard(tmp_ctx);
+		if (wcard == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto out;
+		}
+
+		for (i = 0; wcard[i] != NULL; i++) {
+			status = kdc_add_socket(kdc,
+						model_ops,
+						"kpasswd",
+						wcard[i],
+						kpasswd_port,
+						kpasswd_process,
+						false);
+			if (NT_STATUS_IS_OK(status)) {
+				num_binds++;
+			}
+		}
+		talloc_free(wcard);
+
+		if (num_binds == 0) {
+			status = NT_STATUS_INVALID_PARAMETER_MIX;
+			goto out;
+		}
+
+		done_wildcard = true;
+	}
+
+	for (i = 0; i < num_interfaces; i++) {
+		const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
+
+		status = kdc_add_socket(kdc,
+					model_ops,
+					"kpasswd",
+					address,
+					kpasswd_port,
+					kpasswd_process,
+					done_wildcard);
+		if (NT_STATUS_IS_OK(status)) {
+			goto out;
+		}
+	}
+
+out:
+	talloc_free(tmp_ctx);
+	return status;
+}
+
 /*
  * Startup a copy of the krb5kdc as a child daemon
  */
@@ -42,8 +145,14 @@ void mitkdc_task_init(struct task_server *task)
 {
 	struct tevent_req *subreq;
 	const char * const *kdc_cmd;
+	struct interface *ifaces;
 	const char *kdc_config;
+	struct kdc_server *kdc;
+	krb5_error_code code;
 	NTSTATUS status;
+	kadm5_ret_t ret;
+	kadm5_config_params config;
+	void *server_handle;
 
 	task_server_set_title(task, "task[mitkdc_parent]");
 
@@ -65,6 +174,15 @@ void mitkdc_task_init(struct task_server *task)
 		break;
 	}
 
+	/* Load interfaces for kpasswd */
+	load_interface_list(task, task->lp_ctx, &ifaces);
+	if (iface_list_count(ifaces) == 0) {
+		task_server_terminate(task,
+				      "KDC: no network interfaces configured",
+				      false);
+		return;
+	}
+
 	kdc_config = lpcfg_mit_kdc_config(task->lp_ctx, task);
 	if (kdc_config != NULL && kdc_config[0] != '\0') {
 		/* Do not overwrite the variable if already set! */
@@ -106,6 +224,105 @@ void mitkdc_task_init(struct task_server *task)
 	}
 
 	DEBUG(5,("Started irpc service for kdc_server\n"));
+
+	kdc = talloc_zero(task, struct kdc_server);
+	if (kdc == NULL) {
+		task_server_terminate(task, "KDC: Out of memory", true);
+		return;
+	}
+	talloc_set_destructor(kdc, kdc_server_destroy);
+
+	kdc->task = task;
+
+	kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
+	if (kdc->base_ctx == NULL) {
+		task_server_terminate(task, "KDC: Out of memory", true);
+		return;
+	}
+
+	kdc->base_ctx->ev_ctx = task->event_ctx;
+	kdc->base_ctx->lp_ctx = task->lp_ctx;
+
+	initialize_krb5_error_table();
+
+	code = smb_krb5_init_context(kdc,
+				     kdc->task->lp_ctx,
+				     &kdc->smb_krb5_context);
+	if (code != 0) {
+		task_server_terminate(task,
+				      "KDC: Unable to initialized krb5 context",
+				      true);
+		return;
+	}
+
+	code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
+	if (code != 0) {
+		task_server_terminate(task,
+				      "KDC: Unable to init kadm5 krb5_context",
+				      true);
+		return;
+	}
+
+	ZERO_STRUCT(config);
+	config.mask = KADM5_CONFIG_REALM;
+	config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
+
+	ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
+			 discard_const_p(char, "kpasswd"),
+			 NULL, /* pass */
+			 discard_const_p(char, "kpasswd"),
+			 &config,
+			 KADM5_STRUCT_VERSION,
+			 KADM5_API_VERSION_4,
+			 NULL,
+			 &server_handle);
+	if (ret != 0) {
+		task_server_terminate(task,
+				      "KDC: Initialize kadm5",
+				      true);
+		return;
+	}
+	kdc->private_data = server_handle;
+
+	code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
+	if (code != 0) {
+		task_server_terminate(task,
+				      "KDC: Unable to KDB",
+				      true);
+		return;
+	}
+
+	kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
+	if (kdc->keytab_name == NULL) {
+		task_server_terminate(task,
+				      "KDC: Out of memory",
+				      true);
+		return;
+	}
+
+	kdc->samdb = samdb_connect(kdc,
+				   kdc->task->event_ctx,
+				   kdc->task->lp_ctx,
+				   system_session(kdc->task->lp_ctx),
+				   0);
+	if (kdc->samdb == NULL) {
+		task_server_terminate(task,
+				      "KDC: Unable to connect to sambdb",
+				      true);
+		return;
+	}
+
+	status = startup_kpasswd_server(kdc,
+				    kdc,
+				    task->lp_ctx,
+				    ifaces);
+	if (!NT_STATUS_IS_OK(status)) {
+		task_server_terminate(task,
+				      "KDC: Unable to start kpasswd server",
+				      true);
+	}
+
+	DEBUG(5,("Started kpasswd service for kdc_server\n"));
 }
 
 /*
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index 5e50142dadd..6179e3e6426 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -37,6 +37,11 @@ if bld.CONFIG_GET('SAMBA_USES_MITKDC'):
                           talloc
                           UTIL_RUNCMD
                           MIT_KDC_IRPC
+                          KDC-SERVER
+                          KPASSWD-SERVICE
+                          com_err
+                          kadm5srv_mit
+                          kdb5
                      ''',
                      internal_module=False)
 
@@ -72,6 +77,8 @@ bld.SAMBA_SUBSYSTEM('KDC-SERVER',
 kpasswd_flavor_src = 'kpasswd-service.c kpasswd-helper.c'
 if bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'):
     kpasswd_flavor_src = kpasswd_flavor_src + ' kpasswd-service-heimdal.c'
+elif bld.CONFIG_GET('SAMBA_USES_MITKDC'):
+    kpasswd_flavor_src = kpasswd_flavor_src + ' kpasswd-service-mit.c'
 
 bld.SAMBA_SUBSYSTEM('KPASSWD-SERVICE',
                     source=kpasswd_flavor_src,
-- 
2.12.2


From e2a5000df23c5cb5da9f93d3002dbfe0cfb13a01 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 5 Sep 2016 18:01:57 +0200
Subject: [PATCH 31/50] testprogs: Add MIT Kerberos specific kpasswd blackbox
 test

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/selftest/tests.py              |   1 +
 testprogs/blackbox/test_kpasswd_mit.sh | 231 +++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)
 create mode 100755 testprogs/blackbox/test_kpasswd_mit.sh

diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index b7ac0c5f5f7..75405b9c717 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -404,6 +404,7 @@ else:
     plantestsuite("samba4.blackbox.kinit_trust(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
     plantestsuite("samba4.blackbox.kinit_trust(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
     plantestsuite("samba4.blackbox.export.keytab(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_mit.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4])
+    plantestsuite("samba4.blackbox.kpasswd(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"])
 
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'forest', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
 plantestsuite("samba4.blackbox.trust_ntlm", "fl2003dc:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', 'external', 'auto', 'NT_STATUS_NO_TRUST_LSA_SECRET'])
diff --git a/testprogs/blackbox/test_kpasswd_mit.sh b/testprogs/blackbox/test_kpasswd_mit.sh
new file mode 100755
index 00000000000..8a0bce449f3
--- /dev/null
+++ b/testprogs/blackbox/test_kpasswd_mit.sh
@@ -0,0 +1,231 @@
+#!/bin/sh
+# Blackbox tests for chainging passwords with kinit and kpasswd
+#
+# Copyright (c) 2006-2007 Jelmer Vernooij <jelmer at samba.org>
+# Copyright (c) 2006-2008 Andrew Bartlett <abartlet at samba.org>
+# Copyright (c) 2016      Andreas Schneider <asn at samba.org>
+
+if [ $# -lt 6 ]; then
+cat <<EOF
+Usage: test_kpasswd_mit.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+PASSWORD=$3
+REALM=$4
+DOMAIN=$5
+PREFIX=$6
+shift 6
+failed=0
+
+samba_bindir="$BINDIR"
+
+samba_kinit=kinit
+samba_kpasswd=kpasswd
+
+smbclient="$samba_bindir/smbclient"
+samba_tool="$samba_bindir/samba-tool"
+net_tool="$samba_bindir/net"
+texpect="$samba_bindir/texpect"
+
+newuser="$samba_tool user create"
+SMB_UNC="//$SERVER/tmp"
+
+. `dirname $0`/subunit.sh
+. `dirname $0`/common_test_fns.inc
+
+do_kinit() {
+	principal="$1"
+	password="$2"
+	shift
+	shift
+	echo $password | $samba_kinit $principal
+}
+
+UID_WRAPPER_ROOT=1
+export UID_WRAPPER_ROOT
+
+CONFIG="--configfile=$PREFIX/etc/smb.conf"
+export CONFIG
+
+testit "reset password policies beside of minimum password age of 0 days" \
+	$VALGRIND $samba_tool domain passwordsettings $CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=0 --max-pwd-age=default || failed=`expr $failed + 1`
+
+TEST_USERNAME="samson"
+TEST_PASSWORD="testPaSS at 00%"
+TEST_PASSWORD_NEW="testPaSS at 01%"
+TEST_PASSWORD_SHORT="secret"
+TEST_PASSWORD_WEAK="Supersecret"
+TEST_PRINCIPAL="$TEST_USERNAME@$REALM"
+
+testit "create user locally" \
+	$VALGRIND $newuser $CONFIG $TEST_USERNAME $TEST_PASSWORD || failed=`expr $failed + 1`
+
+KRB5CCNAME="$PREFIX/tmpuserccache"
+export KRB5CCNAME
+
+testit "kinit with user password" \
+	do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1`
+
+test_smbclient "Test login with user kerberos ccache" \
+	"ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1`
+
+testit "change user password with 'samba-tool user password' (unforced)" \
+	$VALGRIND $samba_tool user password -W$DOMAIN -U$TEST_USERNAME%$TEST_PASSWORD -k no --newpassword=$TEST_PASSWORD_NEW || failed=`expr $failed + 1`
+
+TEST_PASSWORD_OLD=$TEST_PASSWORD
+TEST_PASSWORD=$TEST_PASSWORD_NEW
+TEST_PASSWORD_NEW="testPaSS at 02%"
+
+testit "kinit with user password" \
+	do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1`
+
+test_smbclient "Test login with user kerberos ccache" \
+	"ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1`
+
+###########################################################
+### check that a password mismatch is detected
+###########################################################
+
+cat > $PREFIX/tmpkpasswdscript <<EOF
+expect Password for $TEST_PRINCIPAL
+password ${TEST_PASSWORD}\n
+expect Enter new password
+send ${TEST_PASSWORD_WEAK}\n
+expect Enter it again
+send ${TEST_PASSWORD_NEW}\n
+expect kpasswd: Password mismatch while reading password
+EOF
+
+testit_expect_failure "kpasswd check password mismatch" \
+	$texpect $PREFIX/tmpkpasswdscript $samba_kpasswd $TEST_PRINCIPAL && failed=`expr $failed + 1`
+
+###########################################################
+### check that a short password is rejected
+###########################################################
+
+cat > $PREFIX/tmpkpasswdscript <<EOF
+expect Password for $TEST_PRINCIPAL
+password ${TEST_PASSWORD}\n
+expect Enter new password
+send ${TEST_PASSWORD_SHORT}\n
+expect Enter it again
+send ${TEST_PASSWORD_SHORT}\n
+expect Password change rejected: Password too short, password must be at least 7 characters long
+EOF
+
+testit_expect_failure "kpasswd check short user password" \
+	$texpect $PREFIX/tmpkpasswdscript $samba_kpasswd $TEST_PRINCIPAL && failed=`expr $failed + 1`
+
+###########################################################
+### check that a weak password is rejected
+###########################################################
+
+cat > $PREFIX/tmpkpasswdscript <<EOF
+expect Password for $TEST_PRINCIPAL
+password ${TEST_PASSWORD}\n
+expect Enter new password
+send ${TEST_PASSWORD_WEAK}\n
+expect Enter it again
+send ${TEST_PASSWORD_WEAK}\n
+expect Password change rejected: Password does not meet complexity requirement
+EOF
+
+testit_expect_failure "kpasswd check weak user password" \
+	$texpect $PREFIX/tmpkpasswdscript $samba_kpasswd $TEST_PRINCIPAL && failed=`expr $failed + 1`
+
+###########################################################
+### check that a strong password is accepted
+###########################################################
+
+cat > $PREFIX/tmpkpasswdscript <<EOF
+expect Password for $TEST_PRINCIPAL
+password ${TEST_PASSWORD}\n
+expect Enter new password
+send ${TEST_PASSWORD_NEW}\n
+expect Enter it again
+send ${TEST_PASSWORD_NEW}\n
+expect Password changed.
+EOF
+
+testit "kpasswd change user password" \
+	$texpect $PREFIX/tmpkpasswdscript $samba_kpasswd $TEST_PRINCIPAL|| failed=`expr $failed + 1`
+
+TEST_PASSWORD=$TEST_PASSWORD_NEW
+TEST_PASSWORD_NEW="testPaSS at 03%"
+
+test_smbclient "Test login with user kerberos" 'ls' "$SMB_UNC" -k yes -U$TEST_PRINCIPAL%$TEST_PASSWORD || failed=`expr $failed + 1`
+
+###########################################################
+### Force password change at login
+###########################################################
+
+testit "set password on user locally" \
+	$VALGRIND $samba_tool user setpassword $TEST_USERNAME $CONFIG --newpassword=$TEST_PASSWORD_NEW --must-change-at-next-login || failed=`expr $failed + 1`
+
+TEST_PASSWORD=$TEST_PASSWORD_NEW
+TEST_PASSWORD_NEW="testPaSS at 04%"
+
+cat > $PREFIX/tmpkinitscript <<EOF
+expect Password for $TEST_PRINCIPAL
+password ${TEST_PASSWORD}\n
+expect Password expired
+expect Enter new password
+send ${TEST_PASSWORD_NEW}\n
+expect Enter it again
+send ${TEST_PASSWORD_NEW}\n
+EOF
+
+testit "kinit and change user password" \
+	$texpect $PREFIX/tmpkinitscript $samba_kinit $TEST_PRINCIPAL|| failed=`expr $failed + 1`
+
+TEST_PASSWORD=$TEST_PASSWORD_NEW
+TEST_PASSWORD_NEW="testPaSS at 05%"
+
+test_smbclient "Test login with user kerberos" \
+	"ls" "$SMB_UNC" -k yes -U$TEST_PRINCIPAL%$TEST_PASSWORD || failed=`expr $failed + 1`
+
+###########################################################
+### Test kpasswd service via 'net ads password'
+###########################################################
+
+# NOTE: This call works if it is compiled with Heimdal, because the Heimdal
+# krb5_set_password() implementation falls back to change_password. The MIT
+# function doesn't!
+testit_expect_failure "change user password with 'net ads password', admin: $DOMAIN/$TEST_USERNAME, target: $TEST_PRINCIPAL (will fail)" \
+	$VALGRIND $net_tool ads password -W$DOMAIN -U$TEST_PRINCIPAL%$TEST_PASSWORD $TEST_PRINCIPAL "$TEST_PASSWORD_NEW" && failed=`expr $failed + 1`
+
+#TEST_PASSWORD=$TEST_PASSWORD_NEW
+#TEST_PASSWORD_NEW="testPaSS at 06%"
+
+#test_smbclient "Test login with smbclient (ntlm)" \
+#	"ls" "$SMB_UNC" -k no -U$TEST_PRINCIPAL%$TEST_PASSWORD || failed=`expr $failed + 1`
+
+###########################################################
+### Test kpasswd service via 'net ads password' as admin
+###########################################################
+
+testit "set user password with 'net ads password', admin: $DOMAIN/$USERNAME, target: $TEST_PRINCIPAL" \
+	$VALGRIND $net_tool ads password -W$DOMAIN -U$USERNAME@$REALM%$PASSWORD $TEST_PRINCIPAL "$TEST_PASSWORD_NEW" || failed=`expr $failed + 1`
+
+TEST_PASSWORD=$TEST_PASSWORD_NEW
+TEST_PASSWORD_NEW="testPaSS at 07%"
+
+test_smbclient "Test login with smbclient (ntlm)" \
+	"ls" "$SMB_UNC" -k no -U$TEST_PRINCIPAL%$TEST_PASSWORD || failed=`expr $failed + 1`
+
+###########################################################
+### Cleanup
+###########################################################
+
+testit "reset password policies" \
+	$VALGRIND $samba_tool domain passwordsettings $CONFIG set --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1`
+
+testit "delete user" \
+	$VALGRIND $samba_tool user delete $TEST_USERNAME -U"$USERNAME%$PASSWORD" $CONFIG -k no  || failed=`expr $failed + 1`
+
+rm -f $PREFIX/tmpuserccache $PREFIX/tmpkpasswdscript $PREFIX/tmpkinitscript
+exit $failed
-- 
2.12.2


From 4b1ca5dd74453b72d82a0e6ea927436624d99a6f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 13 Apr 2015 15:58:14 +0200
Subject: [PATCH 32/50] selftest: Skip s4u2proxy tests, no support yet

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/skip_mit_kdc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/selftest/skip_mit_kdc b/selftest/skip_mit_kdc
index b0c901514d5..4a51c98ea0b 100644
--- a/selftest/skip_mit_kdc
+++ b/selftest/skip_mit_kdc
@@ -1,3 +1,5 @@
 # We do not support RODC yet
 .*rodc
 .*RODC
+^samba4.ntvfs.cifs.ntlm.base.unlink
+^samba4.ntvfs.cifs.krb5.base.unlink
-- 
2.12.2


From 9a744ba0eddb1552993b438c1be365d6f71afb85 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 23 Nov 2015 11:44:26 +0100
Subject: [PATCH 33/50] waf: Create kerberos_implementation.py for provisioning

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 .gitignore     |  3 +++
 python/wscript | 45 +++++++++++++++++++++++++++++++++++++++++++++
 wscript        |  1 +
 3 files changed, 49 insertions(+)
 create mode 100644 python/wscript

diff --git a/.gitignore b/.gitignore
index 1a43d43b3b3..f8d4eab2a7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,3 +65,6 @@ semantic.cache
 /.emacs.desktop*
 /.gdb_history
 .clang-format
+
+# generated by configure
+python/samba/provision/kerberos_implementation.py
diff --git a/python/wscript b/python/wscript
new file mode 100644
index 00000000000..714d649219d
--- /dev/null
+++ b/python/wscript
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+import os
+
+def configure(conf):
+    kerberos_py = conf.srcdir + "/python/samba/provision/kerberos_implementation.py"
+
+    f = open(kerberos_py, 'w')
+    try:
+        header = """#
+# Copyright (c) 2016      Andreas Schneider <asn at samba.org>
+#
+# 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/>.
+#
+"""
+        f.write(header)
+
+        data = """kdb_modules_dir = "{0}"
+kdc_default_config_dir = "{1}"
+"""
+
+        if conf.env.HEIMDAL_KRB5_CONFIG:
+            f.write(data.format("", ""))
+        else:
+            modulesdir = "%s/krb5/plugins/kdb" % conf.env.LIBDIR
+            paths = [ "/var/kerberos/krb5kdc", "/var/lib/kerberos/krb5kdc" ]
+            kdc_path = None
+            for p in paths:
+                if os.path.exists(p):
+                    kdc_path = p
+
+            f.write(data.format(modulesdir, kdc_path))
+    finally:
+        f.close()
diff --git a/wscript b/wscript
index 57b87850896..2a886e6dd48 100644
--- a/wscript
+++ b/wscript
@@ -210,6 +210,7 @@ def configure(conf):
 
     conf.RECURSE('source3')
     conf.RECURSE('lib/texpect')
+    conf.RECURSE('python')
     if conf.env.with_ctdb:
         conf.RECURSE('ctdb')
     conf.RECURSE('lib/socket')
-- 
2.12.2


From f4743a50b68354aaacfd38801641f9553bbea504 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 12 Sep 2016 21:52:23 +0200
Subject: [PATCH 34/50] selftest: Add a variable to indicate that selftest is
 running

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 selftest/selftest.pl | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index b00ab486e87..3ab07a7a741 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -324,6 +324,8 @@ my $srcdir_abs = abs_path($srcdir);
 die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne "";
 die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/";
 
+$ENV{SAMBA_SELFTEST} = "1";
+
 $ENV{PREFIX} = $prefix;
 $ENV{PREFIX_ABS} = $prefix_abs;
 $ENV{SRCDIR} = $srcdir;
-- 
2.12.2


From aa741fcf05e96e836f1d9b77f5e1f7ced4ad79c3 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 4 Apr 2017 08:10:52 +0200
Subject: [PATCH 35/50] python: Add py_is_heimdal_built() to pyglue

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 python/pyglue.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/python/pyglue.c b/python/pyglue.c
index 2bb6247fdeb..07cde49e16b 100644
--- a/python/pyglue.c
+++ b/python/pyglue.c
@@ -152,6 +152,15 @@ static PyObject *py_is_ntvfs_fileserver_built(PyObject *self)
 #endif
 }
 
+static PyObject *py_is_heimdal_built(PyObject *self)
+{
+#ifdef SAMBA4_USES_HEIMDAL
+	Py_RETURN_TRUE;
+#else
+	Py_RETURN_FALSE;
+#endif
+}
+
 /*
   return the list of interface IPs we have configured
   takes an loadparm context, returns a list of IPs in string form
@@ -307,6 +316,8 @@ static PyMethodDef py_misc_methods[] = {
 		"(for testing) find one string in another with Samba's strstr_m()"},
 	{ "is_ntvfs_fileserver_built", (PyCFunction)py_is_ntvfs_fileserver_built, METH_NOARGS,
 		"is the NTVFS file server built in this installation?" },
+	{ "is_heimdal_built", (PyCFunction)py_is_heimdal_built, METH_NOARGS,
+		"is Samba built with Heimdal Kerberbos?" },
 	{ NULL }
 };
 
-- 
2.12.2


From fc872059f4e0ed41694e01b670e74783cd8905f2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 9 Oct 2015 15:06:52 +0200
Subject: [PATCH 36/50] python: Add provisioning support for MIT KDC in
 samba-tool

Signed-off-by: Andreas Schneider <asn at cryptomilk.org>
---
 python/samba/__init__.py           |   1 +
 python/samba/netcmd/domain.py      |  15 +++++-
 python/samba/provision/__init__.py |  18 ++++---
 python/samba/provision/kerberos.py | 101 +++++++++++++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 7 deletions(-)
 create mode 100644 python/samba/provision/kerberos.py

diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 67aa82300f9..6f79b3cc960 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -391,6 +391,7 @@ generate_random_machine_password = _glue.generate_random_machine_password
 strcasecmp_m = _glue.strcasecmp_m
 strstr_m = _glue.strstr_m
 is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built
+is_heimdal_built = _glue.is_heimdal_built
 
 NTSTATUSError = _glue.NTSTATUSError
 HRESULTError = _glue.HRESULTError
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index 4bd99ba6ff5..bfc4772b7b1 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -87,6 +87,9 @@ from samba.provision import (
     ProvisioningError
     )
 
+from samba.provision.kerberos_implementation import (
+    kdc_default_config_dir)
+
 from samba.provision.common import (
     FILL_FULL,
     FILL_NT4SYNC,
@@ -263,12 +266,20 @@ class cmd_domain_provision(Command):
                default="auto")
     ]
 
+    kdc_options = [
+        Option("--kdc-config-dir", type="string", metavar="KDC-CONFIG-DIR",
+               help="Set the MIT KDC config directory (default='%s')" % kdc_default_config_dir),
+    ]
+
     if os.getenv('TEST_LDAP', "no") == "yes":
         takes_options.extend(openldap_options)
 
     if samba.is_ntvfs_fileserver_built():
          takes_options.extend(ntvfs_options)
 
+    if not samba.is_heimdal_built():
+        takes_options.extend(kdc_options)
+
     takes_args = []
 
     def run(self, sambaopts=None, versionopts=None,
@@ -304,6 +315,7 @@ class cmd_domain_provision(Command):
             use_xattrs="auto",
             slapd_path=None,
             use_ntvfs=False,
+            kdc_config_dir=None,
             use_rfc2307=None,
             ldap_backend_nosync=None,
             ldap_backend_extra_port=None,
@@ -471,7 +483,8 @@ class cmd_domain_provision(Command):
                   use_rfc2307=use_rfc2307, skip_sysvolacl=False,
                   ldap_backend_extra_port=ldap_backend_extra_port,
                   ldap_backend_forced_uri=ldap_backend_forced_uri,
-                  nosync=ldap_backend_nosync, ldap_dryrun_mode=ldap_dryrun_mode)
+                  nosync=ldap_backend_nosync, ldap_dryrun_mode=ldap_dryrun_mode,
+                  kdcconfdir=kdc_config_dir)
 
         except ProvisioningError, e:
             raise CommandError("Provision failed", e)
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index f8e4696a2fd..b001c544fb9 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -118,7 +118,7 @@ import samba.registry
 from samba.schema import Schema
 from samba.samdb import SamDB
 from samba.dbchecker import dbcheck
-
+from samba.provision.kerberos import make_kdcconf
 
 DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9"
 DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04FB984F9"
@@ -668,10 +668,9 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
 
     return names
 
-
 def make_smbconf(smbconf, hostname, domain, realm, targetdir,
                  serverrole=None, eadb=False, use_ntvfs=False, lp=None,
-                 global_param=None):
+                 global_param=None, kdcconfdir=None):
     """Create a new smb.conf file based on a couple of basic settings.
     """
     assert smbconf is not None
@@ -732,6 +731,11 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
                 statedir = lp.get("state directory")
             lp.set("xattr_tdb:file", os.path.abspath(os.path.join(statedir, "xattr.tdb")))
 
+    make_kdcconf(realm, domain, kdcconfdir, os.path.dirname(lp.get("log file")))
+    if kdcconfdir is not None:
+        kdcconf = "%s/kdc.conf" % kdcconfdir
+        lp.set("mit kdc config", kdcconf)
+
     shares = {}
     if serverrole == "active directory domain controller":
         shares["sysvol"] = os.path.join(lp.get("state directory"), "sysvol")
@@ -1925,7 +1929,7 @@ def provision_fake_ypserver(logger, samdb, domaindn, netbiosname, nisdomain,
         samdb.transaction_commit()
 
 
-def provision(logger, session_info, smbconf=None,
+def provision(logger, session_info, smbconf=None, kdcconfdir=None,
         targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
         domaindn=None, schemadn=None, configdn=None, serverdn=None,
         domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
@@ -2009,11 +2013,13 @@ def provision(logger, session_info, smbconf=None,
             make_smbconf(smbconf, hostname, domain, realm,
                          targetdir, serverrole=serverrole,
                          eadb=useeadb, use_ntvfs=use_ntvfs,
-                         lp=lp, global_param=global_param)
+                         lp=lp, global_param=global_param,
+                         kdcconfdir=kdcconfdir)
     else:
         make_smbconf(smbconf, hostname, domain, realm, targetdir,
                      serverrole=serverrole,
-                     eadb=useeadb, use_ntvfs=use_ntvfs, lp=lp, global_param=global_param)
+                     eadb=useeadb, use_ntvfs=use_ntvfs, lp=lp, global_param=global_param,
+                     kdcconfdir=kdcconfdir)
 
     if lp is None:
         lp = samba.param.LoadParm()
diff --git a/python/samba/provision/kerberos.py b/python/samba/provision/kerberos.py
new file mode 100644
index 00000000000..f874ff61567
--- /dev/null
+++ b/python/samba/provision/kerberos.py
@@ -0,0 +1,101 @@
+# Unix SMB/CIFS implementation
+#
+# Backend code for provisioning a Samba AD server
+#
+# Copyright (c) 2015      Andreas Schneider <asn at samba.org>
+#
+# 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/>.
+#
+
+from samba.provision.kerberos_implementation import (
+    kdb_modules_dir,
+    kdc_default_config_dir)
+from samba import _glue
+import os
+
+def make_kdcconf(realm, domain, kdcconfdir, logdir):
+
+    if _glue.is_heimdal_built:
+        return
+
+    # Do nothing if kdc.conf has been set
+    if 'KRB5_KDC_PROFILE' in os.environ:
+        return
+
+    # We are in selftest
+    if 'SAMBA_SELFTEST' in os.environ and 'MITKRB5' in os.environ:
+        return
+
+    # If not specified use the default
+    if kdcconfdir is None:
+        kdcconfdir = kdc_default_config_dir
+
+    kdcconf = "%s/kdc.conf" % kdcconfdir
+
+    assert domain is not None
+    domain = domain.upper()
+
+    assert realm is not None
+    realm = realm.upper()
+
+    f = open(kdcconf, 'w')
+    try:
+        f.write("[kdcdefaults]\n")
+
+        f.write("\tkdc_ports = 88\n")
+        f.write("\tkdc_tcp_ports = 88\n")
+        f.write("\tkadmind_port = 464\n")
+        f.write("\n")
+
+        f.write("[realms]\n")
+
+        f.write("\t%s = {\n" % realm)
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("\t%s = {\n" % realm.lower())
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("\t%s = {\n" % domain)
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("[dbmodules]\n")
+
+        f.write("\tdb_modules_dir = %s\n" % kdb_modules_dir)
+        f.write("\n")
+
+        f.write("\t%s = {\n" % realm)
+        f.write("\t\tdb_library = samba\n")
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("\t%s = {\n" % realm.lower())
+        f.write("\t\tdb_library = samba\n")
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("\t%s = {\n" % domain)
+        f.write("\t\tdb_library = samba\n")
+        f.write("\t}\n")
+        f.write("\n")
+
+        f.write("[logging]\n")
+
+        f.write("\tkdc = FILE:%s/mit_kdc.log\n" % logdir)
+        f.write("\tadmin_server = FILE:%s/mit_kadmin.log\n" % logdir)
+        f.write("\n")
+    finally:
+        f.close()
-- 
2.12.2


From 63f22381bb7928788f1a7ea585bafba6cda6202f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 23 Nov 2015 15:08:54 +0100
Subject: [PATCH 37/50] waf: Move python build instructions to wscript

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 python/wscript       | 44 ++++++++++++++++++++++++++++++++++++++++++++
 python/wscript_build | 36 ------------------------------------
 2 files changed, 44 insertions(+), 36 deletions(-)
 delete mode 100644 python/wscript_build

diff --git a/python/wscript b/python/wscript
index 714d649219d..687a268412f 100644
--- a/python/wscript
+++ b/python/wscript
@@ -43,3 +43,47 @@ kdc_default_config_dir = "{1}"
             f.write(data.format(modulesdir, kdc_path))
     finally:
         f.close()
+
+def build(bld):
+    bld.SAMBA_LIBRARY('samba_python',
+                      source=[],
+                      deps='''
+                           LIBPYTHON
+                           pytalloc-util
+                           pyrpc_util
+                           ''',
+                      grouping_library=True,
+                      private_library=True,
+                      pyembed=True,
+                      enabled=bld.PYTHON_BUILD_IS_ENABLED())
+
+    bld.SAMBA_SUBSYSTEM('LIBPYTHON',
+                        source='modules.c',
+                        public_deps='',
+                        init_function_sentinel='{NULL,NULL}',
+                        deps='talloc',
+                        pyext=True,
+                        enabled=bld.PYTHON_BUILD_IS_ENABLED())
+
+    for env in bld.gen_python_environments():
+        pytalloc_util = bld.pyembed_libname('pytalloc-util')
+        pyparam_util = bld.pyembed_libname('pyparam_util')
+
+        bld.SAMBA_PYTHON('python_glue',
+                         source='pyglue.c',
+                         deps='''
+                              %s
+                              samba-util
+                              netif
+                              %s
+                              ''' % (pyparam_util, pytalloc_util),
+                         realname='samba/_glue.so')
+
+    if bld.PYTHON_BUILD_IS_ENABLED():
+        for env in bld.gen_python_environments():
+            # install out various python scripts for use by make test
+            bld.SAMBA_SCRIPT('samba_python_files',
+                             pattern='samba/**/*.py',
+                             installdir='python')
+
+            bld.INSTALL_WILDCARD('${PYTHONARCHDIR}', 'samba/**/*.py', flat=False)
diff --git a/python/wscript_build b/python/wscript_build
deleted file mode 100644
index 87da26f710f..00000000000
--- a/python/wscript_build
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-bld.SAMBA_LIBRARY('samba_python',
-	source=[],
-	deps='LIBPYTHON pytalloc-util pyrpc_util',
-	grouping_library=True,
-	private_library=True,
-	pyembed=True,
-	enabled=bld.PYTHON_BUILD_IS_ENABLED())
-
-bld.SAMBA_SUBSYSTEM('LIBPYTHON',
-	source='modules.c',
-	public_deps='',
-	init_function_sentinel='{NULL,NULL}',
-	deps='talloc',
-	pyext=True,
-	enabled=bld.PYTHON_BUILD_IS_ENABLED())
-
-for env in bld.gen_python_environments():
-	pytalloc_util = bld.pyembed_libname('pytalloc-util')
-	pyparam_util = bld.pyembed_libname('pyparam_util')
-
-	bld.SAMBA_PYTHON('python_glue',
-		source='pyglue.c',
-		deps='%s samba-util netif %s' % (pyparam_util, pytalloc_util),
-		realname='samba/_glue.so'
-		)
-
-if bld.PYTHON_BUILD_IS_ENABLED():
-    for env in bld.gen_python_environments():
-	# install out various python scripts for use by make test
-	bld.SAMBA_SCRIPT('samba_python_files',
-	                 pattern='samba/**/*.py',
-	                 installdir='python')
-
-	bld.INSTALL_WILDCARD('${PYTHONARCHDIR}', 'samba/**/*.py', flat=False)
-- 
2.12.2


From aa8a42920723e401c85eff3cfaf5246bc3095bf3 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 27 Sep 2016 18:53:44 +0200
Subject: [PATCH 38/50] s4-torture: Fix reauth tests with smaller clockskew
 grace time

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/raw/session.c  | 8 ++++----
 source4/torture/smb2/session.c | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/source4/torture/raw/session.c b/source4/torture/raw/session.c
index 6938c88f95d..26b93cca512 100644
--- a/source4/torture/raw/session.c
+++ b/source4/torture/raw/session.c
@@ -304,8 +304,8 @@ static bool test_session_expire1(struct torture_context *tctx)
 		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
 						"raw_fileinfo failed");
 
-		torture_comment(tctx, "sleep 5 seconds\n");
-		smb_msleep(5*1000);
+		torture_comment(tctx, "sleep 10 seconds\n");
+		smb_msleep(10*1000);
 	}
 
 	/*
@@ -343,8 +343,8 @@ static bool test_session_expire1(struct torture_context *tctx)
 		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
 						"raw_fileinfo failed");
 
-		torture_comment(tctx, "sleep 5 seconds\n");
-		smb_msleep(5*1000);
+		torture_comment(tctx, "sleep 10 seconds\n");
+		smb_msleep(10*1000);
 
 		torture_comment(tctx, "query info => EXPIRED\n");
 		ZERO_STRUCT(qfinfo.access_information.out);
diff --git a/source4/torture/smb2/session.c b/source4/torture/smb2/session.c
index e35ec85c6a3..e3c5676a80a 100644
--- a/source4/torture/smb2/session.c
+++ b/source4/torture/smb2/session.c
@@ -1125,8 +1125,8 @@ static bool test_session_expire1(struct torture_context *tctx)
 		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
 						"smb2_getinfo_file failed");
 
-		torture_comment(tctx, "sleep 5 seconds\n");
-		smb_msleep(5*1000);
+		torture_comment(tctx, "sleep 10 seconds\n");
+		smb_msleep(10*1000);
 
 		torture_comment(tctx, "query info => EXPIRED\n");
 		ZERO_STRUCT(qfinfo.access_information.out);
-- 
2.12.2


From f0b470aa7a22ab53a2dcc9d799480ecf856a6ae2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 30 Sep 2016 07:41:09 +0200
Subject: [PATCH 39/50] s4-kdc: Fix logging with the KDB driver

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 8a2bfe9b715..0531b017fdb 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -76,7 +76,7 @@ int mit_samba_context_init(struct mit_samba_context **_ctx)
 		goto done;
 	}
 
-	setup_logging("mitkdc", DEBUG_STDOUT);
+	setup_logging("mitkdc", DEBUG_DEFAULT_STDOUT);
 
 	/* init s4 configuration */
 	s4_conf_file = lpcfg_configfile(base_ctx.lp_ctx);
-- 
2.12.2


From d8577c05c2ef7284ee7468ed94c17f1ecbe52e6e Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 29 Sep 2016 02:03:35 +0200
Subject: [PATCH 40/50] s4-kdc: Implement mit_samba_get_pac()

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++
 source4/kdc/mit_samba.h |  6 +++++
 2 files changed, 74 insertions(+)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 0531b017fdb..275a507e86e 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -366,6 +366,74 @@ int mit_samba_get_pac_data(struct mit_samba_context *ctx,
 	return 0;
 }
 
+int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
+		      krb5_context context,
+		      krb5_db_entry *client,
+		      krb5_keyblock *client_key,
+		      krb5_pac *pac)
+{
+	TALLOC_CTX *tmp_ctx;
+	DATA_BLOB *logon_info_blob = NULL;
+	DATA_BLOB *upn_dns_info_blob = NULL;
+	DATA_BLOB *cred_ndr = NULL;
+	DATA_BLOB **cred_ndr_ptr = NULL;
+	DATA_BLOB cred_blob = data_blob_null;
+	DATA_BLOB *pcred_blob = NULL;
+	NTSTATUS nt_status;
+	krb5_error_code code;
+	struct samba_kdc_entry *skdc_entry;
+
+	skdc_entry = talloc_get_type_abort(client->e_data,
+					   struct samba_kdc_entry);
+
+	tmp_ctx = talloc_named(smb_ctx,
+			       0,
+			       "mit_samba_get_pac_data_blobs context");
+	if (tmp_ctx == NULL) {
+		return ENOMEM;
+	}
+
+#if 0 /* TODO Find out if this is a pkinit_reply key */
+	/* Check if we have a PREAUTH key */
+	if (client_key != NULL) {
+		cred_ndr_ptr = &cred_ndr;
+	}
+#endif
+
+	nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
+					    skdc_entry,
+					    &logon_info_blob,
+					    cred_ndr_ptr,
+					    &upn_dns_info_blob);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		talloc_free(tmp_ctx);
+		return EINVAL;
+	}
+
+	if (cred_ndr != NULL) {
+		code = samba_kdc_encrypt_pac_credentials(context,
+							 client_key,
+							 cred_ndr,
+							 tmp_ctx,
+							 &cred_blob);
+		if (code != 0) {
+			talloc_free(tmp_ctx);
+			return code;
+		}
+		pcred_blob = &cred_blob;
+	}
+
+	code = samba_make_krb5_pac(context,
+				   logon_info_blob,
+				   pcred_blob,
+				   upn_dns_info_blob,
+				   NULL,
+				   pac);
+
+	talloc_free(tmp_ctx);
+	return code;
+}
+
 int mit_samba_update_pac_data(struct mit_samba_context *ctx,
 			      krb5_db_entry *client,
 			      DATA_BLOB *pac_data,
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
index 277b2e57a93..5be77958dc4 100644
--- a/source4/kdc/mit_samba.h
+++ b/source4/kdc/mit_samba.h
@@ -51,6 +51,12 @@ int mit_samba_get_pac_data(struct mit_samba_context *ctx,
 			   krb5_db_entry *client,
 			   DATA_BLOB *data);
 
+int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
+		      krb5_context context,
+		      krb5_db_entry *client,
+		      krb5_keyblock *client_key,
+		      krb5_pac *pac);
+
 int mit_samba_update_pac_data(struct mit_samba_context *ctx,
 			      krb5_db_entry *client,
 			      DATA_BLOB *pac_data,
-- 
2.12.2


From af2d5ba6e5a975319a1b97c9d79cf2f26c6c8ef2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 29 Sep 2016 02:04:00 +0200
Subject: [PATCH 41/50] s4-kdc: Use mit_samba_get_pac() in ks_get_pac()

This adds UPN_DNS_INFO to the PAC.

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit-kdb/kdb_samba_policies.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c
index 396e6fe9d31..8c3a85b1f1f 100644
--- a/source4/kdc/mit-kdb/kdb_samba_policies.c
+++ b/source4/kdc/mit-kdb/kdb_samba_policies.c
@@ -155,11 +155,10 @@ done:
 
 static krb5_error_code ks_get_pac(krb5_context context,
 				  krb5_db_entry *client,
+				  krb5_keyblock *client_key,
 				  krb5_pac *pac)
 {
 	struct mit_samba_context *mit_ctx;
-	DATA_BLOB pac_data;
-	krb5_data data;
 	krb5_error_code code;
 
 	mit_ctx = ks_get_context(context);
@@ -167,27 +166,15 @@ static krb5_error_code ks_get_pac(krb5_context context,
 		return KRB5_KDB_DBNOTINITED;
 	}
 
-	code = mit_samba_get_pac_data(mit_ctx,
-				      client,
-				      &pac_data);
+	code = mit_samba_get_pac(mit_ctx,
+				 context,
+				 client,
+				 client_key,
+				 pac);
 	if (code != 0) {
 		return code;
 	}
 
-	code = krb5_pac_init(context, pac);
-	if (code != 0) {
-		goto done;
-	}
-
-	data = ks_make_data(pac_data.data, pac_data.length);
-
-	code = krb5_pac_add_buffer(context, *pac, PAC_LOGON_INFO, &data);
-	if (code != 0) {
-		goto done;
-	}
-
-done:
-	free(pac_data.data);
 	return code;
 }
 
@@ -332,8 +319,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
 	is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
 
 	if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) {
-
-		code = ks_get_pac(context, client, &pac);
+		code = ks_get_pac(context, client, client_key, &pac);
 		if (code != 0) {
 			goto done;
 		}
@@ -350,7 +336,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
 
 	if (pac == NULL && client != NULL) {
 
-		code = ks_get_pac(context, client, &pac);
+		code = ks_get_pac(context, client, client_key, &pac);
 		if (code != 0) {
 			goto done;
 		}
-- 
2.12.2


From dfbe4614cf88f889c34dddb98198a76eaa93c4de Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 26 Jan 2017 17:04:19 +0100
Subject: [PATCH 42/50] mit-samba: Remove unused mit_samba_get_pac_data()

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 35 -----------------------------------
 source4/kdc/mit_samba.h |  4 ----
 2 files changed, 39 deletions(-)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 275a507e86e..82a6dfddbe1 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -331,41 +331,6 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx,
 	return ret;
 }
 
-int mit_samba_get_pac_data(struct mit_samba_context *ctx,
-			   krb5_db_entry *client,
-			   DATA_BLOB *data)
-{
-	TALLOC_CTX *tmp_ctx;
-	DATA_BLOB *pac_blob;
-	NTSTATUS nt_status;
-	struct samba_kdc_entry *skdc_entry;
-
-	skdc_entry = talloc_get_type_abort(client->e_data,
-					   struct samba_kdc_entry);
-
-	tmp_ctx = talloc_named(ctx, 0, "mit_samba_get_pac_data context");
-	if (!tmp_ctx) {
-		return ENOMEM;
-	}
-
-	nt_status = samba_kdc_get_pac_blob(tmp_ctx, skdc_entry, &pac_blob);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		talloc_free(tmp_ctx);
-		return EINVAL;
-	}
-
-	data->data = (uint8_t *)malloc(pac_blob->length);
-	if (!data->data) {
-		talloc_free(tmp_ctx);
-		return ENOMEM;
-	}
-	memcpy(data->data, pac_blob->data, pac_blob->length);
-	data->length = pac_blob->length;
-
-	talloc_free(tmp_ctx);
-	return 0;
-}
-
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
 		      krb5_context context,
 		      krb5_db_entry *client,
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
index 5be77958dc4..37e7d8d5126 100644
--- a/source4/kdc/mit_samba.h
+++ b/source4/kdc/mit_samba.h
@@ -47,10 +47,6 @@ int mit_samba_get_firstkey(struct mit_samba_context *ctx,
 int mit_samba_get_nextkey(struct mit_samba_context *ctx,
 			  krb5_db_entry **_kentry);
 
-int mit_samba_get_pac_data(struct mit_samba_context *ctx,
-			   krb5_db_entry *client,
-			   DATA_BLOB *data);
-
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
 		      krb5_context context,
 		      krb5_db_entry *client,
-- 
2.12.2


From 6eda6aeed03001808b59f87b51c63d4ca004c844 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 29 Sep 2016 08:38:58 +0200
Subject: [PATCH 43/50] s4-pac-glue: Do not add an empty PAC_TYPE_LOGON_NAME
 with MIT

MIT Kerberos will insert an empty PAC_TYPE_LOGON_NAME during
krb5_pac_sign().

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/pac-glue.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index 079030ee5e8..1a862e2a8a3 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -420,10 +420,13 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
 	krb5_data cred_data;
 	krb5_data upn_data;
 	krb5_data deleg_data;
-	krb5_data null_data;
 	krb5_error_code ret;
-
-	ZERO_STRUCT(null_data);
+#ifdef SAMBA4_USES_HEIMDAL
+	krb5_data null_data = {
+		.length = 0,
+		.data = NULL,
+	};
+#endif
 
 	/* The user account may be set not to want the PAC */
 	if (logon_blob == NULL) {
@@ -503,10 +506,13 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
 		}
 	}
 
+#ifdef SAMBA4_USES_HEIMDAL
 	/*
 	 * null_data will be filled by the generic KDC code in the caller
 	 * here we just add it in order to have it before
 	 * PAC_TYPE_UPN_DNS_INFO
+	 *
+	 * Not needed with MIT Kerberos - asn
 	 */
 	ret = krb5_pac_add_buffer(context, *pac,
 				  PAC_TYPE_LOGON_NAME,
@@ -516,6 +522,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
 		smb_krb5_free_data_contents(context, &deleg_data);
 		return ret;
 	}
+#endif
 
 	if (upn_blob != NULL) {
 		ret = krb5_pac_add_buffer(context, *pac,
-- 
2.12.2


From b14a768bfc673cf18ecfb8ca151e8f0dc0211fc2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 30 Sep 2016 07:43:31 +0200
Subject: [PATCH 44/50] s4-kdc: Implement mit_samba_get_repac()

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++
 source4/kdc/mit_samba.h |  10 ++
 2 files changed, 392 insertions(+)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 82a6dfddbe1..9e605f05506 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -30,6 +30,7 @@
 #include "kdc/sdb.h"
 #include "kdc/sdb_kdb.h"
 #include "auth/kerberos/kerberos.h"
+#include "auth/kerberos/pac_utils.h"
 #include "kdc/samba_kdc.h"
 #include "kdc/pac-glue.h"
 #include "kdc/db-glue.h"
@@ -468,6 +469,387 @@ done:
 	return ret;
 }
 
+int mit_samba_reget_pac(struct mit_samba_context *ctx,
+			krb5_context context,
+			int flags,
+			krb5_const_principal client_principal,
+			krb5_db_entry *client,
+			krb5_db_entry *server,
+			krb5_db_entry *krbtgt,
+			krb5_keyblock *krbtgt_keyblock,
+			krb5_pac *pac)
+{
+	TALLOC_CTX *tmp_ctx;
+	krb5_error_code code;
+	NTSTATUS nt_status;
+	DATA_BLOB *pac_blob = NULL;
+	DATA_BLOB *upn_blob = NULL;
+	DATA_BLOB *deleg_blob = NULL;
+	struct samba_kdc_entry *client_skdc_entry = NULL;
+	struct samba_kdc_entry *krbtgt_skdc_entry;
+	bool is_in_db = false;
+	bool is_untrusted = false;
+	size_t num_types = 0;
+	uint32_t *types = NULL;
+	uint32_t forced_next_type = 0;
+	size_t i = 0;
+	ssize_t logon_info_idx = -1;
+	ssize_t delegation_idx = -1;
+	ssize_t logon_name_idx = -1;
+	ssize_t upn_dns_info_idx = -1;
+	ssize_t srv_checksum_idx = -1;
+	ssize_t kdc_checksum_idx = -1;
+	krb5_pac new_pac = NULL;
+	bool ok;
+
+	if (client != NULL) {
+		client_skdc_entry =
+			talloc_get_type_abort(client->e_data,
+					      struct samba_kdc_entry);
+
+		/* The user account may be set not to want the PAC */
+		ok = samba_princ_needs_pac(client_skdc_entry);
+		if (!ok) {
+			return EINVAL;
+		}
+	}
+
+	if (krbtgt == NULL) {
+		return EINVAL;
+	}
+	krbtgt_skdc_entry =
+		talloc_get_type_abort(krbtgt->e_data,
+				      struct samba_kdc_entry);
+
+	tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context");
+	if (!tmp_ctx) {
+		return ENOMEM;
+	}
+
+	code = samba_krbtgt_is_in_db(krbtgt_skdc_entry,
+				     &is_in_db,
+				     &is_untrusted);
+	if (code != 0) {
+		goto done;
+	}
+
+	if (is_untrusted) {
+		if (client == NULL) {
+			return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+		}
+
+		nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
+						    client_skdc_entry,
+						    &pac_blob,
+						    NULL,
+						    &upn_blob);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			code = EINVAL;
+			goto done;
+		}
+	} else {
+		struct PAC_SIGNATURE_DATA *pac_srv_sig;
+		struct PAC_SIGNATURE_DATA *pac_kdc_sig;
+
+		pac_blob = talloc_zero(tmp_ctx, DATA_BLOB);
+		if (pac_blob == NULL) {
+			code = ENOMEM;
+			goto done;
+		}
+
+		pac_srv_sig = talloc_zero(tmp_ctx, struct PAC_SIGNATURE_DATA);
+		if (pac_srv_sig == NULL) {
+			code = ENOMEM;
+			goto done;
+		}
+
+		pac_kdc_sig = talloc_zero(tmp_ctx, struct PAC_SIGNATURE_DATA);
+		if (pac_kdc_sig == NULL) {
+			code = ENOMEM;
+			goto done;
+		}
+
+		nt_status = samba_kdc_update_pac_blob(tmp_ctx,
+						      context,
+						      *pac,
+						      pac_blob,
+						      pac_srv_sig,
+						      pac_kdc_sig);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			DEBUG(0, ("Update PAC blob failed: %s\n",
+				  nt_errstr(nt_status)));
+			code = EINVAL;
+			goto done;
+		}
+
+		if (is_in_db) {
+			/*
+			 * Now check the KDC signature, fetching the correct
+			 * key based on the enc type.
+			 */
+			code = check_pac_checksum(pac_srv_sig->signature,
+						  pac_kdc_sig,
+						  context,
+						  krbtgt_keyblock);
+			if (code != 0) {
+				DBG_INFO("PAC KDC signature failed to verify\n");
+				goto done;
+			}
+		}
+	}
+
+	if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
+		deleg_blob = talloc_zero(tmp_ctx, DATA_BLOB);
+		if (deleg_blob == NULL) {
+			code = ENOMEM;
+			goto done;
+		}
+
+		nt_status = samba_kdc_update_delegation_info_blob(tmp_ctx,
+								  context,
+								  *pac,
+								  server->princ,
+								  discard_const(client_principal),
+								  deleg_blob);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			DEBUG(0, ("Update delegation info failed: %s\n",
+				  nt_errstr(nt_status)));
+			code = EINVAL;
+			goto done;
+		}
+	}
+
+	/* Check the types of the given PAC */
+	code = krb5_pac_get_types(context, *pac, &num_types, &types);
+	if (code != 0) {
+		goto done;
+	}
+
+	for (i = 0; i < num_types; i++) {
+		switch (types[i]) {
+		case PAC_TYPE_LOGON_INFO:
+			if (logon_info_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    logon_info_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			logon_info_idx = i;
+			break;
+		case PAC_TYPE_CONSTRAINED_DELEGATION:
+			if (delegation_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    delegation_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			delegation_idx = i;
+			break;
+		case PAC_TYPE_LOGON_NAME:
+			if (logon_name_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    logon_name_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			logon_name_idx = i;
+			break;
+		case PAC_TYPE_UPN_DNS_INFO:
+			if (upn_dns_info_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    upn_dns_info_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			upn_dns_info_idx = i;
+			break;
+		case PAC_TYPE_SRV_CHECKSUM:
+			if (srv_checksum_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    srv_checksum_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			srv_checksum_idx = i;
+			break;
+		case PAC_TYPE_KDC_CHECKSUM:
+			if (kdc_checksum_idx != -1) {
+				DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
+					    types[i],
+					    kdc_checksum_idx,
+					    i);
+				SAFE_FREE(types);
+				code = EINVAL;
+				goto done;
+			}
+			kdc_checksum_idx = i;
+			break;
+		default:
+			continue;
+		}
+	}
+
+	if (logon_info_idx == -1) {
+		DEBUG(1, ("PAC_TYPE_LOGON_INFO missing\n"));
+		SAFE_FREE(types);
+		code = EINVAL;
+		goto done;
+	}
+	if (logon_name_idx == -1) {
+		DEBUG(1, ("PAC_TYPE_LOGON_NAME missing\n"));
+		SAFE_FREE(types);
+		code = EINVAL;
+		goto done;
+	}
+	if (srv_checksum_idx == -1) {
+		DEBUG(1, ("PAC_TYPE_SRV_CHECKSUM missing\n"));
+		SAFE_FREE(types);
+		code = EINVAL;
+		goto done;
+	}
+	if (kdc_checksum_idx == -1) {
+		DEBUG(1, ("PAC_TYPE_KDC_CHECKSUM missing\n"));
+		SAFE_FREE(types);
+		code = EINVAL;
+		goto done;
+	}
+
+	/* Build an updated PAC */
+	code = krb5_pac_init(context, &new_pac);
+	if (code != 0) {
+		SAFE_FREE(types);
+		goto done;
+	}
+
+	for (i = 0;;) {
+		krb5_data type_data;
+		DATA_BLOB type_blob = data_blob_null;
+		uint32_t type;
+
+		if (forced_next_type != 0) {
+			/*
+			 * We need to inject possible missing types
+			 */
+			type = forced_next_type;
+			forced_next_type = 0;
+		} else if (i < num_types) {
+			type = types[i];
+			i++;
+		} else {
+			break;
+		}
+
+		switch (type) {
+		case PAC_TYPE_LOGON_INFO:
+			type_blob = *pac_blob;
+
+			if (delegation_idx == -1 && deleg_blob != NULL) {
+				/* inject CONSTRAINED_DELEGATION behind */
+				forced_next_type = PAC_TYPE_CONSTRAINED_DELEGATION;
+			}
+			break;
+		case PAC_TYPE_CONSTRAINED_DELEGATION:
+			if (deleg_blob != NULL) {
+				type_blob = *deleg_blob;
+			}
+			break;
+		case PAC_TYPE_CREDENTIAL_INFO:
+			/*
+			 * Note that we copy the credential blob,
+			 * as it's only usable with the PKINIT based
+			 * AS-REP reply key, it's only available on the
+			 * host which did the AS-REQ/AS-REP exchange.
+			 *
+			 * This matches Windows 2008R2...
+			 */
+			break;
+		case PAC_TYPE_LOGON_NAME:
+			/*
+			 * This is generated in the main KDC code
+			 */
+			continue;
+		case PAC_TYPE_UPN_DNS_INFO:
+			/*
+			 * Replace in the RODC case, otherwise
+			 * upn_blob is NULL and we just copy.
+			 */
+			if (upn_blob != NULL) {
+				type_blob = *upn_blob;
+			}
+			break;
+		case PAC_TYPE_SRV_CHECKSUM:
+			/*
+			 * This is generated in the main KDC code
+			 */
+			continue;
+		case PAC_TYPE_KDC_CHECKSUM:
+			/*
+			 * This is generated in the main KDC code
+			 */
+			continue;
+		default:
+			/* just copy... */
+			break;
+		}
+
+		if (type_blob.length != 0) {
+			code = smb_krb5_copy_data_contents(&type_data,
+							   type_blob.data,
+							   type_blob.length);
+			if (code != 0) {
+				SAFE_FREE(types);
+				krb5_pac_free(context, new_pac);
+				goto done;
+			}
+		} else {
+			code = krb5_pac_get_buffer(context,
+						   *pac,
+						   type,
+						   &type_data);
+			if (code != 0) {
+				SAFE_FREE(types);
+				krb5_pac_free(context, new_pac);
+				goto done;
+			}
+		}
+
+		code = krb5_pac_add_buffer(context,
+					   new_pac,
+					   type,
+					   &type_data);
+		smb_krb5_free_data_contents(context, &type_data);
+		if (code != 0) {
+			SAFE_FREE(types);
+			krb5_pac_free(context, new_pac);
+			goto done;
+		}
+	}
+
+	SAFE_FREE(types);
+
+	/* We now replace the pac */
+	krb5_pac_free(context, *pac);
+	*pac = new_pac;
+done:
+	talloc_free(tmp_ctx);
+	return code;
+}
+
 /* provide header, function is exported but there are no public headers */
 
 krb5_error_code encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code);
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
index 37e7d8d5126..b74a2d7a971 100644
--- a/source4/kdc/mit_samba.h
+++ b/source4/kdc/mit_samba.h
@@ -53,6 +53,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
 		      krb5_keyblock *client_key,
 		      krb5_pac *pac);
 
+int mit_samba_reget_pac(struct mit_samba_context *ctx,
+			krb5_context context,
+			int flags,
+			krb5_const_principal client_principal,
+			krb5_db_entry *client,
+			krb5_db_entry *server,
+			krb5_db_entry *krbtgt,
+			krb5_keyblock *krbtgt_keyblock,
+			krb5_pac *pac);
+
 int mit_samba_update_pac_data(struct mit_samba_context *ctx,
 			      krb5_db_entry *client,
 			      DATA_BLOB *pac_data,
-- 
2.12.2


From f6bd08861bb2c6d4029e48d9737463514734f87b Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 30 Sep 2016 07:43:47 +0200
Subject: [PATCH 45/50] s4-kdc: Use mit_samba_reget_pac() in ks_verify_pac()

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit-kdb/kdb_samba_policies.c | 50 +++++++++++++++++---------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c
index 8c3a85b1f1f..81140abfd50 100644
--- a/source4/kdc/mit-kdb/kdb_samba_policies.c
+++ b/source4/kdc/mit-kdb/kdb_samba_policies.c
@@ -182,6 +182,8 @@ static krb5_error_code ks_verify_pac(krb5_context context,
 				     unsigned int flags,
 				     krb5_const_principal client_princ,
 				     krb5_db_entry *client,
+				     krb5_db_entry *server,
+				     krb5_db_entry *krbtgt,
 				     krb5_keyblock *server_key,
 				     krb5_keyblock *krbtgt_key,
 				     krb5_timestamp authtime,
@@ -191,9 +193,7 @@ static krb5_error_code ks_verify_pac(krb5_context context,
 	struct mit_samba_context *mit_ctx;
 	krb5_authdata **authdata = NULL;
 	krb5_pac ipac = NULL;
-	DATA_BLOB pac_data = { NULL, 0 };
 	DATA_BLOB logon_data = { NULL, 0 };
-	krb5_data data;
 	krb5_error_code code;
 
 	mit_ctx = ks_get_context(context);
@@ -257,28 +257,23 @@ static krb5_error_code ks_verify_pac(krb5_context context,
 	}
 
 	/* check and update PAC */
-	pac_data.data = authdata[0]->contents;
-	pac_data.length = authdata[0]->length;
-
-	code = mit_samba_update_pac_data(mit_ctx,
-					 client,
-					 &pac_data,
-					 &logon_data);
-	if (code != 0) {
-		goto done;
-	}
-
-	code = krb5_pac_init(context, pac);
+	code = krb5_pac_parse(context,
+			      authdata[0]->contents,
+			      authdata[0]->length,
+			      pac);
 	if (code != 0) {
 		goto done;
 	}
 
-	data = ks_make_data(logon_data.data, logon_data.length);
-
-	code = krb5_pac_add_buffer(context, *pac, PAC_LOGON_INFO, &data);
-	if (code != 0) {
-		goto done;
-	}
+	code = mit_samba_reget_pac(mit_ctx,
+				   context,
+				   flags,
+				   client_princ,
+				   client,
+				   server,
+				   krbtgt,
+				   krbtgt_key,
+				   pac);
 
 done:
 	krb5_free_authdata(context, authdata);
@@ -326,9 +321,17 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
 	}
 
 	if (!is_as_req) {
-		code = ks_verify_pac(context, flags, ks_client_princ, client,
-				server_key, krbtgt_key, authtime,
-				tgt_auth_data, &pac);
+		code = ks_verify_pac(context,
+				     flags,
+				     ks_client_princ,
+				     client,
+				     server,
+				     krbtgt,
+				     server_key,
+				     krbtgt_key,
+				     authtime,
+				     tgt_auth_data,
+				     &pac);
 		if (code != 0) {
 			goto done;
 		}
@@ -350,6 +353,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
 	code = krb5_pac_sign(context, pac, authtime, ks_client_princ,
 			server_key, krbtgt_key, &pac_data);
 	if (code != 0) {
+		DBG_ERR("krb5_pac_sign failed: %d\n", code);
 		goto done;
 	}
 
-- 
2.12.2


From 05de028f14c3b58f0fb6db706d830750629605b7 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 26 Jan 2017 17:07:14 +0100
Subject: [PATCH 46/50] mit-samba: Remove obsolete mit_samba_update_pac_data()

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 69 -------------------------------------------------
 source4/kdc/mit_samba.h | 10 -------
 2 files changed, 79 deletions(-)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 9e605f05506..81189018172 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -400,75 +400,6 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
 	return code;
 }
 
-int mit_samba_update_pac_data(struct mit_samba_context *ctx,
-			      krb5_db_entry *client,
-			      DATA_BLOB *pac_data,
-			      DATA_BLOB *logon_data)
-{
-	TALLOC_CTX *tmp_ctx;
-	DATA_BLOB *logon_blob;
-	krb5_error_code code;
-	NTSTATUS nt_status;
-	krb5_pac pac = NULL;
-	int ret;
-	struct samba_kdc_entry *skdc_entry = NULL;
-
-	if (client) {
-		skdc_entry = talloc_get_type_abort(client->e_data,
-						   struct samba_kdc_entry);
-	}
-
-	/* The user account may be set not to want the PAC */
-	if (client && !samba_princ_needs_pac(skdc_entry)) {
-		return EINVAL;
-	}
-
-	tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac_data context");
-	if (!tmp_ctx) {
-		return ENOMEM;
-	}
-
-	logon_blob = talloc_zero(tmp_ctx, DATA_BLOB);
-	if (!logon_blob) {
-		ret = ENOMEM;
-		goto done;
-	}
-
-	code = krb5_pac_parse(ctx->context,
-			      pac_data->data, pac_data->length, &pac);
-	if (code) {
-		ret = EINVAL;
-		goto done;
-	}
-
-	/* TODO: An implementation-specific decision will need to be
-	 * made as to when to check the KDC pac signature, and how to
-	 * untrust untrusted RODCs */
-	nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
-					      pac, logon_blob, NULL, NULL);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(0, ("Building PAC failed: %s\n",
-			  nt_errstr(nt_status)));
-		ret = EINVAL;
-		goto done;
-	}
-
-	logon_data->data = (uint8_t *)malloc(logon_blob->length);
-	if (!logon_data->data) {
-		ret = ENOMEM;
-		goto done;
-	}
-	memcpy(logon_data->data, logon_blob->data, logon_blob->length);
-	logon_data->length = logon_blob->length;
-
-	ret = 0;
-
-done:
-	if (pac) krb5_pac_free(ctx->context, pac);
-	talloc_free(tmp_ctx);
-	return ret;
-}
-
 int mit_samba_reget_pac(struct mit_samba_context *ctx,
 			krb5_context context,
 			int flags,
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
index b74a2d7a971..df088491ecb 100644
--- a/source4/kdc/mit_samba.h
+++ b/source4/kdc/mit_samba.h
@@ -63,16 +63,6 @@ int mit_samba_reget_pac(struct mit_samba_context *ctx,
 			krb5_keyblock *krbtgt_keyblock,
 			krb5_pac *pac);
 
-int mit_samba_update_pac_data(struct mit_samba_context *ctx,
-			      krb5_db_entry *client,
-			      DATA_BLOB *pac_data,
-			      DATA_BLOB *logon_data);
-
-int mit_samba_update_pac_data(struct mit_samba_context *ctx,
-			      krb5_db_entry *client,
-			      DATA_BLOB *pac_data,
-			      DATA_BLOB *logon_data);
-
 int mit_samba_check_client_access(struct mit_samba_context *ctx,
 				  krb5_db_entry *client,
 				  const char *client_name,
-- 
2.12.2


From b9610333ea87f5d2ad934504be32080313eb553e Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 27 Jan 2017 12:11:33 +0100
Subject: [PATCH 47/50] mit_samba: Fix principal lookup for cross domain
 referral

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit_samba.c | 51 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 81189018172..677e53330a0 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -188,6 +188,7 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
 	krb5_db_entry *kentry;
 	int ret;
 	int sflags = 0;
+	krb5_principal referral_principal = NULL;
 
 	kentry = calloc(1, sizeof(krb5_db_entry));
 	if (kentry == NULL) {
@@ -217,6 +218,8 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
 	 * backend and we will fail to parse the entry later */
 	sflags |= SDB_F_ADMIN_DATA;
 
+
+fetch_referral_principal:
 	ret = samba_kdc_fetch(ctx->context, ctx->db_ctx,
 			      principal, sflags, 0, &sentry);
 	switch (ret) {
@@ -225,14 +228,43 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
 	case SDB_ERR_NOENTRY:
 		ret = KRB5_KDB_NOENTRY;
 		goto done;
-	case SDB_ERR_WRONG_REALM:
-		/*
-		 * If we have a wrong realm e.g. if we try get a cross forest
-		 * ticket, we return a ticket with the correct realm. The KDC
-		 * will detect this an return the appropriate return code.
-		 */
-		ret = 0;
-		break;
+	case SDB_ERR_WRONG_REALM: {
+		char *dest_realm = NULL;
+		const char *our_realm = lpcfg_realm(ctx->db_ctx->lp_ctx);
+
+		if (sflags & SDB_F_FOR_AS_REQ) {
+			ret = 0;
+			break;
+		}
+
+		if (referral_principal != NULL) {
+			sdb_free_entry(&sentry);
+			ret = KRB5_KDB_NOENTRY;
+			goto done;
+		}
+
+		dest_realm = smb_krb5_principal_get_realm(ctx->context,
+							  sentry.entry.principal);
+		sdb_free_entry(&sentry);
+		if (dest_realm == NULL) {
+			ret = KRB5_KDB_NOENTRY;
+			goto done;
+		}
+
+		ret = smb_krb5_make_principal(ctx->context,
+					      &referral_principal,
+					      our_realm,
+					      KRB5_TGS_NAME,
+					      dest_realm,
+					      NULL);
+		SAFE_FREE(dest_realm);
+		if (ret != 0) {
+			goto done;
+		}
+
+		principal = referral_principal;
+		goto fetch_referral_principal;
+	}
 	case SDB_ERR_NOT_FOUND_HERE:
 		/* FIXME: RODC support */
 	default:
@@ -244,6 +276,9 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
 	sdb_free_entry(&sentry);
 
 done:
+	krb5_free_principal(ctx->context, referral_principal);
+	referral_principal = NULL;
+
 	if (ret) {
 		free(kentry);
 	} else {
-- 
2.12.2


From c88377e3b405815e486866fa5609ffce14bc7e34 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 28 Sep 2016 07:22:32 +0200
Subject: [PATCH 48/50] FIXME s4-kdc: Do not segfault if client is not set

Signed-off-by: Andreas Schneider <asn at samba.org>
---
 source4/kdc/mit-kdb/kdb_samba_policies.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c
index 81140abfd50..ec32687fdc6 100644
--- a/source4/kdc/mit-kdb/kdb_samba_policies.c
+++ b/source4/kdc/mit-kdb/kdb_samba_policies.c
@@ -446,6 +446,14 @@ void kdb_samba_db_audit_as_req(krb5_context context,
 		return;
 	}
 
+	/*
+	 * FIXME: This segfaulted with a FAST test
+	 * FIND_FAST: <unknown client> for <unknown server>, Unknown FAST armor type 0
+	 */
+	if (client == NULL) {
+		return;
+	}
+
 	switch (error_code) {
 	case 0:
 		mit_samba_zero_bad_password_count(client);
-- 
2.12.2


From 72a3a1f816943bb168fc3a267a976e5f43e74058 Mon Sep 17 00:00:00 2001
From: Simo Sorce <idra at samba.org>
Date: Thu, 3 Dec 2015 11:02:23 -0500
Subject: [PATCH 49/50] FIXME s4-ldb: Use correct salting for interdomain trust
 accounts

+++++++++++

asn: This patch is incorrect, it breaks salting for computer accounts!

See

make test TESTS="samba.blackbox.wbinfo"

or

make -j testenv SELFTEST_TESTENV="ad_member:local"
bin/wbinfo -K $DC_USERNAME%$DC_PASSWORD

+++++++++++

Interdomain trusts use a salt of krbtgt/OTHER_REALMFLATNAME at OUR.REALM

Signed-off-by: Simo Sorce <idra at samba.org>
---
 source4/dsdb/samdb/ldb_modules/password_hash.c | 65 ++++++++++++++++----------
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 7d38d215f16..c179d51628e 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -127,7 +127,6 @@ struct setup_password_fields_io {
 		NTTIME pwdLastSet;
 		const char *sAMAccountName;
 		const char *user_principal_name;
-		bool is_computer;
 		bool is_krbtgt;
 		uint32_t restrictions;
 		struct dom_sid *account_sid;
@@ -674,6 +673,8 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 	krb5_data salt;
 	krb5_keyblock key;
 	krb5_data cleartext_data;
+	const char *princ_component_1 = NULL;
+	char *princ_component_2 = NULL;
 
 	ldb = ldb_module_get_ctx(io->ac->module);
 	cleartext_data.data = (char *)io->n.cleartext_utf8->data;
@@ -686,9 +687,8 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 	/*
 	 * Determine a salting principal
 	 */
-	if (io->u.is_computer) {
+	if (io->u.sAMAccountType == ATYPE_WORKSTATION_TRUST) {
 		char *name;
-		char *saltbody;
 
 		name = strlower_talloc(io->ac, io->u.sAMAccountName);
 		if (!name) {
@@ -699,40 +699,53 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 			name[strlen(name)-1] = '\0';
 		}
 
-		saltbody = talloc_asprintf(io->ac, "%s.%s", name,
+		princ_component_2 = talloc_asprintf(io->ac, "%s.%s", name,
 					   io->ac->status->domain_data.dns_domain);
-		if (!saltbody) {
+		if (!princ_component_2) {
+			return ldb_oom(ldb);
+		}
+
+		princ_component_1 = talloc_strdup(io->ac, "host");
+		if (!princ_component_1) {
+			return ldb_oom(ldb);
+		}
+
+	} else if (io->u.sAMAccountType == ATYPE_INTERDOMAIN_TRUST) {
+
+		princ_component_2 = strupper_talloc(io->ac, io->u.sAMAccountName);
+		if (!princ_component_2) {
+			return ldb_oom(ldb);
+		}
+
+		if (princ_component_2[strlen(princ_component_2)-1] == '$') {
+			princ_component_2[strlen(princ_component_2)-1] = '\0';
+		}
+
+		princ_component_1 = talloc_strdup(io->ac, "krbtgt");
+		if (!princ_component_1) {
 			return ldb_oom(ldb);
 		}
-		
-		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
-					       &salt_principal,
-					       io->ac->status->domain_data.realm,
-					       "host", saltbody, NULL);
 	} else if (io->u.user_principal_name) {
-		char *user_principal_name;
 		char *p;
 
-		user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name);
-		if (!user_principal_name) {
+		princ_component_1 = talloc_strdup(io->ac, io->u.user_principal_name);
+		if (!princ_component_1) {
 			return ldb_oom(ldb);
 		}
 
-		p = strchr(user_principal_name, '@');
+		p = strchr(princ_component_1, '@');
 		if (p) {
 			p[0] = '\0';
 		}
-
-		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
-					       &salt_principal,
-					       io->ac->status->domain_data.realm,
-					       user_principal_name, NULL);
 	} else {
-		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
-					       &salt_principal,
-					       io->ac->status->domain_data.realm,
-					       io->u.sAMAccountName, NULL);
-	}
+		princ_component_1 = io->u.sAMAccountName;
+	}
+	krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
+					   &salt_principal,
+				           io->ac->status->domain_data.realm,
+				           princ_component_1,
+					   princ_component_2,
+					   NULL);
 	if (krb5_ret) {
 		ldb_asprintf_errstring(ldb,
 				       "setup_kerberos_keys: "
@@ -2935,7 +2948,9 @@ static int setup_io(struct ph_context *ac,
 								      "sAMAccountName", NULL);
 	io->u.user_principal_name	= ldb_msg_find_attr_as_string(info_msg,
 								      "userPrincipalName", NULL);
-	io->u.is_computer		= ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
+	io->u.sAMAccountType = ldb_msg_find_attr_as_uint(info_msg,
+							 "sAMAccountType",
+							 ATYPE_NORMAL_ACCOUNT);
 
 	/* Ensure it has an objectSID too */
 	io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
-- 
2.12.2


From 7f4611a64ab009efb96e811cdd018074308106ad Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 12 Sep 2016 19:40:56 +0200
Subject: [PATCH 50/50] Revert "FIXME s4-ldb: Use correct salting for
 interdomain trust accounts"

This reverts commit bdec068d80d7281c744caa3622131569827bd9b0.
---
 source4/dsdb/samdb/ldb_modules/password_hash.c | 63 ++++++++++----------------
 1 file changed, 24 insertions(+), 39 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index c179d51628e..23814ebc8dc 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -128,6 +128,7 @@ struct setup_password_fields_io {
 		const char *sAMAccountName;
 		const char *user_principal_name;
 		bool is_krbtgt;
+		bool is_computer;
 		uint32_t restrictions;
 		struct dom_sid *account_sid;
 	} u;
@@ -673,8 +674,6 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 	krb5_data salt;
 	krb5_keyblock key;
 	krb5_data cleartext_data;
-	const char *princ_component_1 = NULL;
-	char *princ_component_2 = NULL;
 
 	ldb = ldb_module_get_ctx(io->ac->module);
 	cleartext_data.data = (char *)io->n.cleartext_utf8->data;
@@ -687,8 +686,9 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 	/*
 	 * Determine a salting principal
 	 */
-	if (io->u.sAMAccountType == ATYPE_WORKSTATION_TRUST) {
+	if (io->u.is_computer) {
 		char *name;
+		char *saltbody;
 
 		name = strlower_talloc(io->ac, io->u.sAMAccountName);
 		if (!name) {
@@ -699,53 +699,40 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
 			name[strlen(name)-1] = '\0';
 		}
 
-		princ_component_2 = talloc_asprintf(io->ac, "%s.%s", name,
+		saltbody = talloc_asprintf(io->ac, "%s.%s", name,
 					   io->ac->status->domain_data.dns_domain);
-		if (!princ_component_2) {
+		if (!saltbody) {
 			return ldb_oom(ldb);
 		}
 
-		princ_component_1 = talloc_strdup(io->ac, "host");
-		if (!princ_component_1) {
-			return ldb_oom(ldb);
-		}
-
-	} else if (io->u.sAMAccountType == ATYPE_INTERDOMAIN_TRUST) {
-
-		princ_component_2 = strupper_talloc(io->ac, io->u.sAMAccountName);
-		if (!princ_component_2) {
-			return ldb_oom(ldb);
-		}
-
-		if (princ_component_2[strlen(princ_component_2)-1] == '$') {
-			princ_component_2[strlen(princ_component_2)-1] = '\0';
-		}
-
-		princ_component_1 = talloc_strdup(io->ac, "krbtgt");
-		if (!princ_component_1) {
-			return ldb_oom(ldb);
-		}
+		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
+					       &salt_principal,
+					       io->ac->status->domain_data.realm,
+					       "host", saltbody, NULL);
 	} else if (io->u.user_principal_name) {
+		char *user_principal_name;
 		char *p;
 
-		princ_component_1 = talloc_strdup(io->ac, io->u.user_principal_name);
-		if (!princ_component_1) {
+		user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name);
+		if (!user_principal_name) {
 			return ldb_oom(ldb);
 		}
 
-		p = strchr(princ_component_1, '@');
+		p = strchr(user_principal_name, '@');
 		if (p) {
 			p[0] = '\0';
 		}
+
+		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
+					       &salt_principal,
+					       io->ac->status->domain_data.realm,
+					       user_principal_name, NULL);
 	} else {
-		princ_component_1 = io->u.sAMAccountName;
-	}
-	krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
-					   &salt_principal,
-				           io->ac->status->domain_data.realm,
-				           princ_component_1,
-					   princ_component_2,
-					   NULL);
+		krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context,
+					       &salt_principal,
+					       io->ac->status->domain_data.realm,
+					       io->u.sAMAccountName, NULL);
+	}
 	if (krb5_ret) {
 		ldb_asprintf_errstring(ldb,
 				       "setup_kerberos_keys: "
@@ -2948,9 +2935,7 @@ static int setup_io(struct ph_context *ac,
 								      "sAMAccountName", NULL);
 	io->u.user_principal_name	= ldb_msg_find_attr_as_string(info_msg,
 								      "userPrincipalName", NULL);
-	io->u.sAMAccountType = ldb_msg_find_attr_as_uint(info_msg,
-							 "sAMAccountType",
-							 ATYPE_NORMAL_ACCOUNT);
+	io->u.is_computer		= ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
 
 	/* Ensure it has an objectSID too */
 	io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
-- 
2.12.2



More information about the samba-technical mailing list