[PATCHSET] Samba AD with MIT Kerberos

Jeremy Allison jra at samba.org
Mon Mar 13 17:44:24 UTC 2017


On Mon, Mar 13, 2017 at 08:29:37AM +0100, Andreas Schneider via samba-technical wrote:
> Hello,
> 
> after more than 3 years of work I finally got this:
> 
> 
> 	ALL OK (14658 tests in 2030 testsuites)
> 
> 
> The testsuite completed for the first time!
> 
> 
> The journey started with the cwrap [1] project to make it possible to test 
> Samba with the MIT KDC. We already pushed some code upstream especially code 
> which not only handles MIT Kerberos but also fixed bugs with Heimdal. We 
> discovered a lot of issues while working on this code.
> 
> Attached is the patchset to implement the missing parts and get everything 
> working.
> 
> 
>  46 files changed, 3113 insertions(+), 507 deletions(-)
> 
> 
> What isn't working yet
> ----------------------
> 
> * KDC canon tests are not implemented yet
> * PKINIT
> * S4U2SELF/S4U2PROXY
> * RODC
> 
> 
> The patches are also available at [2].
> 
> 
> It requires MIT Kerberos 1.15.1! Packages for Fedora 25 can be found at [3].
> 
> 
> Review is much appreciated!

w00t!!!!! This is *AMAZING*. Thanks Andreas and everyone
who worked on this.

I will start working on reviewing this as time permits.

Cheers,

Jeremy.

> [1] https://cwrap.org
> [2] https://git.samba.org/?p=asn/samba.git;a=shortlog;h=refs/heads/master-mit-kdc-ok
> [3] https://copr.fedorainfracloud.org/coprs/asn/samba_ad_dc/
> 
> -- 
> Andreas Schneider                   GPG-ID: CC014E3D
> Samba Team                             asn at samba.org
> www.samba.org

> From 1351b58987c672bfc576b0d36baaeed3a5531534 Mon Sep 17 00:00:00 2001
> From: Andreas Schneider <asn at samba.org>
> Date: Wed, 21 Dec 2016 19:08:58 +0100
> Subject: [PATCH 01/49] s4:torture: Fix the remote_pac test
> 
> All the Kerberos implementation do not expect an order of the pac
> buffer. The buffers are not processed in the oder they are sent but when
> required just located.
> 
> I confirmed this with MS at the IO Lab.
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  source4/torture/rpc/remote_pac.c | 72 +++++++++++++++++++++++++---------------
>  1 file changed, 46 insertions(+), 26 deletions(-)
> 
> diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c
> index 25a581bb46b..091309874fe 100644
> --- a/source4/torture/rpc/remote_pac.c
> +++ b/source4/torture/rpc/remote_pac.c
> @@ -122,6 +122,23 @@ static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx,
>  
>  /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
>  
> +static const struct PAC_BUFFER *get_pac_buffer(const struct PAC_DATA *pac_data,
> +					       enum PAC_TYPE type)
> +{
> +	const struct PAC_BUFFER *pac_buf = NULL;
> +	uint32_t i;
> +
> +	for (i = 0; i < pac_data->num_buffers; ++i) {
> +		pac_buf = &pac_data->buffers[i];
> +
> +		if (pac_buf->type == type) {
> +			break;
> +		}
> +	}
> +
> +	return pac_buf;
> +}
> +
>  /* Also happens to be a really good one-step verfication of our Kerberos stack */
>  
>  static bool test_PACVerify(struct torture_context *tctx,
> @@ -274,42 +291,45 @@ static bool test_PACVerify(struct torture_context *tctx,
>  	torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version");
>  	torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers");
>  
> -	pac_buf = pac_data_struct.buffers;
> -	torture_assert_int_equal(tctx, pac_buf->type,
> -				 PAC_TYPE_LOGON_INFO, "PAC_TYPE_LOGON_INFO");
> -	torture_assert(tctx, pac_buf->info != NULL,
> +	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_INFO);
> +	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_INFO");
> +	torture_assert(tctx,
> +		       pac_buf->info != NULL,
>  		       "PAC_TYPE_LOGON_INFO info");
> -	pac_buf++;
> +
>  	if (pkinit_in_use) {
> -		torture_assert_int_equal(tctx, pac_buf->type,
> -					 PAC_TYPE_CREDENTIAL_INFO,
> -					 "PAC_TYPE_CREDENTIAL_INFO");
> -		torture_assert(tctx, pac_buf->info != NULL,
> +		pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_CREDENTIAL_INFO);
> +		torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_CREDENTIAL_INFO");
> +		torture_assert(tctx,
> +			       pac_buf->info != NULL,
>  			       "PAC_TYPE_CREDENTIAL_INFO info");
> -		pac_buf++;
>  	}
> -	torture_assert_int_equal(tctx, pac_buf->type,
> -				 PAC_TYPE_LOGON_NAME, "PAC_TYPE_LOGON_NAME");
> -	torture_assert(tctx, pac_buf->info != NULL,
> +
> +	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_NAME);
> +	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_NAME");
> +	torture_assert(tctx,
> +		       pac_buf->info != NULL,
>  		       "PAC_TYPE_LOGON_NAME info");
> -	pac_buf++;
> +
>  	if (expect_pac_upn_dns_info) {
> -		torture_assert_int_equal(tctx, pac_buf->type,
> -					 PAC_TYPE_UPN_DNS_INFO, "PAC_TYPE_UPN_DNS_INFO");
> -		torture_assert(tctx, pac_buf->info != NULL,
> +		pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_UPN_DNS_INFO);
> +		torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_UPN_DNS_INFO");
> +		torture_assert(tctx,
> +			       pac_buf->info != NULL,
>  			       "PAC_TYPE_UPN_DNS_INFO info");
> -		pac_buf++;
>  	}
> -	torture_assert_int_equal(tctx, pac_buf->type,
> -				 PAC_TYPE_SRV_CHECKSUM, "PAC_TYPE_SRV_CHECKSUM");
> -	torture_assert(tctx, pac_buf->info != NULL,
> +
> +	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_SRV_CHECKSUM);
> +	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_SRV_CHECKSUM");
> +	torture_assert(tctx,
> +		       pac_buf->info != NULL,
>  		       "PAC_TYPE_SRV_CHECKSUM info");
> -	pac_buf++;
> -	torture_assert_int_equal(tctx, pac_buf->type,
> -				 PAC_TYPE_KDC_CHECKSUM, "PAC_TYPE_KDC_CHECKSUM");
> -	torture_assert(tctx, pac_buf->info != NULL,
> +
> +	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_KDC_CHECKSUM);
> +	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_KDC_CHECKSUM");
> +	torture_assert(tctx,
> +		       pac_buf->info != NULL,
>  		       "PAC_TYPE_KDC_CHECKSUM info");
> -	pac_buf++;
>  
>  	pac_wrapped_struct.ChecksumLength = pac_data->pac_srv_sig->signature.length;
>  	pac_wrapped_struct.SignatureType = pac_data->pac_kdc_sig->type;
> -- 
> 2.12.0
> 
> 
> From dbe9c881b9059b5d17534cc13f06cce48ef89263 Mon Sep 17 00:00:00 2001
> From: Andreas Schneider <asn at samba.org>
> Date: Tue, 13 Sep 2016 08:24:06 +0200
> Subject: [PATCH 02/49] testprogs: Add common kinit function
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  testprogs/blackbox/common_test_fns.inc | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/testprogs/blackbox/common_test_fns.inc b/testprogs/blackbox/common_test_fns.inc
> index aff1aa9dc79..db1daf351d7 100755
> --- a/testprogs/blackbox/common_test_fns.inc
> +++ b/testprogs/blackbox/common_test_fns.inc
> @@ -36,3 +36,19 @@ test_smbclient_expect_failure() {
>  	fi
>  	return $status
>  }
> +
> +kerberos_kinit() {
> +	kinit_tool="${1}"
> +	principal="${2}"
> +	password="${3}"
> +	shift 3
> +	kbase=$(basename ${kinit_tool})
> +	if [ ${kase} = "samba4kinit" ]; then
> +		kpassfile=$(mktemp)
> +		echo $password > ${kpassfile}
> +		$kinit_tool --password-file=$PREFIX/tmpuserpassfile $principal $@
> +		rm -f ${kpassfile}
> +	else
> +		echo $password | $kinit_tool $principal $@
> +	fi
> +}
> -- 
> 2.12.0
> 
> 
> From cc424914cfe06f60d2671c0f0d8c7a81c330b816 Mon Sep 17 00:00:00 2001
> From: Andreas Schneider <asn at samba.org>
> Date: Tue, 13 Sep 2016 08:24:41 +0200
> Subject: [PATCH 03/49] s3-tests: Use common functions in
>  test_smbclient_netbios_aliases.sh
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  .../script/tests/test_smbclient_netbios_aliases.sh   | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/source3/script/tests/test_smbclient_netbios_aliases.sh b/source3/script/tests/test_smbclient_netbios_aliases.sh
> index 610eeda5ab6..853d6be789e 100755
> --- a/source3/script/tests/test_smbclient_netbios_aliases.sh
> +++ b/source3/script/tests/test_smbclient_netbios_aliases.sh
> @@ -7,7 +7,7 @@ EOF
>  exit 1;
>  fi
>  
> -SMBCLIENT3=$1
> +smbclient=$1
>  SERVER=$2
>  USERNAME=$3
>  PASSWORD=$4
> @@ -15,11 +15,11 @@ PREFIX=$5
>  shift 5
>  ADDARGS="$*"
>  
> -samba4bindir="$BINDIR"
> -samba4srcdir="$SRCDIR/source4"
> -samba4kinit=kinit
> -if test -x $BINDIR/samba4kinit; then
> -	samba4kinit=$BINDIR/samba4kinit
> +samba_bindir="$BINDIR"
> +samba_srcdir="$SRCDIR/source4"
> +samba_kinit=kinit
> +if test -x ${samba_bindir}/samba4kinit; then
> +	samba4kinit=${samba_bindir}/samba4kinit
>  fi
>  
>  KRB5CCNAME_PATH="$PREFIX/test_smbclient_netbios_aliases_krb5ccache"
> @@ -30,11 +30,11 @@ export KRB5CCNAME
>  
>  incdir=`dirname $0`/../../../testprogs/blackbox
>  . $incdir/subunit.sh
> +. $incdir/common_test_fns.inc
>  
> -echo $PASSWORD > $PREFIX/tmppassfile
> -testit "kinit" $samba4kinit --password-file=$PREFIX/tmppassfile $USERNAME || failed=`expr $failed + 1`
> -rm -f $PREFIX/tmppassfile
> -testit "smbclient" $VALGRIND $SMBCLIENT3 -k //$SERVER/tmp -c 'ls' $ADDARGS || failed=`expr $failed + 1`
> +testit "kinit" kerberos_kinit ${samba_kinit} ${USERNAME} ${PASSWORD}
> +
> +test_smbclient "smbclient (krb5)" "ls" "//$SERVER/tmp" -k || failed=`expr $failed + 1`
>  
>  rm -rf $KRB5CCNAME_PATH
>  
> -- 
> 2.12.0
> 
> 
> From 4e60c2b5607d84e74ef95f5c082fb59482600a72 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 04/49] 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 1633561e173..5e06789887a 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.0
> 
> 
> From e1f0e896236406fb185fa42b17c3aa062bb8340e 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 05/49] 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.0
> 
> 
> From fa42b2a7e102df23a1814a6fe2ef1d02a858e11a 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 06/49] 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_configure_system_mitkrb5 | 27 ++++++++++++++++++---------
>  1 file changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
> index d3e8ebf0dcd..1fb28092e54 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(str, (v.split("."))))
> +
>  def krb5_define_syslib(conf, lib, deps):
>      found = 'FOUND_SYSTEMLIB_' + lib
>      if found in conf.env:
> @@ -44,19 +52,20 @@ 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_version, krb5_required_version))
>              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.0
> 
> 
> From 8d93bb024a1307b602ec6ce0a645cd339e57d340 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 07/49] 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.0
> 
> 
> From ad65ccb65fed7644a272e0961ed4af9bdb139f03 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 08/49] 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 4fd56ed0026..c017c359d32 100644
> --- a/wscript
> +++ b/wscript
> @@ -51,6 +51,11 @@ def set_options(opt):
>                     help='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',
>                     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 Samba 4 client and Samba 3 code base).',
> diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
> index 1fb28092e54..a520238a46b 100644
> --- a/wscript_configure_system_mitkrb5
> +++ b/wscript_configure_system_mitkrb5
> @@ -290,3 +290,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.0
> 
> 
> From ee4d9787fa002b69b879327bc80732d3168c269b 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 09/49] 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 335c54a3abe..70fd58e35ad 100644
> --- a/lib/param/loadparm.c
> +++ b/lib/param/loadparm.c
> @@ -2696,6 +2696,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 c65e613feea..05c825cf2f2 100644
> --- a/source3/param/loadparm.c
> +++ b/source3/param/loadparm.c
> @@ -897,6 +897,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.0
> 
> 
> From 9c946e1cee2f894946f00c9f6a22663d2b34c9eb 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 10/49] 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 24d89f4c89b..e720aab01f8 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.0
> 
> 
> From 90716ec367d411496b954c207dfc80b1795f02fc 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 11/49] 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  |  15 ++++
>  3 files changed, 225 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 e720aab01f8..c6782ea51b1 100644
> --- a/source4/kdc/wscript_build
> +++ b/source4/kdc/wscript_build
> @@ -143,6 +143,21 @@ 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
> +                    auth_sam_reply
> +                    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.0
> 
> 
> From 6a727d512cd1e2b7a71eef0b338408c59c4e83fb 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 12/49] 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 c6782ea51b1..84c5d88b830 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.0
> 
> 
> From 30866a3f093b6271488ae538d1221e559d5c4958 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 13/49] 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/mitkdccommand.xml | 12 ++++++++++++
>  source4/kdc/kdc-service-mit.c                  |  7 +++++++
>  2 files changed, 19 insertions(+)
> 
> diff --git a/docs-xml/smbdotconf/security/mitkdccommand.xml b/docs-xml/smbdotconf/security/mitkdccommand.xml
> index 2c7601fb5f5..a1876f5fa54 100644
> --- a/docs-xml/smbdotconf/security/mitkdccommand.xml
> +++ b/docs-xml/smbdotconf/security/mitkdccommand.xml
> @@ -13,3 +13,15 @@
>  
>  <value type="example">/opt/mit/sbin/krb5kdc</value>
>  </samba:parameter>
> +
> +<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.0
> 
> 
> From 61884959c78a804667472851c2bea00bd5750646 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 14/49] 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 c017c359d32..487260be3ad 100644
> --- a/wscript
> +++ b/wscript
> @@ -182,17 +182,15 @@ def configure(conf):
>          conf.RECURSE('lib/socket_wrapper')
>          conf.RECURSE('lib/uid_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.0
> 
> 
> From e64530829e5d4ab887cf1046790a404358a9f44f 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 15/49] 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 45e0ae0451f..64dacbece8a 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,
> @@ -415,6 +417,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.0
> 
> 
> From 76209e8359447145ff4f4e9fba885a12bde2b622 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 16/49] 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.0
> 
> 
> From 646cd4dec554bda234ca00d4753414e06e212feb 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 17/49] 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 e5c7f93fe03..fa1fc7633b3 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 8b5e699389b..0808eac5835 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};
>  
> @@ -435,6 +438,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";
> @@ -612,6 +616,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) {
> @@ -675,6 +680,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},
> @@ -1362,6 +1368,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 = "";
> @@ -1669,6 +1676,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.0
> 
> 
> From e3bfbbbbb36ce8e0529d9ae9709000977d5eb8b9 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 18/49] selftest: Set clowskew grace time to 1 second
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  selftest/target/Samba.pm | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
> index fa1fc7633b3..ebffa027bc8 100644
> --- a/selftest/target/Samba.pm
> +++ b/selftest/target/Samba.pm
> @@ -201,6 +201,9 @@ sub mk_krb5_conf($$)
>   ticket_lifetime = 24h
>   forwardable = yes
>   allow_weak_crypto = yes
> + # Set the grace clocskew to 1 second
> + # This is especially required by samba3.raw.session krb5
> + clockskew = 1
>  
>  ";
>  
> -- 
> 2.12.0
> 
> 
> From aa9c489c34006f9a6877799e74a1b3616b91f5af 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 19/49] 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.0
> 
> 
> From c5553971a2b3501684a3321ffee8610981140cbb 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 20/49] 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.0
> 
> 
> From c6cc25353bf5f088d2e57ae6b0852118e6ff37b4 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 21/49] 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.0
> 
> 
> From 1a0d7d150c3f15f5af1dc3d13c7f017310505065 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 22/49] 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.0
> 
> 
> From b3b20a4eb53040f916c30c545a5afc80d8f2e8b4 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 23/49] 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 c2c5486d43e..0adac3d6bb1 100755
> --- a/source4/selftest/tests.py
> +++ b/source4/selftest/tests.py
> @@ -396,6 +396,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_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"])
> 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.0
> 
> 
> From a1826448187d3df69cd7d3eca1ec07f0152a1280 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 24/49] 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 0adac3d6bb1..6e52d6d2f7f 100755
> --- a/source4/selftest/tests.py
> +++ b/source4/selftest/tests.py
> @@ -401,6 +401,9 @@ else:
>      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_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.0
> 
> 
> From 6c2ecb98c4a29b54fa14087015a78dd68c6d6655 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 25/49] testprogs: Add test with exported keytab from
>  samba-tool
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  source4/selftest/tests.py                    |   2 +
>  testprogs/blackbox/test_export_keytab_mit.sh | 127 +++++++++++++++++++++++++++
>  2 files changed, 129 insertions(+)
>  create mode 100755 testprogs/blackbox/test_export_keytab_mit.sh
> 
> diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
> index 6e52d6d2f7f..ef9c9332f74 100755
> --- a/source4/selftest/tests.py
> +++ b/source4/selftest/tests.py
> @@ -404,6 +404,8 @@ 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.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_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.0
> 
> 
> From e1d112a2e04669ef984b61a2ec72b41fdb3d6715 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 26/49] 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 88bff0b0ee4..0b2b8651c79 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(void)
>  {
>  	struct torture_suite *suite =
> @@ -46,8 +371,22 @@ NTSTATUS torture_krb5_init(void)
>  	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.0
> 
> 
> From d082f1e36d88f347d45caddae167ee57a5c1468b 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 27/49] 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 0b2b8651c79..9b7b6eed4fc 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(void)
>  {
>  	struct torture_suite *suite =
> @@ -375,10 +454,13 @@ NTSTATUS torture_krb5_init(void)
>  				      "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.0
> 
> 
> From af2c6b4437acf11697428cb1debe9de61c0984fa 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 28/49] 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 9b7b6eed4fc..885b6e40f1b 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(void)
>  {
>  	struct torture_suite *suite =
> @@ -460,10 +544,10 @@ NTSTATUS torture_krb5_init(void)
>  				      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.0
> 
> 
> From ea41ac36e6782a28c2afb35682f35e8bc9b148f2 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 29/49] 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 ebffa027bc8..930cb44e744 100644
> --- a/selftest/target/Samba.pm
> +++ b/selftest/target/Samba.pm
> @@ -204,6 +204,9 @@ sub mk_krb5_conf($$)
>   # Set the grace clocskew to 1 second
>   # This is especially required by samba3.raw.session krb5
>   clockskew = 1
> + # 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 885b6e40f1b..1edaa291689 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(void)
>  {
>  	struct torture_suite *suite =
> @@ -547,10 +604,11 @@ NTSTATUS torture_krb5_init(void)
>  	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.0
> 
> 
> From b4dcd03549f6f61ad8051dc083eca628240dd292 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 30/49] 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 1edaa291689..a4997357c7e 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(void)
>  {
>  	struct torture_suite *suite =
> @@ -611,6 +774,18 @@ NTSTATUS torture_krb5_init(void)
>  #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.0
> 
> 
> From edc090d784cdef38b4203c2d53be09dba0690298 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 31/49] 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 84c5d88b830..26d4bc80f9b 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.0
> 
> 
> From e34a2a9b47d348093ab22300b9f4d93e68b735a5 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 32/49] 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 a520238a46b..6f9330deb2a 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.0
> 
> 
> From aec58ce9498c2f4b52a3ec4e1f6b36e71d573c3f 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 33/49] 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 26d4bc80f9b..d2e0a70c698 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.0
> 
> 
> From 7d634fb50313f7ad8589d8778d273f2ee612efbd 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 34/49] testprogs: Add MIT Kerberos specific kpasswd blackbox
>  test
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  source4/selftest/tests.py              |   2 +
>  testprogs/blackbox/test_kpasswd_mit.sh | 231 +++++++++++++++++++++++++++++++++
>  2 files changed, 233 insertions(+)
>  create mode 100755 testprogs/blackbox/test_kpasswd_mit.sh
> 
> diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
> index ef9c9332f74..bb1691494e1 100755
> --- a/source4/selftest/tests.py
> +++ b/source4/selftest/tests.py
> @@ -404,6 +404,8 @@ 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.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.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_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"])
> 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.0
> 
> 
> From e96c4030c516a03f3174c64bdd0468d34935de43 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 35/49] 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.0
> 
> 
> From 8bff750d5dd8e6e94f878977f96971bd7d8057fb 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 36/49] waf: Create kerberos_implementation.py for provisioning
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  .gitignore     |  3 +++
>  python/wscript | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  wscript        |  1 +
>  3 files changed, 50 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..f85bb6c784a
> --- /dev/null
> +++ b/python/wscript
> @@ -0,0 +1,46 @@
> +#!/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 = """krb5_implementation = "{0}"
> +kdb_modules_dir = "{1}"
> +kdc_default_config_dir = "{2}"
> +"""
> +
> +        if conf.env.HEIMDAL_KRB5_CONFIG:
> +            f.write(data.format("HEIMDAL", "", ""))
> +        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("MIT", modulesdir, kdc_path))
> +    finally:
> +        f.close()
> diff --git a/wscript b/wscript
> index 487260be3ad..abc8cf84f15 100644
> --- a/wscript
> +++ b/wscript
> @@ -202,6 +202,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.0
> 
> 
> From d398671e121307ebd70a76c62c549638a5e37117 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 37/49] 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 64dacbece8a..c1553e79a0b 100755
> --- a/selftest/selftest.pl
> +++ b/selftest/selftest.pl
> @@ -321,6 +321,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.0
> 
> 
> From 941124ceb96249efdc39a48e3ba093e16033d636 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 38/49] python: Add provisioning support for MIT KDC in
>  samba-tool
> 
> Signed-off-by: Andreas Schneider <asn at cryptomilk.org>
> ---
>  python/samba/netcmd/domain.py      |  16 +++++-
>  python/samba/provision/__init__.py |  18 ++++---
>  python/samba/provision/kerberos.py | 101 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 128 insertions(+), 7 deletions(-)
>  create mode 100644 python/samba/provision/kerberos.py
> 
> diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
> index e0397244725..78404fa2edc 100644
> --- a/python/samba/netcmd/domain.py
> +++ b/python/samba/netcmd/domain.py
> @@ -87,6 +87,10 @@ from samba.provision import (
>      ProvisioningError
>      )
>  
> +from samba.provision.kerberos_implementation import (
> +    krb5_implementation,
> +    kdc_default_config_dir)
> +
>  from samba.provision.common import (
>      FILL_FULL,
>      FILL_NT4SYNC,
> @@ -263,12 +267,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 krb5_implementation is "MIT":
> +        takes_options.extend(kdc_options)
> +
>      takes_args = []
>  
>      def run(self, sambaopts=None, versionopts=None,
> @@ -304,6 +316,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 +484,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..e5b8186216c
> --- /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 (
> +    krb5_implementation,
> +    kdb_modules_dir,
> +    kdc_default_config_dir)
> +import os
> +
> +def make_kdcconf(realm, domain, kdcconfdir, logdir):
> +
> +    if krb5_implementation is "HEIMDAL":
> +        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.0
> 
> 
> From 1b78f1cb2f5e36b8c346649e77957ba9153de8ad 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 39/49] 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 f85bb6c784a..cfc127a6a7b 100644
> --- a/python/wscript
> +++ b/python/wscript
> @@ -44,3 +44,47 @@ kdc_default_config_dir = "{2}"
>              f.write(data.format("MIT", 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.0
> 
> 
> From b25a9de92c37dc15fcd579534860640aff8c79a6 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 40/49] s4-torture: Fix reauth tests with smaller clockskew
>  grace time
> 
> Signed-off-by: Andreas Schneider <asn at samba.org>
> ---
>  selftest/target/Samba.pm       | 2 +-
>  source4/torture/raw/session.c  | 8 ++++----
>  source4/torture/smb2/session.c | 4 ++--
>  3 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
> index 930cb44e744..e27939e982e 100644
> --- a/selftest/target/Samba.pm
> +++ b/selftest/target/Samba.pm
> @@ -203,7 +203,7 @@ sub mk_krb5_conf($$)
>   allow_weak_crypto = yes
>   # Set the grace clocskew to 1 second
>   # This is especially required by samba3.raw.session krb5
> - clockskew = 1
> + clockskew = 5
>   # We are running on the same machine, do not correct
>   # system clock differences
>   kdc_timesync = 0
> 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.0
> 
> 
> From af75c775c2903f362c7dfb665ea0802c7e86f9bc 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 41/49] 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.0
> 
> 
> From a3610e6c152ce58f090cdaddc88f9c83a7366d5d 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 42/49] 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.0
> 
> 
> From 89514a8e4d3936765cf1fff9f2845611c2f3f917 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 43/49] 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.0
> 
> 
> From ec0721544a89f9caa996dbf3d558590d80250864 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 44/49] 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.0
> 
> 
> From 89e1ad8de5fcff2cc56069605e6b1d48f791f62e 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 45/49] 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..60c6c8d54f0 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.0
> 
> 
> From 48d6a8761f307a722976111d63071674efac61c4 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 46/49] 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.0
> 
> 
> From a31717e312e984bde6d9d9236c8745882e5bebb8 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 47/49] 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.0
> 
> 
> From a2d37d5bfa2d742e658adf5acf10784819d985e5 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 48/49] 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.0
> 
> 
> From 427eb66dfbb5daddceaa6449f8a65a5865b84c57 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 49/49] 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.0
> 




More information about the samba-technical mailing list