[Pkg-samba-maint] [samba] 05/11: Imported Upstream version 4.3.7+dfsg

Andrew Bartlett abartlet-guest at moszumanska.debian.org
Tue Apr 12 22:37:52 UTC 2016


This is an automated email from the git hooks/post-receive script.

abartlet-guest pushed a commit to branch master
in repository samba.

commit 9b9d1fe944d23b232958cc226c1386ffb340ecc1
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Apr 6 14:25:04 2016 +1200

    Imported Upstream version 4.3.7+dfsg
---
 VERSION                                            |    2 +-
 WHATSNEW.txt                                       |  535 ++++
 auth/credentials/credentials.h                     |    5 +-
 auth/credentials/credentials_ntlm.c                |   12 +-
 auth/gensec/gensec.c                               |  113 +-
 auth/gensec/gensec.h                               |    4 +
 auth/gensec/gensec_internal.h                      |    7 +
 auth/gensec/gensec_start.c                         |   18 +-
 auth/gensec/gensec_util.c                          |    2 +-
 auth/gensec/schannel.c                             |   22 +-
 auth/gensec/spnego.c                               |  301 ++-
 auth/ntlmssp/gensec_ntlmssp.c                      |    9 +
 auth/ntlmssp/gensec_ntlmssp_server.c               |   44 +-
 auth/ntlmssp/ntlmssp.c                             |   91 +-
 auth/ntlmssp/ntlmssp.h                             |   17 +
 auth/ntlmssp/ntlmssp_client.c                      |  534 +++-
 auth/ntlmssp/ntlmssp_ndr.c                         |    1 +
 auth/ntlmssp/ntlmssp_private.h                     |   10 +-
 auth/ntlmssp/ntlmssp_server.c                      |  424 +++-
 auth/ntlmssp/ntlmssp_sign.c                        |  103 +-
 auth/ntlmssp/ntlmssp_util.c                        |  176 +-
 auth/ntlmssp/wscript_build                         |    2 +-
 .../ldap/ldapserverrequirestrongauth.xml           |   26 +
 .../smbdotconf/protocol/clientipcmaxprotocol.xml   |   29 +
 .../smbdotconf/protocol/clientipcminprotocol.xml   |   29 +
 docs-xml/smbdotconf/protocol/clientmaxprotocol.xml |    9 +-
 docs-xml/smbdotconf/protocol/clientminprotocol.xml |    6 +
 docs-xml/smbdotconf/protocol/clientusespnego.xml   |    5 +
 .../security/allowdcerpcauthlevelconnect.xml       |   27 +
 docs-xml/smbdotconf/security/clientipcsigning.xml  |   26 +
 docs-xml/smbdotconf/security/clientntlmv2auth.xml  |    5 +
 docs-xml/smbdotconf/security/clientsigning.xml     |   12 +-
 docs-xml/smbdotconf/security/rawntlmv2auth.xml     |   19 +
 docs-xml/smbdotconf/security/serversigning.xml     |    2 +-
 docs-xml/smbdotconf/security/tlsverifypeer.xml     |   47 +
 docs/manpages/dbwrap_tool.1                        |    4 +-
 docs/manpages/eventlogadm.8                        |    4 +-
 docs/manpages/findsmb.1                            |    4 +-
 docs/manpages/idmap_ad.8                           |    4 +-
 docs/manpages/idmap_autorid.8                      |    4 +-
 docs/manpages/idmap_hash.8                         |    4 +-
 docs/manpages/idmap_ldap.8                         |    4 +-
 docs/manpages/idmap_nss.8                          |    4 +-
 docs/manpages/idmap_rfc2307.8                      |    4 +-
 docs/manpages/idmap_rid.8                          |    4 +-
 docs/manpages/idmap_script.8                       |    4 +-
 docs/manpages/idmap_tdb.8                          |    4 +-
 docs/manpages/idmap_tdb2.8                         |    4 +-
 docs/manpages/libsmbclient.7                       |    4 +-
 docs/manpages/lmhosts.5                            |    4 +-
 docs/manpages/log2pcap.1                           |    4 +-
 docs/manpages/net.8                                |    4 +-
 docs/manpages/nmbd.8                               |    4 +-
 docs/manpages/nmblookup.1                          |    4 +-
 docs/manpages/ntlm_auth.1                          |    4 +-
 docs/manpages/pam_winbind.8                        |    4 +-
 docs/manpages/pam_winbind.conf.5                   |    4 +-
 docs/manpages/pdbedit.8                            |    4 +-
 docs/manpages/profiles.1                           |    4 +-
 docs/manpages/rpcclient.1                          |    4 +-
 docs/manpages/samba-regedit.8                      |    4 +-
 docs/manpages/samba-tool.8                         |    4 +-
 docs/manpages/samba.7                              |    4 +-
 docs/manpages/samba.8                              |    4 +-
 docs/manpages/sharesec.1                           |    4 +-
 docs/manpages/smb.conf.5                           |  227 +-
 docs/manpages/smbcacls.1                           |    4 +-
 docs/manpages/smbclient.1                          |    4 +-
 docs/manpages/smbcontrol.1                         |    4 +-
 docs/manpages/smbcquotas.1                         |    4 +-
 docs/manpages/smbd.8                               |    4 +-
 docs/manpages/smbget.1                             |    4 +-
 docs/manpages/smbgetrc.5                           |    4 +-
 docs/manpages/smbpasswd.5                          |    4 +-
 docs/manpages/smbpasswd.8                          |    4 +-
 docs/manpages/smbspool.8                           |    4 +-
 docs/manpages/smbspool_krb5_wrapper.8              |    4 +-
 docs/manpages/smbstatus.1                          |    4 +-
 docs/manpages/smbta-util.8                         |    4 +-
 docs/manpages/smbtar.1                             |    4 +-
 docs/manpages/smbtree.1                            |    4 +-
 docs/manpages/testparm.1                           |    4 +-
 docs/manpages/vfs_acl_tdb.8                        |    4 +-
 docs/manpages/vfs_acl_xattr.8                      |    4 +-
 docs/manpages/vfs_aio_fork.8                       |    4 +-
 docs/manpages/vfs_aio_linux.8                      |    4 +-
 docs/manpages/vfs_aio_pthread.8                    |    4 +-
 docs/manpages/vfs_audit.8                          |    4 +-
 docs/manpages/vfs_btrfs.8                          |    4 +-
 docs/manpages/vfs_cacheprime.8                     |    4 +-
 docs/manpages/vfs_cap.8                            |    4 +-
 docs/manpages/vfs_catia.8                          |    4 +-
 docs/manpages/vfs_ceph.8                           |    4 +-
 docs/manpages/vfs_commit.8                         |    4 +-
 docs/manpages/vfs_crossrename.8                    |    4 +-
 docs/manpages/vfs_default_quota.8                  |    4 +-
 docs/manpages/vfs_dirsort.8                        |    4 +-
 docs/manpages/vfs_extd_audit.8                     |    4 +-
 docs/manpages/vfs_fake_perms.8                     |    4 +-
 docs/manpages/vfs_fileid.8                         |    4 +-
 docs/manpages/vfs_fruit.8                          |    4 +-
 docs/manpages/vfs_full_audit.8                     |    4 +-
 docs/manpages/vfs_glusterfs.8                      |    4 +-
 docs/manpages/vfs_gpfs.8                           |    4 +-
 docs/manpages/vfs_linux_xfs_sgid.8                 |    4 +-
 docs/manpages/vfs_media_harmony.8                  |    4 +-
 docs/manpages/vfs_netatalk.8                       |    4 +-
 docs/manpages/vfs_prealloc.8                       |    4 +-
 docs/manpages/vfs_preopen.8                        |    4 +-
 docs/manpages/vfs_readahead.8                      |    4 +-
 docs/manpages/vfs_readonly.8                       |    4 +-
 docs/manpages/vfs_recycle.8                        |    4 +-
 docs/manpages/vfs_scannedonly.8                    |    4 +-
 docs/manpages/vfs_shadow_copy.8                    |    4 +-
 docs/manpages/vfs_shadow_copy2.8                   |    4 +-
 docs/manpages/vfs_shell_snap.8                     |    4 +-
 docs/manpages/vfs_smb_traffic_analyzer.8           |    4 +-
 docs/manpages/vfs_snapper.8                        |    4 +-
 docs/manpages/vfs_streams_depot.8                  |    4 +-
 docs/manpages/vfs_streams_xattr.8                  |    4 +-
 docs/manpages/vfs_syncops.8                        |    4 +-
 docs/manpages/vfs_time_audit.8                     |    4 +-
 docs/manpages/vfs_tsmsm.8                          |    4 +-
 docs/manpages/vfs_unityed_media.8                  |    4 +-
 docs/manpages/vfs_worm.8                           |    4 +-
 docs/manpages/vfs_xattr_tdb.8                      |    4 +-
 docs/manpages/vfs_zfsacl.8                         |    4 +-
 docs/manpages/vfstest.1                            |    4 +-
 docs/manpages/wbinfo.1                             |    4 +-
 docs/manpages/winbind_krb5_locator.7               |    4 +-
 docs/manpages/winbindd.8                           |    4 +-
 lib/param/loadparm.c                               |   47 +-
 lib/param/loadparm.h                               |    6 +
 lib/param/param_table.c                            |   83 +
 lib/util/asn1.c                                    |  109 +-
 lib/util/asn1.h                                    |   25 +-
 lib/util/tests/asn1_tests.c                        |    6 +-
 lib/util/util_net.c                                |  247 +-
 lib/util/util_net.h                                |    1 +
 libcli/auth/proto.h                                |    6 +
 libcli/auth/smbencrypt.c                           |  170 +-
 libcli/auth/spnego.h                               |    8 +-
 libcli/auth/spnego_parse.c                         |   55 +-
 libcli/cldap/cldap.c                               |   12 +-
 libcli/ldap/ldap_message.c                         |   32 +-
 libcli/smb/smbXcli_base.c                          |    1 +
 libcli/smb/smb_constants.h                         |    1 +
 libcli/smb/smb_signing.c                           |    4 +
 libcli/smb/tstream_smbXcli_np.c                    |    4 +
 librpc/idl/dcerpc.idl                              |   15 +-
 librpc/idl/epmapper.idl                            |    2 +-
 librpc/idl/ntlmssp.idl                             |   48 +-
 librpc/idl/security.idl                            |    9 +
 librpc/ndr/ndr_ntlmssp.c                           |   16 +
 librpc/ndr/ndr_ntlmssp.h                           |    2 +
 librpc/rpc/binding.c                               |    2 +-
 librpc/rpc/dcerpc_error.c                          |    6 +-
 librpc/rpc/dcerpc_util.c                           |  141 +-
 librpc/rpc/rpc_common.h                            |    9 +-
 nsswitch/libwbclient/wbc_pam.c                     |   21 +-
 nsswitch/winbind_struct_protocol.h                 |    1 +
 python/samba/tests/__init__.py                     |  525 ++++
 python/samba/tests/dcerpc/dnsserver.py             |    2 +-
 python/samba/tests/dcerpc/raw_protocol.py          | 2623 ++++++++++++++++++++
 selftest/knownfail                                 |   28 +
 .../DC-addc.addom.samba.example.com-S02-cert.pem   |  191 ++
 .../DC-addc.addom.samba.example.com-S02-key.pem    |   54 +
 ...DC-addc.addom.samba.example.com-S02-openssl.cnf |  250 ++
 ...ddc.addom.samba.example.com-S02-private-key.pem |   51 +
 .../DC-addc.addom.samba.example.com-S02-req.pem    |   30 +
 .../DC-addc.addom.samba.example.com-cert.pem       |    1 +
 ...DC-addc.addom.samba.example.com-private-key.pem |    1 +
 .../DC-localdc.samba.example.com-S00-cert.pem      |  190 ++
 .../DC-localdc.samba.example.com-S00-key.pem       |   54 +
 .../DC-localdc.samba.example.com-S00-openssl.cnf   |  250 ++
 ...C-localdc.samba.example.com-S00-private-key.pem |   51 +
 .../DC-localdc.samba.example.com-S00-req.pem       |   30 +
 .../DC-localdc.samba.example.com-cert.pem          |    1 +
 .../DC-localdc.samba.example.com-private-key.pem   |    1 +
 .../manage-ca/CA-samba.example.com/NewCerts/00.pem |  190 ++
 .../manage-ca/CA-samba.example.com/NewCerts/01.pem |  169 ++
 .../manage-ca/CA-samba.example.com/NewCerts/02.pem |  191 ++
 .../manage-ca/CA-samba.example.com/NewCerts/03.pem |  169 ++
 .../Private/CA-samba.example.com-crlnumber.txt     |    1 +
 .../Private/CA-samba.example.com-crlnumber.txt.old |    1 +
 .../Private/CA-samba.example.com-index.txt         |    4 +
 .../Private/CA-samba.example.com-index.txt.attr    |    1 +
 .../CA-samba.example.com-index.txt.attr.old        |    1 +
 .../Private/CA-samba.example.com-index.txt.old     |    3 +
 .../Private/CA-samba.example.com-openssl.cnf       |  203 ++
 .../Private/CA-samba.example.com-private-key.pem   |  102 +
 .../Private/CA-samba.example.com-serial.txt        |    1 +
 .../Private/CA-samba.example.com-serial.txt.old    |    1 +
 .../Public/CA-samba.example.com-cert.pem           |   62 +
 .../Public/CA-samba.example.com-crl.pem            |   32 +
 ...inistrator at addom.samba.example.com-S03-cert.pem |  169 ++
 ...ministrator at addom.samba.example.com-S03-key.pem |   30 +
 ...strator at addom.samba.example.com-S03-openssl.cnf |  242 ++
 ...tor at addom.samba.example.com-S03-private-key.pem |   27 +
 ...ministrator at addom.samba.example.com-S03-req.pem |   19 +
 ...-administrator at addom.samba.example.com-cert.pem |    1 +
 ...strator at addom.samba.example.com-private-key.pem |    1 +
 ...ER-administrator at samba.example.com-S01-cert.pem |  169 ++
 ...SER-administrator at samba.example.com-S01-key.pem |   30 +
 ...administrator at samba.example.com-S01-openssl.cnf |  242 ++
 ...nistrator at samba.example.com-S01-private-key.pem |   27 +
 ...SER-administrator at samba.example.com-S01-req.pem |   19 +
 .../USER-administrator at samba.example.com-cert.pem  |    1 +
 ...administrator at samba.example.com-private-key.pem |    1 +
 selftest/manage-ca/manage-CA-samba.example.com.cnf |   21 +
 selftest/manage-ca/manage-CA-samba.example.com.sh  |   18 +
 selftest/manage-ca/manage-ca.sh                    |  387 +++
 .../manage-CA-example.com.cnf                      |   17 +
 .../openssl-BASE-template.cnf                      |  201 ++
 .../manage-ca.templates.d/openssl-CA-template.cnf  |    2 +
 .../manage-ca.templates.d/openssl-DC-template.cnf  |   49 +
 .../openssl-USER-template.cnf                      |   41 +
 selftest/selftest.pl                               |   40 +
 selftest/target/Samba.pm                           |  105 +
 selftest/target/Samba3.pm                          |    1 +
 selftest/target/Samba4.pm                          |  232 +-
 source3/auth/auth_domain.c                         |    2 +-
 source3/auth/auth_samba4.c                         |    4 +-
 source3/auth/auth_util.c                           |   15 +
 source3/include/auth_generic.h                     |    7 +-
 source3/include/proto.h                            |   48 +-
 source3/lib/netapi/cm.c                            |    2 +-
 source3/lib/tldap.c                                |    6 +-
 source3/libads/ads_proto.h                         |    1 -
 source3/libads/ldap.c                              |  134 -
 source3/libads/sasl.c                              |  663 ++---
 source3/libnet/libnet_join.c                       |    6 +-
 source3/librpc/crypto/gse.c                        |   81 +-
 source3/librpc/rpc/dcerpc.h                        |   10 +-
 source3/librpc/rpc/dcerpc_helpers.c                |   98 +-
 source3/libsmb/auth_generic.c                      |   51 +-
 source3/libsmb/cliconnect.c                        |  669 ++---
 source3/libsmb/clientgen.c                         |    9 +
 source3/libsmb/clispnego.c                         |  283 +--
 source3/libsmb/ntlmssp.c                           |  765 ------
 source3/libsmb/ntlmssp_wrap.c                      |  135 -
 source3/libsmb/passchange.c                        |    7 +-
 source3/pam_smbpass/wscript_build                  |    2 +-
 source3/param/loadparm.c                           |   43 +-
 source3/rpc_client/cli_pipe.c                      |  314 ++-
 source3/rpc_server/netlogon/srv_netlog_nt.c        |   57 +-
 source3/rpc_server/rpc_handles.c                   |    1 +
 source3/rpc_server/rpc_ncacn_np.c                  |    3 +-
 source3/rpc_server/rpc_pipes.h                     |   11 +
 source3/rpc_server/rpc_server.c                    |   12 +
 source3/rpc_server/samr/srv_samr_nt.c              |   21 +-
 source3/rpc_server/srv_pipe.c                      |  494 ++--
 source3/rpcclient/rpcclient.c                      |    5 +-
 source3/script/tests/test_ntlm_auth_s3.sh          |    2 +
 source3/script/tests/test_rpcclient_samlogon.sh    |   11 +-
 source3/script/tests/test_smbclient_auth.sh        |   11 +
 source3/selftest/tests.py                          |    7 +-
 source3/smbd/negprot.c                             |    6 +-
 source3/smbd/sesssetup.c                           |    4 +-
 source3/smbd/smb2_negprot.c                        |   10 +-
 source3/smbd/smb2_sesssetup.c                      |    3 +-
 source3/torture/test_ntlm_auth.py                  |  553 +++--
 source3/utils/net_ads.c                            |    2 +-
 source3/utils/net_rpc.c                            |    2 +-
 source3/utils/net_util.c                           |    2 +-
 source3/utils/ntlm_auth.c                          |  803 +-----
 source3/winbindd/winbindd_ccache_access.c          |   44 +-
 source3/winbindd/winbindd_cm.c                     |    6 +-
 source3/wscript_build                              |   10 +-
 source4/auth/gensec/gensec_krb5.c                  |   11 +-
 source4/auth/gensec/pygensec.c                     |   83 +
 source4/auth/ntlm/auth_util.c                      |    4 +-
 source4/ldap_server/ldap_bind.c                    |   50 +-
 source4/ldap_server/ldap_server.c                  |    6 +
 source4/ldap_server/ldap_server.h                  |    2 +
 source4/lib/tls/tls.c                              |    2 +-
 source4/lib/tls/tls.h                              |   23 +
 source4/lib/tls/tls_tstream.c                      |  251 +-
 source4/lib/tls/tlscert.c                          |   18 +-
 source4/lib/tls/wscript                            |    5 +
 source4/libcli/cliconnect.c                        |    2 +-
 source4/libcli/ldap/ldap_bind.c                    |   62 +-
 source4/libcli/ldap/ldap_client.c                  |    9 +-
 source4/libcli/ldap/ldap_controls.c                |   48 +-
 source4/libcli/raw/libcliraw.h                     |    1 +
 source4/libcli/raw/rawnegotiate.c                  |   11 +-
 source4/libcli/smb2/connect.c                      |    7 +-
 source4/libcli/smb_composite/connect.c             |    1 +
 source4/libcli/smb_composite/sesssetup.c           |   35 +-
 source4/librpc/rpc/dcerpc.c                        |  351 ++-
 source4/librpc/rpc/dcerpc.h                        |   14 +-
 source4/librpc/rpc/dcerpc_auth.c                   |   93 +-
 source4/librpc/rpc/dcerpc_connect.c                |   22 +
 source4/librpc/rpc/dcerpc_roh.c                    |   13 +-
 source4/librpc/rpc/dcerpc_util.c                   |   22 +-
 source4/param/loadparm.c                           |    3 +-
 source4/rpc_server/backupkey/dcesrv_backupkey.c    |   13 +-
 source4/rpc_server/common/reply.c                  |   49 +-
 source4/rpc_server/dcerpc_server.c                 |  812 ++++--
 source4/rpc_server/dcerpc_server.h                 |   57 +-
 source4/rpc_server/dcesrv_auth.c                   |  261 +-
 source4/rpc_server/dcesrv_mgmt.c                   |    8 +
 source4/rpc_server/dnsserver/dcerpc_dnsserver.c    |    8 +
 source4/rpc_server/drsuapi/dcesrv_drsuapi.c        |    8 +
 source4/rpc_server/echo/rpc_echo.c                 |    7 +
 source4/rpc_server/epmapper/rpc_epmapper.c         |    8 +
 source4/rpc_server/handles.c                       |    8 +-
 source4/rpc_server/lsa/dcesrv_lsa.c                |    8 +
 source4/rpc_server/lsa/lsa_lookup.c                |   12 +-
 source4/rpc_server/netlogon/dcerpc_netlogon.c      |   46 +-
 source4/rpc_server/remote/dcesrv_remote.c          |    8 +-
 source4/rpc_server/samr/dcesrv_samr.c              |   12 +
 source4/rpc_server/samr/samr_password.c            |   25 +-
 source4/selftest/tests.py                          |   75 +-
 source4/smb_server/smb/negprot.c                   |    6 +-
 source4/smb_server/smb/sesssetup.c                 |   10 +
 source4/smb_server/smb2/negprot.c                  |    7 +-
 source4/smb_server/smb2/sesssetup.c                |    8 -
 source4/torture/basic/base.c                       |   20 +-
 source4/torture/ndr/ntlmssp.c                      |  183 +-
 source4/torture/raw/samba3misc.c                   |    7 +
 source4/torture/rpc/backupkey.c                    |   21 +-
 source4/torture/rpc/forest_trust.c                 |   12 +-
 source4/torture/rpc/lsa.c                          |   14 +-
 source4/torture/rpc/netlogon.c                     |  101 +-
 source4/torture/rpc/netlogon.h                     |    7 +
 source4/torture/rpc/remote_pac.c                   |   39 +-
 source4/torture/rpc/samba3rpc.c                    |   61 +-
 source4/torture/rpc/samlogon.c                     |    3 +-
 source4/torture/rpc/samr.c                         |    4 +-
 source4/torture/rpc/schannel.c                     |   29 +-
 source4/torture/rpc/testjoin.c                     |   35 +-
 testprogs/blackbox/test_ldb_simple.sh              |   41 +
 wscript_configure_system_mitkrb5                   |    4 +-
 334 files changed, 15480 insertions(+), 5067 deletions(-)

diff --git a/VERSION b/VERSION
index 2dec4b2..c0f1823 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=3
-SAMBA_VERSION_RELEASE=6
+SAMBA_VERSION_RELEASE=7
 
 ########################################################
 # If a official release has a serious bug              #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index a47ede4..c0899bd 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,539 @@
                    =============================
+                   Release Notes for Samba 4.3.7
+                           April 12, 2016
+                   =============================
+
+
+This is a security release in order to address the following CVEs:
+
+o  CVE-2015-5370 (Multiple errors in DCE-RPC code)
+
+o  CVE-2016-2110 (Man in the middle attacks possible with NTLMSSP)
+
+o  CVE-2016-2111 (NETLOGON Spoofing Vulnerability)
+
+o  CVE-2016-2112 (LDAP client and server don't enforce integrity)
+
+o  CVE-2016-2113 (Missing TLS certificate validation)
+
+o  CVE-2016-2114 ("server signing = mandatory" not enforced)
+
+o  CVE-2016-2115 (SMB IPC traffic is not integrity protected)
+
+o  CVE-2016-2118 (SAMR and LSA man in the middle attacks possible)
+
+The number of changes are rather huge for a security release,
+compared to typical security releases.
+
+Given the number of problems and the fact that they are all related
+to man in the middle attacks we decided to fix them all at once
+instead of splitting them.
+
+In order to prevent the man in the middle attacks it was required
+to change the (default) behavior for some protocols. Please see the
+"New smb.conf options" and "Behavior changes" sections below.
+
+=======
+Details
+=======
+
+o  CVE-2015-5370
+
+   Versions of Samba from 3.6.0 to 4.4.0 inclusive are vulnerable to
+   denial of service attacks (crashes and high cpu consumption)
+   in the DCE-RPC client and server implementations. In addition,
+   errors in validation of the DCE-RPC packets can lead to a downgrade
+   of a secure connection to an insecure one.
+
+   The above applies all possible server roles Samba can operate in.
+
+   Note that versions before 3.6.0 had completely different marshalling
+   functions for the generic DCE-RPC layer. It's quite possible that
+   that code has similar problems!
+
+   The downgrade of a secure connection to an insecure one may
+   allow an attacker to take control of Active Directory object
+   handles created on a connection created from an Administrator
+   account and re-use them on the now non-privileged connection,
+   compromising the security of the Samba AD-DC.
+
+o  CVE-2016-2110:
+
+   There are several man in the middle attacks possible with
+   NTLMSSP authentication.
+
+   E.g. NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL
+   can be cleared by a man in the middle.
+
+   This was by protocol design in earlier Windows versions.
+
+   Windows Server 2003 RTM and Vista RTM introduced a way
+   to protect against the trivial downgrade.
+
+   See MsvAvFlags and flag 0x00000002 in
+   https://msdn.microsoft.com/en-us/library/cc236646.aspx
+
+   This new feature also implies support for a mechlistMIC
+   when used within SPNEGO, which may prevent downgrades
+   from other SPNEGO mechs, e.g. Kerberos, if sign or
+   seal is finally negotiated.
+
+   The Samba implementation doesn't enforce the existence of
+   required flags, which were requested by the application layer,
+   e.g. LDAP or SMB1 encryption (via the unix extensions).
+   As a result a man in the middle can take over the connection.
+   It is also possible to misguide client and/or
+   server to send unencrypted traffic even if encryption
+   was explicitly requested.
+
+   LDAP (with NTLMSSP authentication) is used as a client
+   by various admin tools of the Samba project,
+   e.g. "net", "samba-tool", "ldbsearch", "ldbedit", ...
+
+   As an active directory member server LDAP is also used
+   by the winbindd service when connecting to domain controllers.
+
+   Samba also offers an LDAP server when running as
+   active directory domain controller.
+
+   The NTLMSSP authentication used by the SMB1 encryption
+   is protected by smb signing, see CVE-2015-5296.
+
+o  CVE-2016-2111:
+
+   It's basically the same as CVE-2015-0005 for Windows:
+
+     The NETLOGON service in Microsoft Windows Server 2003 SP2,
+     Windows Server 2008 SP2 and R2 SP1, and Windows Server 2012 Gold
+     and R2, when a Domain Controller is configured, allows remote
+     attackers to spoof the computer name of a secure channel's
+     endpoint, and obtain sensitive session information, by running a
+     crafted application and leveraging the ability to sniff network
+     traffic, aka "NETLOGON Spoofing Vulnerability".
+
+   The vulnerability in Samba is worse as it doesn't require
+   credentials of a computer account in the domain.
+
+   This only applies to Samba running as classic primary domain controller,
+   classic backup domain controller or active directory domain controller.
+
+   The security patches introduce a new option called "raw NTLMv2 auth"
+   ("yes" or "no") for the [global] section in smb.conf.
+   Samba (the smbd process) will reject client using raw NTLMv2
+   without using NTLMSSP.
+
+   Note that this option also applies to Samba running as
+   standalone server and member server.
+
+   You should also consider using "lanman auth = no" (which is already the default)
+   and "ntlm auth = no". Have a look at the smb.conf manpage for further details,
+   as they might impact compatibility with older clients. These also
+   apply for all server roles.
+
+o  CVE-2016-2112:
+
+   Samba uses various LDAP client libraries, a builtin one and/or the system
+   ldap libraries (typically openldap).
+
+   As active directory domain controller Samba also provides an LDAP server.
+
+   Samba takes care of doing SASL (GSS-SPNEGO) authentication with Kerberos or NTLMSSP
+   for LDAP connections, including possible integrity (sign) and privacy (seal)
+   protection.
+
+   Samba has support for an option called "client ldap sasl wrapping" since version
+   3.2.0. Its default value has changed from "plain" to "sign" with version 4.2.0.
+
+   Tools using the builtin LDAP client library do not obey the
+   "client ldap sasl wrapping" option. This applies to tools like:
+   "samba-tool", "ldbsearch", "ldbedit" and more. Some of them have command line
+   options like "--sign" and "--encrypt". With the security update they will
+   also obey the "client ldap sasl wrapping" option as default.
+
+   In all cases, even if explicitly request via "client ldap sasl wrapping",
+   "--sign" or "--encrypt", the protection can be downgraded by a man in the
+   middle.
+
+   The LDAP server doesn't have an option to enforce strong authentication
+   yet. The security patches will introduce a new option called
+   "ldap server require strong auth", possible values are "no",
+   "allow_sasl_over_tls" and "yes".
+
+   As the default behavior was as "no" before, you may
+   have to explicitly change this option until all clients have
+   been adjusted to handle LDAP_STRONG_AUTH_REQUIRED errors.
+   Windows clients and Samba member servers already use
+   integrity protection.
+
+o  CVE-2016-2113:
+
+   Samba has support for TLS/SSL for some protocols:
+   ldap and http, but currently certificates are not
+   validated at all. While we have a "tls cafile" option,
+   the configured certificate is not used to validate
+   the server certificate.
+
+   This applies to ldaps:// connections triggered by tools like:
+   "ldbsearch", "ldbedit" and more. Note that it only applies
+   to the ldb tools when they are built as part of Samba or with Samba
+   extensions installed, which means the Samba builtin LDAP client library is
+   used.
+
+   It also applies to dcerpc client connections using ncacn_http (with https://),
+   which are only used by the openchange project. Support for ncacn_http
+   was introduced in version 4.2.0.
+
+   The security patches will introduce a new option called
+   "tls verify peer". Possible values are "no_check", "ca_only",
+   "ca_and_name_if_available", "ca_and_name" and "as_strict_as_possible".
+
+   If you use the self-signed certificates which are auto-generated
+   by Samba, you won't have a crl file and need to explicitly
+   set "tls verify peer = ca_and_name".
+
+o  CVE-2016-2114
+
+   Due to a regression introduced in Samba 4.0.0,
+   an explicit "server signing = mandatory" in the [global] section
+   of the smb.conf was not enforced for clients using the SMB1 protocol.
+
+   As a result it does not enforce smb signing and allows man in the middle attacks.
+
+   This problem applies to all possible server roles:
+   standalone server, member server, classic primary domain controller,
+   classic backup domain controller and active directory domain controller.
+
+   In addition, when Samba is configured with "server role = active directory domain controller"
+   the effective default for the "server signing" option should be "mandatory".
+
+   During the early development of Samba 4 we had a new experimental
+   file server located under source4/smb_server. But before
+   the final 4.0.0 release we switched back to the file server
+   under source3/smbd.
+
+   But the logic for the correct default of "server signing" was not
+   ported correctly ported.
+
+   Note that the default for server roles other than active directory domain
+   controller, is "off" because of performance reasons.
+
+o  CVE-2016-2115:
+
+   Samba has an option called "client signing", this is turned off by default
+   for performance reasons on file transfers.
+
+   This option is also used when using DCERPC with ncacn_np.
+
+   In order to get integrity protection for ipc related communication
+   by default the "client ipc signing" option is introduced.
+   The effective default for this new option is "mandatory".
+
+   In order to be compatible with more SMB server implementations,
+   the following additional options are introduced:
+   "client ipc min protocol" ("NT1" by default) and
+   "client ipc max protocol" (the highest support SMB2/3 dialect by default).
+   These options overwrite the "client min protocol" and "client max protocol"
+   options, because the default for "client max protocol" is still "NT1".
+   The reason for this is the fact that all SMB2/3 support SMB signing,
+   while there are still SMB1 implementations which don't offer SMB signing
+   by default (this includes Samba versions before 4.0.0).
+
+   Note that winbindd (in versions 4.2.0 and higher) enforces SMB signing
+   against active directory domain controllers despite of the
+   "client signing" and "client ipc signing" options.
+
+o  CVE-2016-2118 (a.k.a. BADLOCK):
+
+   The Security Account Manager Remote Protocol [MS-SAMR] and the
+   Local Security Authority (Domain Policy) Remote Protocol [MS-LSAD]
+   are both vulnerable to man in the middle attacks. Both are application level
+   protocols based on the generic DCE 1.1 Remote Procedure Call (DCERPC) protocol.
+
+   These protocols are typically available on all Windows installations
+   as well as every Samba server. They are used to maintain
+   the Security Account Manager Database. This applies to all
+   roles, e.g. standalone, domain member, domain controller.
+
+   Any authenticated DCERPC connection a client initiates against a server
+   can be used by a man in the middle to impersonate the authenticated user
+   against the SAMR or LSAD service on the server.
+
+   The client chosen application protocol, auth type (e.g. Kerberos or NTLMSSP)
+   and auth level (NONE, CONNECT, PKT_INTEGRITY, PKT_PRIVACY) do not matter
+   in this case. A man in the middle can change auth level to CONNECT
+   (which means authentication without message protection) and take over
+   the connection.
+
+   As a result, a man in the middle is able to get read/write access to the
+   Security Account Manager Database, which reveals all passwords
+   and any other potential sensitive information.
+
+   Samba running as an active directory domain controller is additionally
+   missing checks to enforce PKT_PRIVACY for the
+   Directory Replication Service Remote Protocol [MS-DRSR] (drsuapi)
+   and the BackupKey Remote Protocol [MS-BKRP] (backupkey).
+   The Domain Name Service Server Management Protocol [MS-DNSP] (dnsserver)
+   is not enforcing at least PKT_INTEGRITY.
+
+====================
+New smb.conf options
+====================
+
+  allow dcerpc auth level connect (G)
+
+    This option controls whether DCERPC services are allowed to be used with
+    DCERPC_AUTH_LEVEL_CONNECT, which provides authentication, but no per
+    message integrity nor privacy protection.
+
+    Some interfaces like samr, lsarpc and netlogon have a hard-coded default
+    of no and epmapper, mgmt and rpcecho have a hard-coded default of yes.
+
+    The behavior can be overwritten per interface name (e.g. lsarpc,
+    netlogon, samr, srvsvc, winreg, wkssvc ...) by using
+    'allow dcerpc auth level connect:interface = yes' as option.
+
+    This option yields precedence to the implementation specific restrictions.
+    E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY.
+    The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY.
+
+    Default: allow dcerpc auth level connect = no
+
+    Example: allow dcerpc auth level connect = yes
+
+  client ipc signing (G)
+
+    This controls whether the client is allowed or required to use
+    SMB signing for IPC$ connections as DCERPC transport. Possible
+    values are auto, mandatory and disabled.
+
+    When set to mandatory or default, SMB signing is required.
+
+    When set to auto, SMB signing is offered, but not enforced and
+    if set to disabled, SMB signing is not offered either.
+
+    Connections from winbindd to Active Directory Domain Controllers
+    always enforce signing.
+
+    Default: client ipc signing = default
+
+  client ipc max protocol (G)
+
+    The value of the parameter (a string) is the highest protocol level that will
+    be supported for IPC$ connections as DCERPC transport.
+
+    Normally this option should not be set as the automatic negotiation phase
+    in the SMB protocol takes care of choosing the appropriate protocol.
+
+    The value default refers to the latest supported protocol, currently SMB3_11.
+
+    See client max protocol for a full list of available protocols.
+    The values CORE, COREPLUS, LANMAN1, LANMAN2 are silently upgraded to NT1.
+
+    Default: client ipc max protocol = default
+
+    Example: client ipc max protocol = SMB2_10
+
+  client ipc min protocol (G)
+
+    This setting controls the minimum protocol version that the will be
+    attempted to use for IPC$ connections as DCERPC transport.
+
+    Normally this option should not be set as the automatic negotiation phase
+    in the SMB protocol takes care of choosing the appropriate protocol.
+
+    The value default refers to the higher value of NT1 and the
+    effective value of "client min protocol".
+
+    See client max protocol for a full list of available protocols.
+    The values CORE, COREPLUS, LANMAN1, LANMAN2 are silently upgraded to NT1.
+
+    Default: client ipc min protocol = default
+
+    Example: client ipc min protocol = SMB3_11
+
+  ldap server require strong auth (G)
+
+    The ldap server require strong auth defines whether the
+    ldap server requires ldap traffic to be signed or
+    signed and encrypted (sealed). Possible values are no,
+    allow_sasl_over_tls and yes.
+
+    A value of no allows simple and sasl binds over all transports.
+
+    A value of allow_sasl_over_tls allows simple and sasl binds (without sign or seal)
+    over TLS encrypted connections. Unencrypted connections only
+    allow sasl binds with sign or seal.
+
+    A value of yes allows only simple binds over TLS encrypted connections.
+    Unencrypted connections only allow sasl binds with sign or seal.
+
+    Default: ldap server require strong auth = yes
+
+  raw NTLMv2 auth (G)
+
+    This parameter determines whether or not smbd(8) will allow SMB1 clients
+    without extended security (without SPNEGO) to use NTLMv2 authentication.
+
+    If this option, lanman auth and ntlm auth are all disabled, then only
+    clients with SPNEGO support will be permitted. That means NTLMv2 is only
+    supported within NTLMSSP.
+
+    Default: raw NTLMv2 auth = no
+
+  tls verify peer (G)
+
+    This controls if and how strict the client will verify the peer's
+    certificate and name. Possible values are (in increasing order): no_check,
+    ca_only, ca_and_name_if_available, ca_and_name and as_strict_as_possible.
+
+    When set to no_check the certificate is not verified at all,
+    which allows trivial man in the middle attacks.
+
+    When set to ca_only the certificate is verified to be signed from a ca
+    specified in the "tls ca file" option. Setting "tls ca file" to a valid file
+    is required. The certificate lifetime is also verified. If the "tls crl file"
+    option is configured, the certificate is also verified against
+    the ca crl.
+
+    When set to ca_and_name_if_available all checks from ca_only are performed.
+    In addition, the peer hostname is verified against the certificate's
+    name, if it is provided by the application layer and not given as
+    an ip address string.
+
+    When set to ca_and_name all checks from ca_and_name_if_available are performed.
+    In addition the peer hostname needs to be provided and even an ip
+    address is checked against the certificate's name.
+
+    When set to as_strict_as_possible all checks from ca_and_name are performed.
+    In addition the "tls crl file" needs to be configured. Future versions
+    of Samba may implement additional checks.
+
+    Default: tls verify peer = as_strict_as_possible
+
+  tls priority (G) (backported from Samba 4.3 to Samba 4.2)
+
+    This option can be set to a string describing the TLS protocols to be
+    supported in the parts of Samba that use GnuTLS, specifically the AD DC.
+
+    The default turns off SSLv3, as this protocol is no longer considered
+    secure after CVE-2014-3566 (otherwise known as POODLE) impacted SSLv3 use
+    in HTTPS applications.
+
+    The valid options are described in the GNUTLS Priority-Strings
+    documentation at http://gnutls.org/manual/html_node/Priority-Strings.html
+
+    Default: tls priority = NORMAL:-VERS-SSL3.0
+
+================
+Behavior changes
+================
+
+o  The default auth level for authenticated binds has changed from
+   DCERPC_AUTH_LEVEL_CONNECT to DCERPC_AUTH_LEVEL_INTEGRITY.
+   That means ncacn_ip_tcp:server is now implicitly the same
+   as ncacn_ip_tcp:server[sign] and offers a similar protection
+   as ncacn_np:server, which relies on smb signing.
+
+o  The following constraints are applied to SMB1 connections:
+
+   - "client lanman auth = yes" is now consistently
+     required for authenticated connections using the
+     SMB1 LANMAN2 dialect.
+   - "client ntlmv2 auth = yes" and "client use spnego = yes"
+     (both the default values), require extended security (SPNEGO)
+     support from the server. That means NTLMv2 is only used within
+     NTLMSSP.
+
+o  Tools like "samba-tool", "ldbsearch", "ldbedit" and more obey the
+   default of "client ldap sasl wrapping = sign". Even with
+   "client ldap sasl wrapping = plain" they will automatically upgrade
+   to "sign" when getting LDAP_STRONG_AUTH_REQUIRED from the LDAP
+   server.
+
+Changes since 4.3.6:
+--------------------
+
+o  Jeremy Allison <jra at samba.org>
+   * Bug 11344 - CVE-2015-5370: Multiple errors in DCE-RPC code.
+
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Christian Ambach <ambi at samba.org>
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Ralph Boehme <slow at samba.org>
+   * Bug 11644 - CVE-2016-2112: The LDAP client and server don't enforce
+     integrity protection.
+
+o  Günther Deschner <gd at samba.org>
+   * Bug 11749 - CVE-2016-2111: NETLOGON Spoofing Vulnerability.
+
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Björn Jacke <bj at sernet.de>
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Volker Lendecke <vl at samba.org>
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * Bug 11344 - CVE-2015-5370: Multiple errors in DCE-RPC code.
+
+   * Bug 11616 - CVE-2016-2118: SAMR and LSA man in the middle attacks possible.
+
+   * Bug 11644 - CVE-2016-2112: The LDAP client and server doesn't enforce
+     integrity protection.
+
+   * Bug 11687 - CVE-2016-2114: "server signing = mandatory" not enforced.
+
+   * Bug 11688 - CVE-2016-2110: Man in the middle attacks possible with NTLMSSP.
+
+   * Bug 11749 - CVE-2016-2111: NETLOGON Spoofing Vulnerability.
+
+   * Bug 11752 - CVE-2016-2113: Missing TLS certificate validation allows man in
+     the middle attacks.
+
+   * Bug 11756 - CVE-2016-2115: SMB client connections for IPC traffic are not
+     integrity protected.
+
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+o  Richard Sharpe <rsharpe at samba.org>
+   * Bug 11804 - prerequisite backports for the security release on
+     April 12th, 2016.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
+
+                   =============================
                    Release Notes for Samba 4.3.6
                            March 8, 2016
                    =============================
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index fdedd63..3779ec0 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -22,6 +22,7 @@
 #ifndef __CREDENTIALS_H__
 #define __CREDENTIALS_H__
 
+#include "../lib/util/time.h"
 #include "../lib/util/data_blob.h"
 #include "librpc/gen_ndr/misc.h"
 
@@ -80,7 +81,9 @@ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALL
 					      const char **domain);
 NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, 
 					   int *flags,
-					   DATA_BLOB challenge, DATA_BLOB target_info, 
+					   DATA_BLOB challenge,
+					   const NTTIME *server_timestamp,
+					   DATA_BLOB target_info,
 					   DATA_BLOB *_lm_response, DATA_BLOB *_nt_response, 
 					   DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key);
 const char *cli_credentials_get_realm(struct cli_credentials *cred);
diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c
index 4e12277..0abbb5c 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -30,7 +30,9 @@
 
 _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, 
 					   int *flags,
-					   DATA_BLOB challenge, DATA_BLOB target_info, 
+					   DATA_BLOB challenge,
+					   const NTTIME *server_timestamp,
+					   DATA_BLOB target_info,
 					   DATA_BLOB *_lm_response, DATA_BLOB *_nt_response, 
 					   DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key) 
 {
@@ -102,7 +104,7 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
 					   user, 
 					   domain, 
 					   nt_hash->hash, &challenge, 
-					   &target_info, 
+					   server_timestamp, &target_info,
 					   &lm_response, &nt_response, 
 					   NULL, &session_key)) {
 			return NT_STATUS_NO_MEMORY;
@@ -110,6 +112,12 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
 
 		/* LM Key is incompatible... */
 		*flags &= ~CLI_CRED_LANMAN_AUTH;
+		if (lm_response.length != 0) {
+			/*
+			 * We should not expose the lm key.
+			 */
+			memset(lm_response.data, 0, lm_response.length);
+		}
 	} else if (*flags & CLI_CRED_NTLM2) {
 		MD5_CTX md5_session_nonce_ctx;
 		uint8_t session_nonce[16];
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 9fd5f25..2a8bba8 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -30,6 +30,16 @@
 #include "auth/gensec/gensec_internal.h"
 #include "librpc/gen_ndr/dcerpc.h"
 
+_PRIVATE_ NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
+					   bool full_reset)
+{
+	if (!gensec_security->ops->may_reset_crypto) {
+		return NT_STATUS_OK;
+	}
+
+	return gensec_security->ops->may_reset_crypto(gensec_security, full_reset);
+}
+
 /*
   wrappers for the gensec function pointers
 */
@@ -217,6 +227,50 @@ _PUBLIC_ size_t gensec_max_update_size(struct gensec_security *gensec_security)
 	return gensec_security->max_update_size;
 }
 
+static NTSTATUS gensec_verify_dcerpc_auth_level(struct gensec_security *gensec_security)
+{
+	if (gensec_security->dcerpc_auth_level == 0) {
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * Because callers using the
+	 * gensec_start_mech_by_auth_type() never call
+	 * gensec_want_feature(), it isn't sensible for them
+	 * to have to call gensec_have_feature() manually, and
+	 * these are not points of negotiation, but are
+	 * asserted by the client
+	 */
+	switch (gensec_security->dcerpc_auth_level) {
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+			DEBUG(0,("Did not manage to negotiate mandetory feature "
+				 "SIGN for dcerpc auth_level %u\n",
+				 gensec_security->dcerpc_auth_level));
+			return NT_STATUS_ACCESS_DENIED;
+		}
+		break;
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+			DEBUG(0,("Did not manage to negotiate mandetory feature "
+				 "SIGN for dcerpc auth_level %u\n",
+				 gensec_security->dcerpc_auth_level));
+			return NT_STATUS_ACCESS_DENIED;
+		}
+		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
+			DEBUG(0,("Did not manage to negotiate mandetory feature "
+				 "SEAL for dcerpc auth_level %u\n",
+				 gensec_security->dcerpc_auth_level));
+			return NT_STATUS_ACCESS_DENIED;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NT_STATUS_OK;
+}
+
 _PUBLIC_ NTSTATUS gensec_update_ev(struct gensec_security *gensec_security,
 				   TALLOC_CTX *out_mem_ctx,
 				   struct tevent_context *ev,
@@ -261,31 +315,9 @@ _PUBLIC_ NTSTATUS gensec_update_ev(struct gensec_security *gensec_security,
 		 * these are not points of negotiation, but are
 		 * asserted by the client
 		 */
-		switch (gensec_security->dcerpc_auth_level) {
-		case DCERPC_AUTH_LEVEL_INTEGRITY:
-			if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
-				DEBUG(0,("Did not manage to negotiate mandetory feature "
-					 "SIGN for dcerpc auth_level %u\n",
-					 gensec_security->dcerpc_auth_level));
-				return NT_STATUS_ACCESS_DENIED;
-			}
-			break;
-		case DCERPC_AUTH_LEVEL_PRIVACY:
-			if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
-				DEBUG(0,("Did not manage to negotiate mandetory feature "
-					 "SIGN for dcerpc auth_level %u\n",
-					 gensec_security->dcerpc_auth_level));
-				return NT_STATUS_ACCESS_DENIED;
-			}
-			if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
-				DEBUG(0,("Did not manage to negotiate mandetory feature "
-					 "SEAL for dcerpc auth_level %u\n",
-					 gensec_security->dcerpc_auth_level));
-				return NT_STATUS_ACCESS_DENIED;
-			}
-			break;
-		default:
-			break;
+		status = gensec_verify_dcerpc_auth_level(gensec_security);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
 		}
 
 		return NT_STATUS_OK;
@@ -458,34 +490,9 @@ static void gensec_update_subreq_done(struct tevent_req *subreq)
 	 * these are not points of negotiation, but are
 	 * asserted by the client
 	 */
-	switch (state->gensec_security->dcerpc_auth_level) {
-	case DCERPC_AUTH_LEVEL_INTEGRITY:
-		if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
-				 "SIGN for dcerpc auth_level %u\n",
-				 state->gensec_security->dcerpc_auth_level));
-			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-			return;
-		}
-		break;
-	case DCERPC_AUTH_LEVEL_PRIVACY:
-		if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
-				 "SIGN for dcerpc auth_level %u\n",
-				 state->gensec_security->dcerpc_auth_level));
-			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-			return;
-		}
-		if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SEAL)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
-				 "SEAL for dcerpc auth_level %u\n",
-				 state->gensec_security->dcerpc_auth_level));
-			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-			return;
-		}
-		break;
-	default:
-		break;
+	status = gensec_verify_dcerpc_auth_level(state->gensec_security);
+	if (tevent_req_nterror(req, status)) {
+		return;
 	}
 
 	tevent_req_done(req);
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index d09813e..e8bd7b1 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -61,6 +61,8 @@ struct gensec_target {
 #define GENSEC_FEATURE_SIGN_PKT_HEADER	0x00000040
 #define GENSEC_FEATURE_NEW_SPNEGO	0x00000080
 #define GENSEC_FEATURE_UNIX_TOKEN	0x00000100
+#define GENSEC_FEATURE_NTLM_CCACHE	0x00000200
+#define GENSEC_FEATURE_LDAP_STYLE	0x00000400
 
 #define GENSEC_EXPIRE_TIME_INFINITY (NTTIME)0x8000000000000000LL
 
@@ -163,6 +165,8 @@ const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_sec
 const struct gensec_security_ops *gensec_security_by_auth_type(
 				struct gensec_security *gensec_security,
 				uint32_t auth_type);
+const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
+							  const char *name);
 const struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
 						   TALLOC_CTX *mem_ctx);
 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h
index 45a66f8..5535241 100644
--- a/auth/gensec/gensec_internal.h
+++ b/auth/gensec/gensec_internal.h
@@ -47,6 +47,8 @@ struct gensec_security_ops {
 	NTSTATUS (*update_recv)(struct tevent_req *req,
 				TALLOC_CTX *out_mem_ctx,
 				DATA_BLOB *out);
+	NTSTATUS (*may_reset_crypto)(struct gensec_security *gensec_security,
+				     bool full_reset);
 	NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx,
 				uint8_t *data, size_t length,
 				const uint8_t *whole_pdu, size_t pdu_length,
@@ -110,6 +112,8 @@ struct gensec_security {
 	 * NTLM authentication backend, and user lookup (such as if no
 	 * PAC is found) */
 	struct auth4_context *auth_context;
+
+	struct gensec_security *child_security;
 };
 
 /* this structure is used by backends to determine the size of some critical types */
@@ -119,4 +123,7 @@ struct gensec_critical_sizes {
 	int sizeof_gensec_security;
 };
 
+NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
+				 bool full_reset);
+
 #endif /* __GENSEC_H__ */
diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c
index be31697..4c43519 100644
--- a/auth/gensec/gensec_start.c
+++ b/auth/gensec/gensec_start.c
@@ -211,8 +211,10 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
 	}
 	backends = gensec_security_mechs(gensec_security, mem_ctx);
 	for (i=0; backends && backends[i]; i++) {
-		if (!gensec_security_ops_enabled(backends[i], gensec_security))
-		    continue;
+		if (gensec_security != NULL &&
+		    !gensec_security_ops_enabled(backends[i], gensec_security)) {
+			continue;
+		}
 		if (backends[i]->sasl_name
 		    && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
 			backend = backends[i];
@@ -232,7 +234,13 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
 	int i;
 	const struct gensec_security_ops **backends;
 	const struct gensec_security_ops *backend;
-	TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
+	TALLOC_CTX *mem_ctx;
+
+	if (auth_type == DCERPC_AUTH_TYPE_NONE) {
+		return NULL;
+	}
+
+	mem_ctx = talloc_new(gensec_security);
 	if (!mem_ctx) {
 		return NULL;
 	}
@@ -253,8 +261,8 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
 	return NULL;
 }
 
-static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
-								 const char *name)
+const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
+							  const char *name)
 {
 	int i;
 	const struct gensec_security_ops **backends;
diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index 8ef4b25..64fffb1 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -81,7 +81,7 @@ static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
 	if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
 	if (!asn1_check_OID(data, oid)) goto err;
 
-	ret = !data->has_error;
+	ret = !asn1_has_error(data);
 
   err:
 
diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c
index 9b28c45..8baf803 100644
--- a/auth/gensec/schannel.c
+++ b/auth/gensec/schannel.c
@@ -467,6 +467,16 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_
 
 	*out = data_blob(NULL, 0);
 
+	if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+		switch (gensec_security->gensec_role) {
+		case GENSEC_CLIENT:
+			return NT_STATUS_INVALID_PARAMETER_MIX;
+		case GENSEC_SERVER:
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
 	switch (gensec_security->gensec_role) {
 	case GENSEC_CLIENT:
 		if (state != NULL) {
@@ -662,9 +672,15 @@ static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
 static bool schannel_have_feature(struct gensec_security *gensec_security,
 					 uint32_t feature)
 {
-	if (feature & (GENSEC_FEATURE_SIGN |
-		       GENSEC_FEATURE_SEAL)) {
-		return true;
+	if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
+		if (feature & GENSEC_FEATURE_SIGN) {
+			return true;
+		}
+	}
+	if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+		if (feature & GENSEC_FEATURE_SEAL) {
+			return true;
+		}
 	}
 	if (feature & GENSEC_FEATURE_DCE_STYLE) {
 		return true;
diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c
index fe2ec43..1d4b172 100644
--- a/auth/gensec/spnego.c
+++ b/auth/gensec/spnego.c
@@ -53,6 +53,11 @@ struct spnego_state {
 	const char *neg_oid;
 
 	DATA_BLOB mech_types;
+	size_t num_targs;
+	bool mic_requested;
+	bool needs_mic_sign;
+	bool needs_mic_check;
+	bool done_mic_check;
 
 	/*
 	 * The following is used to implement
@@ -416,6 +421,11 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_
 					spnego_state->neg_oid = all_sec[i].oid;
 					*unwrapped_out = data_blob_null;
 					nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+					/*
+					 * Indicate the downgrade and request a
+					 * mic.
+					 */
+					spnego_state->mic_requested = true;
 					break;
 				}
 
@@ -674,22 +684,27 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct spnego_state *spnego_st
 	/* compose reply */
 	spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
 	spnego_out.negTokenTarg.responseToken = unwrapped_out;
-	spnego_out.negTokenTarg.mechListMIC = null_data_blob;
+	spnego_out.negTokenTarg.mechListMIC = mech_list_mic;
 	spnego_out.negTokenTarg.supportedMech = NULL;
 
 	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {	
 		spnego_out.negTokenTarg.supportedMech = spnego_state->neg_oid;
-		spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
+		if (spnego_state->mic_requested) {
+			spnego_out.negTokenTarg.negResult = SPNEGO_REQUEST_MIC;
+			spnego_state->mic_requested = false;
+		} else {
+			spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
+		}
 		spnego_state->state_position = SPNEGO_SERVER_TARG;
 	} else if (NT_STATUS_IS_OK(nt_status)) {
 		if (unwrapped_out.data) {
 			spnego_out.negTokenTarg.supportedMech = spnego_state->neg_oid;
 		}
 		spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
-		spnego_out.negTokenTarg.mechListMIC = mech_list_mic;
 		spnego_state->state_position = SPNEGO_DONE;
 	} else {
 		spnego_out.negTokenTarg.negResult = SPNEGO_REJECT;
+		spnego_out.negTokenTarg.mechListMIC = null_data_blob;
 		DEBUG(2, ("SPNEGO login failed: %s\n", nt_errstr(nt_status)));
 		spnego_state->state_position = SPNEGO_DONE;
 	}
@@ -700,6 +715,7 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct spnego_state *spnego_st
 	}
 
 	spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
+	spnego_state->num_targs++;
 
 	return nt_status;
 }
@@ -784,6 +800,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 
 		const char *my_mechs[] = {NULL, NULL};
 		NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
+		bool ok;
 
 		if (!in.length) {
 			/* client to produce negTokenInit */
@@ -846,6 +863,14 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 				return NT_STATUS_INVALID_PARAMETER;
 		}
 
+		ok = spnego_write_mech_types(spnego_state,
+					     my_mechs,
+					     &spnego_state->mech_types);
+		if (!ok) {
+			DEBUG(1, ("SPNEGO: Failed to write mechTypes\n"));
+			return NT_STATUS_NO_MEMORY;
+		}
+
 		/* set next state */
 		spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
 		spnego_state->state_position = SPNEGO_CLIENT_TARG;
@@ -883,18 +908,57 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 			return NT_STATUS_INVALID_PARAMETER;
 		}
 
+		spnego_state->num_targs++;
+
 		if (!spnego_state->sub_sec_security) {
 			DEBUG(1, ("SPNEGO: Did not setup a mech in NEG_TOKEN_INIT\n"));
 			spnego_free_data(&spnego);
 			return NT_STATUS_INVALID_PARAMETER;
 		}
 
+		if (spnego_state->needs_mic_check) {
+			if (spnego.negTokenTarg.responseToken.length != 0) {
+				DEBUG(1, ("SPNEGO: Did not setup a mech in NEG_TOKEN_INIT\n"));
+				spnego_free_data(&spnego);
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+
+			nt_status = gensec_check_packet(spnego_state->sub_sec_security,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							&spnego.negTokenTarg.mechListMIC);
+			if (NT_STATUS_IS_OK(nt_status)) {
+				spnego_state->needs_mic_check = false;
+				spnego_state->done_mic_check = true;
+			} else {
+				DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
+					nt_errstr(nt_status)));
+			}
+			goto server_response;
+		}
+
 		nt_status = gensec_update_ev(spnego_state->sub_sec_security,
-					  out_mem_ctx, ev,
-					  spnego.negTokenTarg.responseToken,
-					  &unwrapped_out);
-		if (NT_STATUS_IS_OK(nt_status) && spnego.negTokenTarg.mechListMIC.length > 0) {
+					     out_mem_ctx, ev,
+					     spnego.negTokenTarg.responseToken,
+					     &unwrapped_out);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			goto server_response;
+		}
+
+		new_spnego = gensec_have_feature(spnego_state->sub_sec_security,
+						 GENSEC_FEATURE_NEW_SPNEGO);
+		if (spnego.negTokenTarg.mechListMIC.length > 0) {
 			new_spnego = true;
+		}
+
+		if (new_spnego) {
+			spnego_state->needs_mic_check = true;
+			spnego_state->needs_mic_sign = true;
+		}
+
+		if (spnego.negTokenTarg.mechListMIC.length > 0) {
 			nt_status = gensec_check_packet(spnego_state->sub_sec_security,
 							spnego_state->mech_types.data,
 							spnego_state->mech_types.length,
@@ -904,9 +968,14 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 			if (!NT_STATUS_IS_OK(nt_status)) {
 				DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
 					nt_errstr(nt_status)));
+				goto server_response;
 			}
+
+			spnego_state->needs_mic_check = false;
+			spnego_state->done_mic_check = true;
 		}
-		if (NT_STATUS_IS_OK(nt_status) && new_spnego) {
+
+		if (spnego_state->needs_mic_sign) {
 			nt_status = gensec_sign_packet(spnego_state->sub_sec_security,
 						       out_mem_ctx,
 						       spnego_state->mech_types.data,
@@ -917,9 +986,16 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 			if (!NT_STATUS_IS_OK(nt_status)) {
 				DEBUG(2,("GENSEC SPNEGO: failed to sign mechListMIC: %s\n",
 					nt_errstr(nt_status)));
+				goto server_response;
 			}
+			spnego_state->needs_mic_sign = false;
 		}
 
+		if (spnego_state->needs_mic_check) {
+			nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+		}
+
+ server_response:
 		nt_status = gensec_spnego_server_negTokenTarg(spnego_state,
 							      out_mem_ctx, 
 							      nt_status,
@@ -933,7 +1009,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 	}
 	case SPNEGO_CLIENT_TARG:
 	{
-		NTSTATUS nt_status;
+		NTSTATUS nt_status = NT_STATUS_INTERNAL_ERROR;
+
 		if (!in.length) {
 			return NT_STATUS_INVALID_PARAMETER;
 		}
@@ -955,19 +1032,27 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 			return NT_STATUS_INVALID_PARAMETER;
 		}
 
+		spnego_state->num_targs++;
+
 		if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) {
 			spnego_free_data(&spnego);
 			return NT_STATUS_LOGON_FAILURE;
 		}
 
+		if (spnego.negTokenTarg.negResult == SPNEGO_REQUEST_MIC) {
+			spnego_state->mic_requested = true;
+		}
+
 		/* Server didn't like our choice of mech, and chose something else */
-		if ((spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_INCOMPLETE) &&
+		if (((spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_INCOMPLETE) ||
+		     (spnego.negTokenTarg.negResult == SPNEGO_REQUEST_MIC)) &&
 		    spnego.negTokenTarg.supportedMech &&
 		    strcmp(spnego.negTokenTarg.supportedMech, spnego_state->neg_oid) != 0) {
 			DEBUG(3,("GENSEC SPNEGO: client preferred mech (%s) not accepted, server wants: %s\n",
-				 gensec_get_name_by_oid(gensec_security, spnego.negTokenTarg.supportedMech), 
-				 gensec_get_name_by_oid(gensec_security, spnego_state->neg_oid)));
+				 gensec_get_name_by_oid(gensec_security, spnego_state->neg_oid),
+				 gensec_get_name_by_oid(gensec_security, spnego.negTokenTarg.supportedMech)));
 
+			spnego_state->no_response_expected = false;
 			talloc_free(spnego_state->sub_sec_security);
 			nt_status = gensec_subcontext_start(spnego_state,
 							    gensec_security,
@@ -984,64 +1069,143 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 				return nt_status;
 			}
 
-			nt_status = gensec_update_ev(spnego_state->sub_sec_security,
-						  out_mem_ctx, ev,
-						  spnego.negTokenTarg.responseToken,
-						  &unwrapped_out);
-			spnego_state->neg_oid = talloc_strdup(spnego_state, spnego.negTokenTarg.supportedMech);
-		} else if (spnego_state->no_response_expected) {
-			if (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED) {
-				DEBUG(3,("GENSEC SPNEGO: client GENSEC accepted, but server rejected (bad password?)\n"));
-				nt_status = NT_STATUS_INVALID_PARAMETER;
-			} else if (spnego.negTokenTarg.responseToken.length) {
-				DEBUG(2,("GENSEC SPNEGO: client GENSEC accepted, but server continued negotiation!\n"));
-				nt_status = NT_STATUS_INVALID_PARAMETER;
-			} else {
-				nt_status = NT_STATUS_OK;
+			spnego_state->neg_oid = talloc_strdup(spnego_state,
+						spnego.negTokenTarg.supportedMech);
+			if (spnego_state->neg_oid == NULL) {
+				spnego_free_data(&spnego);
+				return NT_STATUS_NO_MEMORY;
+			};
+		}
+
+		if (spnego.negTokenTarg.mechListMIC.length > 0) {
+			if (spnego_state->no_response_expected) {
+				spnego_state->needs_mic_check = true;
 			}
-			if (NT_STATUS_IS_OK(nt_status) && spnego.negTokenTarg.mechListMIC.length > 0) {
-				nt_status = gensec_check_packet(spnego_state->sub_sec_security,
-								spnego_state->mech_types.data,
-								spnego_state->mech_types.length,
-								spnego_state->mech_types.data,
-								spnego_state->mech_types.length,
-								&spnego.negTokenTarg.mechListMIC);
-				if (!NT_STATUS_IS_OK(nt_status)) {
-					DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
-						nt_errstr(nt_status)));
-				}
+		}
+
+		if (spnego_state->needs_mic_check) {
+			if (spnego.negTokenTarg.responseToken.length != 0) {
+				DEBUG(1, ("SPNEGO: Did not setup a mech in NEG_TOKEN_INIT\n"));
+				spnego_free_data(&spnego);
+				return NT_STATUS_INVALID_PARAMETER;
 			}
-		} else {
-			bool new_spnego = false;
 
+			nt_status = gensec_check_packet(spnego_state->sub_sec_security,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							&spnego.negTokenTarg.mechListMIC);
+			if (!NT_STATUS_IS_OK(nt_status)) {
+				DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
+					nt_errstr(nt_status)));
+				spnego_free_data(&spnego);
+				return nt_status;
+			}
+			spnego_state->needs_mic_check = false;
+			spnego_state->done_mic_check = true;
+			goto client_response;
+		}
+
+		if (!spnego_state->no_response_expected) {
 			nt_status = gensec_update_ev(spnego_state->sub_sec_security,
 						  out_mem_ctx, ev,
 						  spnego.negTokenTarg.responseToken, 
 						  &unwrapped_out);
+			if (!NT_STATUS_IS_OK(nt_status)) {
+				goto client_response;
+			}
+
+			spnego_state->no_response_expected = true;
+		} else {
+			nt_status = NT_STATUS_OK;
+		}
+
+		if (spnego_state->no_response_expected &&
+		    !spnego_state->done_mic_check)
+		{
+			bool new_spnego = false;
 
-			if (NT_STATUS_IS_OK(nt_status)
-			    && spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED) {
-				new_spnego = gensec_have_feature(spnego_state->sub_sec_security,
-								 GENSEC_FEATURE_NEW_SPNEGO);
+			new_spnego = gensec_have_feature(spnego_state->sub_sec_security,
+							 GENSEC_FEATURE_NEW_SPNEGO);
+
+			switch (spnego.negTokenTarg.negResult) {
+			case SPNEGO_ACCEPT_COMPLETED:
+			case SPNEGO_NONE_RESULT:
+				if (spnego_state->num_targs == 1) {
+					/*
+					 * the first exchange doesn't require
+					 * verification
+					 */
+					new_spnego = false;
+				}
+				break;
+
+			case SPNEGO_ACCEPT_INCOMPLETE:
+			case SPNEGO_REQUEST_MIC:
+				if (spnego.negTokenTarg.mechListMIC.length > 0) {
+					new_spnego = true;
+				}
+				break;
+			default:
+				break;
 			}
-			if (NT_STATUS_IS_OK(nt_status) && new_spnego) {
-				nt_status = gensec_sign_packet(spnego_state->sub_sec_security,
-							       out_mem_ctx,
-							       spnego_state->mech_types.data,
-							       spnego_state->mech_types.length,
-							       spnego_state->mech_types.data,
-							       spnego_state->mech_types.length,
-							       &mech_list_mic);
-				if (!NT_STATUS_IS_OK(nt_status)) {
-					DEBUG(2,("GENSEC SPNEGO: failed to sign mechListMIC: %s\n",
-						nt_errstr(nt_status)));
+
+			if (spnego_state->mic_requested) {
+				bool sign;
+
+				sign = gensec_have_feature(spnego_state->sub_sec_security,
+							   GENSEC_FEATURE_SIGN);
+				if (sign) {
+					new_spnego = true;
 				}
 			}
-			if (NT_STATUS_IS_OK(nt_status)) {
-				spnego_state->no_response_expected = true;
+
+			if (new_spnego) {
+				spnego_state->needs_mic_check = true;
+				spnego_state->needs_mic_sign = true;
 			}
-		} 
+		}
 
+		if (spnego.negTokenTarg.mechListMIC.length > 0) {
+			nt_status = gensec_check_packet(spnego_state->sub_sec_security,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							spnego_state->mech_types.data,
+							spnego_state->mech_types.length,
+							&spnego.negTokenTarg.mechListMIC);
+			if (!NT_STATUS_IS_OK(nt_status)) {
+				DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
+					nt_errstr(nt_status)));
+				spnego_free_data(&spnego);
+				return nt_status;
+			}
+			spnego_state->needs_mic_check = false;
+			spnego_state->done_mic_check = true;
+		}
+
+		if (spnego_state->needs_mic_sign) {
+			nt_status = gensec_sign_packet(spnego_state->sub_sec_security,
+						       out_mem_ctx,
+						       spnego_state->mech_types.data,
+						       spnego_state->mech_types.length,
+						       spnego_state->mech_types.data,
+						       spnego_state->mech_types.length,
+						       &mech_list_mic);
+			if (!NT_STATUS_IS_OK(nt_status)) {
+				DEBUG(2,("GENSEC SPNEGO: failed to sign mechListMIC: %s\n",
+					nt_errstr(nt_status)));
+				spnego_free_data(&spnego);
+				return nt_status;
+			}
+			spnego_state->needs_mic_sign = false;
+		}
+
+		if (spnego_state->needs_mic_check) {
+			nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+		}
+
+ client_response:
 		spnego_free_data(&spnego);
 
 		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
@@ -1065,6 +1229,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 				return NT_STATUS_INVALID_PARAMETER;
 			}
 
+			spnego_state->num_targs++;
 			spnego_state->state_position = SPNEGO_CLIENT_TARG;
 			nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
 		} else {
@@ -1095,26 +1260,24 @@ static NTSTATUS gensec_spnego_update_in(struct gensec_security *gensec_security,
 {
 	struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
 	size_t expected;
-	NTSTATUS status;
 	bool ok;
 
 	*full_in = data_blob_null;
 
 	if (spnego_state->in_needed == 0) {
 		size_t size = 0;
+		int ret;
 
 		/*
 		 * try to work out the size of the full
 		 * input token, it might be fragmented
 		 */
-		status = asn1_peek_full_tag(in,  ASN1_APPLICATION(0), &size);
-		if (!NT_STATUS_IS_OK(status) &&
-		    !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-			status = asn1_peek_full_tag(in, ASN1_CONTEXT(1), &size);
+		ret = asn1_peek_full_tag(in,  ASN1_APPLICATION(0), &size);
+		if ((ret != 0) && (ret != EAGAIN)) {
+			ret = asn1_peek_full_tag(in, ASN1_CONTEXT(1), &size);
 		}
 
-		if (NT_STATUS_IS_OK(status) ||
-		    NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+		if ((ret == 0) || (ret == EAGAIN)) {
 			spnego_state->in_needed = size;
 		} else {
 			/*
@@ -1262,6 +1425,16 @@ static NTSTATUS gensec_spnego_update_wrapper(struct gensec_security *gensec_secu
 				      &spnego_state->out_frag);
 	data_blob_free(&spnego_state->in_frag);
 	spnego_state->in_needed = 0;
+	if (NT_STATUS_IS_OK(status)) {
+		bool reset_full = true;
+
+		gensec_security->child_security = spnego_state->sub_sec_security;
+
+		reset_full = !spnego_state->done_mic_check;
+
+		status = gensec_may_reset_crypto(spnego_state->sub_sec_security,
+						 reset_full);
+	}
 	if (!NT_STATUS_IS_OK(status) &&
 	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 		return status;
diff --git a/auth/ntlmssp/gensec_ntlmssp.c b/auth/ntlmssp/gensec_ntlmssp.c
index 5672589..329d8eb 100644
--- a/auth/ntlmssp/gensec_ntlmssp.c
+++ b/auth/ntlmssp/gensec_ntlmssp.c
@@ -105,6 +105,15 @@ bool gensec_ntlmssp_have_feature(struct gensec_security *gensec_security,
 	if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
 		return true;
 	}
+	if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
+		if (!ntlmssp_state->session_key.length) {
+			return false;
+		}
+		if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+			return false;
+		}
+		return ntlmssp_state->new_spnego;
+	}
 
 	return false;
 }
diff --git a/auth/ntlmssp/gensec_ntlmssp_server.c b/auth/ntlmssp/gensec_ntlmssp_server.c
index 69c56fb..6147b14 100644
--- a/auth/ntlmssp/gensec_ntlmssp_server.c
+++ b/auth/ntlmssp/gensec_ntlmssp_server.c
@@ -34,7 +34,7 @@
 #include "auth/gensec/gensec_internal.h"
 #include "auth/common_auth.h"
 #include "param/param.h"
-
+#include "param/loadparm.h"
 
 /**
  * Return the credentials of a logged on user, including session keys
@@ -98,6 +98,9 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
 	const char *netbios_domain;
 	const char *dns_name;
 	const char *dns_domain;
+	enum server_role role;
+
+	role = lpcfg_server_role(gensec_security->settings->lp_ctx);
 
 	nt_status = gensec_ntlmssp_start(gensec_security);
 	NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -117,13 +120,32 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
 
 	ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
 
-	if (lpcfg_lanman_auth(gensec_security->settings->lp_ctx) &&
+	ntlmssp_state->allow_lm_response =
+		lpcfg_lanman_auth(gensec_security->settings->lp_ctx);
+
+	if (ntlmssp_state->allow_lm_response &&
 	    gensec_setting_bool(gensec_security->settings,
 				"ntlmssp_server", "allow_lm_key", false))
 	{
 		ntlmssp_state->allow_lm_key = true;
 	}
 
+	if (lpcfg_map_to_guest(gensec_security->settings->lp_ctx) != NEVER_MAP_TO_GUEST) {
+		/*
+		 * map to guest is not secure anyway, so
+		 * try to make it work and don't try to
+		 * negotiate new_spnego and MIC checking
+		 */
+		ntlmssp_state->force_old_spnego = true;
+	}
+
+	if (role == ROLE_ACTIVE_DIRECTORY_DC) {
+		/*
+		 * map to guest is not supported on an AD DC.
+		 */
+		ntlmssp_state->force_old_spnego = false;
+	}
+
 	ntlmssp_state->neg_flags =
 		NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION;
 
@@ -147,18 +169,31 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
 	}
 
+	if (ntlmssp_state->allow_lm_key) {
+		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
+	}
+
 	if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
 	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+
+		if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
+			/*
+			 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
+			 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
+			 * is requested.
+			 */
+			ntlmssp_state->force_wrap_seal = true;
+		}
 	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
 	}
 
-	if (lpcfg_server_role(gensec_security->settings->lp_ctx) == ROLE_STANDALONE) {
+	if (role == ROLE_STANDALONE) {
 		ntlmssp_state->server.is_standalone = true;
 	} else {
 		ntlmssp_state->server.is_standalone = false;
@@ -215,6 +250,9 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
 	ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain);
 	NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain);
 
+	ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
+	ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
+
 	return NT_STATUS_OK;
 }
 
diff --git a/auth/ntlmssp/ntlmssp.c b/auth/ntlmssp/ntlmssp.c
index 916b376..4abab88 100644
--- a/auth/ntlmssp/ntlmssp.c
+++ b/auth/ntlmssp/ntlmssp.c
@@ -48,6 +48,10 @@ static const struct ntlmssp_callbacks {
 		.command	= NTLMSSP_INITIAL,
 		.sync_fn	= ntlmssp_client_initial,
 	},{
+		.role		= NTLMSSP_CLIENT,
+		.command	= NTLMSSP_NEGOTIATE,
+		.sync_fn	= gensec_ntlmssp_resume_ccache,
+	},{
 		.role		= NTLMSSP_SERVER,
 		.command	= NTLMSSP_NEGOTIATE,
 		.sync_fn	= gensec_ntlmssp_server_negotiate,
@@ -82,6 +86,15 @@ static NTSTATUS gensec_ntlmssp_update_find(struct gensec_security *gensec_securi
 	if (!input.length) {
 		switch (gensec_ntlmssp->ntlmssp_state->role) {
 		case NTLMSSP_CLIENT:
+			if (gensec_ntlmssp->ntlmssp_state->resume_ccache) {
+				/*
+				 * make sure gensec_ntlmssp_resume_ccache()
+				 * will be called
+				 */
+				ntlmssp_command = NTLMSSP_NEGOTIATE;
+				break;
+			}
+
 			ntlmssp_command = NTLMSSP_INITIAL;
 			break;
 		case NTLMSSP_SERVER:
@@ -166,6 +179,30 @@ NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security,
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS gensec_ntlmssp_may_reset_crypto(struct gensec_security *gensec_security,
+						bool full_reset)
+{
+	struct gensec_ntlmssp_context *gensec_ntlmssp =
+		talloc_get_type_abort(gensec_security->private_data,
+				      struct gensec_ntlmssp_context);
+	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
+	NTSTATUS status;
+	bool reset_seqnums = full_reset;
+
+	if (!gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+		return NT_STATUS_OK;
+	}
+
+	status = ntlmssp_sign_reset(ntlmssp_state, reset_seqnums);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Could not reset NTLMSSP signing/sealing system (error was: %s)\n",
+			  nt_errstr(status)));
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
 static const char *gensec_ntlmssp_oids[] = {
 	GENSEC_OID_NTLMSSP,
 	NULL
@@ -180,6 +217,7 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
 	.server_start   = gensec_ntlmssp_server_start,
 	.magic 	        = gensec_ntlmssp_magic,
 	.update 	= gensec_ntlmssp_update,
+	.may_reset_crypto= gensec_ntlmssp_may_reset_crypto,
 	.sig_size	= gensec_ntlmssp_sig_size,
 	.sign_packet	= gensec_ntlmssp_sign_packet,
 	.check_packet	= gensec_ntlmssp_check_packet,
@@ -194,6 +232,15 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
 	.priority       = GENSEC_NTLMSSP
 };
 
+static const struct gensec_security_ops gensec_ntlmssp_resume_ccache_ops = {
+	.name		= "ntlmssp_resume_ccache",
+	.client_start   = gensec_ntlmssp_resume_ccache_start,
+	.update 	= gensec_ntlmssp_update,
+	.session_key	= gensec_ntlmssp_session_key,
+	.have_feature   = gensec_ntlmssp_have_feature,
+	.enabled        = true,
+	.priority       = GENSEC_NTLMSSP
+};
 
 _PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
 {
@@ -206,16 +253,58 @@ _PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
 		return ret;
 	}
 
+	ret = gensec_register(&gensec_ntlmssp_resume_ccache_ops);
+	if (!NT_STATUS_IS_OK(ret)) {
+		DEBUG(0,("Failed to register '%s' gensec backend!\n",
+			gensec_ntlmssp_resume_ccache_ops.name));
+		return ret;
+	}
+
 	return ret;
 }
 
+static struct gensec_security *gensec_find_child_by_ops(struct gensec_security *gensec_security,
+							const struct gensec_security_ops *ops)
+{
+	struct gensec_security *current = gensec_security;
+
+	while (current != NULL) {
+		if (current->ops == ops) {
+			return current;
+		}
+
+		current = current->child_security;
+	}
+
+	return NULL;
+}
+
 uint32_t gensec_ntlmssp_neg_flags(struct gensec_security *gensec_security)
 {
 	struct gensec_ntlmssp_context *gensec_ntlmssp;
-	if (gensec_security->ops != &gensec_ntlmssp_security_ops) {
+
+	gensec_security = gensec_find_child_by_ops(gensec_security,
+					&gensec_ntlmssp_security_ops);
+	if (gensec_security == NULL) {
 		return 0;
 	}
+
 	gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
 					       struct gensec_ntlmssp_context);
 	return gensec_ntlmssp->ntlmssp_state->neg_flags;
 }
+
+const char *gensec_ntlmssp_server_domain(struct gensec_security *gensec_security)
+{
+	struct gensec_ntlmssp_context *gensec_ntlmssp;
+
+	gensec_security = gensec_find_child_by_ops(gensec_security,
+					&gensec_ntlmssp_security_ops);
+	if (gensec_security == NULL) {
+		return NULL;
+	}
+
+	gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
+					       struct gensec_ntlmssp_context);
+	return gensec_ntlmssp->ntlmssp_state->server.netbios_domain;
+}
diff --git a/auth/ntlmssp/ntlmssp.h b/auth/ntlmssp/ntlmssp.h
index 6061cd0..2412768 100644
--- a/auth/ntlmssp/ntlmssp.h
+++ b/auth/ntlmssp/ntlmssp.h
@@ -62,7 +62,9 @@ struct ntlmssp_state
 	bool unicode;
 	bool use_ntlmv2;
 	bool use_ccache;
+	bool resume_ccache;
 	bool use_nt_response;  /* Set to 'False' to debug what happens when the NT response is omited */
+	bool allow_lm_response;/* The LM_RESPONSE code is not very secure... */
 	bool allow_lm_key;     /* The LM_KEY code is not very secure... */
 
 	const char *user;
@@ -70,9 +72,15 @@ struct ntlmssp_state
 	uint8_t *nt_hash;
 	uint8_t *lm_hash;
 
+	DATA_BLOB negotiate_blob;
+	DATA_BLOB challenge_blob;
+	bool new_spnego;
+	bool force_old_spnego;
+
 	struct {
 		const char *netbios_name;
 		const char *netbios_domain;
+		struct AV_PAIR_LIST av_pair_list;
 	} client;
 
 	struct {
@@ -81,6 +89,8 @@ struct ntlmssp_state
 		const char *netbios_domain;
 		const char *dns_name;
 		const char *dns_domain;
+		NTTIME challenge_endtime;
+		struct AV_PAIR_LIST av_pair_list;
 	} server;
 
 	DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */
@@ -90,8 +100,12 @@ struct ntlmssp_state
 	DATA_BLOB nt_resp;
 	DATA_BLOB session_key;
 
+	uint32_t conf_flags;
+	uint32_t required_flags;
 	uint32_t neg_flags; /* the current state of negotiation with the NTLMSSP partner */
 
+	bool force_wrap_seal;
+
 	union ntlmssp_crypt_state *crypt;
 };
 
@@ -123,6 +137,8 @@ NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_stae,
 			TALLOC_CTX *out_mem_ctx,
 			const DATA_BLOB *in,
 			DATA_BLOB *out);
+NTSTATUS ntlmssp_sign_reset(struct ntlmssp_state *ntlmssp_state,
+			    bool reset_seqnums);
 NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state);
 
 bool ntlmssp_blob_matches_magic(const DATA_BLOB *blob);
@@ -132,3 +148,4 @@ bool ntlmssp_blob_matches_magic(const DATA_BLOB *blob);
 NTSTATUS gensec_ntlmssp_init(void);
 
 uint32_t gensec_ntlmssp_neg_flags(struct gensec_security *gensec_security);
+const char *gensec_ntlmssp_server_domain(struct gensec_security *gensec_security);
diff --git a/auth/ntlmssp/ntlmssp_client.c b/auth/ntlmssp/ntlmssp_client.c
index d8531e4c..b419615 100644
--- a/auth/ntlmssp/ntlmssp_client.c
+++ b/auth/ntlmssp/ntlmssp_client.c
@@ -34,6 +34,7 @@ struct auth_session_info;
 #include "auth/ntlmssp/ntlmssp_private.h"
 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
 #include "../auth/ntlmssp/ntlmssp_ndr.h"
+#include "../nsswitch/libwbclient/wbclient.h"
 
 /*********************************************************************
  Client side NTLMSSP
@@ -57,38 +58,18 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
 		talloc_get_type_abort(gensec_security->private_data,
 				      struct gensec_ntlmssp_context);
 	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
-	const char *domain = ntlmssp_state->client.netbios_domain;
-	const char *workstation = ntlmssp_state->client.netbios_name;
 	NTSTATUS status;
-
-	/* These don't really matter in the initial packet, so don't panic if they are not set */
-	if (!domain) {
-		domain = "";
-	}
-
-	if (!workstation) {
-		workstation = "";
-	}
-
-	if (ntlmssp_state->unicode) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
-	} else {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
-	}
-
-	if (ntlmssp_state->use_ntlmv2) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
-	}
+	const DATA_BLOB version_blob = ntlmssp_version_blob();
 
 	/* generate the ntlmssp negotiate packet */
 	status = msrpc_gen(out_mem_ctx,
-		  out, "CddAA",
+		  out, "CddAAb",
 		  "NTLMSSP",
 		  NTLMSSP_NEGOTIATE,
 		  ntlmssp_state->neg_flags,
-		  domain,
-		  workstation);
-
+		  "", /* domain */
+		  "", /* workstation */
+		  version_blob.data, version_blob.length);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("ntlmssp_client_initial: failed to generate "
 			  "ntlmssp negotiate packet\n"));
@@ -109,6 +90,122 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
 		}
 	}
 
+	ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
+							     *out);
+	if (ntlmssp_state->negotiate_blob.length != out->length) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+
+	return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
+				TALLOC_CTX *out_mem_ctx,
+				DATA_BLOB in, DATA_BLOB *out)
+{
+	struct gensec_ntlmssp_context *gensec_ntlmssp =
+		talloc_get_type_abort(gensec_security->private_data,
+				      struct gensec_ntlmssp_context);
+	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
+	uint32_t neg_flags = 0;
+	uint32_t ntlmssp_command;
+	NTSTATUS status;
+	bool ok;
+
+	*out = data_blob_null;
+
+	if (in.length == 0) {
+		/*
+		 * This is compat code for older callers
+		 * which were missing the "initial_blob"/"negotiate_blob".
+		 *
+		 * That means we can't calculate the NTLMSSP_MIC
+		 * field correctly and need to force the
+		 * old_spnego behaviour.
+		 */
+		DEBUG(10, ("%s: in.length==%u force_old_spnego!\n",
+			   __func__, (unsigned int)in.length));
+		ntlmssp_state->force_old_spnego = true;
+		ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
+		ntlmssp_state->required_flags = 0;
+		ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
+		return NT_STATUS_MORE_PROCESSING_REQUIRED;
+	}
+
+	/* parse the NTLMSSP packet */
+
+	if (in.length > UINT16_MAX) {
+		DEBUG(1, ("%s: reject large request of length %u\n",
+			__func__, (unsigned int)in.length));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
+			 "NTLMSSP",
+			 &ntlmssp_command,
+			 &neg_flags);
+	if (!ok) {
+		DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
+			__func__, (unsigned int)in.length));
+		dump_data(2, in.data, in.length);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
+		DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
+			__func__, (unsigned int)in.length));
+		dump_data(2, in.data, in.length);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	ntlmssp_state->neg_flags = neg_flags;
+	DEBUG(3, ("Imported Negotiate flags:\n"));
+	debug_ntlmssp_flags(neg_flags);
+
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+		ntlmssp_state->unicode = true;
+	} else {
+		ntlmssp_state->unicode = false;
+	}
+
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
+		gensec_security->want_features |= GENSEC_FEATURE_SIGN;
+
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
+	}
+
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+		gensec_security->want_features |= GENSEC_FEATURE_SEAL;
+
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
+	}
+
+	ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
+	ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
+
+	if (DEBUGLEVEL >= 10) {
+		struct NEGOTIATE_MESSAGE *negotiate = talloc(
+			ntlmssp_state, struct NEGOTIATE_MESSAGE);
+		if (negotiate != NULL) {
+			status = ntlmssp_pull_NEGOTIATE_MESSAGE(
+				&in, negotiate, negotiate);
+			if (NT_STATUS_IS_OK(status)) {
+				NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
+						negotiate);
+			}
+			TALLOC_FREE(negotiate);
+		}
+	}
+
+	ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
+							     in);
+	if (ntlmssp_state->negotiate_blob.length != in.length) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
 
 	return NT_STATUS_MORE_PROCESSING_REQUIRED;
@@ -147,7 +244,13 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 	DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
 	NTSTATUS nt_status;
 	int flags = 0;
-	const char *user, *domain;
+	const char *user = NULL, *domain = NULL, *workstation = NULL;
+	bool is_anonymous = false;
+	const DATA_BLOB version_blob = ntlmssp_version_blob();
+	const NTTIME *server_timestamp = NULL;
+	uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
+	DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
+	HMACMD5Context ctx;
 
 	TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
 	if (!mem_ctx) {
@@ -172,7 +275,11 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 	DEBUG(3, ("Got challenge flags:\n"));
 	debug_ntlmssp_flags(chal_flags);
 
-	ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, ntlmssp_state->allow_lm_key);
+	nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
+					     chal_flags, "challenge");
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		return nt_status;
+	}
 
 	if (ntlmssp_state->unicode) {
 		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
@@ -181,7 +288,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 			chal_parse_string = "CdUdbdd";
 			chal_parse_string_short = "CdUdb";
 		}
-		auth_gen_string = "CdBBUUUBd";
+		auth_gen_string = "CdBBUUUBdbb";
 	} else {
 		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
 			chal_parse_string = "CdAdbddB";
@@ -190,7 +297,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 			chal_parse_string_short = "CdAdb";
 		}
 
-		auth_gen_string = "CdBBAAABd";
+		auth_gen_string = "CdBBAAABdbb";
 	}
 
 	if (!msrpc_parse(mem_ctx,
@@ -244,7 +351,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 	}
 	/* TODO: parse struct_blob and fill in the rest */
 	ntlmssp_state->server.netbios_name = "";
-	ntlmssp_state->server.netbios_domain = server_domain;
+	ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
 	ntlmssp_state->server.dns_name = "";
 	ntlmssp_state->server.dns_domain = "";
 
@@ -253,9 +360,118 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
 	cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
 						 &user, &domain);
 
+	workstation = cli_credentials_get_workstation(gensec_security->credentials);
+
+	if (user == NULL) {
+		DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (domain == NULL) {
+		DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (workstation == NULL) {
+		DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (is_anonymous) {
+		ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
+		/*
+		 * don't use the ccache for anonymous auth
+		 */
+		ntlmssp_state->use_ccache = false;
+	}
+	if (ntlmssp_state->use_ccache) {
+		struct samr_Password *nt_hash = NULL;
+
+		/*
+		 * If we have a password given we don't
+		 * use the ccache
+		 */
+		nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
+						      mem_ctx);
+		if (nt_hash != NULL) {
+			ZERO_STRUCTP(nt_hash);
+			TALLOC_FREE(nt_hash);
+			ntlmssp_state->use_ccache = false;
+		}
+	}
+
+	if (ntlmssp_state->use_ccache) {
+		struct wbcCredentialCacheParams params;
+		struct wbcCredentialCacheInfo *info = NULL;
+		struct wbcAuthErrorInfo *error = NULL;
+		struct wbcNamedBlob auth_blobs[2];
+		const struct wbcBlob *wbc_auth_blob = NULL;
+		const struct wbcBlob *wbc_session_key = NULL;
+		wbcErr wbc_status;
+		int i;
+		bool new_spnego = false;
+
+		params.account_name = user;
+		params.domain_name = domain;
+		params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
+
+		auth_blobs[0].name = "challenge_blob";
+		auth_blobs[0].flags = 0;
+		auth_blobs[0].blob.data = in.data;
+		auth_blobs[0].blob.length = in.length;
+		auth_blobs[1].name = "negotiate_blob";
+		auth_blobs[1].flags = 0;
+		auth_blobs[1].blob.data = ntlmssp_state->negotiate_blob.data;
+		auth_blobs[1].blob.length = ntlmssp_state->negotiate_blob.length;
+		params.num_blobs = ARRAY_SIZE(auth_blobs);
+		params.blobs = auth_blobs;
+
+		wbc_status = wbcCredentialCache(&params, &info, &error);
+		wbcFreeMemory(error);
+		if (!WBC_ERROR_IS_OK(wbc_status)) {
+			return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
+		}
+
+		for (i=0; i<info->num_blobs; i++) {
+			if (strequal(info->blobs[i].name, "auth_blob")) {
+				wbc_auth_blob = &info->blobs[i].blob;
+			}
+			if (strequal(info->blobs[i].name, "session_key")) {
+				wbc_session_key = &info->blobs[i].blob;
+			}
+			if (strequal(info->blobs[i].name, "new_spnego")) {
+				new_spnego = true;
+			}
+		}
+		if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
+			wbcFreeMemory(info);
+			return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
+		}
+
+		session_key = data_blob_talloc(mem_ctx,
+					       wbc_session_key->data,
+					       wbc_session_key->length);
+		if (session_key.length != wbc_session_key->length) {
+			wbcFreeMemory(info);
+			return NT_STATUS_NO_MEMORY;
+		}
+		*out = data_blob_talloc(mem_ctx,
+					wbc_auth_blob->data,
+					wbc_auth_blob->length);
+		if (out->length != wbc_auth_blob->length) {
+			wbcFreeMemory(info);
+			return NT_STATUS_NO_MEMORY;
+		}
+		ntlmssp_state->new_spnego = new_spnego;
+
+		wbcFreeMemory(info);
+		goto done;
+	}
+
 	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
 		flags |= CLI_CRED_NTLM2;
 	}
@@ -265,15 +481,159 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 	if (ntlmssp_state->use_nt_response) {
 		flags |= CLI_CRED_NTLM_AUTH;
 	}
-	if (lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx)) {
+	if (ntlmssp_state->allow_lm_response) {
 		flags |= CLI_CRED_LANMAN_AUTH;
 	}
 
+	if (target_info.length != 0 && !is_anonymous) {
+		struct AV_PAIR *pairs = NULL;
+		uint32_t count = 0;
+		enum ndr_err_code err;
+		struct AV_PAIR *timestamp = NULL;
+		struct AV_PAIR *eol = NULL;
+		uint32_t i = 0;
+		const char *service = NULL;
+		const char *hostname = NULL;
+
+		err = ndr_pull_struct_blob(&target_info,
+					ntlmssp_state,
+					&ntlmssp_state->server.av_pair_list,
+					(ndr_pull_flags_fn_t)ndr_pull_AV_PAIR_LIST);
+		if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+			return ndr_map_error2ntstatus(err);
+		}
+
+		count = ntlmssp_state->server.av_pair_list.count;
+		/*
+		 * We need room for Flags, SingleHost,
+		 * ChannelBindings and Target
+		 */
+		pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR,
+					  count + 4);
+		if (pairs == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		for (i = 0; i < count; i++) {
+			pairs[i] = ntlmssp_state->server.av_pair_list.pair[i];
+		}
+
+		ntlmssp_state->client.av_pair_list.count = count;
+		ntlmssp_state->client.av_pair_list.pair = pairs;
+
+		eol = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
+					  MsvAvEOL);
+		if (eol == NULL) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		timestamp = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
+						MsvAvTimestamp);
+		if (timestamp != NULL) {
+			uint32_t sign_features =
+					GENSEC_FEATURE_SESSION_KEY |
+					GENSEC_FEATURE_SIGN |
+					GENSEC_FEATURE_SEAL;
+
+			server_timestamp = &timestamp->Value.AvTimestamp;
+
+			if (ntlmssp_state->force_old_spnego) {
+				sign_features = 0;
+			}
+
+			if (gensec_security->want_features & sign_features) {
+				struct AV_PAIR *av_flags = NULL;
+
+				av_flags = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
+							       MsvAvFlags);
+				if (av_flags == NULL) {
+					av_flags = eol;
+					eol++;
+					count++;
+					*eol = *av_flags;
+					av_flags->AvId = MsvAvFlags;
+					av_flags->Value.AvFlags = 0;
+				}
+
+				av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
+				ntlmssp_state->new_spnego = true;
+			}
+		}
+
+		{
+			struct AV_PAIR *SingleHost = NULL;
+
+			SingleHost = eol;
+			eol++;
+			count++;
+			*eol = *SingleHost;
+
+			/*
+			 * This is not really used, but we want to
+			 * add some more random bytes and match
+			 * Windows.
+			 */
+			SingleHost->AvId = MsvAvSingleHost;
+			SingleHost->Value.AvSingleHost.token_info.Flags = 0;
+			SingleHost->Value.AvSingleHost.token_info.TokenIL = 0;
+			generate_random_buffer(SingleHost->Value.AvSingleHost.token_info.MachineId,
+					sizeof(SingleHost->Value.AvSingleHost.token_info.MachineId));
+			SingleHost->Value.AvSingleHost.remaining = data_blob_null;
+		}
+
+		{
+			struct AV_PAIR *ChannelBindings = NULL;
+
+			ChannelBindings = eol;
+			eol++;
+			count++;
+			*eol = *ChannelBindings;
+
+			/*
+			 * gensec doesn't support channel bindings yet,
+			 * but we want to match Windows on the wire
+			 */
+			ChannelBindings->AvId = MsvChannelBindings;
+			memset(ChannelBindings->Value.ChannelBindings, 0,
+			       sizeof(ChannelBindings->Value.ChannelBindings));
+		}
+
+		service = gensec_get_target_service(gensec_security);
+		hostname = gensec_get_target_hostname(gensec_security);
+		if (service != NULL && hostname != NULL) {
+			struct AV_PAIR *target = NULL;
+
+			target = eol;
+			eol++;
+			count++;
+			*eol = *target;
+
+			target->AvId = MsvAvTargetName;
+			target->Value.AvTargetName = talloc_asprintf(pairs, "%s/%s",
+								     service,
+								     hostname);
+			if (target->Value.AvTargetName == NULL) {
+				return NT_STATUS_NO_MEMORY;
+			}
+		}
+
+		ntlmssp_state->client.av_pair_list.count = count;
+		ntlmssp_state->client.av_pair_list.pair = pairs;
+
+		err = ndr_push_struct_blob(&target_info,
+					ntlmssp_state,
+					&ntlmssp_state->client.av_pair_list,
+					(ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
+		if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
 	nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
-						      &flags, challenge_blob, target_info,
+						      &flags, challenge_blob,
+						      server_timestamp, target_info,
 						      &lm_response, &nt_response,
 						      &lm_session_key, &session_key);
-
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		return nt_status;
 	}
@@ -292,7 +652,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 	}
 
 	if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
-	    && lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx) && lm_session_key.length == 16) {
+	    && ntlmssp_state->allow_lm_key && lm_session_key.length == 16) {
 		DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
 		if (lm_response.length == 24) {
 			SMBsesskeygen_lm_sess_key(lm_session_key.data, lm_response.data,
@@ -325,9 +685,6 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 		session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
 	}
 
-	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
-	debug_ntlmssp_flags(ntlmssp_state->neg_flags);
-
 	/* this generates the actual auth packet */
 	nt_status = msrpc_gen(mem_ctx,
 		       out, auth_gen_string,
@@ -337,22 +694,48 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 		       nt_response.data, nt_response.length,
 		       domain,
 		       user,
-		       cli_credentials_get_workstation(gensec_security->credentials),
+		       workstation,
 		       encrypted_session_key.data, encrypted_session_key.length,
-		       ntlmssp_state->neg_flags);
+		       ntlmssp_state->neg_flags,
+		       version_blob.data, version_blob.length,
+		       mic_blob.data, mic_blob.length);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		talloc_free(mem_ctx);
 		return nt_status;
 	}
 
+	/*
+	 * We always include the MIC, even without:
+	 * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
+	 * ntlmssp_state->new_spnego = true;
+	 *
+	 * This matches a Windows client.
+	 */
+	hmac_md5_init_limK_to_64(session_key.data,
+				 session_key.length,
+				 &ctx);
+	hmac_md5_update(ntlmssp_state->negotiate_blob.data,
+			ntlmssp_state->negotiate_blob.length,
+			&ctx);
+	hmac_md5_update(in.data, in.length, &ctx);
+	hmac_md5_update(out->data, out->length, &ctx);
+	hmac_md5_final(mic_buffer, &ctx);
+	memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
+
+done:
+	data_blob_free(&ntlmssp_state->negotiate_blob);
+
 	ntlmssp_state->session_key = session_key;
 	talloc_steal(ntlmssp_state, session_key.data);
 
+	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
+	debug_ntlmssp_flags(ntlmssp_state->neg_flags);
+
 	talloc_steal(out_mem_ctx, out->data);
 
 	ntlmssp_state->expected_state = NTLMSSP_DONE;
 
-	if (gensec_security->want_features & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL)) {
+	if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 		nt_status = ntlmssp_sign_init(ntlmssp_state);
 		if (!NT_STATUS_IS_OK(nt_status)) {
 			DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
@@ -398,7 +781,9 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 
 	ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true);
 
-	ntlmssp_state->allow_lm_key = (lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx)
+	ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
+
+	ntlmssp_state->allow_lm_key = (ntlmssp_state->allow_lm_response
 					      && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
 						  || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
 
@@ -408,8 +793,15 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 
 	ntlmssp_state->neg_flags =
 		NTLMSSP_NEGOTIATE_NTLM |
+		NTLMSSP_NEGOTIATE_VERSION |
 		NTLMSSP_REQUEST_TARGET;
 
+	if (ntlmssp_state->unicode) {
+		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
+	} else {
+		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
+	}
+
 	if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;
 	}
@@ -437,6 +829,16 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 		ntlmssp_state->use_ntlmv2 = false;
 	}
 
+	if (ntlmssp_state->use_ntlmv2) {
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
+		ntlmssp_state->allow_lm_response = false;
+		ntlmssp_state->allow_lm_key = false;
+	}
+
+	if (ntlmssp_state->allow_lm_key) {
+		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
+	}
+
 	if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
 		/*
 		 * We need to set this to allow a later SetPassword
@@ -447,15 +849,57 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
 		 * that it thinks is only used for NTLMSSP signing and
 		 * sealing.  (It is actually pulled out and used directly)
 		 */
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
 	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
+
+		if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
+			/*
+			 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
+			 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
+			 * is requested.
+			 */
+			ntlmssp_state->force_wrap_seal = true;
+			/*
+			 * We want also work against old Samba servers
+			 * which didn't had GENSEC_FEATURE_LDAP_STYLE
+			 * we negotiate SEAL too. We may remove this
+			 * in a few years. As all servers should have
+			 * GENSEC_FEATURE_LDAP_STYLE by then.
+			 */
+			ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
+		}
 	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
+		ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
+	}
+	if (gensec_security->want_features & GENSEC_FEATURE_NTLM_CCACHE) {
+		ntlmssp_state->use_ccache = true;
 	}
 
+	ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
+	ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
+{
+	struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
+	NTSTATUS status;
+
+	status = gensec_ntlmssp_client_start(gensec_security);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
+					       struct gensec_ntlmssp_context);
+	gensec_ntlmssp->ntlmssp_state->use_ccache = false;
+	gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
+	gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
+
 	return NT_STATUS_OK;
 }
diff --git a/auth/ntlmssp/ntlmssp_ndr.c b/auth/ntlmssp/ntlmssp_ndr.c
index af24be9..c8b16cc 100644
--- a/auth/ntlmssp/ntlmssp_ndr.c
+++ b/auth/ntlmssp/ntlmssp_ndr.c
@@ -25,6 +25,7 @@
 #define NTLMSSP_PULL_MESSAGE(type, blob, mem_ctx, r) \
 do { \
 	enum ndr_err_code __ndr_err; \
+	ZERO_STRUCTP(r); /* in order to deal with unset neg flags */\
 	__ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, \
 			(ndr_pull_flags_fn_t)ndr_pull_ ##type); \
 	if (!NDR_ERR_CODE_IS_SUCCESS(__ndr_err)) { \
diff --git a/auth/ntlmssp/ntlmssp_private.h b/auth/ntlmssp/ntlmssp_private.h
index 778d638..e938e5c 100644
--- a/auth/ntlmssp/ntlmssp_private.h
+++ b/auth/ntlmssp/ntlmssp_private.h
@@ -59,8 +59,9 @@ NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security,
 /* The following definitions come from auth/ntlmssp_util.c  */
 
 void debug_ntlmssp_flags(uint32_t neg_flags);
-void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
-			      uint32_t neg_flags, bool allow_lm);
+NTSTATUS ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
+				  uint32_t neg_flags, const char *name);
+const DATA_BLOB ntlmssp_version_blob(void);
 
 /* The following definitions come from auth/ntlmssp_server.c  */
 
@@ -88,6 +89,10 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
 				TALLOC_CTX *out_mem_ctx,
 				DATA_BLOB in, DATA_BLOB *out) ;
 
+NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
+				TALLOC_CTX *out_mem_ctx,
+				DATA_BLOB in, DATA_BLOB *out);
+
 /**
  * Next state function for the Challenge Packet.  Generate an auth packet.
  *
@@ -101,6 +106,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 				  TALLOC_CTX *out_mem_ctx,
 				  const DATA_BLOB in, DATA_BLOB *out) ;
 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security);
+NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security);
 
 /* The following definitions come from auth/ntlmssp/gensec_ntlmssp_server.c  */
 
diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 2f3f0bb..17d5ade 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -21,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "lib/util/time_basic.h"
 #include "auth/ntlmssp/ntlmssp.h"
 #include "auth/ntlmssp/ntlmssp_private.h"
 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
@@ -84,6 +85,27 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 	uint8_t cryptkey[8];
 	const char *target_name;
 	NTSTATUS status;
+	struct timeval tv_now = timeval_current();
+	/*
+	 * See [MS-NLMP]
+	 *
+	 * Windows NT 4.0, windows_2000: use 30 minutes,
+	 * Windows XP, Windows Server 2003, Windows Vista,
+	 * Windows Server 2008, Windows 7, and Windows Server 2008 R2
+	 * use 36 hours.
+	 *
+	 * Newer systems doesn't check this, likely because the
+	 * connectionless NTLMSSP is no longer supported.
+	 *
+	 * As we expect the AUTHENTICATION_MESSAGE to arrive
+	 * directly after the NEGOTIATE_MESSAGE (typically less than
+	 * as 1 second later). We use a hard timeout of 30 Minutes.
+	 *
+	 * We don't look at AUTHENTICATE_MESSAGE.NtChallengeResponse.TimeStamp
+	 * instead we just remember our own time.
+	 */
+	uint32_t max_lifetime = 30 * 60;
+	struct timeval tv_end = timeval_add(&tv_now, max_lifetime, 0);
 
 	/* parse the NTLMSSP packet */
 #if 0
@@ -91,6 +113,12 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 #endif
 
 	if (request.length) {
+		if (request.length > UINT16_MAX) {
+			DEBUG(1, ("ntlmssp_server_negotiate: reject large request of length %u\n",
+				(unsigned int)request.length));
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
 		if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
 							  "NTLMSSP",
 							  &ntlmssp_command,
@@ -117,7 +145,10 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 		}
 	}
 
-	ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);
+	status = ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, "negotiate");
+	if (!NT_STATUS_IS_OK(status)){
+		return status;
+	}
 
 	/* Ask our caller what challenge they would like in the packet */
 	if (auth_context->get_ntlm_challenge) {
@@ -138,6 +169,7 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 	 */
 
 	chal_flags = ntlmssp_state->neg_flags;
+	ntlmssp_state->server.challenge_endtime = timeval_to_nttime(&tv_end);
 
 	/* get the right name to fill in as 'target' */
 	target_name = ntlmssp_target_name(ntlmssp_state,
@@ -150,16 +182,48 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 							cryptkey, 8);
 
 	/* This creates the 'blob' of names that appears at the end of the packet */
-	if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
-	{
-		status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
-			  MsvAvNbDomainName, target_name,
-			  MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
-			  MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
-			  MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
-			  MsvAvEOL, "");
-		if (!NT_STATUS_IS_OK(status)) {
-			return status;
+	if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
+		enum ndr_err_code err;
+		struct AV_PAIR *pairs = NULL;
+		uint32_t count = 5;
+
+		pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR, count + 1);
+		if (pairs == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		pairs[0].AvId			= MsvAvNbDomainName;
+		pairs[0].Value.AvNbDomainName	= target_name;
+
+		pairs[1].AvId			= MsvAvNbComputerName;
+		pairs[1].Value.AvNbComputerName	= ntlmssp_state->server.netbios_name;
+
+		pairs[2].AvId			= MsvAvDnsDomainName;
+		pairs[2].Value.AvDnsDomainName	= ntlmssp_state->server.dns_domain;
+
+		pairs[3].AvId			= MsvAvDnsComputerName;
+		pairs[3].Value.AvDnsComputerName= ntlmssp_state->server.dns_name;
+
+		if (!ntlmssp_state->force_old_spnego) {
+			pairs[4].AvId			= MsvAvTimestamp;
+			pairs[4].Value.AvTimestamp	=
+						timeval_to_nttime(&tv_now);
+			count += 1;
+
+			pairs[5].AvId			= MsvAvEOL;
+		} else {
+			pairs[4].AvId			= MsvAvEOL;
+		}
+
+		ntlmssp_state->server.av_pair_list.count = count;
+		ntlmssp_state->server.av_pair_list.pair = pairs;
+
+		err = ndr_push_struct_blob(&struct_blob,
+					ntlmssp_state,
+					&ntlmssp_state->server.av_pair_list,
+					(ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
+		if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+			return NT_STATUS_NO_MEMORY;
 		}
 	} else {
 		struct_blob = data_blob_null;
@@ -168,29 +232,7 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 	{
 		/* Marshal the packet in the right format, be it unicode or ASCII */
 		const char *gen_string;
-		DATA_BLOB version_blob = data_blob_null;
-
-		if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
-			enum ndr_err_code err;
-			struct ntlmssp_VERSION vers;
-
-			/* "What Windows returns" as a version number. */
-			ZERO_STRUCT(vers);
-			vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
-			vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
-			vers.ProductBuild = 0;
-			vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
-
-			err = ndr_push_struct_blob(&version_blob,
-						ntlmssp_state,
-						&vers,
-						(ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);
-
-			if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
-				data_blob_free(&struct_blob);
-				return NT_STATUS_NO_MEMORY;
-			}
-		}
+		const DATA_BLOB version_blob = ntlmssp_version_blob();
 
 		if (ntlmssp_state->unicode) {
 			gen_string = "CdUdbddBb";
@@ -209,13 +251,10 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 			version_blob.data, version_blob.length);
 
 		if (!NT_STATUS_IS_OK(status)) {
-			data_blob_free(&version_blob);
 			data_blob_free(&struct_blob);
 			return status;
 		}
 
-		data_blob_free(&version_blob);
-
 		if (DEBUGLEVEL >= 10) {
 			struct CHALLENGE_MESSAGE *challenge = talloc(
 				ntlmssp_state, struct CHALLENGE_MESSAGE);
@@ -234,6 +273,18 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security
 
 	data_blob_free(&struct_blob);
 
+	ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
+							     request);
+	if (ntlmssp_state->negotiate_blob.length != request.length) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ntlmssp_state->challenge_blob = data_blob_dup_talloc(ntlmssp_state,
+							     *reply);
+	if (ntlmssp_state->challenge_blob.length != reply->length) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	ntlmssp_state->expected_state = NTLMSSP_AUTH;
 
 	return NT_STATUS_MORE_PROCESSING_REQUIRED;
@@ -266,19 +317,24 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 	struct auth4_context *auth_context = gensec_security->auth_context;
 	uint32_t ntlmssp_command, auth_flags;
 	NTSTATUS nt_status;
-
+	const unsigned int version_len = 8;
+	DATA_BLOB version_blob = data_blob_null;
+	const unsigned int mic_len = NTLMSSP_MIC_SIZE;
+	DATA_BLOB mic_blob = data_blob_null;
 	uint8_t session_nonce_hash[16];
-
 	const char *parse_string;
+	bool ok;
+	struct timeval endtime;
+	bool expired = false;
 
 #if 0
 	file_save("ntlmssp_auth.dat", request.data, request.length);
 #endif
 
 	if (ntlmssp_state->unicode) {
-		parse_string = "CdBBUUUBd";
+		parse_string = "CdBBUUUBdbb";
 	} else {
-		parse_string = "CdBBAAABd";
+		parse_string = "CdBBAAABdbb";
 	}
 
 	/* zero these out */
@@ -291,7 +347,7 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 	ntlmssp_state->client.netbios_name = NULL;
 
 	/* now the NTLMSSP encoded auth hashes */
-	if (!msrpc_parse(ntlmssp_state, &request, parse_string,
+	ok = msrpc_parse(ntlmssp_state, &request, parse_string,
 			 "NTLMSSP",
 			 &ntlmssp_command,
 			 &ntlmssp_state->lm_resp,
@@ -300,7 +356,35 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 			 &ntlmssp_state->user,
 			 &ntlmssp_state->client.netbios_name,
 			 &state->encrypted_session_key,
-			 &auth_flags)) {
+			 &auth_flags,
+			 &version_blob, version_len,
+			 &mic_blob, mic_len);
+	if (!ok) {
+		DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
+		dump_data(10, request.data, request.length);
+
+		data_blob_free(&version_blob);
+		data_blob_free(&mic_blob);
+
+		if (ntlmssp_state->unicode) {
+			parse_string = "CdBBUUUBd";
+		} else {
+			parse_string = "CdBBAAABd";
+		}
+
+		ok = msrpc_parse(ntlmssp_state, &request, parse_string,
+				 "NTLMSSP",
+				 &ntlmssp_command,
+				 &ntlmssp_state->lm_resp,
+				 &ntlmssp_state->nt_resp,
+				 &ntlmssp_state->domain,
+				 &ntlmssp_state->user,
+				 &ntlmssp_state->client.netbios_name,
+				 &state->encrypted_session_key,
+				 &auth_flags);
+	}
+
+	if (!ok) {
 		DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
 		dump_data(10, request.data, request.length);
 
@@ -333,8 +417,14 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 
 	talloc_steal(state, state->encrypted_session_key.data);
 
-	if (auth_flags)
-		ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, ntlmssp_state->allow_lm_key);
+	if (auth_flags != 0) {
+		nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
+						     auth_flags,
+						     "authenticate");
+		if (!NT_STATUS_IS_OK(nt_status)){
+			return nt_status;
+		}
+	}
 
 	if (DEBUGLEVEL >= 10) {
 		struct AUTHENTICATE_MESSAGE *authenticate = talloc(
@@ -363,6 +453,194 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security,
 	file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);
 #endif
 
+	if (ntlmssp_state->nt_resp.length > 24) {
+		struct NTLMv2_RESPONSE v2_resp;
+		enum ndr_err_code err;
+		uint32_t i = 0;
+		uint32_t count = 0;
+		const struct AV_PAIR *flags = NULL;
+		const struct AV_PAIR *eol = NULL;
+		uint32_t av_flags = 0;
+
+		err = ndr_pull_struct_blob(&ntlmssp_state->nt_resp,
+					ntlmssp_state,
+					&v2_resp,
+					(ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE);
+		if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+			nt_status = ndr_map_error2ntstatus(err);
+			DEBUG(1,("%s: failed to parse NTLMv2_RESPONSE of length %zu for "
+				 "user=[%s] domain=[%s] workstation=[%s] - %s %s\n",
+				 __func__, ntlmssp_state->nt_resp.length,
+				 ntlmssp_state->user, ntlmssp_state->domain,
+				 ntlmssp_state->client.netbios_name,
+				 ndr_errstr(err), nt_errstr(nt_status)));
+			return nt_status;
+		}
+
+		if (DEBUGLVL(10)) {
+			NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &v2_resp);
+		}
+
+		eol = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+					  MsvAvEOL);
+		if (eol == NULL) {
+			DEBUG(1,("%s: missing MsvAvEOL for "
+				 "user=[%s] domain=[%s] workstation=[%s]\n",
+				 __func__, ntlmssp_state->user, ntlmssp_state->domain,
+				 ntlmssp_state->client.netbios_name));
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		flags = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+					    MsvAvFlags);
+		if (flags != NULL) {
+			av_flags = flags->Value.AvFlags;
+		}
+
+		if (av_flags & NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE) {
+			if (mic_blob.length != NTLMSSP_MIC_SIZE) {
+				DEBUG(1,("%s: mic_blob.length[%u] for "
+					 "user=[%s] domain=[%s] workstation=[%s]\n",
+					 __func__,
+					 (unsigned)mic_blob.length,
+					 ntlmssp_state->user,
+					 ntlmssp_state->domain,
+					 ntlmssp_state->client.netbios_name));
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+
+			if (request.length <
+			    (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE))
+			{
+				DEBUG(1,("%s: missing MIC "
+					 "request.length[%u] for "
+					 "user=[%s] domain=[%s] workstation=[%s]\n",
+					 __func__,
+					 (unsigned)request.length,
+					 ntlmssp_state->user,
+					 ntlmssp_state->domain,
+					 ntlmssp_state->client.netbios_name));
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+
+			ntlmssp_state->new_spnego = true;
+		}
+
+		count = ntlmssp_state->server.av_pair_list.count;
+		if (v2_resp.Challenge.AvPairs.count < count) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		for (i = 0; i < count; i++) {
+			const struct AV_PAIR *sp =
+				&ntlmssp_state->server.av_pair_list.pair[i];
+			const struct AV_PAIR *cp = NULL;
+
+			if (sp->AvId == MsvAvEOL) {
+				continue;
+			}
+
+			cp = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+						 sp->AvId);
+			if (cp == NULL) {
+				DEBUG(1,("%s: AvId 0x%x missing for"
+					 "user=[%s] domain=[%s] "
+					 "workstation=[%s]\n",
+					 __func__,
+					 (unsigned)sp->AvId,
+					 ntlmssp_state->user,
+					 ntlmssp_state->domain,
+					 ntlmssp_state->client.netbios_name));
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+
+			switch (cp->AvId) {
+#define CASE_STRING(v) case Msv ## v: do { \
+	int cmp; \
+	if (sp->Value.v == NULL) { \
+		return NT_STATUS_INTERNAL_ERROR; \
+	} \
+	if (cp->Value.v == NULL) { \
+		DEBUG(1,("%s: invalid %s " \
+			 "got[%s] expect[%s] for " \
+			 "user=[%s] domain=[%s] workstation=[%s]\n", \
+			 __func__, #v, \
+			 cp->Value.v, \
+			 sp->Value.v, \
+			 ntlmssp_state->user, \
+			 ntlmssp_state->domain, \
+			 ntlmssp_state->client.netbios_name)); \
+		return NT_STATUS_INVALID_PARAMETER; \
+	} \
+	cmp = strcmp(cp->Value.v, sp->Value.v); \
+	if (cmp != 0) { \
+		DEBUG(1,("%s: invalid %s " \
+			 "got[%s] expect[%s] for " \
+			 "user=[%s] domain=[%s] workstation=[%s]\n", \
+			 __func__, #v, \
+			 cp->Value.v, \
+			 sp->Value.v, \
+			 ntlmssp_state->user, \
+			 ntlmssp_state->domain, \
+			 ntlmssp_state->client.netbios_name)); \
+		return NT_STATUS_INVALID_PARAMETER; \
+	} \
+} while(0); break
+			CASE_STRING(AvNbComputerName);
+			CASE_STRING(AvNbDomainName);
+			CASE_STRING(AvDnsComputerName);
+			CASE_STRING(AvDnsDomainName);
+			CASE_STRING(AvDnsTreeName);
+			case MsvAvTimestamp:
+				if (cp->Value.AvTimestamp != sp->Value.AvTimestamp) {
+					struct timeval ct;
+					struct timeval st;
+					struct timeval_buf tmp1;
+					struct timeval_buf tmp2;
+
+					nttime_to_timeval(&ct,
+							  cp->Value.AvTimestamp);
+					nttime_to_timeval(&st,
+							  sp->Value.AvTimestamp);
+
+					DEBUG(1,("%s: invalid AvTimestamp "
+						 "got[%s] expect[%s] for "
+						 "user=[%s] domain=[%s] "
+						 "workstation=[%s]\n",
+						 __func__,
+						 timeval_str_buf(&ct, false,
+								 true, &tmp1),
+						 timeval_str_buf(&st, false,
+								 true, &tmp2),
+						 ntlmssp_state->user,
+						 ntlmssp_state->domain,
+						 ntlmssp_state->client.netbios_name));
+					return NT_STATUS_INVALID_PARAMETER;
+				}
+				break;
+			default:
+				/*
+				 * This can't happen as we control
+				 * ntlmssp_state->server.av_pair_list
+				 */
+				return NT_STATUS_INTERNAL_ERROR;
+			}
+		}
+	}
+
+	nttime_to_timeval(&endtime, ntlmssp_state->server.challenge_endtime);
+	expired = timeval_expired(&endtime);
+	if (expired) {
+		struct timeval_buf tmp;
+		DEBUG(1,("%s: challenge invalid (expired %s) for "
+			 "user=[%s] domain=[%s] workstation=[%s]\n",
+			 __func__,
+			 timeval_str_buf(&endtime, false, true, &tmp),
+			 ntlmssp_state->user, ntlmssp_state->domain,
+			 ntlmssp_state->client.netbios_name));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	/* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
 	   client challenge
 
@@ -474,7 +752,8 @@ static NTSTATUS ntlmssp_server_check_password(struct gensec_security *gensec_sec
 
 static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
 					struct gensec_ntlmssp_context *gensec_ntlmssp,
-					struct ntlmssp_server_auth_state *state)
+					struct ntlmssp_server_auth_state *state,
+					DATA_BLOB request)
 {
 	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
 	DATA_BLOB user_session_key = state->user_session_key;
@@ -591,7 +870,56 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
 		talloc_steal(ntlmssp_state, session_key.data);
 	}
 
-	if (ntlmssp_state->session_key.length) {
+	if (ntlmssp_state->new_spnego) {
+		HMACMD5Context ctx;
+		uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
+		int cmp;
+
+		hmac_md5_init_limK_to_64(ntlmssp_state->session_key.data,
+					 ntlmssp_state->session_key.length,
+					 &ctx);
+
+		hmac_md5_update(ntlmssp_state->negotiate_blob.data,
+				ntlmssp_state->negotiate_blob.length,
+				&ctx);
+		hmac_md5_update(ntlmssp_state->challenge_blob.data,
+				ntlmssp_state->challenge_blob.length,
+				&ctx);
+
+		/* checked were we set ntlmssp_state->new_spnego */
+		SMB_ASSERT(request.length >
+			   (NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE));
+
+		hmac_md5_update(request.data, NTLMSSP_MIC_OFFSET, &ctx);
+		hmac_md5_update(mic_buffer, NTLMSSP_MIC_SIZE, &ctx);
+		hmac_md5_update(request.data +
+				(NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE),
+				request.length -
+				(NTLMSSP_MIC_OFFSET + NTLMSSP_MIC_SIZE),
+				&ctx);
+		hmac_md5_final(mic_buffer, &ctx);
+
+		cmp = memcmp(request.data + NTLMSSP_MIC_OFFSET,
+			     mic_buffer, NTLMSSP_MIC_SIZE);
+		if (cmp != 0) {
+			DEBUG(1,("%s: invalid NTLMSSP_MIC for "
+				 "user=[%s] domain=[%s] workstation=[%s]\n",
+				 __func__,
+				 ntlmssp_state->user,
+				 ntlmssp_state->domain,
+				 ntlmssp_state->client.netbios_name));
+			dump_data(1, request.data + NTLMSSP_MIC_OFFSET,
+				  NTLMSSP_MIC_SIZE);
+			dump_data(1, mic_buffer,
+				  NTLMSSP_MIC_SIZE);
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+	}
+
+	data_blob_free(&ntlmssp_state->negotiate_blob);
+	data_blob_free(&ntlmssp_state->challenge_blob);
+
+	if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 		nt_status = ntlmssp_sign_init(ntlmssp_state);
 	}
 
@@ -656,7 +984,7 @@ NTSTATUS gensec_ntlmssp_server_auth(struct gensec_security *gensec_security,
 	   ntlmssp_state->check_password, the ntlmssp_server_postpath
 	   can be done in a callback */
 
-	nt_status = ntlmssp_server_postauth(gensec_security, gensec_ntlmssp, state);
+	nt_status = ntlmssp_server_postauth(gensec_security, gensec_ntlmssp, state, in);
 	TALLOC_FREE(state);
 	return nt_status;
 }
diff --git a/auth/ntlmssp/ntlmssp_sign.c b/auth/ntlmssp/ntlmssp_sign.c
index c0be914..a975725 100644
--- a/auth/ntlmssp/ntlmssp_sign.c
+++ b/auth/ntlmssp/ntlmssp_sign.c
@@ -479,57 +479,18 @@ NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_state,
 					     &sig);
 
 	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
-		NTSTATUS status;
-		struct ntlmssp_crypt_direction save_direction;
-
 		if (in->length < NTLMSSP_SIG_SIZE) {
 			return NT_STATUS_INVALID_PARAMETER;
 		}
 		sig.data = in->data;
 		sig.length = NTLMSSP_SIG_SIZE;
-		*out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
-
-		if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-			save_direction = ntlmssp_state->crypt->ntlm2.receiving;
-		} else {
-			save_direction = ntlmssp_state->crypt->ntlm;
-		}
-
-		status = ntlmssp_check_packet(ntlmssp_state,
-					      out->data, out->length,
-					      out->data, out->length,
-					      &sig);
-		if (!NT_STATUS_IS_OK(status)) {
-			NTSTATUS check_status = status;
-			/*
-			 * The Windows LDAP libraries seems to have a bug
-			 * and always use sealing even if only signing was
-			 * negotiated. So we need to fallback.
-			 */
 
-			if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-				ntlmssp_state->crypt->ntlm2.receiving = save_direction;
-			} else {
-				ntlmssp_state->crypt->ntlm = save_direction;
-			}
-
-			status = ntlmssp_unseal_packet(ntlmssp_state,
-						       out->data,
-						       out->length,
-						       out->data,
-						       out->length,
-						       &sig);
-			if (NT_STATUS_IS_OK(status)) {
-				ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
-			} else {
-				status = check_status;
-			}
-		}
+		*out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
 
-		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(1, ("NTLMSSP packet check for unwrap failed due to invalid signature\n"));
-		}
-		return status;
+		return ntlmssp_check_packet(ntlmssp_state,
+					    out->data, out->length,
+					    out->data, out->length,
+					    &sig);
 	} else {
 		*out = data_blob_talloc(out_mem_ctx, in->data, in->length);
 		if (!out->data) {
@@ -542,20 +503,30 @@ NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_state,
 /**
    Initialise the state for NTLMSSP signing.
 */
-NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
+NTSTATUS ntlmssp_sign_reset(struct ntlmssp_state *ntlmssp_state,
+			    bool reset_seqnums)
 {
 	DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
 	debug_ntlmssp_flags(ntlmssp_state->neg_flags);
 
-	if (ntlmssp_state->session_key.length < 8) {
-		DEBUG(3, ("NO session key, cannot intialise signing\n"));
-		return NT_STATUS_NO_USER_SESSION_KEY;
+	if (ntlmssp_state->crypt == NULL) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
 
-	ntlmssp_state->crypt = talloc_zero(ntlmssp_state,
-					   union ntlmssp_crypt_state);
-	if (ntlmssp_state->crypt == NULL) {
-		return NT_STATUS_NO_MEMORY;
+	if (ntlmssp_state->force_wrap_seal &&
+	    (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN))
+	{
+		/*
+		 * We need to handle NTLMSSP_NEGOTIATE_SIGN as
+		 * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
+		 * is requested.
+		 *
+		 * The negotiation of flags (and authentication)
+		 * is completed when ntlmssp_sign_init() is called
+		 * so we can safely pretent NTLMSSP_NEGOTIATE_SEAL
+		 * was negotiated.
+		 */
+		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
 	}
 
 	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
@@ -629,7 +600,9 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
 				&ntlmssp_state->crypt->ntlm2.sending.seal_state);
 
 		/* SEND: seq num */
-		ntlmssp_state->crypt->ntlm2.sending.seq_num = 0;
+		if (reset_seqnums) {
+			ntlmssp_state->crypt->ntlm2.sending.seq_num = 0;
+		}
 
 		/* RECV: sign key */
 		calc_ntlmv2_key(ntlmssp_state->crypt->ntlm2.receiving.sign_key,
@@ -649,7 +622,9 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
 				&ntlmssp_state->crypt->ntlm2.receiving.seal_state);
 
 		/* RECV: seq num */
-		ntlmssp_state->crypt->ntlm2.receiving.seq_num = 0;
+		if (reset_seqnums) {
+			ntlmssp_state->crypt->ntlm2.receiving.seq_num = 0;
+		}
 	} else {
 		uint8_t weak_session_key[8];
 		DATA_BLOB seal_session_key = ntlmssp_state->session_key;
@@ -699,8 +674,26 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
 		dump_arc4_state("NTLMv1 arc4 state:\n",
 				&ntlmssp_state->crypt->ntlm.seal_state);
 
-		ntlmssp_state->crypt->ntlm.seq_num = 0;
+		if (reset_seqnums) {
+			ntlmssp_state->crypt->ntlm.seq_num = 0;
+		}
 	}
 
 	return NT_STATUS_OK;
 }
+
+NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
+{
+	if (ntlmssp_state->session_key.length < 8) {
+		DEBUG(3, ("NO session key, cannot intialise signing\n"));
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
+	ntlmssp_state->crypt = talloc_zero(ntlmssp_state,
+					   union ntlmssp_crypt_state);
+	if (ntlmssp_state->crypt == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return ntlmssp_sign_reset(ntlmssp_state, true);
+}
diff --git a/auth/ntlmssp/ntlmssp_util.c b/auth/ntlmssp/ntlmssp_util.c
index 96793ab..4ae6101 100644
--- a/auth/ntlmssp/ntlmssp_util.c
+++ b/auth/ntlmssp/ntlmssp_util.c
@@ -25,6 +25,41 @@
 #include "../auth/ntlmssp/ntlmssp.h"
 #include "../auth/ntlmssp/ntlmssp_private.h"
 
+static void debug_ntlmssp_flags_raw(int level, uint32_t flags)
+{
+#define _PRINT_FLAG_LINE(v) do { \
+	if (flags & (v)) { \
+		DEBUGADD(level, ("  " #v "\n")); \
+	} \
+} while (0)
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_UNICODE);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_OEM);
+	_PRINT_FLAG_LINE(NTLMSSP_REQUEST_TARGET);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_SIGN);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_SEAL);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_DATAGRAM);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_LM_KEY);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_NETWARE);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_NTLM);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_NT_ONLY);
+	_PRINT_FLAG_LINE(NTLMSSP_ANONYMOUS);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_ALWAYS_SIGN);
+	_PRINT_FLAG_LINE(NTLMSSP_TARGET_TYPE_DOMAIN);
+	_PRINT_FLAG_LINE(NTLMSSP_TARGET_TYPE_SERVER);
+	_PRINT_FLAG_LINE(NTLMSSP_TARGET_TYPE_SHARE);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_IDENTIFY);
+	_PRINT_FLAG_LINE(NTLMSSP_REQUEST_NON_NT_SESSION_KEY);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_TARGET_INFO);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_VERSION);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_128);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_KEY_EXCH);
+	_PRINT_FLAG_LINE(NTLMSSP_NEGOTIATE_56);
+}
+
 /**
  * Print out the NTLMSSP flags for debugging
  * @param neg_flags The flags from the packet
@@ -32,53 +67,15 @@
 void debug_ntlmssp_flags(uint32_t neg_flags)
 {
 	DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
-
-	if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_OEM)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
-	if (neg_flags & NTLMSSP_REQUEST_TARGET)
-		DEBUGADD(4, ("  NTLMSSP_REQUEST_TARGET\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_SEAL)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_DATAGRAM\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
-	if (neg_flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
-		DEBUGADD(4, ("  NTLMSSP_REQUEST_NON_NT_SESSION_KEY\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_TARGET_INFO\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_VERSION)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_VERSION\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_128)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_128\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
-	if (neg_flags & NTLMSSP_NEGOTIATE_56)
-		DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_56\n"));
+	debug_ntlmssp_flags_raw(4, neg_flags);
 }
 
-void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
-			      uint32_t neg_flags, bool allow_lm)
+NTSTATUS ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
+				  uint32_t flags, const char *name)
 {
-	if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+	uint32_t missing_flags = ntlmssp_state->required_flags;
+
+	if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
 		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;
 		ntlmssp_state->unicode = true;
@@ -88,49 +85,69 @@ void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
 		ntlmssp_state->unicode = false;
 	}
 
-	if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm) {
-		/* other end forcing us to use LM */
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
-		ntlmssp_state->use_ntlmv2 = false;
-	} else {
+	/*
+	 * NTLMSSP_NEGOTIATE_NTLM2 (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
+	 * has priority over NTLMSSP_NEGOTIATE_LM_KEY
+	 */
+	if (!(flags & NTLMSSP_NEGOTIATE_NTLM2)) {
+		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+	}
+
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
-		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+	if (!(flags & NTLMSSP_NEGOTIATE_LM_KEY)) {
+		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
-		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+	if (!(flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {
+	if (!(flags & NTLMSSP_NEGOTIATE_128)) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) {
+	if (!(flags & NTLMSSP_NEGOTIATE_56)) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+	if (!(flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+	if (!(flags & NTLMSSP_NEGOTIATE_SIGN)) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+	if (!(flags & NTLMSSP_NEGOTIATE_SEAL)) {
 		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;
 	}
 
-	if (!(neg_flags & NTLMSSP_NEGOTIATE_VERSION)) {
-		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_VERSION;
+	if ((flags & NTLMSSP_REQUEST_TARGET)) {
+		ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
 	}
 
-	if ((neg_flags & NTLMSSP_REQUEST_TARGET)) {
-		ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
+	missing_flags &= ~ntlmssp_state->neg_flags;
+	if (missing_flags != 0) {
+		HRESULT hres = HRES_SEC_E_UNSUPPORTED_FUNCTION;
+		NTSTATUS status = NT_STATUS(HRES_ERROR_V(hres));
+		DEBUG(1, ("%s: Got %s flags[0x%08x] "
+			  "- possible downgrade detected! "
+			  "missing_flags[0x%08x] - %s\n",
+			  __func__, name,
+			  (unsigned)flags,
+			  (unsigned)missing_flags,
+			  nt_errstr(status)));
+		debug_ntlmssp_flags_raw(1, missing_flags);
+		DEBUGADD(4, ("neg_flags[0x%08x]\n",
+			     (unsigned)ntlmssp_state->neg_flags));
+		debug_ntlmssp_flags_raw(4, ntlmssp_state->neg_flags);
+		return status;
 	}
+
+	return NT_STATUS_OK;
 }
 
 /* Does this blob looks like it could be NTLMSSP? */
@@ -142,3 +159,38 @@ bool ntlmssp_blob_matches_magic(const DATA_BLOB *blob)
 		return false;
 	}
 }
+
+const DATA_BLOB ntlmssp_version_blob(void)
+{
+	/*
+	 * This is a simplified version of
+	 *
+	 * enum ndr_err_code err;
+	 * struct ntlmssp_VERSION vers;
+	 *
+	 * ZERO_STRUCT(vers);
+	 * vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
+	 * vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
+	 * vers.ProductBuild = 0;
+	 * vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
+	 *
+	 * err = ndr_push_struct_blob(&version_blob,
+	 * 			ntlmssp_state,
+	 * 			&vers,
+	 * 			(ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);
+	 *
+	 * if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+	 * 	data_blob_free(&struct_blob);
+	 * 	return NT_STATUS_NO_MEMORY;
+	 * }
+	 */
+	static const uint8_t version_buffer[8] = {
+		NTLMSSP_WINDOWS_MAJOR_VERSION_6,
+		NTLMSSP_WINDOWS_MINOR_VERSION_1,
+		0x00, 0x00, /* product build */
+		0x00, 0x00, 0x00, /* reserved */
+		NTLMSSP_REVISION_W2K3
+	};
+
+	return data_blob_const(version_buffer, ARRAY_SIZE(version_buffer));
+}
diff --git a/auth/ntlmssp/wscript_build b/auth/ntlmssp/wscript_build
index 8725a80..e28d4eb 100644
--- a/auth/ntlmssp/wscript_build
+++ b/auth/ntlmssp/wscript_build
@@ -7,7 +7,7 @@ bld.SAMBA_SUBSYSTEM('NTLMSSP_COMMON',
 		    ntlmssp_server.c
 		    ntlmssp_sign.c
 		    gensec_ntlmssp_server.c''',
-                    deps='samba-util NDR_NTLMSSP MSRPC_PARSE NTLM_CHECK samba-credentials')
+                    deps='samba-util NDR_NTLMSSP MSRPC_PARSE NTLM_CHECK samba-credentials wbclient')
 
 bld.SAMBA_MODULE('gensec_ntlmssp',
 	source='''''',
diff --git a/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml b/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml
new file mode 100644
index 0000000..02bdd81
--- /dev/null
+++ b/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml
@@ -0,0 +1,26 @@
+<samba:parameter name="ldap server require strong auth"
+                 context="G"
+                 type="enum"
+                 enumlist="enum_ldap_server_require_strong_auth_vals"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>
+	The <smbconfoption name="ldap server require strong auth"/> defines whether
+	the ldap server requires ldap traffic to be signed or signed and encrypted (sealed).
+	Possible values are <emphasis>no</emphasis>, <emphasis>allow_sasl_over_tls</emphasis>
+	and <emphasis>yes</emphasis>.
+	</para>
+
+	<para>A value of <emphasis>no</emphasis> allows simple and sasl binds over
+	all transports.</para>
+
+	<para>A value of <emphasis>allow_sasl_over_tls</emphasis> allows simple and sasl binds
+	(without sign or seal) over TLS encrypted connections. Unencrypted connections only
+	allow sasl binds with sign or seal.</para>
+
+	<para>A value of <emphasis>yes</emphasis> allows only simple binds
+	over TLS encrypted connections. Unencrypted connections only
+	allow sasl binds with sign or seal.</para>
+</description>
+<value type="default">yes</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/protocol/clientipcmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientipcmaxprotocol.xml
new file mode 100644
index 0000000..408af50
--- /dev/null
+++ b/docs-xml/smbdotconf/protocol/clientipcmaxprotocol.xml
@@ -0,0 +1,29 @@
+<samba:parameter name="client ipc max protocol"
+                 context="G"
+                 type="enum"
+                 function="_client_ipc_max_protocol"
+                 enumlist="enum_protocol"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>The value of the parameter (a string) is the highest
+    protocol level that will be supported for IPC$ connections as DCERPC transport.</para>
+
+    <para>Normally this option should not be set as the automatic
+    negotiation phase in the SMB protocol takes care of choosing
+    the appropriate protocol.</para>
+
+    <para>The value <constant>default</constant> refers to the latest
+    supported protocol, currently <constant>SMB3_11</constant>.</para>
+
+    <para>See <smbconfoption name="client max protocol"/> for a full list
+    of available protocols. The values CORE, COREPLUS, LANMAN1, LANMAN2
+    are silently upgraded to NT1.</para>
+</description>
+
+<related>client ipc min protocol</related>
+<related>client min protocol</related>
+<related>client max protocol</related>
+
+<value type="default">default</value>
+<value type="example">SMB2_10</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/protocol/clientipcminprotocol.xml b/docs-xml/smbdotconf/protocol/clientipcminprotocol.xml
new file mode 100644
index 0000000..fc04b78
--- /dev/null
+++ b/docs-xml/smbdotconf/protocol/clientipcminprotocol.xml
@@ -0,0 +1,29 @@
+<samba:parameter name="client ipc min protocol"
+                 context="G"
+                 type="enum"
+                 function="_client_ipc_min_protocol"
+                 enumlist="enum_protocol"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>This setting controls the minimum protocol version that the
+	will be attempted to use for IPC$ connections as DCERPC transport.</para>
+
+	<para>Normally this option should not be set as the automatic
+	negotiation phase in the SMB protocol takes care of choosing
+	the appropriate protocol.</para>
+
+	<para>The value <constant>default</constant> refers to the higher value
+	of <constant>NT1</constant> and the effective value of
+	<smbconfoption name="client min protocol"/>.</para>
+
+	<para>See <smbconfoption name="client max protocol"/>  for a full list
+	of available protocols. The values CORE, COREPLUS, LANMAN1, LANMAN2
+	are silently upgraded to NT1.</para>
+</description>
+
+<related>client ipc max protocol</related>
+<related>client min protocol</related>
+<related>client max protocol</related>
+<value type="default">default</value>
+<value type="example">SMB3_11</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
index e68226f..252c47e 100644
--- a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
@@ -78,13 +78,16 @@
     negotiation phase in the SMB protocol takes care of choosing 
     the appropriate protocol.</para>
 
-    <para>The value <constant>default</constant> refers to the default protocol in each
-    part of the code, currently <constant>NT1</constant> in the client tools and
-    <constant>SMB3_02</constant> in winbindd.</para>
+    <para>The value <constant>default</constant> refers to <constant>NT1</constant>.</para>
+
+    <para>IPC$ connections for DCERPC e.g. in winbindd, are handled by the
+    <smbconfoption name="client ipc max protocol"/> option.</para>
 </description>
 
 <related>server max protocol</related>
 <related>client min protocol</related>
+<related>client ipc min protocol</related>
+<related>client ipc max protocol</related>
 
 <value type="default">default</value>
 <value type="example">LANMAN1</value>
diff --git a/docs-xml/smbdotconf/protocol/clientminprotocol.xml b/docs-xml/smbdotconf/protocol/clientminprotocol.xml
index c906a15..441f0ca 100644
--- a/docs-xml/smbdotconf/protocol/clientminprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/clientminprotocol.xml
@@ -12,10 +12,16 @@
 
 	<para>See <related>client max protocol</related> for a full list
 	of available protocols.</para>
+
+	<para>IPC$ connections for DCERPC e.g. in winbindd, are handled by the
+	<smbconfoption name="client ipc min protocol"/> option.</para>
 </description>
 
 <related>client max protocol</related>
 <related>server min protocol</related>
+<related>client ipc min protocol</related>
+<related>client ipc max protocol</related>
+
 <value type="default">CORE</value>
 <value type="example">NT1</value>
 </samba:parameter>
diff --git a/docs-xml/smbdotconf/protocol/clientusespnego.xml b/docs-xml/smbdotconf/protocol/clientusespnego.xml
index b95ad0e..7f415b5 100644
--- a/docs-xml/smbdotconf/protocol/clientusespnego.xml
+++ b/docs-xml/smbdotconf/protocol/clientusespnego.xml
@@ -8,6 +8,11 @@
     supporting servers (including WindowsXP, Windows2000 and Samba
     3.0) to agree upon an authentication
     mechanism.  This enables Kerberos authentication in particular.</para>
+
+    <para>When <smbconfoption name="client NTLMv2 auth"/> is also set to
+    <constant>yes</constant> extended security (SPNEGO) is required
+    in order to use NTLMv2 only within NTLMSSP. This behavior was
+    introduced with the patches for CVE-2016-2111.</para>
 </description>
 
 <value type="default">yes</value>
diff --git a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
new file mode 100644
index 0000000..03531ad
--- /dev/null
+++ b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
@@ -0,0 +1,27 @@
+<samba:parameter name="allow dcerpc auth level connect"
+                 context="G"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>This option controls whether DCERPC services are allowed to
+	be used with DCERPC_AUTH_LEVEL_CONNECT, which provides authentication,
+	but no per message integrity nor privacy protection.</para>
+
+	<para>Some interfaces like samr, lsarpc and netlogon have a hard-coded default of
+	<constant>no</constant> and epmapper, mgmt and rpcecho have a hard-coded default of
+	<constant>yes</constant>.
+	</para>
+
+	<para>The behavior can be overwritten per interface name (e.g. lsarpc, netlogon, samr, srvsvc,
+	winreg, wkssvc ...) by using 'allow dcerpc auth level connect:interface = yes' as option.</para>
+
+	<para>This option yields precedence to the implementation specific restrictions.
+	E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY.
+	The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY.
+	</para>
+</description>
+
+<value type="default">no</value>
+<value type="example">yes</value>
+
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/security/clientipcsigning.xml b/docs-xml/smbdotconf/security/clientipcsigning.xml
new file mode 100644
index 0000000..0881c6c
--- /dev/null
+++ b/docs-xml/smbdotconf/security/clientipcsigning.xml
@@ -0,0 +1,26 @@
+<samba:parameter name="client ipc signing"
+                 context="G"
+                 type="enum"
+                 function="_client_ipc_signing"
+                 enumlist="enum_smb_signing_vals"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>This controls whether the client is allowed or required to use SMB signing for IPC$
+    connections as DCERPC transport. Possible values
+    are <emphasis>auto</emphasis>, <emphasis>mandatory</emphasis>
+    and <emphasis>disabled</emphasis>.
+    </para>
+
+    <para>When set to mandatory or default, SMB signing is required.</para>
+
+    <para>When set to auto, SMB signing is offered, but not enforced and if set
+    to disabled, SMB signing is not offered either.</para>
+
+    <para>Connections from winbindd to Active Directory Domain Controllers
+    always enforce signing.</para>
+</description>
+
+<related>client signing</related>
+
+<value type="default">default</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/security/clientntlmv2auth.xml b/docs-xml/smbdotconf/security/clientntlmv2auth.xml
index d0f0a37..8c9a333 100644
--- a/docs-xml/smbdotconf/security/clientntlmv2auth.xml
+++ b/docs-xml/smbdotconf/security/clientntlmv2auth.xml
@@ -27,6 +27,11 @@
     NTLMv2 by default, and some sites (particularly those following
     'best practice' security polices) only allow NTLMv2 responses, and
     not the weaker LM or NTLM.</para>
+
+    <para>When <smbconfoption name="client use spnego"/> is also set to
+    <constant>yes</constant> extended security (SPNEGO) is required
+    in order to use NTLMv2 only within NTLMSSP. This behavior was
+    introduced with the patches for CVE-2016-2111.</para>
 </description>
 <value type="default">yes</value>
 </samba:parameter>
diff --git a/docs-xml/smbdotconf/security/clientsigning.xml b/docs-xml/smbdotconf/security/clientsigning.xml
index 60b8ffe..0e72674 100644
--- a/docs-xml/smbdotconf/security/clientsigning.xml
+++ b/docs-xml/smbdotconf/security/clientsigning.xml
@@ -8,14 +8,16 @@
     and <emphasis>disabled</emphasis>. 
     </para>
 
-    <para>When set to auto or default, SMB signing is offered, but not
-    enforced, except in winbindd, where it is enforced to Active
-    Directory Domain Controllers. </para>
+    <para>When set to auto or default, SMB signing is offered, but not enforced.</para>
 
     <para>When set to mandatory, SMB signing is required and if set
-	to disabled, SMB signing is not offered either.
-</para>
+    to disabled, SMB signing is not offered either.</para>
+
+    <para>IPC$ connections for DCERPC e.g. in winbindd, are handled by the
+    <smbconfoption name="client ipc signing"/> option.</para>
 </description>
 
+<related>client ipc signing</related>
+
 <value type="default">default</value>
 </samba:parameter>
diff --git a/docs-xml/smbdotconf/security/rawntlmv2auth.xml b/docs-xml/smbdotconf/security/rawntlmv2auth.xml
new file mode 100644
index 0000000..30e7280
--- /dev/null
+++ b/docs-xml/smbdotconf/security/rawntlmv2auth.xml
@@ -0,0 +1,19 @@
+<samba:parameter name="raw NTLMv2 auth"
+                 context="G"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+    <para>This parameter determines whether or not <citerefentry><refentrytitle>smbd</refentrytitle>
+    <manvolnum>8</manvolnum></citerefentry> will allow SMB1 clients without
+    extended security (without SPNEGO) to use NTLMv2 authentication.</para>
+
+    <para>If this option, <command moreinfo="none">lanman auth</command>
+    and <command moreinfo="none">ntlm auth</command> are all disabled,
+    then only clients with SPNEGO support will be permitted.
+    That means NTLMv2 is only supported within NTLMSSP.</para>
+</description>
+
+<related>lanman auth</related>
+<related>ntlm auth</related>
+<value type="default">no</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/security/serversigning.xml b/docs-xml/smbdotconf/security/serversigning.xml
index 9fdb833..8bd7fda 100644
--- a/docs-xml/smbdotconf/security/serversigning.xml
+++ b/docs-xml/smbdotconf/security/serversigning.xml
@@ -10,7 +10,7 @@
     </para>
 
     <para>By default, and when smb signing is set to
-    <emphasis>default</emphasis>, smb signing enabled when
+    <emphasis>default</emphasis>, smb signing is required when
     <smbconfoption name="server role"/> is <emphasis>active directory
     domain controller</emphasis> and disabled otherwise.</para>
 
diff --git a/docs-xml/smbdotconf/security/tlsverifypeer.xml b/docs-xml/smbdotconf/security/tlsverifypeer.xml
new file mode 100644
index 0000000..4f47dd4
--- /dev/null
+++ b/docs-xml/smbdotconf/security/tlsverifypeer.xml
@@ -0,0 +1,47 @@
+<samba:parameter name="tls verify peer"
+                 context="G"
+                 type="enum"
+                 enumlist="enum_tls_verify_peer_vals"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>This controls if and how strict the client will verify the peer's certificate and name.
+	Possible values are (in increasing order):
+	<constant>no_check</constant>,
+	<constant>ca_only</constant>,
+	<constant>ca_and_name_if_available</constant>,
+	<constant>ca_and_name</constant>
+	and
+	<constant>as_strict_as_possible</constant>.</para>
+
+	<para>When set to <constant>no_check</constant> the certificate is not verified at
+	all, which allows trivial man in the middle attacks.
+	</para>
+
+	<para>When set to <constant>ca_only</constant> the certificate is verified to
+	be signed from a ca specified in the <smbconfoption name="tls ca file"/> option.
+	Setting <smbconfoption name="tls ca file"/> to a valid file is required.
+	The certificate lifetime is also verified. If the <smbconfoption name="tls crl file"/>
+	option is configured, the certificate is also verified against the ca crl.
+	</para>
+
+	<para>When set to <constant>ca_and_name_if_available</constant> all checks from
+	<constant>ca_only</constant> are performed. In addition, the peer hostname is verified
+	against the certificate's name, if it is provided by the application layer and
+	not given as an ip address string.
+	</para>
+
+	<para>When set to <constant>ca_and_name</constant> all checks from
+	<constant>ca_and_name_if_available</constant> are performed.
+	In addition the peer hostname needs to be provided and even an ip
+	address is checked against the certificate's name.
+	</para>
+
+	<para>When set to <constant>as_strict_as_possible</constant> all checks from
+	<constant>ca_and_name</constant> are performed. In addition the
+	<smbconfoption name="tls crl file"/> needs to be configured.
+	Future versions of Samba may implement additional checks.
+	</para>
+</description>
+
+<value type="default">as_strict_as_possible</value>
+</samba:parameter>
diff --git a/docs/manpages/dbwrap_tool.1 b/docs/manpages/dbwrap_tool.1
index 38a088c..5f93c2a 100644
--- a/docs/manpages/dbwrap_tool.1
+++ b/docs/manpages/dbwrap_tool.1
@@ -2,12 +2,12 @@
 .\"     Title: dbwrap_tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "DBWRAP_TOOL" "1" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "DBWRAP_TOOL" "1" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/eventlogadm.8 b/docs/manpages/eventlogadm.8
index 1fdf559..5b0fb52 100644
--- a/docs/manpages/eventlogadm.8
+++ b/docs/manpages/eventlogadm.8
@@ -2,12 +2,12 @@
 .\"     Title: eventlogadm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "EVENTLOGADM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "EVENTLOGADM" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/findsmb.1 b/docs/manpages/findsmb.1
index c0c1ea3..1a1b848 100644
--- a/docs/manpages/findsmb.1
+++ b/docs/manpages/findsmb.1
@@ -2,12 +2,12 @@
 .\"     Title: findsmb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "FINDSMB" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "FINDSMB" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ad.8 b/docs/manpages/idmap_ad.8
index c33d927..c3e61a0 100644
--- a/docs/manpages/idmap_ad.8
+++ b/docs/manpages/idmap_ad.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ad
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_AD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_autorid.8 b/docs/manpages/idmap_autorid.8
index e06e626..eca4bcd 100644
--- a/docs/manpages/idmap_autorid.8
+++ b/docs/manpages/idmap_autorid.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_autorid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_AUTORID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AUTORID" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_hash.8 b/docs/manpages/idmap_hash.8
index 6b2c3b2..cac7bf2 100644
--- a/docs/manpages/idmap_hash.8
+++ b/docs/manpages/idmap_hash.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_hash
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_HASH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_HASH" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ldap.8 b/docs/manpages/idmap_ldap.8
index 8383973..8a85dba 100644
--- a/docs/manpages/idmap_ldap.8
+++ b/docs/manpages/idmap_ldap.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ldap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_LDAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_LDAP" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_nss.8 b/docs/manpages/idmap_nss.8
index 5ebfafe..22b1caa 100644
--- a/docs/manpages/idmap_nss.8
+++ b/docs/manpages/idmap_nss.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_nss
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_NSS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_NSS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rfc2307.8 b/docs/manpages/idmap_rfc2307.8
index 0f7532c..3889091 100644
--- a/docs/manpages/idmap_rfc2307.8
+++ b/docs/manpages/idmap_rfc2307.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rfc2307
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_RFC2307" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RFC2307" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rid.8 b/docs/manpages/idmap_rid.8
index 8a87aff..433b0ca 100644
--- a/docs/manpages/idmap_rid.8
+++ b/docs/manpages/idmap_rid.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_RID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RID" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_script.8 b/docs/manpages/idmap_script.8
index 85deee2..3dabae5 100644
--- a/docs/manpages/idmap_script.8
+++ b/docs/manpages/idmap_script.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_script
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_SCRIPT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_SCRIPT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb.8 b/docs/manpages/idmap_tdb.8
index dd060f7..f21810c 100644
--- a/docs/manpages/idmap_tdb.8
+++ b/docs/manpages/idmap_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb2.8 b/docs/manpages/idmap_tdb2.8
index e38f223..12e871f 100644
--- a/docs/manpages/idmap_tdb2.8
+++ b/docs/manpages/idmap_tdb2.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb2
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB2" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/libsmbclient.7 b/docs/manpages/libsmbclient.7
index e4b20e3..68bbb83 100644
--- a/docs/manpages/libsmbclient.7
+++ b/docs/manpages/libsmbclient.7
@@ -2,12 +2,12 @@
 .\"     Title: libsmbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: 7
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LIBSMBCLIENT" "7" "02/24/2016" "Samba 4\&.3" "7"
+.TH "LIBSMBCLIENT" "7" "03/30/2016" "Samba 4\&.3" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/lmhosts.5 b/docs/manpages/lmhosts.5
index a8ff381..7ecccd5 100644
--- a/docs/manpages/lmhosts.5
+++ b/docs/manpages/lmhosts.5
@@ -2,12 +2,12 @@
 .\"     Title: lmhosts
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LMHOSTS" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
+.TH "LMHOSTS" "5" "03/30/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/log2pcap.1 b/docs/manpages/log2pcap.1
index b489e7d..a2cb85d 100644
--- a/docs/manpages/log2pcap.1
+++ b/docs/manpages/log2pcap.1
@@ -2,12 +2,12 @@
 .\"     Title: log2pcap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LOG2PCAP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "LOG2PCAP" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/net.8 b/docs/manpages/net.8
index b0978a9..03f193a 100644
--- a/docs/manpages/net.8
+++ b/docs/manpages/net.8
@@ -2,12 +2,12 @@
 .\"     Title: net
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NET" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "NET" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8
index bcf774a..7f6d90c 100644
--- a/docs/manpages/nmbd.8
+++ b/docs/manpages/nmbd.8
@@ -2,12 +2,12 @@
 .\"     Title: nmbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "NMBD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmblookup.1 b/docs/manpages/nmblookup.1
index 6b2677d..91733f0 100644
--- a/docs/manpages/nmblookup.1
+++ b/docs/manpages/nmblookup.1
@@ -2,12 +2,12 @@
 .\"     Title: nmblookup
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NMBLOOKUP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "NMBLOOKUP" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/ntlm_auth.1 b/docs/manpages/ntlm_auth.1
index 1d0fed8..d2ee318 100644
--- a/docs/manpages/ntlm_auth.1
+++ b/docs/manpages/ntlm_auth.1
@@ -2,12 +2,12 @@
 .\"     Title: ntlm_auth
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NTLM_AUTH" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "NTLM_AUTH" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.8 b/docs/manpages/pam_winbind.8
index dbfca2b..79c951d 100644
--- a/docs/manpages/pam_winbind.8
+++ b/docs/manpages/pam_winbind.8
@@ -2,12 +2,12 @@
 .\"     Title: pam_winbind
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: 8
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND" "8" "02/24/2016" "Samba 4\&.3" "8"
+.TH "PAM_WINBIND" "8" "03/30/2016" "Samba 4\&.3" "8"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.conf.5 b/docs/manpages/pam_winbind.conf.5
index 9e3d7c8..bd1c823 100644
--- a/docs/manpages/pam_winbind.conf.5
+++ b/docs/manpages/pam_winbind.conf.5
@@ -2,12 +2,12 @@
 .\"     Title: pam_winbind.conf
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: 5
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "5"
+.TH "PAM_WINBIND\&.CONF" "5" "03/30/2016" "Samba 4\&.3" "5"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pdbedit.8 b/docs/manpages/pdbedit.8
index 12245f1..1e2c015 100644
--- a/docs/manpages/pdbedit.8
+++ b/docs/manpages/pdbedit.8
@@ -2,12 +2,12 @@
 .\"     Title: pdbedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PDBEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "PDBEDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/profiles.1 b/docs/manpages/profiles.1
index 33296d1..3f8f85e 100644
--- a/docs/manpages/profiles.1
+++ b/docs/manpages/profiles.1
@@ -2,12 +2,12 @@
 .\"     Title: profiles
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PROFILES" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "PROFILES" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/rpcclient.1 b/docs/manpages/rpcclient.1
index 9e721db..0607ced 100644
--- a/docs/manpages/rpcclient.1
+++ b/docs/manpages/rpcclient.1
@@ -2,12 +2,12 @@
 .\"     Title: rpcclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "RPCCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "RPCCLIENT" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-regedit.8 b/docs/manpages/samba-regedit.8
index 3b282b1..2f96069 100644
--- a/docs/manpages/samba-regedit.8
+++ b/docs/manpages/samba-regedit.8
@@ -2,12 +2,12 @@
 .\"     Title: samba-regedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA\-REGEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-REGEDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-tool.8 b/docs/manpages/samba-tool.8
index c55158d..bd264ca 100644
--- a/docs/manpages/samba-tool.8
+++ b/docs/manpages/samba-tool.8
@@ -2,12 +2,12 @@
 .\"     Title: samba-tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA\-TOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-TOOL" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7
index 3628bfd..2d2c6bb 100644
--- a/docs/manpages/samba.7
+++ b/docs/manpages/samba.7
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: Miscellanea
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA" "7" "02/24/2016" "Samba 4\&.3" "Miscellanea"
+.TH "SAMBA" "7" "03/30/2016" "Samba 4\&.3" "Miscellanea"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.8 b/docs/manpages/samba.8
index 0bd4e30..3b86327 100644
--- a/docs/manpages/samba.8
+++ b/docs/manpages/samba.8
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/sharesec.1 b/docs/manpages/sharesec.1
index e654488..d933e59 100644
--- a/docs/manpages/sharesec.1
+++ b/docs/manpages/sharesec.1
@@ -2,12 +2,12 @@
 .\"     Title: sharesec
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SHARESEC" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SHARESEC" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5
index 796aa3a..13af0a3 100644
--- a/docs/manpages/smb.conf.5
+++ b/docs/manpages/smb.conf.5
@@ -2,12 +2,12 @@
 .\"     Title: smb.conf
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMB\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMB\&.CONF" "5" "03/30/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -1275,6 +1275,28 @@ Example:
 \fI\fIallocation roundup size\fR\fR\fI = \fR\fI0 # (to disable roundups)\fR\fI \fR
 .RE
 
+allow dcerpc auth level connect (G)
+.\" allow dcerpc auth level connect
+.PP
+.RS 4
+This option controls whether DCERPC services are allowed to be used with DCERPC_AUTH_LEVEL_CONNECT, which provides authentication, but no per message integrity nor privacy protection\&.
+.sp
+Some interfaces like samr, lsarpc and netlogon have a hard\-coded default of
+\fBno\fR
+and epmapper, mgmt and rpcecho have a hard\-coded default of
+\fByes\fR\&.
+.sp
+The behavior can be overwritten per interface name (e\&.g\&. lsarpc, netlogon, samr, srvsvc, winreg, wkssvc \&.\&.\&.) by using \*(Aqallow dcerpc auth level connect:interface = yes\*(Aq as option\&.
+.sp
+This option yields precedence to the implementation specific restrictions\&. E\&.g\&. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY\&. The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY\&.
+.sp
+Default:
+\fI\fIallow dcerpc auth level connect\fR\fR\fI = \fR\fIno\fR\fI \fR
+.sp
+Example:
+\fI\fIallow dcerpc auth level connect\fR\fR\fI = \fR\fIyes\fR\fI \fR
+.RE
+
 allow dns updates (G)
 .\" allow dns updates
 .PP
@@ -1741,6 +1763,76 @@ Example:
 \fI\fIcldap port\fR\fR\fI = \fR\fI3389\fR\fI \fR
 .RE
 
+client ipc max protocol (G)
+.\" client ipc max protocol
+.PP
+.RS 4
+The value of the parameter (a string) is the highest protocol level that will be supported for IPC$ connections as DCERPC transport\&.
+.sp
+Normally this option should not be set as the automatic negotiation phase in the SMB protocol takes care of choosing the appropriate protocol\&.
+.sp
+The value
+\fBdefault\fR
+refers to the latest supported protocol, currently
+\fBSMB3_11\fR\&.
+.sp
+See
+\m[blue]\fBclient max protocol\fR\m[]
+for a full list of available protocols\&. The values CORE, COREPLUS, LANMAN1, LANMAN2 are silently upgraded to NT1\&.
+.sp
+Default:
+\fI\fIclient ipc max protocol\fR\fR\fI = \fR\fIdefault\fR\fI \fR
+.sp
+Example:
+\fI\fIclient ipc max protocol\fR\fR\fI = \fR\fISMB2_10\fR\fI \fR
+.RE
+
+client ipc min protocol (G)
+.\" client ipc min protocol
+.PP
+.RS 4
+This setting controls the minimum protocol version that the will be attempted to use for IPC$ connections as DCERPC transport\&.
+.sp
+Normally this option should not be set as the automatic negotiation phase in the SMB protocol takes care of choosing the appropriate protocol\&.
+.sp
+The value
+\fBdefault\fR
+refers to the higher value of
+\fBNT1\fR
+and the effective value of
+\m[blue]\fBclient min protocol\fR\m[]\&.
+.sp
+See
+\m[blue]\fBclient max protocol\fR\m[]
+for a full list of available protocols\&. The values CORE, COREPLUS, LANMAN1, LANMAN2 are silently upgraded to NT1\&.
+.sp
+Default:
+\fI\fIclient ipc min protocol\fR\fR\fI = \fR\fIdefault\fR\fI \fR
+.sp
+Example:
+\fI\fIclient ipc min protocol\fR\fR\fI = \fR\fISMB3_11\fR\fI \fR
+.RE
+
+client ipc signing (G)
+.\" client ipc signing
+.PP
+.RS 4
+This controls whether the client is allowed or required to use SMB signing for IPC$ connections as DCERPC transport\&. Possible values are
+\fIauto\fR,
+\fImandatory\fR
+and
+\fIdisabled\fR\&.
+.sp
+When set to mandatory or default, SMB signing is required\&.
+.sp
+When set to auto, SMB signing is offered, but not enforced and if set to disabled, SMB signing is not offered either\&.
+.sp
+Connections from winbindd to Active Directory Domain Controllers always enforce signing\&.
+.sp
+Default:
+\fI\fIclient ipc signing\fR\fR\fI = \fR\fIdefault\fR\fI \fR
+.RE
+
 client lanman auth (G)
 .\" client lanman auth
 .PP
@@ -1982,11 +2074,12 @@ Normally this option should not be set as the automatic negotiation phase in the
 .sp
 The value
 \fBdefault\fR
-refers to the default protocol in each part of the code, currently
-\fBNT1\fR
-in the client tools and
-\fBSMB3_02\fR
-in winbindd\&.
+refers to
+\fBNT1\fR\&.
+.sp
+IPC$ connections for DCERPC e\&.g\&. in winbindd, are handled by the
+\m[blue]\fBclient ipc max protocol\fR\m[]
+option\&.
 .sp
 Default:
 \fI\fIclient max protocol\fR\fR\fI = \fR\fIdefault\fR\fI \fR
@@ -2007,6 +2100,10 @@ See
 Related command: \m[blue]\fBclient max protocol\fR\m[]
 for a full list of available protocols\&.
 .sp
+IPC$ connections for DCERPC e\&.g\&. in winbindd, are handled by the
+\m[blue]\fBclient ipc min protocol\fR\m[]
+option\&.
+.sp
 Default:
 \fI\fIclient min protocol\fR\fR\fI = \fR\fICORE\fR\fI \fR
 .sp
@@ -2035,6 +2132,12 @@ client lanman auth\&.
 .sp
 Note that Windows Vista and later versions already use NTLMv2 by default, and some sites (particularly those following \*(Aqbest practice\*(Aq security polices) only allow NTLMv2 responses, and not the weaker LM or NTLM\&.
 .sp
+When
+\m[blue]\fBclient use spnego\fR\m[]
+is also set to
+\fByes\fR
+extended security (SPNEGO) is required in order to use NTLMv2 only within NTLMSSP\&. This behavior was introduced with the patches for CVE\-2016\-2111\&.
+.sp
 Default:
 \fI\fIclient NTLMv2 auth\fR\fR\fI = \fR\fIyes\fR\fI \fR
 .RE
@@ -2085,10 +2188,14 @@ This controls whether the client is allowed or required to use SMB signing\&. Po
 and
 \fIdisabled\fR\&.
 .sp
-When set to auto or default, SMB signing is offered, but not enforced, except in winbindd, where it is enforced to Active Directory Domain Controllers\&.
+When set to auto or default, SMB signing is offered, but not enforced\&.
 .sp
 When set to mandatory, SMB signing is required and if set to disabled, SMB signing is not offered either\&.
 .sp
+IPC$ connections for DCERPC e\&.g\&. in winbindd, are handled by the
+\m[blue]\fBclient ipc signing\fR\m[]
+option\&.
+.sp
 Default:
 \fI\fIclient signing\fR\fR\fI = \fR\fIdefault\fR\fI \fR
 .RE
@@ -2121,6 +2228,12 @@ client use spnego (G)
 .RS 4
 This variable controls whether Samba clients will try to use Simple and Protected NEGOciation (as specified by rfc2478) with supporting servers (including WindowsXP, Windows2000 and Samba 3\&.0) to agree upon an authentication mechanism\&. This enables Kerberos authentication in particular\&.
 .sp
+When
+\m[blue]\fBclient NTLMv2 auth\fR\m[]
+is also set to
+\fByes\fR
+extended security (SPNEGO) is required in order to use NTLMv2 only within NTLMSSP\&. This behavior was introduced with the patches for CVE\-2016\-2111\&.
+.sp
 Default:
 \fI\fIclient use spnego\fR\fR\fI = \fR\fIyes\fR\fI \fR
 .RE
@@ -5071,6 +5184,34 @@ Default:
 \fI\fIldapsam:trusted\fR\fR\fI = \fR\fIno\fR\fI \fR
 .RE
 
+ldap server require strong auth (G)
+.\" ldap server require strong auth
+.PP
+.RS 4
+The
+\m[blue]\fBldap server require strong auth\fR\m[]
+defines whether the ldap server requires ldap traffic to be signed or signed and encrypted (sealed)\&. Possible values are
+\fIno\fR,
+\fIallow_sasl_over_tls\fR
+and
+\fIyes\fR\&.
+.sp
+A value of
+\fIno\fR
+allows simple and sasl binds over all transports\&.
+.sp
+A value of
+\fIallow_sasl_over_tls\fR
+allows simple and sasl binds (without sign or seal) over TLS encrypted connections\&. Unencrypted connections only allow sasl binds with sign or seal\&.
+.sp
+A value of
+\fIyes\fR
+allows only simple binds over TLS encrypted connections\&. Unencrypted connections only allow sasl binds with sign or seal\&.
+.sp
+Default:
+\fI\fIldap server require strong auth\fR\fR\fI = \fR\fIyes\fR\fI \fR
+.RE
+
 ldap ssl (G)
 .\" ldap ssl
 .PP
@@ -8346,6 +8487,24 @@ Example:
 \fI\fIqueueresume command\fR\fR\fI = \fR\fIenable %p\fR\fI \fR
 .RE
 
+raw NTLMv2 auth (G)
+.\" raw NTLMv2 auth
+.PP
+.RS 4
+This parameter determines whether or not
+\fBsmbd\fR(8)
+will allow SMB1 clients without extended security (without SPNEGO) to use NTLMv2 authentication\&.
+.sp
+If this option,
+lanman auth
+and
+ntlm auth
+are all disabled, then only clients with SPNEGO support will be permitted\&. That means NTLMv2 is only supported within NTLMSSP\&.
+.sp
+Default:
+\fI\fIraw NTLMv2 auth\fR\fR\fI = \fR\fIno\fR\fI \fR
+.RE
+
 read list (S)
 .\" read list
 .PP
@@ -9581,7 +9740,7 @@ and
 \fIdisabled\fR\&.
 .sp
 By default, and when smb signing is set to
-\fIdefault\fR, smb signing enabled when
+\fIdefault\fR, smb signing is required when
 \m[blue]\fBserver role\fR\m[]
 is
 \fIactive directory domain controller\fR
@@ -11132,6 +11291,56 @@ Default:
 \fI\fItls priority\fR\fR\fI = \fR\fINORMAL:\-VERS\-SSL3\&.0\fR\fI \fR
 .RE
 
+tls verify peer (G)
+.\" tls verify peer
+.PP
+.RS 4
+This controls if and how strict the client will verify the peer\*(Aqs certificate and name\&. Possible values are (in increasing order):
+\fBno_check\fR,
+\fBca_only\fR,
+\fBca_and_name_if_available\fR,
+\fBca_and_name\fR
+and
+\fBas_strict_as_possible\fR\&.
+.sp
+When set to
+\fBno_check\fR
+the certificate is not verified at all, which allows trivial man in the middle attacks\&.
+.sp
+When set to
+\fBca_only\fR
+the certificate is verified to be signed from a ca specified in the
+\m[blue]\fBtls ca file\fR\m[]
+option\&. Setting
+\m[blue]\fBtls ca file\fR\m[]
+to a valid file is required\&. The certificate lifetime is also verified\&. If the
+\m[blue]\fBtls crl file\fR\m[]
+option is configured, the certificate is also verified against the ca crl\&.
+.sp
+When set to
+\fBca_and_name_if_available\fR
+all checks from
+\fBca_only\fR
+are performed\&. In addition, the peer hostname is verified against the certificate\*(Aqs name, if it is provided by the application layer and not given as an ip address string\&.
+.sp
+When set to
+\fBca_and_name\fR
+all checks from
+\fBca_and_name_if_available\fR
+are performed\&. In addition the peer hostname needs to be provided and even an ip address is checked against the certificate\*(Aqs name\&.
+.sp
+When set to
+\fBas_strict_as_possible\fR
+all checks from
+\fBca_and_name\fR
+are performed\&. In addition the
+\m[blue]\fBtls crl file\fR\m[]
+needs to be configured\&. Future versions of Samba may implement additional checks\&.
+.sp
+Default:
+\fI\fItls verify peer\fR\fR\fI = \fR\fIas_strict_as_possible\fR\fI \fR
+.RE
+
 unicode (G)
 .\" unicode
 .PP
diff --git a/docs/manpages/smbcacls.1 b/docs/manpages/smbcacls.1
index 291ac5e..048ed5e 100644
--- a/docs/manpages/smbcacls.1
+++ b/docs/manpages/smbcacls.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcacls
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCACLS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBCACLS" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbclient.1 b/docs/manpages/smbclient.1
index 395fbcf..d8af88f 100644
--- a/docs/manpages/smbclient.1
+++ b/docs/manpages/smbclient.1
@@ -2,12 +2,12 @@
 .\"     Title: smbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBCLIENT" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcontrol.1 b/docs/manpages/smbcontrol.1
index c8cf7ff..20ca814 100644
--- a/docs/manpages/smbcontrol.1
+++ b/docs/manpages/smbcontrol.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcontrol
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCONTROL" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBCONTROL" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcquotas.1 b/docs/manpages/smbcquotas.1
index 22365d0..9d2e005 100644
--- a/docs/manpages/smbcquotas.1
+++ b/docs/manpages/smbcquotas.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcquotas
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCQUOTAS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBCQUOTAS" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbd.8 b/docs/manpages/smbd.8
index 0171d72..9a15516 100644
--- a/docs/manpages/smbd.8
+++ b/docs/manpages/smbd.8
@@ -2,12 +2,12 @@
 .\"     Title: smbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SMBD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbget.1 b/docs/manpages/smbget.1
index 566a67a..f6de8f7 100644
--- a/docs/manpages/smbget.1
+++ b/docs/manpages/smbget.1
@@ -2,12 +2,12 @@
 .\"     Title: smbget
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBGET" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBGET" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbgetrc.5 b/docs/manpages/smbgetrc.5
index c959419..982b03e 100644
--- a/docs/manpages/smbgetrc.5
+++ b/docs/manpages/smbgetrc.5
@@ -2,12 +2,12 @@
 .\"     Title: smbgetrc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBGETRC" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBGETRC" "5" "03/30/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.5 b/docs/manpages/smbpasswd.5
index 31b52a9..a510685 100644
--- a/docs/manpages/smbpasswd.5
+++ b/docs/manpages/smbpasswd.5
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBPASSWD" "5" "03/30/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.8 b/docs/manpages/smbpasswd.8
index 3d00776..e05dbc6 100644
--- a/docs/manpages/smbpasswd.8
+++ b/docs/manpages/smbpasswd.8
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SMBPASSWD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbspool.8 b/docs/manpages/smbspool.8
index c4bc508..0d49e8f 100644
--- a/docs/manpages/smbspool.8
+++ b/docs/manpages/smbspool.8
@@ -2,12 +2,12 @@
 .\"     Title: smbspool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBSPOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SMBSPOOL" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbspool_krb5_wrapper.8 b/docs/manpages/smbspool_krb5_wrapper.8
index bd6f2b5..c7447e5 100644
--- a/docs/manpages/smbspool_krb5_wrapper.8
+++ b/docs/manpages/smbspool_krb5_wrapper.8
@@ -2,12 +2,12 @@
 .\"     Title: smbspool_krb5_wrapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.4
 .\"  Language: English
 .\"
-.TH "SMBSPOOL_KRB5_WRAPPE" "8" "02/24/2016" "Samba 4\&.4" "System Administration tools"
+.TH "SMBSPOOL_KRB5_WRAPPE" "8" "03/30/2016" "Samba 4\&.4" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbstatus.1 b/docs/manpages/smbstatus.1
index c2766d5..122b1ab 100644
--- a/docs/manpages/smbstatus.1
+++ b/docs/manpages/smbstatus.1
@@ -2,12 +2,12 @@
 .\"     Title: smbstatus
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBSTATUS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBSTATUS" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbta-util.8 b/docs/manpages/smbta-util.8
index f7349c7..71bf5d6 100644
--- a/docs/manpages/smbta-util.8
+++ b/docs/manpages/smbta-util.8
@@ -2,12 +2,12 @@
 .\"     Title: smbta-util
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTA\-UTIL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SMBTA\-UTIL" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtar.1 b/docs/manpages/smbtar.1
index 130b1a3..2a600b2 100644
--- a/docs/manpages/smbtar.1
+++ b/docs/manpages/smbtar.1
@@ -2,12 +2,12 @@
 .\"     Title: smbtar
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTAR" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBTAR" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtree.1 b/docs/manpages/smbtree.1
index e757082..3ce18f1 100644
--- a/docs/manpages/smbtree.1
+++ b/docs/manpages/smbtree.1
@@ -2,12 +2,12 @@
 .\"     Title: smbtree
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTREE" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "SMBTREE" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/testparm.1 b/docs/manpages/testparm.1
index 5b42305..3b047c0 100644
--- a/docs/manpages/testparm.1
+++ b/docs/manpages/testparm.1
@@ -2,12 +2,12 @@
 .\"     Title: testparm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "TESTPARM" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "TESTPARM" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_tdb.8 b/docs/manpages/vfs_acl_tdb.8
index 9c69b5f..3f9de9c 100644
--- a/docs/manpages/vfs_acl_tdb.8
+++ b/docs/manpages/vfs_acl_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_acl_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ACL_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_TDB" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_xattr.8 b/docs/manpages/vfs_acl_xattr.8
index 9ed7731..a711b86 100644
--- a/docs/manpages/vfs_acl_xattr.8
+++ b/docs/manpages/vfs_acl_xattr.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_acl_xattr
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ACL_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_XATTR" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_fork.8 b/docs/manpages/vfs_aio_fork.8
index a5a8838..9e536ad 100644
--- a/docs/manpages/vfs_aio_fork.8
+++ b/docs/manpages/vfs_aio_fork.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_fork
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_FORK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_FORK" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_linux.8 b/docs/manpages/vfs_aio_linux.8
index 9029985..824b5d8 100644
--- a/docs/manpages/vfs_aio_linux.8
+++ b/docs/manpages/vfs_aio_linux.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_linux
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_LINUX" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_LINUX" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_pthread.8 b/docs/manpages/vfs_aio_pthread.8
index 0606288..189d880 100644
--- a/docs/manpages/vfs_aio_pthread.8
+++ b/docs/manpages/vfs_aio_pthread.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_pthread
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_PTHREAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_PTHREAD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_audit.8 b/docs/manpages/vfs_audit.8
index 0154f99..3667234 100644
--- a/docs/manpages/vfs_audit.8
+++ b/docs/manpages/vfs_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AUDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_btrfs.8 b/docs/manpages/vfs_btrfs.8
index aea6e5a..c36130e 100644
--- a/docs/manpages/vfs_btrfs.8
+++ b/docs/manpages/vfs_btrfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_btrfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_BTRFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_BTRFS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cacheprime.8 b/docs/manpages/vfs_cacheprime.8
index ce1cad4..65b5ad5 100644
--- a/docs/manpages/vfs_cacheprime.8
+++ b/docs/manpages/vfs_cacheprime.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cacheprime
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CACHEPRIME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CACHEPRIME" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cap.8 b/docs/manpages/vfs_cap.8
index 326c412..0481d5f 100644
--- a/docs/manpages/vfs_cap.8
+++ b/docs/manpages/vfs_cap.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CAP" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_catia.8 b/docs/manpages/vfs_catia.8
index bc68933..5ac1f92 100644
--- a/docs/manpages/vfs_catia.8
+++ b/docs/manpages/vfs_catia.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_catia
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CATIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CATIA" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_ceph.8 b/docs/manpages/vfs_ceph.8
index 73b3d61..b468d5e 100644
--- a/docs/manpages/vfs_ceph.8
+++ b/docs/manpages/vfs_ceph.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_ceph
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CEPH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CEPH" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_commit.8 b/docs/manpages/vfs_commit.8
index afbb350..e1b4327 100644
--- a/docs/manpages/vfs_commit.8
+++ b/docs/manpages/vfs_commit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_commit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_COMMIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_COMMIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_crossrename.8 b/docs/manpages/vfs_crossrename.8
index 4b037a1..712aa45 100644
--- a/docs/manpages/vfs_crossrename.8
+++ b/docs/manpages/vfs_crossrename.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_crossrename
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CROSSRENAME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CROSSRENAME" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_default_quota.8 b/docs/manpages/vfs_default_quota.8
index 9347894..823b3b7 100644
--- a/docs/manpages/vfs_default_quota.8
+++ b/docs/manpages/vfs_default_quota.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_default_quota
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_DEFAULT_QUOTA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DEFAULT_QUOTA" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_dirsort.8 b/docs/manpages/vfs_dirsort.8
index 6455c07..64c186e 100644
--- a/docs/manpages/vfs_dirsort.8
+++ b/docs/manpages/vfs_dirsort.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_dirsort
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_DIRSORT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DIRSORT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_extd_audit.8 b/docs/manpages/vfs_extd_audit.8
index 48f605b..1ef888a 100644
--- a/docs/manpages/vfs_extd_audit.8
+++ b/docs/manpages/vfs_extd_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_extd_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_EXTD_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_EXTD_AUDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fake_perms.8 b/docs/manpages/vfs_fake_perms.8
index 68aac1f..1ecd646 100644
--- a/docs/manpages/vfs_fake_perms.8
+++ b/docs/manpages/vfs_fake_perms.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fake_perms
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FAKE_PERMS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FAKE_PERMS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fileid.8 b/docs/manpages/vfs_fileid.8
index 2121630..623fc38 100644
--- a/docs/manpages/vfs_fileid.8
+++ b/docs/manpages/vfs_fileid.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fileid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FILEID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FILEID" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fruit.8 b/docs/manpages/vfs_fruit.8
index 7b8f212..0d260c4 100644
--- a/docs/manpages/vfs_fruit.8
+++ b/docs/manpages/vfs_fruit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fruit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FRUIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FRUIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_full_audit.8 b/docs/manpages/vfs_full_audit.8
index 4ea3f03..551e3f9 100644
--- a/docs/manpages/vfs_full_audit.8
+++ b/docs/manpages/vfs_full_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_full_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FULL_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FULL_AUDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_glusterfs.8 b/docs/manpages/vfs_glusterfs.8
index e70933f..ce9f0bb 100644
--- a/docs/manpages/vfs_glusterfs.8
+++ b/docs/manpages/vfs_glusterfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_glusterfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_GLUSTERFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GLUSTERFS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_gpfs.8 b/docs/manpages/vfs_gpfs.8
index a5b158e..1d3d9d6 100644
--- a/docs/manpages/vfs_gpfs.8
+++ b/docs/manpages/vfs_gpfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_gpfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_GPFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GPFS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_linux_xfs_sgid.8 b/docs/manpages/vfs_linux_xfs_sgid.8
index 0acaee5..fc734ca 100644
--- a/docs/manpages/vfs_linux_xfs_sgid.8
+++ b/docs/manpages/vfs_linux_xfs_sgid.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_media_harmony.8 b/docs/manpages/vfs_media_harmony.8
index eefadb3..99afb02 100644
--- a/docs/manpages/vfs_media_harmony.8
+++ b/docs/manpages/vfs_media_harmony.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_media_harmony
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_MEDIA_HARMONY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_MEDIA_HARMONY" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_netatalk.8 b/docs/manpages/vfs_netatalk.8
index 6cbe456..66948c4 100644
--- a/docs/manpages/vfs_netatalk.8
+++ b/docs/manpages/vfs_netatalk.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_netatalk
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_NETATALK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_NETATALK" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_prealloc.8 b/docs/manpages/vfs_prealloc.8
index 242a7e4..36d4ce4 100644
--- a/docs/manpages/vfs_prealloc.8
+++ b/docs/manpages/vfs_prealloc.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_prealloc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_PREALLOC" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREALLOC" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_preopen.8 b/docs/manpages/vfs_preopen.8
index db8e404..6abc238 100644
--- a/docs/manpages/vfs_preopen.8
+++ b/docs/manpages/vfs_preopen.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_preopen
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_PREOPEN" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREOPEN" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readahead.8 b/docs/manpages/vfs_readahead.8
index 6c9fec5..06d715f 100644
--- a/docs/manpages/vfs_readahead.8
+++ b/docs/manpages/vfs_readahead.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readahead
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_READAHEAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READAHEAD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readonly.8 b/docs/manpages/vfs_readonly.8
index c335680..3382be4 100644
--- a/docs/manpages/vfs_readonly.8
+++ b/docs/manpages/vfs_readonly.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readonly
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_READONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READONLY" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_recycle.8 b/docs/manpages/vfs_recycle.8
index d8e1ae8..3dc4f69 100644
--- a/docs/manpages/vfs_recycle.8
+++ b/docs/manpages/vfs_recycle.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_recycle
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_RECYCLE" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_RECYCLE" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_scannedonly.8 b/docs/manpages/vfs_scannedonly.8
index a5d9d5d..50f723b 100644
--- a/docs/manpages/vfs_scannedonly.8
+++ b/docs/manpages/vfs_scannedonly.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_scannedonly
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SCANNEDONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SCANNEDONLY" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy.8 b/docs/manpages/vfs_shadow_copy.8
index deff1c2..84dca07 100644
--- a/docs/manpages/vfs_shadow_copy.8
+++ b/docs/manpages/vfs_shadow_copy.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shadow_copy
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy2.8 b/docs/manpages/vfs_shadow_copy2.8
index f4da715..63db272 100644
--- a/docs/manpages/vfs_shadow_copy2.8
+++ b/docs/manpages/vfs_shadow_copy2.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shadow_copy2
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY2" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shell_snap.8 b/docs/manpages/vfs_shell_snap.8
index dba4e3f..bc54846 100644
--- a/docs/manpages/vfs_shell_snap.8
+++ b/docs/manpages/vfs_shell_snap.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shell_snap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHELL_SNAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHELL_SNAP" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_smb_traffic_analyzer.8 b/docs/manpages/vfs_smb_traffic_analyzer.8
index b506a22..b571c17 100644
--- a/docs/manpages/vfs_smb_traffic_analyzer.8
+++ b/docs/manpages/vfs_smb_traffic_analyzer.8
@@ -2,12 +2,12 @@
 .\"     Title: smb_traffic_analyzer
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMB_TRAFFIC_ANALYZER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "SMB_TRAFFIC_ANALYZER" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_snapper.8 b/docs/manpages/vfs_snapper.8
index 401a35b..634b7a0 100644
--- a/docs/manpages/vfs_snapper.8
+++ b/docs/manpages/vfs_snapper.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_snapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SNAPPER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SNAPPER" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_depot.8 b/docs/manpages/vfs_streams_depot.8
index 30238e2..eb1d58a 100644
--- a/docs/manpages/vfs_streams_depot.8
+++ b/docs/manpages/vfs_streams_depot.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_streams_depot
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_DEPOT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_DEPOT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_xattr.8 b/docs/manpages/vfs_streams_xattr.8
index 609d39e..13fb29e 100644
--- a/docs/manpages/vfs_streams_xattr.8
+++ b/docs/manpages/vfs_streams_xattr.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_streams_xattr
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_XATTR" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_syncops.8 b/docs/manpages/vfs_syncops.8
index a36ff94..d5b247e 100644
--- a/docs/manpages/vfs_syncops.8
+++ b/docs/manpages/vfs_syncops.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_time_audit.8 b/docs/manpages/vfs_time_audit.8
index 6e422fd..d4bf70b 100644
--- a/docs/manpages/vfs_time_audit.8
+++ b/docs/manpages/vfs_time_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_time_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_TIME_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TIME_AUDIT" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_tsmsm.8 b/docs/manpages/vfs_tsmsm.8
index 973455e..2266db3 100644
--- a/docs/manpages/vfs_tsmsm.8
+++ b/docs/manpages/vfs_tsmsm.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_tsmsm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_TSMSM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TSMSM" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_unityed_media.8 b/docs/manpages/vfs_unityed_media.8
index a4263ee..aebfd0c 100644
--- a/docs/manpages/vfs_unityed_media.8
+++ b/docs/manpages/vfs_unityed_media.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_unityed_media
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_UNITYED_MEDIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_UNITYED_MEDIA" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_worm.8 b/docs/manpages/vfs_worm.8
index 9272ca4..b0cc6c3 100644
--- a/docs/manpages/vfs_worm.8
+++ b/docs/manpages/vfs_worm.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_worm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_WORM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_WORM" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_xattr_tdb.8 b/docs/manpages/vfs_xattr_tdb.8
index ab5624a..e82ab90 100644
--- a/docs/manpages/vfs_xattr_tdb.8
+++ b/docs/manpages/vfs_xattr_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_xattr_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_XATTR_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_XATTR_TDB" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_zfsacl.8 b/docs/manpages/vfs_zfsacl.8
index 49761b9..f29148a 100644
--- a/docs/manpages/vfs_zfsacl.8
+++ b/docs/manpages/vfs_zfsacl.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_zfsacl
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ZFSACL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ZFSACL" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfstest.1 b/docs/manpages/vfstest.1
index aa5f3d5..cb1e1d2 100644
--- a/docs/manpages/vfstest.1
+++ b/docs/manpages/vfstest.1
@@ -2,12 +2,12 @@
 .\"     Title: vfstest
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFSTEST" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "VFSTEST" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/wbinfo.1 b/docs/manpages/wbinfo.1
index b50f729..c9c5556 100644
--- a/docs/manpages/wbinfo.1
+++ b/docs/manpages/wbinfo.1
@@ -2,12 +2,12 @@
 .\"     Title: wbinfo
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WBINFO" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
+.TH "WBINFO" "1" "03/30/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbind_krb5_locator.7 b/docs/manpages/winbind_krb5_locator.7
index b9a7ed6..6b2b36e 100644
--- a/docs/manpages/winbind_krb5_locator.7
+++ b/docs/manpages/winbind_krb5_locator.7
@@ -2,12 +2,12 @@
 .\"     Title: winbind_krb5_locator
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: 7
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WINBIND_KRB5_LOCATOR" "7" "02/24/2016" "Samba 4\&.3" "7"
+.TH "WINBIND_KRB5_LOCATOR" "7" "03/30/2016" "Samba 4\&.3" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbindd.8 b/docs/manpages/winbindd.8
index 8f30460..a78de6e 100644
--- a/docs/manpages/winbindd.8
+++ b/docs/manpages/winbindd.8
@@ -2,12 +2,12 @@
 .\"     Title: winbindd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 02/24/2016
+.\"      Date: 03/30/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WINBINDD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
+.TH "WINBINDD" "8" "03/30/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 7b75f13..dac0f00 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2514,6 +2514,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "server max protocol", "SMB3");
 	lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE");
 	lpcfg_do_global_parameter(lp_ctx, "client max protocol", "default");
+	lpcfg_do_global_parameter(lp_ctx, "client ipc min protocol", "default");
+	lpcfg_do_global_parameter(lp_ctx, "client ipc max protocol", "default");
 	lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
 	lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
 	lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
@@ -2529,8 +2531,11 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
 	lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
 	lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True");
+	lpcfg_do_global_parameter(lp_ctx, "RawNTLMv2Auth", "False");
 	lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
 
+	lpcfg_do_global_parameter(lp_ctx, "allow dcerpc auth level connect", "False");
+
 	lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "True");
 
 	lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
@@ -2553,6 +2558,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%D/%U");
 
 	lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
+	lpcfg_do_global_parameter(lp_ctx, "client ipc signing", "default");
 	lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
 
 	lpcfg_do_global_parameter(lp_ctx, "use spnego", "True");
@@ -2573,6 +2579,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "21600");
 
 	lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
+	lpcfg_do_global_parameter(lp_ctx, "tls verify peer", "as_strict_as_possible");
 	lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
 	lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
 	lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
@@ -2709,6 +2716,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 
 	lpcfg_do_global_parameter(lp_ctx, "client ldap sasl wrapping", "sign");
 
+	lpcfg_do_global_parameter(lp_ctx, "ldap server require strong auth", "yes");
+
 	lpcfg_do_global_parameter(lp_ctx, "follow symlinks", "yes");
 
 	lpcfg_do_global_parameter(lp_ctx, "machine password timeout", "604800");
@@ -3212,6 +3221,39 @@ int lpcfg_client_max_protocol(struct loadparm_context *lp_ctx)
 	return client_max_protocol;
 }
 
+int lpcfg_client_ipc_min_protocol(struct loadparm_context *lp_ctx)
+{
+	int client_ipc_min_protocol = lpcfg__client_ipc_min_protocol(lp_ctx);
+	if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
+		client_ipc_min_protocol = lpcfg_client_min_protocol(lp_ctx);
+	}
+	if (client_ipc_min_protocol < PROTOCOL_NT1) {
+		return PROTOCOL_NT1;
+	}
+	return client_ipc_min_protocol;
+}
+
+int lpcfg_client_ipc_max_protocol(struct loadparm_context *lp_ctx)
+{
+	int client_ipc_max_protocol = lpcfg__client_ipc_max_protocol(lp_ctx);
+	if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
+		return PROTOCOL_LATEST;
+	}
+	if (client_ipc_max_protocol < PROTOCOL_NT1) {
+		return PROTOCOL_NT1;
+	}
+	return client_ipc_max_protocol;
+}
+
+int lpcfg_client_ipc_signing(struct loadparm_context *lp_ctx)
+{
+	int client_ipc_signing = lpcfg__client_ipc_signing(lp_ctx);
+	if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
+		return SMB_SIGNING_REQUIRED;
+	}
+	return client_ipc_signing;
+}
+
 bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandatory)
 {
 	bool allowed = true;
@@ -3246,10 +3288,13 @@ bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandato
 	case SMB_SIGNING_DESIRED:
 	case SMB_SIGNING_IF_REQUIRED:
 		break;
-	case SMB_SIGNING_DEFAULT:
 	case SMB_SIGNING_OFF:
 		allowed = false;
 		break;
+	case SMB_SIGNING_DEFAULT:
+	case SMB_SIGNING_IPC_DEFAULT:
+		smb_panic(__location__);
+		break;
 	}
 
 	return allowed;
diff --git a/lib/param/loadparm.h b/lib/param/loadparm.h
index c762259..cc6f13d 100644
--- a/lib/param/loadparm.h
+++ b/lib/param/loadparm.h
@@ -193,6 +193,12 @@ enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,
 #define ADS_AUTH_SASL_FORCE       0x0080
 #define ADS_AUTH_USER_CREDS       0x0100
 
+enum ldap_server_require_strong_auth {
+	LDAP_SERVER_REQUIRE_STRONG_AUTH_NO,
+	LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS,
+	LDAP_SERVER_REQUIRE_STRONG_AUTH_YES,
+};
+
 /* DNS update settings */
 enum dns_update_settings {DNS_UPDATE_OFF, DNS_UPDATE_ON, DNS_UPDATE_SIGNED};
 
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 3a0247c..5f699cf 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -32,6 +32,7 @@
 #include "lib/param/loadparm.h"
 #include "lib/param/param_global.h"
 #include "libcli/smb/smb_constants.h"
+#include "source4/lib/tls/tls.h"
 
 #ifndef N_
 #define N_(x) x
@@ -124,6 +125,20 @@ static const struct enum_list enum_smb_signing_vals[] = {
 	{-1, NULL}
 };
 
+static const struct enum_list enum_tls_verify_peer_vals[] = {
+	{TLS_VERIFY_PEER_NO_CHECK,
+	 TLS_VERIFY_PEER_NO_CHECK_STRING},
+	{TLS_VERIFY_PEER_CA_ONLY,
+	 TLS_VERIFY_PEER_CA_ONLY_STRING},
+	{TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE,
+	 TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING},
+	{TLS_VERIFY_PEER_CA_AND_NAME,
+	 TLS_VERIFY_PEER_CA_AND_NAME_STRING},
+	{TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE,
+	 TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING},
+	{-1, NULL}
+};
+
 /* DNS update options. */
 static const struct enum_list enum_dns_update_settings[] = {
 	{DNS_UPDATE_OFF, "disabled"},
@@ -222,6 +237,18 @@ static const struct enum_list enum_ldap_sasl_wrapping[] = {
 	{-1, NULL}
 };
 
+static const struct enum_list enum_ldap_server_require_strong_auth_vals[] = {
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_NO, "No" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_NO, "False" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_NO, "0" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS,
+	  "allow_sasl_over_tls" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "Yes" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "True" },
+	{ LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "1" },
+	{-1, NULL}
+};
+
 static const struct enum_list enum_ldap_ssl[] = {
 	{LDAP_SSL_OFF, "no"},
 	{LDAP_SSL_OFF, "off"},
@@ -676,6 +703,14 @@ struct parm_struct parm_table[] = {
 		.enum_list	= NULL,
 	},
 	{
+		.label		= "raw NTLMv2 auth",
+		.type		= P_BOOL,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(raw_ntlmv2_auth),
+		.special	= NULL,
+		.enum_list	= NULL,
+	},
+	{
 		.label		= "client NTLMv2 auth",
 		.type		= P_BOOL,
 		.p_class	= P_GLOBAL,
@@ -1544,6 +1579,14 @@ struct parm_struct parm_table[] = {
 		.enum_list	= enum_ldap_sasl_wrapping,
 	},
 	{
+		.label		= "ldap server require strong auth",
+		.type		= P_ENUM,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(ldap_server_require_strong_auth),
+		.special	= NULL,
+		.enum_list	= enum_ldap_server_require_strong_auth_vals
+	},
+	{
 		.label		= "enable asu support",
 		.type		= P_BOOL,
 		.p_class	= P_GLOBAL,
@@ -4005,6 +4048,46 @@ struct parm_struct parm_table[] = {
 		.special	= NULL,
 		.enum_list	= NULL
 	},
+	{
+		.label		= "tls verify peer",
+		.type		= P_ENUM,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(tls_verify_peer),
+		.special	= NULL,
+		.enum_list	= enum_tls_verify_peer_vals,
+	},
+	{
+		.label		= "client ipc max protocol",
+		.type		= P_ENUM,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(_client_ipc_max_protocol),
+		.special	= NULL,
+		.enum_list	= enum_protocol,
+	},
+	{
+		.label		= "client ipc min protocol",
+		.type		= P_ENUM,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(_client_ipc_min_protocol),
+		.special	= NULL,
+		.enum_list	= enum_protocol,
+	},
+	{
+		.label		= "client ipc signing",
+		.type		= P_ENUM,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(_client_ipc_signing),
+		.special	= NULL,
+		.enum_list	= enum_smb_signing_vals,
+	},
+	{
+		.label		= "allow dcerpc auth level connect",
+		.type		= P_BOOL,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(allow_dcerpc_auth_level_connect),
+		.special	= NULL,
+		.enum_list	= NULL
+	},
 
 	{NULL,  P_BOOL,  P_NONE,  0,  NULL,  NULL,  0}
 };
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
index 9f4924c..fed6590 100644
--- a/lib/util/asn1.c
+++ b/lib/util/asn1.c
@@ -20,6 +20,21 @@
 #include "includes.h"
 #include "../lib/util/asn1.h"
 
+struct nesting {
+	off_t start;
+	size_t taglen; /* for parsing */
+	struct nesting *next;
+};
+
+
+struct asn1_data {
+	uint8_t *data;
+	size_t length;
+	off_t ofs;
+	struct nesting *nesting;
+	bool has_error;
+};
+
 /* allocate an asn1 structure */
 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx)
 {
@@ -36,10 +51,36 @@ void asn1_free(struct asn1_data *data)
 	talloc_free(data);
 }
 
+bool asn1_has_error(const struct asn1_data *data)
+{
+	return data->has_error;
+}
+
+void asn1_set_error(struct asn1_data *data)
+{
+	data->has_error = true;
+}
+
+bool asn1_has_nesting(const struct asn1_data *data)
+{
+	return data->nesting != NULL;
+}
+
+off_t asn1_current_ofs(const struct asn1_data *data)
+{
+	return data->ofs;
+}
+
 /* write to the ASN1 buffer, advancing the buffer pointer */
 bool asn1_write(struct asn1_data *data, const void *p, int len)
 {
 	if (data->has_error) return false;
+
+	if ((len < 0) || (data->ofs + (size_t)len < data->ofs)) {
+		data->has_error = true;
+		return false;
+	}
+
 	if (data->length < data->ofs+len) {
 		uint8_t *newp;
 		newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);
@@ -66,7 +107,9 @@ bool asn1_push_tag(struct asn1_data *data, uint8_t tag)
 {
 	struct nesting *nesting;
 
-	asn1_write_uint8(data, tag);
+	if (!asn1_write_uint8(data, tag)) {
+		return false;
+	}
 	nesting = talloc(data, struct nesting);
 	if (!nesting) {
 		data->has_error = true;
@@ -85,6 +128,10 @@ bool asn1_pop_tag(struct asn1_data *data)
 	struct nesting *nesting;
 	size_t len;
 
+	if (data->has_error) {
+		return false;
+	}
+
 	nesting = data->nesting;
 
 	if (!nesting) {
@@ -184,6 +231,10 @@ static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool nega
 
 bool asn1_write_implicit_Integer(struct asn1_data *data, int i)
 {
+	if (data->has_error) {
+		return false;
+	}
+
 	if (i == -1) {
 		/* -1 is special as it consists of all-0xff bytes. In
                     push_int_bigendian this is the only case that is not
@@ -986,6 +1037,26 @@ bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob)
 	return true;
 }
 
+bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
+		       DATA_BLOB *pblob)
+{
+	DATA_BLOB blob;
+
+	if (!asn1_blob(asn1, &blob)) {
+		return false;
+	}
+
+	*pblob = (DATA_BLOB) { .length = blob.length };
+	pblob->data = talloc_move(mem_ctx, &blob.data);
+
+	/*
+	 * Stop access from here on
+	 */
+	asn1->has_error = true;
+
+	return true;
+}
+
 /*
   Fill in an asn1 struct without making a copy
 */
@@ -996,35 +1067,7 @@ void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len)
 	data->length = len;
 }
 
-/*
-  check if a ASN.1 blob is a full tag
-*/
-NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
-{
-	struct asn1_data *asn1 = asn1_init(NULL);
-	int size;
-
-	NT_STATUS_HAVE_NO_MEMORY(asn1);
-
-	asn1->data = blob.data;
-	asn1->length = blob.length;
-	if (!asn1_start_tag(asn1, tag)) {
-		talloc_free(asn1);
-		return STATUS_MORE_ENTRIES;
-	}
-	size = asn1_tag_remaining(asn1) + asn1->ofs;
-
-	talloc_free(asn1);
-
-	if (size > blob.length) {
-		return STATUS_MORE_ENTRIES;
-	}
-
-	*packet_size = size;
-	return NT_STATUS_OK;
-}
-
-NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
+int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
 {
 	struct asn1_data asn1;
 	size_t size;
@@ -1036,14 +1079,14 @@ NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size)
 
 	ok = asn1_peek_tag_needed_size(&asn1, tag, &size);
 	if (!ok) {
-		return NT_STATUS_INVALID_BUFFER_SIZE;
+		return EMSGSIZE;
 	}
 
 	if (size > blob.length) {
 		*packet_size = size;
-		return STATUS_MORE_ENTRIES;
+		return EAGAIN;
 	}		
 
 	*packet_size = size;
-	return NT_STATUS_OK;
+	return 0;
 }
diff --git a/lib/util/asn1.h b/lib/util/asn1.h
index 568b4e4..4eb8506 100644
--- a/lib/util/asn1.h
+++ b/lib/util/asn1.h
@@ -20,20 +20,8 @@
 #ifndef _ASN_1_H
 #define _ASN_1_H
 
-struct nesting {
-	off_t start;
-	size_t taglen; /* for parsing */
-	struct nesting *next;
-};
-
-struct asn1_data {
-	uint8_t *data;
-	size_t length;
-	off_t ofs;
-	struct nesting *nesting;
-	bool has_error;
-};
-
+struct nesting;
+struct asn1_data;
 typedef struct asn1_data ASN1_DATA;
 
 #define ASN1_APPLICATION(x) ((x)+0x60)
@@ -54,6 +42,10 @@ typedef struct asn1_data ASN1_DATA;
 
 struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx);
 void asn1_free(struct asn1_data *data);
+bool asn1_has_error(const struct asn1_data *data);
+void asn1_set_error(struct asn1_data *data);
+bool asn1_has_nesting(const struct asn1_data *data);
+off_t asn1_current_ofs(const struct asn1_data *data);
 bool asn1_write(struct asn1_data *data, const void *p, int len);
 bool asn1_write_uint8(struct asn1_data *data, uint8_t v);
 bool asn1_push_tag(struct asn1_data *data, uint8_t tag);
@@ -99,8 +91,9 @@ bool asn1_read_enumerated(struct asn1_data *data, int *v);
 bool asn1_check_enumerated(struct asn1_data *data, int v);
 bool asn1_write_enumerated(struct asn1_data *data, uint8_t v);
 bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob);
+bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
+		       DATA_BLOB *pblob);
 void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len);
-NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
-NTSTATUS asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
+int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size);
 
 #endif /* _ASN_1_H */
diff --git a/lib/util/tests/asn1_tests.c b/lib/util/tests/asn1_tests.c
index 6dd7c64..e4b386a 100644
--- a/lib/util/tests/asn1_tests.c
+++ b/lib/util/tests/asn1_tests.c
@@ -337,8 +337,10 @@ static bool test_asn1_Integer(struct torture_context *tctx)
 
 		if (!asn1_write_Integer(data, integer_tests[i].value)) goto err;
 
-		blob.data = data->data;
-		blob.length = data->length;
+		if (!asn1_blob(data, &blob)) {
+			goto err;
+		}
+
 		torture_assert_data_blob_equal(tctx, blob, integer_tests[i].blob, "asn1_write_Integer gave incorrect result");
 
 		if (!asn1_load(data, blob)) goto err;
diff --git a/lib/util/util_net.c b/lib/util/util_net.c
index d58855d..e5b33aa 100644
--- a/lib/util/util_net.c
+++ b/lib/util/util_net.c
@@ -41,6 +41,115 @@ void zero_sockaddr(struct sockaddr_storage *pss)
 	pss->ss_family = AF_INET;
 }
 
+static char *normalize_ipv6_literal(const char *str, char *buf, size_t *_len)
+{
+#define IPv6_LITERAL_NET ".ipv6-literal.net"
+	static const size_t llen = sizeof(IPv6_LITERAL_NET) - 1;
+	size_t len = *_len;
+	int cmp;
+	size_t i;
+	size_t idx_chars = 0;
+	size_t cnt_delimiter = 0;
+	size_t cnt_chars = 0;
+
+	if (len <= llen) {
+		return false;
+	}
+
+	/* ignore a trailing '.' */
+	if (str[len - 1] == '.') {
+		len -= 1;
+	}
+
+	len -= llen;
+	if (len >= INET6_ADDRSTRLEN) {
+		return NULL;
+	}
+	if (len < 2) {
+		return NULL;
+	}
+
+	cmp = strncasecmp(&str[len], IPv6_LITERAL_NET, llen);
+	if (cmp != 0) {
+		return NULL;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (idx_chars != 0) {
+			break;
+		}
+
+		switch (str[i]) {
+		case '-':
+			buf[i] = ':';
+			cnt_chars = 0;
+			cnt_delimiter += 1;
+			break;
+		case 's':
+			buf[i] = '%';
+			idx_chars += 1;
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case 'a':
+		case 'A':
+		case 'b':
+		case 'B':
+		case 'c':
+		case 'C':
+		case 'd':
+		case 'D':
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'F':
+			buf[i] = str[i];
+			cnt_chars += 1;
+			break;
+		default:
+			return NULL;
+		}
+		if (cnt_chars > 4) {
+			return NULL;
+		}
+		if (cnt_delimiter > 7) {
+			return NULL;
+		}
+	}
+
+	if (cnt_delimiter < 2) {
+		return NULL;
+	}
+
+	for (; idx_chars != 0 && i < len; i++) {
+		switch (str[i]) {
+		case '%':
+		case ':':
+			return NULL;
+		default:
+			buf[i] = str[i];
+			idx_chars += 1;
+			break;
+		}
+	}
+
+	if (idx_chars == 1) {
+		return NULL;
+	}
+
+	buf[i] = '\0';
+	*_len = len;
+	return buf;
+}
+
 /**
  * Wrap getaddrinfo...
  */
@@ -49,6 +158,11 @@ bool interpret_string_addr_internal(struct addrinfo **ppres,
 {
 	int ret;
 	struct addrinfo hints;
+#if defined(HAVE_IPV6)
+	char addr[INET6_ADDRSTRLEN*2] = { 0, };
+	unsigned int scope_id = 0;
+	size_t len = strlen(str);
+#endif
 
 	ZERO_STRUCT(hints);
 
@@ -58,8 +172,72 @@ bool interpret_string_addr_internal(struct addrinfo **ppres,
 	/* always try as a numeric host first. This prevents unnecessary name
 	 * lookups, and also ensures we accept IPv6 addresses */
 	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+
+#if defined(HAVE_IPV6)
+	if (len < sizeof(addr)) {
+		char *p = NULL;
+
+		p = normalize_ipv6_literal(str, addr, &len);
+		if (p != NULL) {
+			hints.ai_family = AF_INET6;
+			str = p;
+		}
+	}
+
+	if (strchr_m(str, ':')) {
+		char *p = strchr_m(str, '%');
+
+		/*
+		 * Cope with link-local.
+		 * This is IP:v6:addr%ifname.
+		 */
+
+		if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
+			/* Length of string we want to copy.
+			   This is IP:v6:addr (removing the %ifname).
+			 */
+			len = PTR_DIFF(p,str);
+
+			if (len+1 > sizeof(addr)) {
+				/* string+nul too long for array. */
+				return false;
+			}
+			if (str != addr) {
+				memcpy(addr, str, len);
+			}
+			addr[len] = '\0';
+
+			str = addr;
+		}
+	}
+#endif
+
 	ret = getaddrinfo(str, NULL, &hints, ppres);
 	if (ret == 0) {
+#if defined(HAVE_IPV6)
+		struct sockaddr_in6 *ps6 = NULL;
+
+		if (scope_id == 0) {
+			return true;
+		}
+		if (ppres == NULL) {
+			return true;
+		}
+		if ((*ppres) == NULL) {
+			return true;
+		}
+		if ((*ppres)->ai_addr->sa_family != AF_INET6) {
+			return true;
+		}
+
+		ps6 = (struct sockaddr_in6 *)(*ppres)->ai_addr;
+
+		if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
+				ps6->sin6_scope_id == 0) {
+			ps6->sin6_scope_id = scope_id;
+		}
+#endif
+
 		return true;
 	}
 
@@ -94,35 +272,6 @@ static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
 {
 	struct addrinfo *res = NULL;
 	int int_flags;
-#if defined(HAVE_IPV6)
-	char addr[INET6_ADDRSTRLEN];
-	unsigned int scope_id = 0;
-
-	if (strchr_m(str, ':')) {
-		char *p = strchr_m(str, '%');
-
-		/*
-		 * Cope with link-local.
-		 * This is IP:v6:addr%ifname.
-		 */
-
-		if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
-			/* Length of string we want to copy.
-			   This is IP:v6:addr (removing the %ifname).
-			 */
-			size_t len = PTR_DIFF(p,str);
-
-			if (len+1 > sizeof(addr)) {
-				/* string+nul too long for array. */
-				return false;
-			}
-			memcpy(addr, str, len);
-			addr[len] = '\0';
-
-			str = addr;
-		}
-	}
-#endif
 
 	zero_sockaddr(pss);
 
@@ -157,16 +306,6 @@ static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
 		memcpy(pss, res->ai_addr, res->ai_addrlen);
 	}
 
-#if defined(HAVE_IPV6)
-	if (pss->ss_family == AF_INET6 && scope_id) {
-		struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss;
-		if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
-				ps6->sin6_scope_id == 0) {
-			ps6->sin6_scope_id = scope_id;
-		}
-	}
-#endif
-
 	freeaddrinfo(res);
 	return true;
 }
@@ -320,6 +459,28 @@ bool is_ipaddress_v4(const char *str)
 	return false;
 }
 
+bool is_ipv6_literal(const char *str)
+{
+#if defined(HAVE_IPV6)
+	char buf[INET6_ADDRSTRLEN*2] = { 0, };
+	size_t len = strlen(str);
+	char *p = NULL;
+
+	if (len >= sizeof(buf)) {
+		return false;
+	}
+
+	p = normalize_ipv6_literal(str, buf, &len);
+	if (p == NULL) {
+		return false;
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
 /**
  * Return true if a string could be a IPv6 address.
  */
@@ -328,16 +489,20 @@ bool is_ipaddress_v6(const char *str)
 {
 #if defined(HAVE_IPV6)
 	int ret = -1;
+	char *p = NULL;
 
-	if (strchr_m(str, ':')) {
+	p = strchr_m(str, ':');
+	if (p == NULL) {
+		return is_ipv6_literal(str);
+	} else {
 		char buf[INET6_ADDRSTRLEN] = { 0, };
 		size_t len;
 		const char *addr = str;
 		const char *idxs = NULL;
 		unsigned int idx = 0;
 		struct in6_addr ip6;
-		char *p = strchr_m(str, '%');
 
+		p = strchr_m(str, '%');
 		if (p && (p > str)) {
 			len = PTR_DIFF(p, str);
 			idxs = p + 1;
diff --git a/lib/util/util_net.h b/lib/util/util_net.h
index 2f1beff..29468b4 100644
--- a/lib/util/util_net.h
+++ b/lib/util/util_net.h
@@ -86,6 +86,7 @@ _PUBLIC_ uint32_t interpret_addr(const char *str);
 _PUBLIC_ struct in_addr interpret_addr2(const char *str);
 
 _PUBLIC_ bool is_ipaddress_v4(const char *str);
+_PUBLIC_ bool is_ipv6_literal(const char *str);
 _PUBLIC_ bool is_ipaddress_v6(const char *str);
 
 bool is_address_any(const struct sockaddr *psa);
diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h
index c58a23f..cc9ae33 100644
--- a/libcli/auth/proto.h
+++ b/libcli/auth/proto.h
@@ -144,6 +144,7 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
 bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx, 
 			   const char *user, const char *domain, const uint8_t nt_hash[16],
 			   const DATA_BLOB *server_chal, 
+			   const NTTIME *server_timestamp,
 			   const DATA_BLOB *names_blob,
 			   DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
 			   DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) ;
@@ -154,6 +155,11 @@ bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
 		      const DATA_BLOB *names_blob,
 		      DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
 		      DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) ;
+NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds(const char *account_name,
+			const char *account_domain,
+			const DATA_BLOB response,
+			const struct netlogon_creds_CredentialState *creds,
+			const char *workgroup);
 
 /***********************************************************
  encode a password buffer with a unicode password.  The buffer
diff --git a/libcli/auth/smbencrypt.c b/libcli/auth/smbencrypt.c
index e9eaadf..ebf6812 100644
--- a/libcli/auth/smbencrypt.c
+++ b/libcli/auth/smbencrypt.c
@@ -26,7 +26,7 @@
 #include "../libcli/auth/msrpc_parse.h"
 #include "../lib/crypto/crypto.h"
 #include "../libcli/auth/libcli_auth.h"
-#include "../librpc/gen_ndr/ntlmssp.h"
+#include "../librpc/gen_ndr/ndr_ntlmssp.h"
 
 void SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24])
 {
@@ -387,14 +387,13 @@ DATA_BLOB NTLMv2_generate_names_blob(TALLOC_CTX *mem_ctx,
 	return names_blob;
 }
 
-static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob)
+static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx,
+					     NTTIME nttime,
+					     const DATA_BLOB *names_blob)
 {
 	uint8_t client_chal[8];
 	DATA_BLOB response = data_blob(NULL, 0);
 	uint8_t long_date[8];
-	NTTIME nttime;
-
-	unix_to_nt_time(&nttime, time(NULL));
 
 	generate_random_buffer(client_chal, sizeof(client_chal));
 
@@ -417,6 +416,7 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO
 static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
 					  const uint8_t ntlm_v2_hash[16],
 					  const DATA_BLOB *server_chal,
+					  NTTIME nttime,
 					  const DATA_BLOB *names_blob)
 {
 	uint8_t ntlmv2_response[16];
@@ -433,7 +433,7 @@ static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
 	/* NTLMv2 */
 	/* generate some data to pass into the response function - including
 	   the hostname and domain name of the server */
-	ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, names_blob);
+	ntlmv2_client_data = NTLMv2_generate_client_data(mem_ctx, nttime, names_blob);
 
 	/* Given that data, and the challenge from the server, generate a response */
 	SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response);
@@ -479,6 +479,7 @@ static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx,
 bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
 			   const char *user, const char *domain, const uint8_t nt_hash[16],
 			   const DATA_BLOB *server_chal,
+			   const NTTIME *server_timestamp,
 			   const DATA_BLOB *names_blob,
 			   DATA_BLOB *lm_response, DATA_BLOB *nt_response,
 			   DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key)
@@ -494,8 +495,19 @@ bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
 	}
 
 	if (nt_response) {
+		const NTTIME *nttime = server_timestamp;
+		NTTIME _now = 0;
+
+		if (nttime == NULL) {
+			struct timeval tv_now = timeval_current();
+			_now = timeval_to_nttime(&tv_now);
+			nttime = &_now;
+		}
+
 		*nt_response = NTLMv2_generate_response(mem_ctx,
-							ntlm_v2_hash, server_chal,
+							ntlm_v2_hash,
+							server_chal,
+							*nttime,
 							names_blob);
 		if (user_session_key) {
 			*user_session_key = data_blob_talloc(mem_ctx, NULL, 16);
@@ -509,8 +521,13 @@ bool SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
 	/* LMv2 */
 
 	if (lm_response) {
-		*lm_response = LMv2_generate_response(mem_ctx,
-						      ntlm_v2_hash, server_chal);
+		if (server_timestamp != NULL) {
+			*lm_response = data_blob_talloc_zero(mem_ctx, 24);
+		} else {
+			*lm_response = LMv2_generate_response(mem_ctx,
+							      ntlm_v2_hash,
+							      server_chal);
+		}
 		if (lm_session_key) {
 			*lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
 
@@ -535,10 +552,143 @@ bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
 	E_md4hash(password, nt_hash);
 
 	return SMBNTLMv2encrypt_hash(mem_ctx,
-				     user, domain, nt_hash, server_chal, names_blob,
+				     user, domain, nt_hash,
+				     server_chal, NULL, names_blob,
 				     lm_response, nt_response, lm_session_key, user_session_key);
 }
 
+NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds(const char *account_name,
+			const char *account_domain,
+			const DATA_BLOB response,
+			const struct netlogon_creds_CredentialState *creds,
+			const char *workgroup)
+{
+	TALLOC_CTX *frame = NULL;
+	/* RespType + HiRespType */
+	static const char *magic = "\x01\x01";
+	int cmp;
+	struct NTLMv2_RESPONSE v2_resp;
+	enum ndr_err_code err;
+	const struct AV_PAIR *av_nb_cn = NULL;
+	const struct AV_PAIR *av_nb_dn = NULL;
+
+	if (response.length < 48) {
+		/*
+		 * NTLMv2_RESPONSE has at least 48 bytes.
+		 */
+		return NT_STATUS_OK;
+	}
+
+	cmp = memcmp(response.data + 16, magic, 2);
+	if (cmp != 0) {
+		/*
+		 * It doesn't look like a valid NTLMv2_RESPONSE
+		 */
+		return NT_STATUS_OK;
+	}
+
+	frame = talloc_stackframe();
+
+	err = ndr_pull_struct_blob(&response, frame, &v2_resp,
+		(ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE);
+	if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+		NTSTATUS status;
+		status = ndr_map_error2ntstatus(err);
+		DEBUG(2,("Failed to parse NTLMv2_RESPONSE "
+			 "length %u - %s - %s\n",
+			 (unsigned)response.length,
+			 ndr_map_error2string(err),
+			 nt_errstr(status)));
+		dump_data(2, response.data, response.length);
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	if (DEBUGLVL(10)) {
+		NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &v2_resp);
+	}
+
+	/*
+	 * Make sure the netbios computer name in the
+	 * NTLMv2_RESPONSE matches the computer name
+	 * in the secure channel credentials for workstation
+	 * trusts.
+	 *
+	 * And the netbios domain name matches our
+	 * workgroup.
+	 *
+	 * This prevents workstations from requesting
+	 * the session key of NTLMSSP sessions of clients
+	 * to other hosts.
+	 */
+	if (creds->secure_channel_type == SEC_CHAN_WKSTA) {
+		av_nb_cn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+					       MsvAvNbComputerName);
+		av_nb_dn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+					       MsvAvNbDomainName);
+	}
+
+	if (av_nb_cn != NULL) {
+		const char *v = NULL;
+		char *a = NULL;
+		size_t len;
+
+		v = av_nb_cn->Value.AvNbComputerName;
+
+		a = talloc_strdup(frame, creds->account_name);
+		if (a == NULL) {
+			TALLOC_FREE(frame);
+			return NT_STATUS_NO_MEMORY;
+		}
+		len = strlen(a);
+		if (len > 0 && a[len - 1] == '$') {
+			a[len - 1] = '\0';
+		}
+
+		cmp = strcasecmp_m(a, v);
+		if (cmp != 0) {
+			DEBUG(2,("%s: NTLMv2_RESPONSE with "
+				 "NbComputerName[%s] rejected "
+				 "for user[%s\\%s] "
+				 "against SEC_CHAN_WKSTA[%s/%s] "
+				 "in workgroup[%s]\n",
+				 __func__, v,
+				 account_domain,
+				 account_name,
+				 creds->computer_name,
+				 creds->account_name,
+				 workgroup));
+			TALLOC_FREE(frame);
+			return NT_STATUS_LOGON_FAILURE;
+		}
+	}
+	if (av_nb_dn != NULL) {
+		const char *v = NULL;
+
+		v = av_nb_dn->Value.AvNbDomainName;
+
+		cmp = strcasecmp_m(workgroup, v);
+		if (cmp != 0) {
+			DEBUG(2,("%s: NTLMv2_RESPONSE with "
+				 "NbDomainName[%s] rejected "
+				 "for user[%s\\%s] "
+				 "against SEC_CHAN_WKSTA[%s/%s] "
+				 "in workgroup[%s]\n",
+				 __func__, v,
+				 account_domain,
+				 account_name,
+				 creds->computer_name,
+				 creds->account_name,
+				 workgroup));
+			TALLOC_FREE(frame);
+			return NT_STATUS_LOGON_FAILURE;
+		}
+	}
+
+	TALLOC_FREE(frame);
+	return NT_STATUS_OK;
+}
+
 /***********************************************************
  encode a password buffer with a unicode password.  The buffer
  is filled with random data to make it harder to attack.
diff --git a/libcli/auth/spnego.h b/libcli/auth/spnego.h
index 539b903..49645e0 100644
--- a/libcli/auth/spnego.h
+++ b/libcli/auth/spnego.h
@@ -45,7 +45,11 @@ enum spnego_negResult {
 	SPNEGO_ACCEPT_COMPLETED = 0,
 	SPNEGO_ACCEPT_INCOMPLETE = 1,
 	SPNEGO_REJECT = 2,
-	SPNEGO_NONE_RESULT = 3
+	SPNEGO_REQUEST_MIC = 3,
+	/*
+	 * The max value is 0xff (255) on the wire
+	 */
+	SPNEGO_NONE_RESULT = 256
 };
 
 struct spnego_negTokenInit {
@@ -58,7 +62,7 @@ struct spnego_negTokenInit {
 };
 
 struct spnego_negTokenTarg {
-	uint8_t negResult;
+	enum spnego_negResult negResult;
 	const char *supportedMech;
 	DATA_BLOB responseToken;
 	DATA_BLOB mechListMIC;
diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c
index d4c5bdc..1230376 100644
--- a/libcli/auth/spnego_parse.c
+++ b/libcli/auth/spnego_parse.c
@@ -32,12 +32,12 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 	if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
 	if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
-	while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
+	while (!asn1_has_error(asn1) && 0 < asn1_tag_remaining(asn1)) {
 		int i;
 		uint8_t context;
 
 		if (!asn1_peek_uint8(asn1, &context)) {
-			asn1->has_error = true;
+			asn1_set_error(asn1);
 			break;
 		}
 
@@ -51,10 +51,10 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 
 			mechTypes = talloc(mem_ctx, const char *);
 			if (mechTypes == NULL) {
-				asn1->has_error = true;
+				asn1_set_error(asn1);
 				return false;
 			}
-			for (i = 0; !asn1->has_error &&
+			for (i = 0; !asn1_has_error(asn1) &&
 				     0 < asn1_tag_remaining(asn1); i++) {
 				char *oid;
 				const char **p;
@@ -63,7 +63,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 						   const char *, i+2);
 				if (p == NULL) {
 					talloc_free(mechTypes);
-					asn1->has_error = true;
+					asn1_set_error(asn1);
 					return false;
 				}
 				mechTypes = p;
@@ -97,7 +97,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 			uint8_t type_peek;
 			if (!asn1_start_tag(asn1, ASN1_CONTEXT(3))) return false;
 			if (!asn1_peek_uint8(asn1, &type_peek)) {
-				asn1->has_error = true;
+				asn1_set_error(asn1);
 				break;
 			}
 			if (type_peek == ASN1_OCTET_STRING) {
@@ -119,7 +119,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 			break;
 		}
 		default:
-			asn1->has_error = true;
+			asn1_set_error(asn1);
 			break;
 		}
 	}
@@ -127,7 +127,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 	if (!asn1_end_tag(asn1)) return false;
 	if (!asn1_end_tag(asn1)) return false;
 
-	return !asn1->has_error;
+	return !asn1_has_error(asn1);
 }
 
 static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenInit *token)
@@ -190,7 +190,7 @@ static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenIni
 	if (!asn1_pop_tag(asn1)) return false;
 	if (!asn1_pop_tag(asn1)) return false;
 
-	return !asn1->has_error;
+	return !asn1_has_error(asn1);
 }
 
 static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
@@ -201,11 +201,13 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 	if (!asn1_start_tag(asn1, ASN1_CONTEXT(1))) return false;
 	if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
-	while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
+	while (!asn1_has_error(asn1) && 0 < asn1_tag_remaining(asn1)) {
 		uint8_t context;
+		uint8_t neg_result;
 		char *oid;
+
 		if (!asn1_peek_uint8(asn1, &context)) {
-			asn1->has_error = true;
+			asn1_set_error(asn1);
 			break;
 		}
 
@@ -213,7 +215,8 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 		case ASN1_CONTEXT(0):
 			if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
 			if (!asn1_start_tag(asn1, ASN1_ENUMERATED)) return false;
-			if (!asn1_read_uint8(asn1, &token->negResult)) return false;
+			if (!asn1_read_uint8(asn1, &neg_result)) return false;
+			token->negResult = neg_result;
 			if (!asn1_end_tag(asn1)) return false;
 			if (!asn1_end_tag(asn1)) return false;
 			break;
@@ -234,7 +237,7 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 			if (!asn1_end_tag(asn1)) return false;
 			break;
 		default:
-			asn1->has_error = true;
+			asn1_set_error(asn1);
 			break;
 		}
 	}
@@ -242,7 +245,7 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 	if (!asn1_end_tag(asn1)) return false;
 	if (!asn1_end_tag(asn1)) return false;
 
-	return !asn1->has_error;
+	return !asn1_has_error(asn1);
 }
 
 static bool write_negTokenTarg(struct asn1_data *asn1, struct spnego_negTokenTarg *token)
@@ -279,7 +282,7 @@ static bool write_negTokenTarg(struct asn1_data *asn1, struct spnego_negTokenTar
 	if (!asn1_pop_tag(asn1)) return false;
 	if (!asn1_pop_tag(asn1)) return false;
 
-	return !asn1->has_error;
+	return !asn1_has_error(asn1);
 }
 
 ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data *token)
@@ -302,7 +305,7 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
 	if (!asn1_load(asn1, data)) goto err;
 
 	if (!asn1_peek_uint8(asn1, &context)) {
-		asn1->has_error = true;
+		asn1_set_error(asn1);
 	} else {
 		switch (context) {
 		case ASN1_APPLICATION(0):
@@ -319,12 +322,14 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
 			}
 			break;
 		default:
-			asn1->has_error = true;
+			asn1_set_error(asn1);
 			break;
 		}
 	}
 
-	if (!asn1->has_error) ret = asn1->ofs;
+	if (!asn1_has_error(asn1)) {
+		ret = asn1_current_ofs(asn1);
+	}
 
   err:
 
@@ -353,15 +358,16 @@ ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_da
 		write_negTokenTarg(asn1, &spnego->negTokenTarg);
 		break;
 	default:
-		asn1->has_error = true;
+		asn1_set_error(asn1);
 		break;
 	}
 
-	if (!asn1->has_error) {
-		*blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
-		ret = asn1->ofs;
+	if (!asn1_extract_blob(asn1, mem_ctx, blob)) {
+		goto err;
 	}
 
+	ret = asn1_current_ofs(asn1);
+
   err:
 
 	asn1_free(asn1);
@@ -423,12 +429,11 @@ bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
 		if (!asn1_pop_tag(asn1)) goto err;
 	}
 
-	if (asn1->has_error) {
+	if (asn1_has_error(asn1)) {
 		goto err;
 	}
 
-	*blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
-	if (blob->length != asn1->length) {
+	if (!asn1_extract_blob(asn1, mem_ctx, blob)) {
 		goto err;
 	}
 
diff --git a/libcli/cldap/cldap.c b/libcli/cldap/cldap.c
index 964cb0a..dd9d40b 100644
--- a/libcli/cldap/cldap.c
+++ b/libcli/cldap/cldap.c
@@ -220,7 +220,6 @@ nomem:
 static bool cldap_socket_recv_dgram(struct cldap_socket *c,
 				    struct cldap_incoming *in)
 {
-	DATA_BLOB blob;
 	struct asn1_data *asn1;
 	void *p;
 	struct cldap_search_state *search;
@@ -230,16 +229,12 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c,
 		goto error;
 	}
 
-	blob = data_blob_const(in->buf, in->len);
-
 	asn1 = asn1_init(in);
 	if (!asn1) {
 		goto nomem;
 	}
 
-	if (!asn1_load(asn1, blob)) {
-		goto nomem;
-	}
+	asn1_load_nocopy(asn1, in->buf, in->len);
 
 	in->ldap_msg = talloc(in, struct ldap_message);
 	if (in->ldap_msg == NULL) {
@@ -267,8 +262,11 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c,
 
 	search = talloc_get_type_abort(p, struct cldap_search_state);
 	search->response.in = talloc_move(search, &in);
+
 	search->response.asn1 = asn1;
-	search->response.asn1->ofs = 0;
+
+	asn1_load_nocopy(search->response.asn1,
+			 search->response.in->buf, search->response.in->len);
 
 	DLIST_REMOVE(c->searches.list, search);
 
diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c
index 0c664b7..cb3d9b3 100644
--- a/libcli/ldap/ldap_message.c
+++ b/libcli/ldap/ldap_message.c
@@ -322,7 +322,7 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false;
 		if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false;
 		if (!asn1_pop_tag(data)) return false;
-		return !data->has_error;
+		return !asn1_has_error(data);
 
 	case LDB_OP_APPROX:
 		/* approx test */
@@ -366,7 +366,7 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 	default:
 		return false;
 	}
-	return !data->has_error;
+	return !asn1_has_error(data);
 }
 
 static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
@@ -691,7 +691,10 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
 
 	if (!asn1_pop_tag(data)) goto err;
 
-	*result = data_blob_talloc(mem_ctx, data->data, data->length);
+	if (!asn1_extract_blob(data, mem_ctx, result)) {
+		goto err;
+	}
+
 	asn1_free(data);
 
 	return true;
@@ -845,7 +848,8 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
 		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
 		if (!asn1_end_tag(data)) goto failed;
-		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
+		if (asn1_has_error(data) || (attrib == NULL) ||
+		    (value.data == NULL)) {
 			goto failed;
 		}
 
@@ -960,7 +964,8 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
 		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
 		if (!asn1_end_tag(data)) goto failed;
-		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
+		if (asn1_has_error(data) || (attrib == NULL) ||
+		    (value.data == NULL)) {
 			goto failed;
 		}
 
@@ -979,7 +984,8 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
 		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
 		if (!asn1_end_tag(data)) goto failed;
-		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
+		if (asn1_has_error(data) || (attrib == NULL) ||
+		    (value.data == NULL)) {
 			goto failed;
 		}
 
@@ -1017,7 +1023,8 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
 		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
 		if (!asn1_end_tag(data)) goto failed;
-		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
+		if (asn1_has_error(data) || (attrib == NULL) ||
+		    (value.data == NULL)) {
 			goto failed;
 		}
 
@@ -1618,7 +1625,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 	}
 
 	if (!asn1_end_tag(data)) goto prot_err;
-	if ((data->has_error) || (data->nesting != NULL)) {
+	if (asn1_has_error(data) || asn1_has_nesting(data)) {
 		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
 	}
 	return NT_STATUS_OK;
@@ -1635,6 +1642,8 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 */
 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
 {
+	int ret;
+
 	if (blob.length < 6) {
 		/*
 		 * We need at least 6 bytes to workout the length
@@ -1642,5 +1651,10 @@ NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_siz
 		 */
 		return STATUS_MORE_ENTRIES;
 	}
-	return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
+
+	ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
+	if (ret != 0) {
+		return map_nt_error_from_unix_common(ret);
+	}
+	return NT_STATUS_OK;
 }
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 505d40d..14b5992 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -382,6 +382,7 @@ struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
 		conn->desire_signing = true;
 		conn->mandatory_signing = false;
 		break;
+	case SMB_SIGNING_IPC_DEFAULT:
 	case SMB_SIGNING_REQUIRED:
 		/* always */
 		conn->allow_signing = true;
diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index c4cca15..04c9001 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -95,6 +95,7 @@ enum protocol_types {
 #define PROTOCOL_LATEST PROTOCOL_SMB3_11
 
 enum smb_signing_setting {
+	SMB_SIGNING_IPC_DEFAULT = -2, /* Only used in C code */
 	SMB_SIGNING_DEFAULT = -1,
 	SMB_SIGNING_OFF = 0,
 	SMB_SIGNING_IF_REQUIRED = 1,
diff --git a/libcli/smb/smb_signing.c b/libcli/smb/smb_signing.c
index e128e8f..a7bc819 100644
--- a/libcli/smb/smb_signing.c
+++ b/libcli/smb/smb_signing.c
@@ -424,6 +424,10 @@ bool smb_signing_set_negotiated(struct smb_signing_state *si,
 		return true;
 	}
 
+	if (mandatory) {
+		allowed = true;
+	}
+
 	if (!si->allowed && mandatory) {
 		return false;
 	}
diff --git a/libcli/smb/tstream_smbXcli_np.c b/libcli/smb/tstream_smbXcli_np.c
index 9cd6302..248bfb0 100644
--- a/libcli/smb/tstream_smbXcli_np.c
+++ b/libcli/smb/tstream_smbXcli_np.c
@@ -111,7 +111,11 @@ static int tstream_smbXcli_np_destructor(struct tstream_smbXcli_np *cli_nps)
 	 * Once we've fixed all callers to call
 	 * tstream_disconnect_send()/_recv(), this will
 	 * never be called.
+	 *
+	 * We use a maximun timeout of 1 second == 1000 msec.
 	 */
+	cli_nps->timeout = MIN(cli_nps->timeout, 1000);
+
 	if (cli_nps->is_smb1) {
 		status = smb1cli_close(cli_nps->conn,
 				       cli_nps->timeout,
diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl
index 1036693..015eb3d 100644
--- a/librpc/idl/dcerpc.idl
+++ b/librpc/idl/dcerpc.idl
@@ -197,18 +197,21 @@ interface dcerpc
 		DCERPC_NCA_S_FAULT_TX_OPEN_FAILED	= 0x1C000022,
 		DCERPC_NCA_S_FAULT_CODESET_CONV_ERROR	= 0x1C000023,
 		DCERPC_NCA_S_FAULT_OBJECT_NOT_FOUND	= 0x1C000024,
-		DCERPC_NCA_S_FAULT_NO_CLIENT_STUB	= 0x1C000025
+		DCERPC_NCA_S_FAULT_NO_CLIENT_STUB	= 0x1C000025,
+		DCERPC_FAULT_ACCESS_DENIED		= 0x00000005,
+		DCERPC_FAULT_NO_CALL_ACTIVE		= 0x000006bd,
+		DCERPC_FAULT_CANT_PERFORM		= 0x000006d8,
+		DCERPC_FAULT_OUT_OF_RESOURCES		= 0x000006d9,
+		DCERPC_FAULT_BAD_STUB_DATA		= 0x000006f7,
+		DCERPC_FAULT_SEC_PKG_ERROR		= 0x00000721
 	} dcerpc_nca_status;
 
 	const int DCERPC_FAULT_OP_RNG_ERROR       = DCERPC_NCA_S_OP_RNG_ERROR;
 	const int DCERPC_FAULT_UNK_IF             = DCERPC_NCA_S_UNKNOWN_IF;
-	const int DCERPC_FAULT_NDR                = 0x000006f7;
+	const int DCERPC_FAULT_NDR                = DCERPC_FAULT_BAD_STUB_DATA;
 	const int DCERPC_FAULT_INVALID_TAG        = DCERPC_NCA_S_FAULT_INVALID_TAG;
 	const int DCERPC_FAULT_CONTEXT_MISMATCH   = DCERPC_NCA_S_FAULT_CONTEXT_MISMATCH;
 	const int DCERPC_FAULT_OTHER              = 0x00000001;
-	const int DCERPC_FAULT_ACCESS_DENIED      = 0x00000005;
-	const int DCERPC_FAULT_CANT_PERFORM       = 0x000006d8;
-	const int DCERPC_FAULT_SEC_PKG_ERROR      = 0x00000721;
 
 	/* we return this fault when we haven't yet run the test
 	   to see what fault w2k3 returns in this case */
@@ -529,8 +532,10 @@ interface dcerpc
 	const uint8 DCERPC_PFC_OFFSET      =  3;
 	const uint8 DCERPC_DREP_OFFSET     =  4;
 	const uint8 DCERPC_FRAG_LEN_OFFSET =  8;
+	const uint32 DCERPC_FRAG_MAX_SIZE  = 5840;
 	const uint8 DCERPC_AUTH_LEN_OFFSET = 10;
 	const uint8 DCERPC_NCACN_PAYLOAD_OFFSET = 16;
+	const uint32 DCERPC_NCACN_PAYLOAD_MAX_SIZE = 0x400000; /* 4 MByte */
 
 	/* little-endian flag */
 	const uint8 DCERPC_DREP_LE  = 0x10;
diff --git a/librpc/idl/epmapper.idl b/librpc/idl/epmapper.idl
index 5f3d653..fd8eeb4 100644
--- a/librpc/idl/epmapper.idl
+++ b/librpc/idl/epmapper.idl
@@ -214,7 +214,7 @@ interface epmapper
 		epm_floor floors[num_floors];
 	} epm_tower;
 
-	typedef struct {
+	typedef [public] struct {
 		[value(ndr_size_epm_tower(&tower, ndr->flags))] uint32  tower_length;
 		[subcontext(4)] epm_tower tower;
 	} epm_twr_t;
diff --git a/librpc/idl/ntlmssp.idl b/librpc/idl/ntlmssp.idl
index 4a9e7c2..f041e32 100644
--- a/librpc/idl/ntlmssp.idl
+++ b/librpc/idl/ntlmssp.idl
@@ -1,5 +1,7 @@
 #include "idl_types.h"
 
+import "security.idl";
+
 /*
   ntlmssp interface definition
 */
@@ -54,18 +56,21 @@ interface ntlmssp
 
 	/*
 	   NTLMSSP_WINDOWS_MAJOR_VERSION_5: Windows XP SP2 and Server 2003
-	   NTLMSSP_WINDOWS_MAJOR_VERSION_6: Windows Vista, Server 2008, 7 and Server 2008 R2
+	   NTLMSSP_WINDOWS_MAJOR_VERSION_6: Windows Vista, Server 2008, 7, Server 2008 R2, 8, Server 2012, 8.1, Server 2012 R2
+	   NTLMSSP_WINDOWS_MAJOR_VERSION_10: Windows 10, Windows Server 2016 Technical Preview
 	 */
 
 	typedef [enum8bit] enum {
 		NTLMSSP_WINDOWS_MAJOR_VERSION_5	= 0x05,
-		NTLMSSP_WINDOWS_MAJOR_VERSION_6	= 0x06
+		NTLMSSP_WINDOWS_MAJOR_VERSION_6	= 0x06,
+		NTLMSSP_WINDOWS_MAJOR_VERSION_10 = 0x0A
 	} ntlmssp_WindowsMajorVersion;
 
 	/*
-	   NTLMSSP_WINDOWS_MINOR_VERSION_0: Windows Vista, Server 2008, 7, Server 2008 R2
-	   NTLMSSP_WINDOWS_MINOR_VERSION_1: Windows XP SP2
-	   NTLMSSP_WINDOWS_MINOR_VERSION_2: Windows Server 2003
+	   NTLMSSP_WINDOWS_MINOR_VERSION_0: Windows Vista, 10, Server 2016 Technical Preview
+	   NTLMSSP_WINDOWS_MINOR_VERSION_1: Windows XP SP2, 7, Server 2008 R2
+	   NTLMSSP_WINDOWS_MINOR_VERSION_2: Windows Server 2003, 8, Server 2012
+	   NTLMSSP_WINDOWS_MINOR_VERSION_3: Windows 8.1, Server 2012 R2
 	 */
 
 	typedef [enum8bit] enum {
@@ -124,24 +129,24 @@ interface ntlmssp
 		MsvAvDnsTreeName	= 5,
 		MsvAvFlags		= 6,
 		MsvAvTimestamp		= 7,
-		MsAvRestrictions	= 8,
+		MsvAvSingleHost		= 8,
 		MsvAvTargetName		= 9,
 		MsvChannelBindings	= 10
 	} ntlmssp_AvId;
 
-	/* [MS-NLMP] 2.2.2.2 Restriction_Encoding */
+	/* [MS-NLMP] 2.2.2.2 SingleHostData */
 
-	typedef struct {
-		uint32 Size;
+	typedef [flag(NDR_PAHEX)] struct {
+		[value(8+ndr_size_LSAP_TOKEN_INFO_INTEGRITY(&r->token_info, 0)+r->remaining.length)] uint32 Size;
 		[value(0)] uint32 Z4;
-		boolean32 IntegrityLevel;
-		uint32 SubjectIntegrityLevel;
-		uint8 MachineId[32];
-	} Restriction_Encoding;
+		LSAP_TOKEN_INFO_INTEGRITY token_info;
+		[flag(NDR_REMAINING)] DATA_BLOB remaining;
+	} ntlmssp_SingleHostData;
 
 	typedef [bitmap32bit] bitmap {
 		NTLMSSP_AVFLAG_CONSTRAINTED_ACCOUNT		= 0x00000001,
-		NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE	= 0x00000002
+		NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE	= 0x00000002,
+		NTLMSSP_AVFLAG_TARGET_SPN_FROM_UNTRUSTED_SOURCE	= 0x00000004
 	} ntlmssp_AvFlags;
 
 	typedef [gensize,nodiscriminant,flag(NDR_NOALIGN)] union {
@@ -153,7 +158,7 @@ interface ntlmssp
 		[case(MsvAvDnsTreeName)]	[flag(ndr_ntlmssp_negotiated_string_flags(NTLMSSP_NEGOTIATE_UNICODE))] string AvDnsTreeName;
 		[case(MsvAvFlags)]		ntlmssp_AvFlags AvFlags;
 		[case(MsvAvTimestamp)]		NTTIME AvTimestamp;
-		[case(MsAvRestrictions)]	Restriction_Encoding AvRestrictions;
+		[case(MsvAvSingleHost)]		ntlmssp_SingleHostData AvSingleHost;
 		[case(MsvAvTargetName)]		[flag(ndr_ntlmssp_negotiated_string_flags(NTLMSSP_NEGOTIATE_UNICODE))] string AvTargetName;
 		[case(MsvChannelBindings)]	uint8 ChannelBindings[16];
 		[default]			[flag(NDR_REMAINING)] DATA_BLOB blob;
@@ -167,7 +172,7 @@ interface ntlmssp
 		[subcontext(0),subcontext_size(AvLen),switch_is(AvId)] ntlmssp_AvValue Value;
 	} AV_PAIR;
 
-	typedef [gensize,nopush,nopull,flag(NDR_NOALIGN)] struct {
+	typedef [public,gensize,nopush,nopull,flag(NDR_NOALIGN)] struct {
 		uint32 count;
 		AV_PAIR pair[count];
 	} AV_PAIR_LIST;
@@ -184,7 +189,7 @@ interface ntlmssp
 		uint8 ServerChallenge[8];
 		uint8 Reserved[8];
 		[value(ndr_size_AV_PAIR_LIST(TargetInfo, ndr->flags))] uint16 TargetInfoLen;
-		[value(TargetInfoLen)] uint16 TargetNameInfoMaxLen;
+		[value(TargetInfoLen)] uint16 TargetInfoMaxLen;
 		[relative] [subcontext(0),subcontext_size(TargetInfoLen)] AV_PAIR_LIST *TargetInfo;
 		[switch_is(NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)] ntlmssp_Version Version;
 	} CHALLENGE_MESSAGE;
@@ -239,9 +244,12 @@ interface ntlmssp
 		[default] NTLMv2_RESPONSE v2;
 	} ntlmssp_NTLM_RESPONSE;
 
+	const int NTLMSSP_MIC_OFFSET = 72;
+	const int NTLMSSP_MIC_SIZE = 16;
+
 	typedef [flag(NDR_PAHEX)] struct {
-		uint8 MIC[16];
-	} MIC;
+		uint8 MIC[NTLMSSP_MIC_SIZE];
+	} ntlmssp_MIC;
 
 	/* [MS-NLMP] 2.2.1.3 AUTHENTICATE_MESSAGE */
 
@@ -270,7 +278,7 @@ interface ntlmssp
 		[switch_is(NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)] ntlmssp_Version Version;
 		/* MIC (Message Integrity) is only included when the client has
 		 * sent a timestap Av struct in the CHALLENGE_MESSAGE AvPair */
-		/* [flag(NDR_REMAINING)] MIC mic; */
+		/* [flag(NDR_REMAINING)] ntlmssp_MIC mic; */
 	} AUTHENTICATE_MESSAGE;
 
 	/* NTLMSSP signature version */
diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl
index b78307e..bb811ae 100644
--- a/librpc/idl/security.idl
+++ b/librpc/idl/security.idl
@@ -649,6 +649,15 @@ interface security
 		0);
 
 	/*
+	 * See [MS-KILE] 2.2.5 LSAP_TOKEN_INFO_INTEGRITY
+	 */
+	typedef [public,gensize,flag(NDR_PAHEX)] struct {
+		uint32 Flags;
+		uint32 TokenIL;
+		uint8 MachineId[32];
+	} LSAP_TOKEN_INFO_INTEGRITY;
+
+	/*
 	 * See [MS-KILE] 2.2.6 Supported Encryption Types Bit Flags
 	 */
 	typedef [public,bitmap32bit] bitmap {
diff --git a/librpc/ndr/ndr_ntlmssp.c b/librpc/ndr/ndr_ntlmssp.c
index d024da5..7027ac0 100644
--- a/librpc/ndr/ndr_ntlmssp.c
+++ b/librpc/ndr/ndr_ntlmssp.c
@@ -176,4 +176,20 @@ _PUBLIC_ void ndr_print_ntlmssp_Version(struct ndr_print *ndr, const char *name,
 	}
 }
 
+_PUBLIC_ struct AV_PAIR *ndr_ntlmssp_find_av(const struct AV_PAIR_LIST *av_list,
+					     enum ntlmssp_AvId AvId)
+{
+	struct AV_PAIR *res = NULL;
+	uint32_t i = 0;
+
+	for (i = 0; i < av_list->count; i++) {
+		if (av_list->pair[i].AvId != AvId) {
+			continue;
+		}
 
+		res = discard_const_p(struct AV_PAIR, &av_list->pair[i]);
+		break;
+	}
+
+	return res;
+}
diff --git a/librpc/ndr/ndr_ntlmssp.h b/librpc/ndr/ndr_ntlmssp.h
index e07ff15..5c979ff 100644
--- a/librpc/ndr/ndr_ntlmssp.h
+++ b/librpc/ndr/ndr_ntlmssp.h
@@ -31,3 +31,5 @@ _PUBLIC_ void ndr_print_ntlmssp_lm_response(TALLOC_CTX *mem_ctx,
 					    bool ntlmv2);
 _PUBLIC_ void ndr_print_ntlmssp_Version(struct ndr_print *ndr, const char *name, const union ntlmssp_Version *r);
 
+_PUBLIC_ struct AV_PAIR *ndr_ntlmssp_find_av(const struct AV_PAIR_LIST *av_list,
+					     enum ntlmssp_AvId AvId);
diff --git a/librpc/rpc/binding.c b/librpc/rpc/binding.c
index f131d00..8e251ef 100644
--- a/librpc/rpc/binding.c
+++ b/librpc/rpc/binding.c
@@ -591,7 +591,7 @@ _PUBLIC_ void dcerpc_binding_get_auth_info(const struct dcerpc_binding *b,
 	} else if (b->flags & DCERPC_CONNECT) {
 		auth_level = DCERPC_AUTH_LEVEL_CONNECT;
 	} else if (auth_type != DCERPC_AUTH_TYPE_NONE) {
-		auth_level = DCERPC_AUTH_LEVEL_CONNECT;
+		auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
 	} else {
 		auth_level = DCERPC_AUTH_LEVEL_NONE;
 	}
diff --git a/librpc/rpc/dcerpc_error.c b/librpc/rpc/dcerpc_error.c
index 2b90334..f386025 100644
--- a/librpc/rpc/dcerpc_error.c
+++ b/librpc/rpc/dcerpc_error.c
@@ -88,9 +88,11 @@ static const struct dcerpc_fault_table dcerpc_faults[] =
 	_FAULT_STR_NO_NT_MAPPING(DCERPC_NCA_S_FAULT_OBJECT_NOT_FOUND),
 	_FAULT_STR_NO_NT_MAPPING(DCERPC_NCA_S_FAULT_NO_CLIENT_STUB),
 	_FAULT_STR(DCERPC_FAULT_OTHER, NT_STATUS_RPC_CALL_FAILED),
-	_FAULT_STR(DCERPC_FAULT_CANT_PERFORM, NT_STATUS_EPT_CANT_PERFORM_OP),
-	_FAULT_STR(DCERPC_FAULT_NDR, NT_STATUS_RPC_BAD_STUB_DATA),
 	_FAULT_STR(DCERPC_FAULT_ACCESS_DENIED, NT_STATUS_ACCESS_DENIED),
+	_FAULT_STR(DCERPC_FAULT_NO_CALL_ACTIVE, NT_STATUS_RPC_NO_CALL_ACTIVE),
+	_FAULT_STR(DCERPC_FAULT_CANT_PERFORM, NT_STATUS_EPT_CANT_PERFORM_OP),
+	_FAULT_STR(DCERPC_FAULT_OUT_OF_RESOURCES, NT_STATUS_RPC_OUT_OF_RESOURCES),
+	_FAULT_STR(DCERPC_FAULT_BAD_STUB_DATA, NT_STATUS_RPC_BAD_STUB_DATA),
 	_FAULT_STR(DCERPC_FAULT_SEC_PKG_ERROR, NT_STATUS_RPC_SEC_PKG_ERROR),
 	{ NULL, 0 }
 #undef _FAULT_STR
diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c
index 696bcda..43e1b7f 100644
--- a/librpc/rpc/dcerpc_util.c
+++ b/librpc/rpc/dcerpc_util.c
@@ -83,31 +83,49 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob)
 *
 * @return		- A NTSTATUS error code.
 */
-NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
+NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
 				  TALLOC_CTX *mem_ctx,
-				  DATA_BLOB *pkt_trailer,
+				  const DATA_BLOB *pkt_trailer,
 				  struct dcerpc_auth *auth,
-				  uint32_t *auth_length,
+				  uint32_t *_auth_length,
 				  bool auth_data_only)
 {
 	struct ndr_pull *ndr;
 	enum ndr_err_code ndr_err;
-	uint32_t data_and_pad;
+	uint16_t data_and_pad;
+	uint16_t auth_length;
+	uint32_t tmp_length;
 
-	data_and_pad = pkt_trailer->length
-			- (DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length);
+	ZERO_STRUCTP(auth);
+	if (_auth_length != NULL) {
+		*_auth_length = 0;
+	}
+
+	/* Paranoia checks for auth_length. The caller should check this... */
+	if (pkt->auth_length == 0) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	/* Paranoia checks for auth_length. The caller should check this... */
+	if (pkt->auth_length > pkt->frag_length) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	tmp_length = DCERPC_NCACN_PAYLOAD_OFFSET;
+	tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
+	tmp_length += pkt->auth_length;
+	if (tmp_length > pkt->frag_length) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+	if (pkt_trailer->length > UINT16_MAX) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
 
-	/* paranoia check for pad size. This would be caught anyway by
-	   the ndr_pull_advance() a few lines down, but it scared
-	   Jeremy enough for him to call me, so we might as well check
-	   it now, just to prevent someone posting a bogus YouTube
-	   video in the future.
-	*/
-	if (data_and_pad > pkt_trailer->length) {
-		return NT_STATUS_INFO_LENGTH_MISMATCH;
+	auth_length = DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length;
+	if (pkt_trailer->length < auth_length) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
 	}
 
-	*auth_length = pkt_trailer->length - data_and_pad;
+	data_and_pad = pkt_trailer->length - auth_length;
 
 	ndr = ndr_pull_init_blob(pkt_trailer, mem_ctx);
 	if (!ndr) {
@@ -127,14 +145,28 @@ NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
 	ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		talloc_free(ndr);
+		ZERO_STRUCTP(auth);
 		return ndr_map_error2ntstatus(ndr_err);
 	}
 
+	if (data_and_pad < auth->auth_pad_length) {
+		DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
+			  "Calculated %u  got %u\n",
+			  (unsigned)data_and_pad,
+			  (unsigned)auth->auth_pad_length));
+		talloc_free(ndr);
+		ZERO_STRUCTP(auth);
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	if (auth_data_only && data_and_pad != auth->auth_pad_length) {
-		DEBUG(1, (__location__ ": WARNING: pad length mismatch. "
+		DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
 			  "Calculated %u  got %u\n",
 			  (unsigned)data_and_pad,
 			  (unsigned)auth->auth_pad_length));
+		talloc_free(ndr);
+		ZERO_STRUCTP(auth);
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
 	}
 
 	DEBUG(6,(__location__ ": auth_pad_length %u\n",
@@ -143,6 +175,83 @@ NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
 	talloc_steal(mem_ctx, auth->credentials.data);
 	talloc_free(ndr);
 
+	if (_auth_length != NULL) {
+		*_auth_length = auth_length;
+	}
+
+	return NT_STATUS_OK;
+}
+
+/**
+* @brief	Verify the fields in ncacn_packet header.
+*
+* @param pkt		- The ncacn_packet strcuture
+* @param ptype		- The expected PDU type
+* @param max_auth_info	- The maximum size of a possible auth trailer
+* @param required_flags	- The required flags for the pdu.
+* @param optional_flags	- The possible optional flags for the pdu.
+*
+* @return		- A NTSTATUS error code.
+*/
+NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
+					   enum dcerpc_pkt_type ptype,
+					   size_t max_auth_info,
+					   uint8_t required_flags,
+					   uint8_t optional_flags)
+{
+	if (pkt->rpc_vers != 5) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (pkt->rpc_vers_minor != 0) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (pkt->auth_length > pkt->frag_length) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (pkt->ptype != ptype) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (max_auth_info > UINT16_MAX) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (pkt->auth_length > 0) {
+		size_t max_auth_length;
+
+		if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) {
+			return NT_STATUS_RPC_PROTOCOL_ERROR;
+		}
+		max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH;
+
+		if (pkt->auth_length > max_auth_length) {
+			return NT_STATUS_RPC_PROTOCOL_ERROR;
+		}
+	}
+
+	if ((pkt->pfc_flags & required_flags) != required_flags) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+	if (pkt->pfc_flags & ~(optional_flags|required_flags)) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (pkt->drep[0] & ~DCERPC_DREP_LE) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+	if (pkt->drep[1] != 0) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+	if (pkt->drep[2] != 0) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+	if (pkt->drep[3] != 0) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	return NT_STATUS_OK;
 }
 
diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h
index 28600c9..e3c9c0f 100644
--- a/librpc/rpc/rpc_common.h
+++ b/librpc/rpc/rpc_common.h
@@ -186,12 +186,17 @@ const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx,
 *
 * @return		- A NTSTATUS error code.
 */
-NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
+NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
 				  TALLOC_CTX *mem_ctx,
-				  DATA_BLOB *pkt_trailer,
+				  const DATA_BLOB *pkt_trailer,
 				  struct dcerpc_auth *auth,
 				  uint32_t *auth_length,
 				  bool auth_data_only);
+NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
+					   enum dcerpc_pkt_type ptype,
+					   size_t max_auth_info,
+					   uint8_t required_flags,
+					   uint8_t optional_flags);
 struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
 						 struct tevent_context *ev,
 						 struct tstream_context *stream);
diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c
index 672cf37..0d1b90c 100644
--- a/nsswitch/libwbclient/wbc_pam.c
+++ b/nsswitch/libwbclient/wbc_pam.c
@@ -1286,7 +1286,17 @@ wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
 	}
 
 	for (i=0; i<params->num_blobs; i++) {
-		if (strcasecmp(params->blobs[i].name, "initial_blob") == 0) {
+		/*
+		 * Older callers may used to provide the NEGOTIATE request
+		 * as "initial_blob", but it was completely ignored by winbindd.
+		 *
+		 * So we keep ignoring it.
+		 *
+		 * A new callers that is capable to support "new_spnego",
+		 * will provide the NEGOTIATE request as "negotiate_blob"
+		 * instead.
+		 */
+		if (strcasecmp(params->blobs[i].name, "negotiate_blob") == 0) {
 			if (initial_blob != NULL) {
 				status = WBC_ERR_INVALID_PARAM;
 				goto fail;
@@ -1384,6 +1394,15 @@ wbcErr wbcCtxCredentialCache(struct wbcContext *ctx,
 	if (!WBC_ERROR_IS_OK(status)) {
 		goto fail;
 	}
+	if (response.data.ccache_ntlm_auth.new_spnego) {
+		status = wbcAddNamedBlob(
+			&result->num_blobs, &result->blobs, "new_spnego", 0,
+			&response.data.ccache_ntlm_auth.new_spnego,
+			sizeof(response.data.ccache_ntlm_auth.new_spnego));
+		if (!WBC_ERROR_IS_OK(status)) {
+			goto fail;
+		}
+	}
 
 	*info = result;
 	result = NULL;
diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h
index 0dffa4b..245162d 100644
--- a/nsswitch/winbind_struct_protocol.h
+++ b/nsswitch/winbind_struct_protocol.h
@@ -486,6 +486,7 @@ struct winbindd_response {
 		struct {
 			uint8_t session_key[16];
 			uint32_t auth_blob_len; /* blob in extra_data */
+			uint8_t new_spnego;
 		} ccache_ntlm_auth;
 		struct {
 			fstring dc_unc;
diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py
index b53c4ea..0499b4e 100644
--- a/python/samba/tests/__init__.py
+++ b/python/samba/tests/__init__.py
@@ -1,5 +1,6 @@
 # Unix SMB/CIFS implementation.
 # Copyright (C) Jelmer Vernooij <jelmer at samba.org> 2007-2010
+# Copyright (C) Stefan Metzmacher 2014,2015
 #
 # 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
@@ -24,6 +25,12 @@ import samba.auth
 from samba import param
 from samba.samdb import SamDB
 from samba import credentials
+import samba.ndr
+import samba.dcerpc.dcerpc
+import samba.dcerpc.base
+import samba.dcerpc.epmapper
+import socket
+import struct
 import subprocess
 import sys
 import tempfile
@@ -222,6 +229,524 @@ cmdline_credentials = None
 class RpcInterfaceTestCase(TestCase):
     """DCE/RPC Test case."""
 
+class RawDCERPCTest(TestCase):
+    """A raw DCE/RPC Test case."""
+
+    def _disconnect(self, reason):
+        if self.s is None:
+            return
+        self.s.close()
+        self.s = None
+        if self.do_hexdump:
+            sys.stderr.write("disconnect[%s]\n" % reason)
+
+    def connect(self):
+        try:
+            self.a = socket.getaddrinfo(self.host, self.tcp_port, socket.AF_UNSPEC,
+                                        socket.SOCK_STREAM, socket.SOL_TCP,
+                                        0)
+            self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2])
+            self.s.settimeout(10)
+            self.s.connect(self.a[0][4])
+        except socket.error as e:
+            self.s.close()
+            raise
+        except IOError as e:
+            self.s.close()
+            raise
+        except Exception as e:
+            raise
+        finally:
+            pass
+
+    def setUp(self):
+        super(RawDCERPCTest, self).setUp()
+        self.do_ndr_print = False
+        self.do_hexdump = False
+
+        self.host = samba.tests.env_get_var_value('SERVER')
+        self.tcp_port = 135
+
+        self.settings = {}
+        self.settings["lp_ctx"] = self.lp_ctx = samba.tests.env_loadparm()
+        self.settings["target_hostname"] = self.host
+
+        self.connect()
+
+    def epmap_reconnect(self, abstract):
+        ndr32 = samba.dcerpc.base.transfer_syntax_ndr()
+
+        tsf0_list = [ndr32]
+        ctx0 = samba.dcerpc.dcerpc.ctx_list()
+        ctx0.context_id = 1
+        ctx0.num_transfer_syntaxes = len(tsf0_list)
+        ctx0.abstract_syntax = samba.dcerpc.epmapper.abstract_syntax()
+        ctx0.transfer_syntaxes = tsf0_list
+
+        req = self.generate_bind(call_id=0, ctx_list=[ctx0])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_BIND_ACK,
+                        req.call_id, auth_length=0)
+        self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEqual(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEqual(rep.u.secondary_address_size, 4)
+        self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEqual(len(rep.u._pad1), 2)
+        self.assertEqual(rep.u._pad1, '\0' * 2)
+        self.assertEqual(rep.u.num_results, 1)
+        self.assertEqual(rep.u.ctx_list[0].result,
+                samba.dcerpc.dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEqual(rep.u.ctx_list[0].reason,
+                samba.dcerpc.dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEqual(rep.u.auth_info, '\0' * 0)
+
+        # And now try a request
+        data1 = samba.ndr.ndr_pack(abstract)
+        lhs1 = samba.dcerpc.epmapper.epm_lhs()
+        lhs1.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_UUID
+        lhs1.lhs_data = data1[:18]
+        rhs1 = samba.dcerpc.epmapper.epm_rhs_uuid()
+        rhs1.unknown = data1[18:]
+        floor1 = samba.dcerpc.epmapper.epm_floor()
+        floor1.lhs = lhs1
+        floor1.rhs = rhs1
+        data2 = samba.ndr.ndr_pack(ndr32)
+        lhs2 = samba.dcerpc.epmapper.epm_lhs()
+        lhs2.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_UUID
+        lhs2.lhs_data = data2[:18]
+        rhs2 = samba.dcerpc.epmapper.epm_rhs_uuid()
+        rhs2.unknown = data1[18:]
+        floor2 = samba.dcerpc.epmapper.epm_floor()
+        floor2.lhs = lhs2
+        floor2.rhs = rhs2
+        lhs3 = samba.dcerpc.epmapper.epm_lhs()
+        lhs3.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_NCACN
+        lhs3.lhs_data = ""
+        floor3 = samba.dcerpc.epmapper.epm_floor()
+        floor3.lhs = lhs3
+        floor3.rhs.minor_version = 0
+        lhs4 = samba.dcerpc.epmapper.epm_lhs()
+        lhs4.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_TCP
+        lhs4.lhs_data = ""
+        floor4 = samba.dcerpc.epmapper.epm_floor()
+        floor4.lhs = lhs4
+        floor4.rhs.port = self.tcp_port
+        lhs5 = samba.dcerpc.epmapper.epm_lhs()
+        lhs5.protocol = samba.dcerpc.epmapper.EPM_PROTOCOL_IP
+        lhs5.lhs_data = ""
+        floor5 = samba.dcerpc.epmapper.epm_floor()
+        floor5.lhs = lhs5
+        floor5.rhs.ipaddr = "0.0.0.0"
+
+        floors = [floor1,floor2,floor3,floor4,floor5]
+        req_tower = samba.dcerpc.epmapper.epm_tower()
+        req_tower.num_floors = len(floors)
+        req_tower.floors = floors
+        req_twr = samba.dcerpc.epmapper.epm_twr_t()
+        req_twr.tower = req_tower
+
+        pack_twr = samba.ndr.ndr_pack(req_twr)
+
+        # object
+        stub =  "\x01\x00\x00\x00"
+        stub += "\x00" * 16
+        # tower
+        stub += "\x02\x00\x00\x00"
+        stub += pack_twr
+        # padding?
+        stub += "\x00" * 1
+        # handle
+        stub += "\x00" * 20
+        # max_towers
+        stub += "\x04\x00\x00\x00"
+
+        # we do an epm_Map() request
+        req = self.generate_request(call_id = 1,
+                                    context_id=ctx0.context_id,
+                                    opnum=3,
+                                    stub=stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, samba.dcerpc.dcerpc.DCERPC_PKT_RESPONSE,
+                        req.call_id, auth_length=0)
+        self.assertNotEqual(rep.u.alloc_hint, 0)
+        self.assertEqual(rep.u.context_id, req.u.context_id)
+        self.assertEqual(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        num_towers = struct.unpack_from("<I", rep.u.stub_and_verifier, 20)
+        (array_max, array_ofs, array_cnt) = struct.unpack_from("<III", rep.u.stub_and_verifier, 24)
+        status = struct.unpack_from("<I", rep.u.stub_and_verifier, len(rep.u.stub_and_verifier) - 4)
+        self.assertEqual(status[0], 0)
+        self.assertGreaterEqual(num_towers[0], 1)
+        self.assertEqual(array_max, 4)
+        self.assertEqual(array_ofs, 0)
+        self.assertGreaterEqual(array_cnt, 1)
+
+        unpack_twr = rep.u.stub_and_verifier[(36 + 4 * array_cnt):-4]
+        rep_twr = samba.ndr.ndr_unpack(samba.dcerpc.epmapper.epm_twr_t, unpack_twr, allow_remaining=True)
+        self.assertEqual(rep_twr.tower_length, 75)
+        self.assertEqual(rep_twr.tower.num_floors, 5)
+        self.assertEqual(len(rep_twr.tower.floors), 5)
+        self.assertEqual(rep_twr.tower.floors[3].lhs.protocol,
+                          samba.dcerpc.epmapper.EPM_PROTOCOL_TCP)
+        self.assertEqual(rep_twr.tower.floors[3].lhs.protocol,
+                          samba.dcerpc.epmapper.EPM_PROTOCOL_TCP)
+
+        # reconnect to the given port
+        self._disconnect("epmap_reconnect")
+        self.tcp_port = rep_twr.tower.floors[3].rhs.port
+        self.connect()
+
+    def send_pdu(self, req, ndr_print=None, hexdump=None):
+        if ndr_print is None:
+            ndr_print = self.do_ndr_print
+        if hexdump is None:
+            hexdump = self.do_hexdump
+        try:
+            req_pdu = samba.ndr.ndr_pack(req)
+            if ndr_print:
+                sys.stderr.write("send_pdu: %s" % samba.ndr.ndr_print(req))
+            if hexdump:
+                sys.stderr.write("send_pdu: %d\n%s" % (len(req_pdu), self.hexdump(req_pdu)))
+            while True:
+                sent = self.s.send(req_pdu, 0)
+                if sent == len(req_pdu):
+                    break
+                req_pdu = req_pdu[sent:]
+        except socket.error as e:
+            self._disconnect("send_pdu: %s" % e)
+            raise
+        except IOError as e:
+            self._disconnect("send_pdu: %s" % e)
+            raise
+        finally:
+            pass
+
+    def recv_raw(self, hexdump=None, timeout=None):
+        rep_pdu = None
+        if hexdump is None:
+            hexdump = self.do_hexdump
+        try:
+            if timeout is not None:
+                self.s.settimeout(timeout)
+            rep_pdu = self.s.recv(0xffff, 0)
+            self.s.settimeout(10)
+            if len(rep_pdu) == 0:
+                self._disconnect("recv_raw: EOF")
+                return None
+            if hexdump:
+                sys.stderr.write("recv_raw: %d\n%s" % (len(rep_pdu), self.hexdump(rep_pdu)))
+        except socket.timeout as e:
+            self.s.settimeout(10)
+            sys.stderr.write("recv_raw: TIMEOUT\n")
+            pass
+        except socket.error as e:
+            self._disconnect("recv_raw: %s" % e)
+            raise
+        except IOError as e:
+            self._disconnect("recv_raw: %s" % e)
+            raise
+        finally:
+            pass
+        return rep_pdu
+
+    def recv_pdu(self, ndr_print=None, hexdump=None, timeout=None):
+        rep = None
+        if ndr_print is None:
+            ndr_print = self.do_ndr_print
+        if hexdump is None:
+            hexdump = self.do_hexdump
+        try:
+            rep_pdu = self.recv_raw(hexdump=hexdump, timeout=timeout)
+            if rep_pdu is None:
+                return None
+            rep = samba.ndr.ndr_unpack(samba.dcerpc.dcerpc.ncacn_packet, rep_pdu, allow_remaining=True)
+            if ndr_print:
+                sys.stderr.write("recv_pdu: %s" % samba.ndr.ndr_print(rep))
+            self.assertEqual(rep.frag_length, len(rep_pdu))
+        finally:
+            pass
+        return rep
+
+    def generate_auth(self,
+                      auth_type=None,
+                      auth_level=None,
+                      auth_pad_length=0,
+                      auth_context_id=None,
+                      auth_blob=None,
+                      ndr_print=None, hexdump=None):
+        if ndr_print is None:
+            ndr_print = self.do_ndr_print
+        if hexdump is None:
+            hexdump = self.do_hexdump
+
+        if auth_type is not None:
+            a = samba.dcerpc.dcerpc.auth()
+            a.auth_type = auth_type
+            a.auth_level = auth_level
+            a.auth_pad_length = auth_pad_length
+            a.auth_context_id= auth_context_id
+            a.credentials = auth_blob
+
+            ai = samba.ndr.ndr_pack(a)
+            if ndr_print:
+                sys.stderr.write("generate_auth: %s" % samba.ndr.ndr_print(a))
+            if hexdump:
+                sys.stderr.write("generate_auth: %d\n%s" % (len(ai), self.hexdump(ai)))
+        else:
+            ai = ""
+
+        return ai
+
+    def parse_auth(self, auth_info, ndr_print=None, hexdump=None):
+        if ndr_print is None:
+            ndr_print = self.do_ndr_print
+        if hexdump is None:
+            hexdump = self.do_hexdump
+
+        if (len(auth_info) <= samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH):
+            return None
+
+        if hexdump:
+            sys.stderr.write("parse_auth: %d\n%s" % (len(auth_info), self.hexdump(auth_info)))
+        a = samba.ndr.ndr_unpack(samba.dcerpc.dcerpc.auth, auth_info, allow_remaining=True)
+        if ndr_print:
+            sys.stderr.write("parse_auth: %s" % samba.ndr.ndr_print(a))
+
+        return a
+
+    def generate_pdu(self, ptype, call_id, payload,
+                     rpc_vers=5,
+                     rpc_vers_minor=0,
+                     pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                 samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                     drep = [samba.dcerpc.dcerpc.DCERPC_DREP_LE, 0, 0, 0],
+                     ndr_print=None, hexdump=None):
+
+        if getattr(payload, 'auth_info', None):
+            ai = payload.auth_info
+        else:
+            ai = ""
+
+        p = samba.dcerpc.dcerpc.ncacn_packet()
+        p.rpc_vers = rpc_vers
+        p.rpc_vers_minor = rpc_vers_minor
+        p.ptype = ptype
+        p.pfc_flags = pfc_flags
+        p.drep = drep
+        p.frag_length = 0
+        if len(ai) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
+            p.auth_length = len(ai) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        else:
+            p.auth_length = 0
+        p.call_id = call_id
+        p.u = payload
+
+        pdu = samba.ndr.ndr_pack(p)
+        p.frag_length = len(pdu)
+
+        return p
+
+    def verify_pdu(self, p, ptype, call_id,
+                   rpc_vers=5,
+                   rpc_vers_minor=0,
+                   pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                               samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                   drep = [samba.dcerpc.dcerpc.DCERPC_DREP_LE, 0, 0, 0],
+                   auth_length=None):
+
+        self.assertIsNotNone(p, "No valid pdu")
+
+        if getattr(p.u, 'auth_info', None):
+            ai = p.u.auth_info
+        else:
+            ai = ""
+
+        self.assertEqual(p.rpc_vers, rpc_vers)
+        self.assertEqual(p.rpc_vers_minor, rpc_vers_minor)
+        self.assertEqual(p.ptype, ptype)
+        self.assertEqual(p.pfc_flags, pfc_flags)
+        self.assertEqual(p.drep, drep)
+        self.assertGreaterEqual(p.frag_length,
+                samba.dcerpc.dcerpc.DCERPC_NCACN_PAYLOAD_OFFSET)
+        if len(ai) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
+            self.assertEqual(p.auth_length,
+                    len(ai) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH)
+        elif auth_length is not None:
+            self.assertEqual(p.auth_length, auth_length)
+        else:
+            self.assertEqual(p.auth_length, 0)
+        self.assertEqual(p.call_id, call_id)
+
+        return
+
+    def generate_bind(self, call_id,
+                      pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                  samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                      max_xmit_frag=5840,
+                      max_recv_frag=5840,
+                      assoc_group_id=0,
+                      ctx_list=[],
+                      auth_info="",
+                      ndr_print=None, hexdump=None):
+
+        b = samba.dcerpc.dcerpc.bind()
+        b.max_xmit_frag = max_xmit_frag
+        b.max_recv_frag = max_recv_frag
+        b.assoc_group_id = assoc_group_id
+        b.num_contexts = len(ctx_list)
+        b.ctx_list = ctx_list
+        b.auth_info = auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_BIND,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=b,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def generate_alter(self, call_id,
+                       pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                   samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                       max_xmit_frag=5840,
+                       max_recv_frag=5840,
+                       assoc_group_id=0,
+                       ctx_list=[],
+                       auth_info="",
+                       ndr_print=None, hexdump=None):
+
+        a = samba.dcerpc.dcerpc.bind()
+        a.max_xmit_frag = max_xmit_frag
+        a.max_recv_frag = max_recv_frag
+        a.assoc_group_id = assoc_group_id
+        a.num_contexts = len(ctx_list)
+        a.ctx_list = ctx_list
+        a.auth_info = auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ALTER,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=a,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def generate_auth3(self, call_id,
+                       pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                   samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                       auth_info="",
+                       ndr_print=None, hexdump=None):
+
+        a = samba.dcerpc.dcerpc.auth3()
+        a.auth_info = auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_AUTH3,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=a,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def generate_request(self, call_id,
+                         pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                     samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                         alloc_hint=None,
+                         context_id=None,
+                         opnum=None,
+                         object=None,
+                         stub=None,
+                         auth_info="",
+                         ndr_print=None, hexdump=None):
+
+        if alloc_hint is None:
+            alloc_hint = len(stub)
+
+        r = samba.dcerpc.dcerpc.request()
+        r.alloc_hint = alloc_hint
+        r.context_id = context_id
+        r.opnum = opnum
+        if object is not None:
+            r.object = object
+        r.stub_and_verifier = stub + auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_REQUEST,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=r,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        if len(auth_info) > samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH:
+            p.auth_length = len(auth_info) - samba.dcerpc.dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+
+        return p
+
+    def generate_co_cancel(self, call_id,
+                           pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                       samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                           auth_info="",
+                           ndr_print=None, hexdump=None):
+
+        c = samba.dcerpc.dcerpc.co_cancel()
+        c.auth_info = auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_CO_CANCEL,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=c,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def generate_orphaned(self, call_id,
+                          pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                      samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                          auth_info="",
+                          ndr_print=None, hexdump=None):
+
+        o = samba.dcerpc.dcerpc.orphaned()
+        o.auth_info = auth_info
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_ORPHANED,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=o,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def generate_shutdown(self, call_id,
+                          pfc_flags = samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                      samba.dcerpc.dcerpc.DCERPC_PFC_FLAG_LAST,
+                          ndr_print=None, hexdump=None):
+
+        s = samba.dcerpc.dcerpc.shutdown()
+
+        p = self.generate_pdu(ptype=samba.dcerpc.dcerpc.DCERPC_PKT_SHUTDOWN,
+                              pfc_flags=pfc_flags,
+                              call_id=call_id,
+                              payload=s,
+                              ndr_print=ndr_print, hexdump=hexdump)
+
+        return p
+
+    def assertIsConnected(self):
+        self.assertIsNotNone(self.s, msg="Not connected")
+        return
+
+    def assertNotConnected(self):
+        self.assertIsNone(self.s, msg="Is connected")
+        return
+
+    def assertNDRSyntaxEquals(self, s1, s2):
+        self.assertEqual(s1.uuid, s2.uuid)
+        self.assertEqual(s1.if_version, s2.if_version)
+        return
 
 class ValidNetbiosNameTests(TestCase):
 
diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py
index 2b421d0..7229877 100644
--- a/python/samba/tests/dcerpc/dnsserver.py
+++ b/python/samba/tests/dcerpc/dnsserver.py
@@ -27,7 +27,7 @@ class DnsserverTests(RpcInterfaceTestCase):
         super(DnsserverTests, self).setUp()
         self.server = env_get_var_value("SERVER_IP")
         self.zone = env_get_var_value("REALM").lower()
-        self.conn = dnsserver.dnsserver("ncacn_ip_tcp:%s" % (self.server),
+        self.conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server),
                                         self.get_loadparm(),
                                         self.get_credentials())
 
diff --git a/python/samba/tests/dcerpc/raw_protocol.py b/python/samba/tests/dcerpc/raw_protocol.py
new file mode 100755
index 0000000..ccd0f6b
--- /dev/null
+++ b/python/samba/tests/dcerpc/raw_protocol.py
@@ -0,0 +1,2623 @@
+#!/usr/bin/env python
+# Unix SMB/CIFS implementation.
+# Copyright (C) Stefan Metzmacher 2014,2015
+#
+# 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/>.
+#
+
+import sys
+import os
+
+sys.path.insert(0, "bin/python")
+os.environ["PYTHONUNBUFFERED"] = "1"
+
+import samba.dcerpc.dcerpc as dcerpc
+import samba.dcerpc.base as base
+import samba.dcerpc.epmapper
+import samba.dcerpc.mgmt
+import samba.dcerpc.netlogon
+import struct
+from samba.credentials import Credentials
+from samba import gensec
+from samba.tests import RawDCERPCTest
+
+global_ndr_print = False
+global_hexdump = False
+
+class TestDCERPC_BIND(RawDCERPCTest):
+
+    def setUp(self):
+        super(TestDCERPC_BIND, self).setUp()
+        self.do_ndr_print = global_ndr_print
+        self.do_hexdump = global_hexdump
+
+    def _test_no_auth_request_bind_pfc_flags(self, req_pfc_flags, rep_pfc_flags):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0, pfc_flags=req_pfc_flags, ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        pfc_flags=rep_pfc_flags, auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # sometimes windows sends random bytes
+        # self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # And now try a request
+        req = self.generate_request(call_id = 1,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+    def _test_no_auth_request_alter_pfc_flags(self, req_pfc_flags, rep_pfc_flags):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0, ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # sometimes windows sends random bytes
+        # self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # And now try a alter context
+        req = self.generate_alter(call_id=0, pfc_flags=req_pfc_flags, ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id,
+                        pfc_flags=rep_pfc_flags, auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(rep.u.secondary_address, "")
+        self.assertEquals(len(rep.u._pad1), 2)
+        # sometimes windows sends random bytes
+        # self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # And now try a request
+        req = self.generate_request(call_id = 1,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+    def test_no_auth_request(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_bind_pfc_00(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_bind_pfc_FIRST(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_bind_pfc_LAST(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    # TODO: doesn't announce DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
+    # without authentication
+    def _test_no_auth_request_bind_pfc_HDR_SIGNING(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
+
+    def test_no_auth_request_bind_pfc_08(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        8 |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    # TODO: doesn't announce DCERPC_PFC_FLAG_CONC_MPX
+    # by default
+    def _test_no_auth_request_bind_pfc_CONC_MPX(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_CONC_MPX |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        dcerpc.DCERPC_PFC_FLAG_CONC_MPX)
+
+    def test_no_auth_request_bind_pfc_DID_NOT_EXECUTE(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_bind_pfc_MAYBE(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_MAYBE |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_bind_pfc_OBJECT_UUID(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_OBJECT_UUID |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    # TODO: doesn't announce DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
+    # without authentication
+    # TODO: doesn't announce DCERPC_PFC_FLAG_CONC_MPX
+    # by default
+    def _test_no_auth_request_bind_pfc_ff(self):
+        return self._test_no_auth_request_bind_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        0xff |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+                                        dcerpc.DCERPC_PFC_FLAG_CONC_MPX)
+
+    def test_no_auth_request_alter_pfc_00(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_FIRST(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_LAST(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    # TODO: doesn't announce DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
+    # without authentication
+    def _test_no_auth_request_alter_pfc_HDR_SIGNING(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
+
+    def test_no_auth_request_alter_pfc_08(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        8 |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_CONC_MPX(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_CONC_MPX |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_DID_NOT_EXECUTE(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_MAYBE(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_MAYBE |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    def test_no_auth_request_alter_pfc_OBJECT_UUID(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_OBJECT_UUID |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST)
+
+    # TODO: doesn't announce DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
+    # without authentication
+    def _test_no_auth_request_alter_pfc_ff(self):
+        return self._test_no_auth_request_alter_pfc_flags(
+                                        req_pfc_flags=0 |
+                                        0xff |
+                                        0,
+                                        rep_pfc_flags=0 |
+                                        dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                                        dcerpc.DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
+
+    def test_no_auth_no_ctx(self):
+        # send an useless bind
+        req = self.generate_bind(call_id=0)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason,
+                dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+    def test_invalid_auth_noctx(self):
+        req = self.generate_bind(call_id=0)
+        req.auth_length = dcerpc.DCERPC_AUTH_TRAILER_LENGTH
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason,
+                dcerpc.DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+    def test_no_auth_valid_valid_request(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0, ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # Send a bind again
+        tsf2_list = [ndr32]
+        ctx2 = dcerpc.ctx_list()
+        ctx2.context_id = 2
+        ctx2.num_transfer_syntaxes = len(tsf2_list)
+        ctx2.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx2.transfer_syntaxes = tsf2_list
+
+        req = self.generate_bind(call_id=1, ctx_list=[ctx2])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason,
+                dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_no_auth_invalid_valid_request(self):
+        # send an useless bind
+        req = self.generate_bind(call_id=0)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason,
+                dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_alter_no_auth_no_ctx(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0, ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # Send a alter
+        req = self.generate_alter(call_id=1, ctx_list=[])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def _test_auth_none_level_bind(self, auth_level,
+                                   reason=dcerpc.DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NONE
+        auth_context_id = 0
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="none")
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.reject_reason, reason)
+        self.assertEquals(rep.u.num_versions, 1)
+        self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers)
+        self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor)
+        self.assertEquals(len(rep.u._pad), 3)
+        self.assertEquals(rep.u._pad, '\0' * 3)
+
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_auth_none_none_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_NONE,
+                            reason=dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+
+    def test_auth_none_connect_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_CONNECT)
+
+    def test_auth_none_call_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_CALL)
+
+    def test_auth_none_packet_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_PACKET)
+
+    def test_auth_none_integrity_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY)
+
+    def test_auth_none_privacy_bind(self):
+        return self._test_auth_none_level_bind(dcerpc.DCERPC_AUTH_LEVEL_PRIVACY)
+
+    def test_auth_none_0_bind(self):
+        return self._test_auth_none_level_bind(0,
+                            reason=dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+
+    def test_auth_none_7_bind(self):
+        return self._test_auth_none_level_bind(7,
+                            reason=dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+
+    def test_auth_none_255_bind(self):
+        return self._test_auth_none_level_bind(255,
+                            reason=dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED)
+
+    def _test_auth_none_level_request(self, auth_level):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_NONE
+        auth_context_id = 0
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(len(rep.u.auth_info), 0)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="none")
+
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_auth_none_none_request(self):
+        return self._test_auth_none_level_request(dcerpc.DCERPC_AUTH_LEVEL_NONE)
+
+    def test_auth_none_connect_request(self):
+        return self._test_auth_none_level_request(dcerpc.DCERPC_AUTH_LEVEL_CONNECT)
+
+    def test_auth_none_call_request(self):
+        return self._test_auth_none_level_request(dcerpc.DCERPC_AUTH_LEVEL_CALL)
+
+    def _test_neg_xmit_check_values(self,
+                                    req_xmit=None,
+                                    req_recv=None,
+                                    rep_both=None,
+                                    alter_xmit=None,
+                                    alter_recv=None):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0,
+                                 max_xmit_frag=req_xmit,
+                                 max_recv_frag=req_recv,
+                                 ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, rep_both)
+        self.assertEquals(rep.u.max_recv_frag, rep_both)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        assoc_group_id = rep.u.assoc_group_id
+        if alter_xmit is None:
+            alter_xmit = rep_both - 8
+        if alter_recv is None:
+            alter_recv = rep_both - 8
+
+        # max_{xmit,recv}_frag and assoc_group_id are completely
+        # ignored in alter_context requests
+        req = self.generate_alter(call_id=1,
+                                  max_xmit_frag=alter_xmit,
+                                  max_recv_frag=alter_recv,
+                                  assoc_group_id=0xffffffff-rep.u.assoc_group_id,
+                                  ctx_list=[ctx1])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, rep_both)
+        self.assertEquals(rep.u.max_recv_frag, rep_both)
+        self.assertEquals(rep.u.assoc_group_id, rep.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        chunk_size = rep_both - dcerpc.DCERPC_REQUEST_LENGTH
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    alloc_hint=0xffffffff,
+                                    stub="\00" * chunk_size)
+        self.send_pdu(req,ndr_print=True,hexdump=True)
+        rep = self.recv_pdu(ndr_print=True,hexdump=True)
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        chunk_size = 5840 - dcerpc.DCERPC_REQUEST_LENGTH
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    alloc_hint=0xffffffff,
+                                    stub="\00" * chunk_size)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        chunk_size += 1
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    alloc_hint=0xffffffff,
+                                    stub="\00" * chunk_size)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_neg_xmit_ffff_ffff(self):
+        return self._test_neg_xmit_check_values(req_xmit=0xffff,
+                                                req_recv=0xffff,
+                                                rep_both=5840)
+
+    def test_neg_xmit_0_ffff(self):
+        return self._test_neg_xmit_check_values(req_xmit=0,
+                                                req_recv=0xffff,
+                                                rep_both=2048,
+                                                alter_xmit=0xffff,
+                                                alter_recv=0xffff)
+
+    def test_neg_xmit_ffff_0(self):
+        return self._test_neg_xmit_check_values(req_xmit=0xffff,
+                                                req_recv=0,
+                                                rep_both=2048)
+
+    def test_neg_xmit_0_0(self):
+        return self._test_neg_xmit_check_values(req_xmit=0,
+                                                req_recv=0,
+                                                rep_both=2048,
+                                                alter_xmit=0xffff,
+                                                alter_recv=0xffff)
+
+    def test_neg_xmit_3199_0(self):
+        return self._test_neg_xmit_check_values(req_xmit=3199,
+                                                req_recv=0,
+                                                rep_both=2048)
+    def test_neg_xmit_0_3199(self):
+        return self._test_neg_xmit_check_values(req_xmit=0,
+                                                req_recv=3199,
+                                                rep_both=2048)
+
+    def test_neg_xmit_3199_ffff(self):
+        return self._test_neg_xmit_check_values(req_xmit=3199,
+                                                req_recv=0xffff,
+                                                rep_both=3192)
+    def test_neg_xmit_ffff_3199(self):
+        return self._test_neg_xmit_check_values(req_xmit=0xffff,
+                                                req_recv=3199,
+                                                rep_both=3192)
+
+    def test_alloc_hint(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx = dcerpc.ctx_list()
+        ctx.context_id = 0
+        ctx.num_transfer_syntaxes = len(tsf1_list)
+        ctx.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx.context_id,
+                                    opnum=0,
+                                    alloc_hint=0xffffffff,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx.context_id,
+                                    opnum=1,
+                                    alloc_hint=0xffffffff,
+                                    stub="\04\00\00\00\00\00\00\00")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        req = self.generate_request(call_id = 4,
+                                    context_id=ctx.context_id,
+                                    opnum=1,
+                                    alloc_hint=1,
+                                    stub="\04\00\00\00\00\00\00\00")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+    def _get_netlogon_ctx(self):
+        abstract = samba.dcerpc.netlogon.abstract_syntax()
+        self.epmap_reconnect(abstract)
+
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx = dcerpc.ctx_list()
+        ctx.context_id = 0
+        ctx.num_transfer_syntaxes = len(tsf1_list)
+        ctx.abstract_syntax = abstract
+        ctx.transfer_syntaxes = tsf1_list
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id,
+                        auth_length=0)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        port_str = "%d" % self.tcp_port
+        port_len = len(port_str) + 1
+        mod_len = (2 + port_len) % 4
+        if mod_len != 0:
+            port_pad = 4 - mod_len
+        else:
+            port_pad = 0
+        self.assertEquals(rep.u.secondary_address_size, port_len)
+        self.assertEquals(rep.u.secondary_address, port_str)
+        self.assertEquals(len(rep.u._pad1), port_pad)
+        self.assertEquals(rep.u._pad1, '\0' * port_pad)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertEquals(rep.u.auth_info, '\0' * 0)
+
+        server = '\\\\' + self.host
+        server_utf16 = unicode(server, 'utf-8').encode('utf-16-le')
+        computer = 'UNKNOWNCOMPUTER'
+        computer_utf16 = unicode(computer, 'utf-8').encode('utf-16-le')
+
+        real_stub  = struct.pack('<IIII', 0x00200000,
+                                 len(server)+1, 0, len(server)+1)
+        real_stub += server_utf16 + '\x00\x00'
+        mod_len = len(real_stub) % 4
+        if mod_len != 0:
+            real_stub += '\x00' * (4 - mod_len)
+        real_stub += struct.pack('<III',
+                                 len(computer)+1, 0, len(computer)+1)
+        real_stub += computer_utf16 + '\x00\x00'
+        real_stub += '\x11\x22\x33\x44\x55\x66\x77\x88'
+
+        return (ctx, rep, real_stub)
+
+    def _test_fragmented_requests(self, remaining=None, alloc_hint=None,
+                                  fault_first=None, fault_last=None):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        chunk = rep.u.max_recv_frag - dcerpc.DCERPC_REQUEST_LENGTH
+
+        total = 0
+        first = True
+        while remaining > 0:
+            thistime = min(remaining, chunk)
+            remaining -= thistime
+            total += thistime
+
+            pfc_flags = 0
+            if first:
+                pfc_flags |= dcerpc.DCERPC_PFC_FLAG_FIRST
+                first = False
+                stub = real_stub + '\x00' * (thistime - len(real_stub))
+            else:
+                stub = "\x00" * thistime
+
+            if remaining == 0:
+                pfc_flags |= dcerpc.DCERPC_PFC_FLAG_LAST
+
+            # And now try a request without auth_info
+            # netr_ServerReqChallenge()
+            req = self.generate_request(call_id = 2,
+                                        pfc_flags=pfc_flags,
+                                        context_id=ctx.context_id,
+                                        opnum=4,
+                                        alloc_hint=alloc_hint,
+                                        stub=stub)
+            if alloc_hint >= thistime:
+                alloc_hint -= thistime
+            else:
+                alloc_hint = 0
+            self.send_pdu(req,hexdump=False)
+            if fault_first is not None:
+                rep = self.recv_pdu()
+                # We get a fault back
+                self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                                auth_length=0)
+                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertEquals(rep.u.context_id, req.u.context_id)
+                self.assertEquals(rep.u.cancel_count, 0)
+                self.assertEquals(rep.u.status, fault_first)
+                self.assertEquals(len(rep.u._pad), 4)
+                self.assertEquals(rep.u._pad, '\0' * 4)
+
+                # wait for a disconnect
+                rep = self.recv_pdu()
+                self.assertIsNone(rep)
+                self.assertNotConnected()
+                return
+            if remaining == 0:
+                break
+            if total >= 0x400000 and fault_last is not None:
+                rep = self.recv_pdu()
+                # We get a fault back
+                self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                                auth_length=0)
+                self.assertNotEquals(rep.u.alloc_hint, 0)
+                self.assertEquals(rep.u.context_id, req.u.context_id)
+                self.assertEquals(rep.u.cancel_count, 0)
+                self.assertEquals(rep.u.status, fault_last)
+                self.assertEquals(len(rep.u._pad), 4)
+                self.assertEquals(rep.u._pad, '\0' * 4)
+
+                # wait for a disconnect
+                rep = self.recv_pdu()
+                self.assertIsNone(rep)
+                self.assertNotConnected()
+                return
+            rep = self.recv_pdu(timeout=0.01)
+            self.assertIsNone(rep)
+            self.assertIsConnected()
+
+        if total >= 0x400000 and fault_last is not None:
+            rep = self.recv_pdu()
+            # We get a fault back
+            self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                            auth_length=0)
+            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertEquals(rep.u.context_id, req.u.context_id)
+            self.assertEquals(rep.u.cancel_count, 0)
+            self.assertEquals(rep.u.status, fault_last)
+            self.assertEquals(len(rep.u._pad), 4)
+            self.assertEquals(rep.u._pad, '\0' * 4)
+
+            # wait for a disconnect
+            rep = self.recv_pdu()
+            self.assertIsNone(rep)
+            self.assertNotConnected()
+            return
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        self.assertEquals(len(rep.u.stub_and_verifier), 12)
+        status = struct.unpack_from("<I", rep.u.stub_and_verifier, len(rep.u.stub_and_verifier) - 4)
+        self.assertEquals(status[0], 0)
+
+    def test_fragmented_requests01(self):
+        return self._test_fragmented_requests(remaining=0x400000,
+                                              alloc_hint=0x400000)
+
+    def test_fragmented_requests02(self):
+        return self._test_fragmented_requests(remaining=0x400000,
+                                              alloc_hint=0x100000)
+
+    def test_fragmented_requests03(self):
+        return self._test_fragmented_requests(remaining=0x400000,
+                                              alloc_hint=0)
+
+    def test_fragmented_requests04(self):
+        return self._test_fragmented_requests(remaining=0x400000,
+                                              alloc_hint=0x400001,
+                                              fault_first=dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+
+    def test_fragmented_requests05(self):
+        return self._test_fragmented_requests(remaining=0x500001,
+                                              alloc_hint=0,
+                                              fault_last=dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+
+    def _test_same_requests(self, pfc_flags, fault_1st=False, fault_2nd=False):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=pfc_flags,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        if fault_1st:
+            rep = self.recv_pdu()
+            # We get a fault back
+            self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                            auth_length=0)
+            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertEquals(rep.u.context_id, req.u.context_id)
+            self.assertEquals(rep.u.cancel_count, 0)
+            self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+            self.assertEquals(len(rep.u._pad), 4)
+            self.assertEquals(rep.u._pad, '\0' * 4)
+
+            # wait for a disconnect
+            rep = self.recv_pdu()
+            self.assertIsNone(rep)
+            self.assertNotConnected()
+            return
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # netr_ServerReqChallenge without DCERPC_PFC_FLAG_LAST
+        # with the same call_id
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=pfc_flags,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        if fault_2nd:
+            rep = self.recv_pdu()
+            # We get a fault back
+            self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                            auth_length=0)
+            self.assertNotEquals(rep.u.alloc_hint, 0)
+            self.assertEquals(rep.u.context_id, req.u.context_id)
+            self.assertEquals(rep.u.cancel_count, 0)
+            self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+            self.assertEquals(len(rep.u._pad), 4)
+            self.assertEquals(rep.u._pad, '\0' * 4)
+
+            # wait for a disconnect
+            rep = self.recv_pdu()
+            self.assertIsNone(rep)
+            self.assertNotConnected()
+            return
+
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+    def test_first_only_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST,
+                                        fault_2nd=True)
+
+    def test_none_only_requests(self):
+        return self._test_same_requests(pfc_flags=0, fault_1st=True)
+
+    def test_last_only_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_LAST,
+                                        fault_1st=True)
+
+    def test_first_maybe_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_MAYBE,
+                                        fault_2nd=True)
+
+    def test_first_didnot_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                                        fault_2nd=True)
+
+    def test_first_cmpx_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        dcerpc.DCERPC_PFC_FLAG_CONC_MPX,
+                                        fault_2nd=True)
+
+    def test_first_08_requests(self):
+        return self._test_same_requests(pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                        0x08,
+                                        fault_2nd=True)
+
+    def test_first_cancel_requests(self):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                                              dcerpc.DCERPC_PFC_FLAG_PENDING_CANCEL,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                        dcerpc.DCERPC_PFC_FLAG_LAST |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_NO_CALL_ACTIVE)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_2nd_cancel_requests(self):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_PENDING_CANCEL,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_LAST,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        self.assertEquals(len(rep.u.stub_and_verifier), 12)
+        status = struct.unpack_from("<I", rep.u.stub_and_verifier, len(rep.u.stub_and_verifier) - 4)
+        self.assertEquals(status[0], 0)
+
+    def test_last_cancel_requests(self):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub[:4])
+        self.send_pdu(req)
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 2,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_LAST |
+                                    dcerpc.DCERPC_PFC_FLAG_PENDING_CANCEL,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub[4:])
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        self.assertEquals(len(rep.u.stub_and_verifier), 12)
+        status = struct.unpack_from("<I", rep.u.stub_and_verifier, len(rep.u.stub_and_verifier) - 4)
+        self.assertEquals(status[0], 0)
+
+    def test_mix_requests(self):
+        (ctx, rep, real_stub) = self._get_netlogon_ctx()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 50,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu(timeout=0.1)
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # netr_ServerReqChallenge with given flags
+        req = self.generate_request(call_id = 51,
+                                    pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST,
+                                    context_id=ctx.context_id,
+                                    opnum=4,
+                                    stub=real_stub)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, 50,
+                        pfc_flags=dcerpc.DCERPC_PFC_FLAG_FIRST |
+                        dcerpc.DCERPC_PFC_FLAG_LAST,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+    def test_spnego_connect_request(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # Windows sends garbage
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We don't get an auth_info back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 4,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_integrity_request(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # Windows sends garbage
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=dcerpc.DCERPC_AUTH_LEVEL_CONNECT,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_unfinished_request(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        assoc_group_id = rep.u.assoc_group_id
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 1,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_auth3(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_auth3(call_id=0,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertIsConnected()
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_connect_reauth_alter(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # Windows sends garbage
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We don't get an auth_info back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a reauth
+
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=ctx_list,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_connect_reauth_auth3(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+        ctx_list = [ctx1]
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=ctx_list,
+                                 auth_info=auth_info)
+
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 0)
+        self.assertEquals(len(rep.u._pad1), 2)
+        # Windows sends garbage
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertTrue(finished)
+
+        # And now try a request without auth_info
+        req = self.generate_request(call_id = 2,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="")
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a request with auth_info DCERPC_AUTH_LEVEL_CONNECT
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob="\x01"+"\x00"*15)
+        req = self.generate_request(call_id = 3,
+                                    context_id=ctx1.context_id,
+                                    opnum=0,
+                                    stub="",
+                                    auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We don't get an auth_info back
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, req.u.context_id)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint)
+
+        # Now a reauth
+
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_CONNECT
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_auth3(call_id=0,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        # We get a fault
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_auth_level(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=dcerpc.DCERPC_AUTH_LEVEL_PRIVACY,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_abstract(self):
+        ndr32 = base.transfer_syntax_ndr()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        ctx1b = dcerpc.ctx_list()
+        ctx1b.context_id = 1
+        ctx1b.num_transfer_syntaxes = len(tsf1_list)
+        ctx1b.abstract_syntax = samba.dcerpc.epmapper.abstract_syntax()
+        ctx1b.transfer_syntaxes = tsf1_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=dcerpc.DCERPC_AUTH_LEVEL_PRIVACY,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1b],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_transfer(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        tsf1b_list = [ndr32,ndr64]
+        ctx1b = dcerpc.ctx_list()
+        ctx1b.context_id = 1
+        ctx1b.num_transfer_syntaxes = len(tsf1b_list)
+        ctx1b.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1b.transfer_syntaxes = tsf1b_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        # We change ctx_list and auth_level
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=dcerpc.DCERPC_AUTH_LEVEL_PRIVACY,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1b],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_auth_type1(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        # We change ctx_list and auth_level
+        auth_info = self.generate_auth(auth_type=dcerpc.DCERPC_AUTH_TYPE_KRB5,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_SEC_PKG_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_auth_type2(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        tsf1b_list = [ndr32,ndr64]
+        ctx1b = dcerpc.ctx_list()
+        ctx1b.context_id = 1
+        ctx1b.num_transfer_syntaxes = len(tsf1b_list)
+        ctx1b.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1b.transfer_syntaxes = tsf1b_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        # We change ctx_list and auth_level
+        auth_info = self.generate_auth(auth_type=dcerpc.DCERPC_AUTH_TYPE_KRB5,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1b],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+    def test_spnego_change_auth_type3(self):
+        ndr32 = base.transfer_syntax_ndr()
+        ndr64 = base.transfer_syntax_ndr64()
+
+        tsf1_list = [ndr32]
+        ctx1 = dcerpc.ctx_list()
+        ctx1.context_id = 1
+        ctx1.num_transfer_syntaxes = len(tsf1_list)
+        ctx1.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1.transfer_syntaxes = tsf1_list
+
+        tsf1b_list = [ndr32,ndr64]
+        ctx1b = dcerpc.ctx_list()
+        ctx1b.context_id = 1
+        ctx1b.num_transfer_syntaxes = len(tsf1b_list)
+        ctx1b.abstract_syntax = samba.dcerpc.mgmt.abstract_syntax()
+        ctx1b.transfer_syntaxes = tsf1b_list
+
+        c = Credentials()
+        c.set_anonymous()
+        g = gensec.Security.start_client(self.settings)
+        g.set_credentials(c)
+        g.want_feature(gensec.FEATURE_DCE_STYLE)
+        auth_type = dcerpc.DCERPC_AUTH_TYPE_SPNEGO
+        auth_level = dcerpc.DCERPC_AUTH_LEVEL_INTEGRITY
+        auth_context_id = 2
+        g.start_mech_by_authtype(auth_type, auth_level)
+        from_server = ""
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        auth_info = self.generate_auth(auth_type=auth_type,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_bind(call_id=0,
+                                 ctx_list=[ctx1],
+                                 auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id)
+        self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag)
+        self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag)
+        self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id)
+        self.assertEquals(rep.u.secondary_address_size, 4)
+        self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port)
+        self.assertEquals(len(rep.u._pad1), 2)
+        #self.assertEquals(rep.u._pad1, '\0' * 2)
+        self.assertEquals(rep.u.num_results, 1)
+        self.assertEquals(rep.u.ctx_list[0].result,
+                dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE)
+        self.assertEquals(rep.u.ctx_list[0].reason,
+                dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED)
+        self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32)
+        self.assertNotEquals(len(rep.u.auth_info), 0)
+        a = self.parse_auth(rep.u.auth_info)
+
+        from_server = a.credentials
+        (finished, to_server) = g.update(from_server)
+        self.assertFalse(finished)
+
+        # We change ctx_list and auth_level
+        auth_info = self.generate_auth(auth_type=dcerpc.DCERPC_AUTH_TYPE_NONE,
+                                       auth_level=auth_level,
+                                       auth_context_id=auth_context_id,
+                                       auth_blob=to_server)
+        req = self.generate_alter(call_id=0,
+                                  ctx_list=[ctx1b],
+                                  assoc_group_id=rep.u.assoc_group_id,
+                                  auth_info=auth_info)
+        self.send_pdu(req)
+        rep = self.recv_pdu()
+        self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id,
+                        pfc_flags=req.pfc_flags |
+                        dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
+                        auth_length=0)
+        self.assertNotEquals(rep.u.alloc_hint, 0)
+        self.assertEquals(rep.u.context_id, 0)
+        self.assertEquals(rep.u.cancel_count, 0)
+        self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED)
+        self.assertEquals(len(rep.u._pad), 4)
+        self.assertEquals(rep.u._pad, '\0' * 4)
+
+        # wait for a disconnect
+        rep = self.recv_pdu()
+        self.assertIsNone(rep)
+        self.assertNotConnected()
+
+if __name__ == "__main__":
+    global_ndr_print = True
+    global_hexdump = True
+    import unittest
+    unittest.main()
diff --git a/selftest/knownfail b/selftest/knownfail
index d9e2823..0973e06 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -86,6 +86,9 @@
 ^samba4.rpc.lsalookup with seal,padcheck
 ^samba4.rpc.lsalookup with validate
 ^samba4.rpc.lsalookup with bigendian
+^samba4.rpc.lsa on ncacn_np with seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY
+^samba4.rpc.lsa with seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY
+^samba4.rpc.lsa.secrets.*seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY
 ^samba4.rpc.netlogon.*.LogonUasLogon
 ^samba4.rpc.netlogon.*.LogonUasLogoff
 ^samba4.rpc.netlogon.*.DatabaseSync
@@ -94,6 +97,10 @@
 ^samba4.rpc.netlogon.*.NetrEnumerateTrustedDomainsEx
 ^samba4.rpc.netlogon.*.GetPassword
 ^samba4.rpc.netlogon.*.DatabaseRedo
+^samba4.rpc.drsuapi.*ncacn_ip_tcp.*validate # should only work with seal
+^samba4.rpc.drsuapi.*ncacn_ip_tcp.*bigendian # should only work with seal
+^samba4.rpc.samr.passwords.validate.*ncacn_ip_tcp.*with.validate # should only work with seal
+^samba4.rpc.samr.passwords.validate.*ncacn_ip_tcp.*with.bigendian # should only work with seal
 ^samba4.base.charset.*.Testing partial surrogate
 ^samba4.*.base.maximum_allowed		# broken until we implement NTCREATEX_OPTIONS_BACKUP_INTENT
 .*net.api.delshare.*				# DelShare isn't implemented yet
@@ -211,6 +218,7 @@
 ^samba3.smb2.replay.replay4
 ^samba3.smb2.lock.*replay
 ^samba3.raw.session.*reauth2 # maybe fix this?
+^samba3.rpc.lsa.secrets.seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY
 ^samba3.rpc.samr.passwords.badpwdcount.samr.badPwdCount\(nt4_dc\) # We fail this test currently
 ^samba3.rpc.samr.passwords.lockout.*\(nt4_dc\)$ # We fail this test currently
 ^samba3.rpc.spoolss.printer.addprinter.driver_info_winreg # knownfail or flapping?
@@ -312,3 +320,23 @@
 # we can watch for set methods on.
 #
 ^samba.tests.dcerpc.integer.samba.tests.dcerpc.integer.IntegerTests.test_.*_into_uint8_list
+#
+## We assert all "ldap server require strong auth" combinations
+#
+^samba4.ldb.simple.ldap with SIMPLE-BIND.*ad_dc_ntvfs # ldap server require strong auth = allow_sasl_over_tls
+^samba4.ldb.simple.ldap with SIMPLE-BIND.*fl2003dc    # ldap server require strong auth = yes
+^samba4.ldb.simple.ldaps with SASL-BIND.*fl2003dc     # ldap server require strong auth = yes
+# These are supposed to fail as we want to verify the "tls verify peer"
+# restrictions. Note that fl2008r2dc uses a self-signed certificate
+# with does not have a crl file.
+#
+^samba4.ldb.simple.ldaps.*SERVER_NAME.*tlsverifypeer=ca_and_name_if_available\(
+^samba4.ldb.simple.ldaps.*SERVER_NAME.*tlsverifypeer=ca_and_name\(
+^samba4.ldb.simple.ldaps.*SERVER_NAME.*tlsverifypeer=as_strict_as_possible\(
+^samba4.ldb.simple.ldaps.*SERVER_IP.*tlsverifypeer=ca_and_name\(
+^samba4.ldb.simple.ldaps.*SERVER_IP.*tlsverifypeer=as_strict_as_possible\(
+^samba4.ldb.simple.ldaps.*SERVER.REALM.*tlsverifypeer=as_strict_as_possible.*fl2008r2dc
+#
+# we don't allow auth_level_connect anymore...
+#
+^samba3.blackbox.rpcclient.*ncacn_np.*with.*connect.*rpcclient # we don't allow auth_level_connect anymore
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-cert.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-cert.pem
new file mode 100644
index 0000000..2e2a8b9
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-cert.pem
@@ -0,0 +1,191 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:25 2016 GMT
+            Not After : Mar 11 23:29:25 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Domain Controllers, CN=addc.addom.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:a6:c4:a9:bf:75:ea:4c:8d:3b:fd:8a:0f:b0:a2:
+                    b6:c7:a8:1f:e4:0e:3e:41:ef:d6:10:48:77:7b:4e:
+                    4c:59:e1:bf:6d:c7:18:7b:a8:01:a7:d5:d2:2c:21:
+                    3e:d0:1a:da:58:03:e8:42:f1:53:0e:a7:91:b9:2c:
+                    b9:e7:7a:c9:de:5e:ed:4c:93:6b:cc:dd:17:d0:c7:
+                    d1:f1:7c:3d:0d:6f:df:5d:53:5a:b1:1f:a3:7b:5b:
+                    41:65:0c:7c:ea:53:df:bb:da:41:15:da:49:e3:b9:
+                    2d:bb:b5:af:ef:8c:b8:84:74:d0:18:16:8e:5c:e4:
+                    c2:e7:a1:87:8f:e3:87:8b:0b:bb:90:30:e8:e0:f3:
+                    eb:c0:50:5f:b5:7f:54:9a:1b:34:43:fd:be:5a:80:
+                    6e:0f:63:a2:b3:79:42:4a:85:c8:07:c7:82:55:23:
+                    88:d4:4e:03:2f:f1:95:bd:ed:15:2d:3e:16:cd:ff:
+                    c7:9b:03:29:36:a6:5d:c9:1a:1e:89:a5:ba:66:83:
+                    0f:96:a8:07:9f:24:b9:1b:8f:02:9a:b8:50:29:8b:
+                    be:63:45:fa:45:c3:38:23:a0:98:3a:b4:6b:42:99:
+                    13:36:4b:84:ef:27:89:39:34:79:f8:67:16:7b:9c:
+                    2a:03:41:15:63:46:e4:db:2f:f2:3e:6d:fe:7c:20:
+                    1e:9f:02:48:a4:bc:15:42:a6:f8:38:86:dc:6b:7c:
+                    4e:67:a3:31:81:8e:b6:30:1a:eb:3d:08:25:19:5f:
+                    42:dc:39:ec:79:1d:30:0a:fb:16:8f:3d:19:14:cc:
+                    f5:af:d7:c6:75:cf:b3:96:a2:b2:9b:d9:03:01:a3:
+                    ca:88:1d:72:ed:6f:d1:bf:57:56:8e:b9:07:9b:b9:
+                    04:13:1e:0b:5a:06:6b:2b:43:a2:dc:d5:b7:f4:ba:
+                    d3:ae:9d:ad:fd:d3:8a:7c:2f:87:32:fa:89:88:58:
+                    00:ae:16:2b:9c:1d:58:82:4d:e5:21:da:d5:6c:f7:
+                    a8:40:8b:c7:02:d5:36:30:ef:3f:09:9b:a6:d2:31:
+                    a3:bf:20:d4:a2:9e:26:c4:b4:c3:0f:0b:6c:00:d1:
+                    2c:16:b1:2a:eb:06:d9:d5:98:c3:cd:cb:20:68:ad:
+                    0a:2c:a1:2f:27:41:5c:91:de:49:62:ed:d8:3a:ef:
+                    68:1c:6d:fe:94:c3:28:68:32:60:08:65:cd:02:9f:
+                    97:96:2f:0f:87:27:3d:b9:0f:85:62:e8:2b:9a:b4:
+                    f4:d3:d7:c1:93:96:27:23:29:88:b1:39:99:53:3a:
+                    20:aa:88:44:3b:4a:24:2a:8b:e0:b4:8d:dd:66:30:
+                    df:a6:6e:b7:fc:21:43:16:9e:3e:12:20:c8:7a:30:
+                    c1:3d:ab
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Domain Controller Certificate addc.addom.samba.example.com
+            X509v3 Subject Key Identifier: 
+                3D:BC:70:0C:74:D4:B8:85:49:1D:08:84:C4:1B:27:F2:AF:72:37:D3
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                DNS:addc.addom.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication, msKDC
+    Signature Algorithm: sha256WithRSAEncryption
+         9e:8b:bb:0a:7a:dc:c0:94:33:bc:18:a5:e6:4a:1f:ff:8e:21:
+         b1:8f:33:f0:3e:8b:6c:72:55:c4:47:71:5f:ce:e7:31:ef:5b:
+         62:04:b7:57:8f:a8:27:9f:ed:69:d2:ec:a8:0d:e2:76:33:8d:
+         41:3a:67:61:5c:53:60:c7:53:ed:d7:99:72:29:1d:ae:d3:ee:
+         c9:76:1c:6d:18:47:e9:94:dd:2e:97:3f:99:af:b5:f4:a1:7c:
+         92:f6:4d:b5:c1:7a:0c:38:ba:d1:b6:19:9a:9f:e2:02:84:d4:
+         54:01:38:7b:55:86:4a:ee:3d:85:48:01:da:34:09:69:43:25:
+         7e:6e:06:73:e0:b9:7c:b5:9c:4e:9c:b5:52:85:32:62:62:25:
+         39:fa:02:4b:51:2e:df:8e:52:17:02:50:f4:99:29:bf:7e:97:
+         53:91:12:85:9a:69:62:45:59:c4:5b:3f:af:18:e6:7b:e4:86:
+         5d:f1:9e:5a:2b:3e:14:6e:7e:d4:47:24:ef:d9:a8:ec:d9:a6:
+         cb:b8:4f:1a:86:d9:43:20:41:16:15:5f:81:0d:fe:6b:31:53:
+         c1:f6:84:4c:f3:03:64:d2:e6:44:3d:7a:60:79:d7:37:6f:33:
+         de:c0:a8:b9:6e:fe:b2:79:ac:b4:53:92:b8:0a:59:2b:cc:6b:
+         37:c4:6f:c6:44:02:f7:7c:c5:c6:a6:6f:c2:ad:de:78:1e:48:
+         96:cc:fe:59:2e:53:ce:34:d6:e8:f0:56:43:30:32:90:6f:f9:
+         47:76:ab:99:63:e3:e8:a3:f3:83:98:e9:05:2b:ea:f9:f9:9d:
+         66:70:c7:2c:00:c2:9e:57:3e:31:43:50:50:c8:db:a8:2d:21:
+         4e:6f:39:c2:bd:ef:d8:47:99:27:0d:48:b2:58:f1:be:45:bd:
+         fe:c4:a2:56:fc:06:02:dc:19:33:85:53:ed:38:59:01:16:bc:
+         aa:c5:d3:4b:37:54:83:1b:e5:c1:4b:dd:34:6b:e5:d8:35:86:
+         95:e6:9f:d2:22:84:b1:e2:4f:a7:2e:4d:e6:9c:eb:db:df:42:
+         e1:b4:66:e6:58:d3:28:10:34:97:f3:9c:6b:5f:05:2c:47:2c:
+         e3:75:eb:6f:74:0a:ec:d7:1d:30:80:56:44:12:26:f6:4e:5f:
+         ff:92:f4:62:02:36:9c:62:eb:39:98:53:68:68:95:fb:94:68:
+         69:b8:3c:66:1a:ce:78:c4:cf:c4:6f:21:ac:a8:a6:f4:ab:69:
+         2a:2e:00:5d:f7:67:06:b1:4f:97:58:88:55:d8:6e:eb:a5:98:
+         50:36:21:70:3d:b0:a4:f5:3b:21:b3:1c:f5:a9:dd:c6:4a:c2:
+         89:b8:5a:b3:bc:1f:21:ce:4c:68:5f:98:d8:39:70:d2:7e:a0:
+         90:df:ad:a3:13:eb:3c:93:f6:b8:f4:d9:a7:51:b3:0d:ea:ee:
+         d4:57:aa:db:ca:7c:8a:a0:08:c3:98:9a:3a:b7:ba:2a:50:92:
+         26:c2:e3:11:ba:12:60:24:b9:59:df:62:a8:d7:4d:a3:cb:ea:
+         46:e8:39:f9:83:14:a8:5c:44:75:71:6b:7f:99:bd:68:58:d9:
+         6b:d1:cd:c7:45:95:9e:44:1e:85:35:c0:30:2b:18:aa:eb:2f:
+         93:d5:be:66:5d:70:ed:1d:04:f2:c1:1e:b5:ec:45:0c:04:f6:
+         9d:88:d3:0c:20:5e:5b:23:df:34:a1:f5:ea:b4:a1:44:c0:da:
+         d5:ea:89:e8:b5:cb:dc:f8:92:ee:ac:8d:61:ed:bf:74:2b:28:
+         79:1f:f4:9a:ff:63:bd:e6:aa:79:1d:2c:26:4a:b2:26:53:57:
+         ba:88:0e:eb:19:57:c0:10:a0:1e:81:2a:c0:56:2e:c3:2a:81:
+         bf:c1:5a:e7:48:ce:c1:6a:b9:6c:41:cc:44:a6:b8:70:e2:57:
+         0e:6d:41:d6:61:da:bf:ac:20:2c:a7:2a:67:23:98:00:ba:ce:
+         8b:a8:c2:45:66:a7:08:eb:7f:0a:b5:e7:9b:d6:f4:07:d5:b3:
+         43:cd:27:d4:fa:c9:40:8f:af:b2:36:1c:e7:44:b4:4e:cc:5a:
+         2b:73:ad:8f:c4:d9:47:a6:fb:2c:7d:1a:80:2a:55:b3:80:34:
+         6f:8e:17:27:93:05:21:40:e9:8f:bf:47:6a:52:f5:2e:b5:18:
+         d1:8c:1d:83:04:80:55:fd:21:28:dc:7c:be:c8:c1:5f:e4:40:
+         d3:13:e4:66:bf:ad:92:4e:9b:db:c1:be:a3:42:74:da:c3:2c:
+         0a:da:3f:94:14:ad:7e:de:81:c6:01:6a:f7:7a:b4:25:51:b0:
+         ab:cd:b3:3a:77:bf:c3:6b:04:44:30:73:41:ad:93:49:67:ee:
+         43:d1:96:8e:36:83:2b:1b:6c:e7:cc:3e:d6:16:b9:88:4a:ab:
+         56:c0:76:00:f6:9a:6a:8a:e3:e0:41:75:9d:3b:47:0f:c9:0a:
+         8e:9f:9c:00:92:bb:ae:d8:42:56:35:64:eb:59:13:da:2c:63:
+         83:c3:ec:68:91:b5:f3:71:85:48:54:c3:9d:a1:c8:63:f3:de:
+         5d:a5:34:a9:1e:85:2c:2c:b5:d8:a9:62:8d:26:1f:b2:9e:a7:
+         83:4d:df:69:63:b5:b7:e5:dd:e7:3b:18:e5:b3:77:df:c5:47:
+         b3:f7:8c:e7:5e:87:2e:46:e3:8f:b1:2b:9b:c6:26:2d:1a:28:
+         30:13:10:86:5b:46:87:b1:2d:12:ce:b6:fe:1c:4e:44
+-----BEGIN CERTIFICATE-----
+MIIJ9DCCBdygAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5MjVaFw0zNjAzMTEyMzI5MjVaMIG4MQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEbMBkGA1UE
+CwwSRG9tYWluIENvbnRyb2xsZXJzMSUwIwYDVQQDDBxhZGRjLmFkZG9tLnNhbWJh
+LmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkBFiZjYS1zYW1iYS5leGFtcGxlLmNv
+bUBzYW1iYS5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAKbEqb916kyNO/2KD7CitseoH+QOPkHv1hBId3tOTFnhv23HGHuoAafV0iwh
+PtAa2lgD6ELxUw6nkbksued6yd5e7UyTa8zdF9DH0fF8PQ1v311TWrEfo3tbQWUM
+fOpT37vaQRXaSeO5Lbu1r++MuIR00BgWjlzkwuehh4/jh4sLu5Aw6ODz68BQX7V/
+VJobNEP9vlqAbg9jorN5QkqFyAfHglUjiNROAy/xlb3tFS0+Fs3/x5sDKTamXcka
+HomlumaDD5aoB58kuRuPApq4UCmLvmNF+kXDOCOgmDq0a0KZEzZLhO8niTk0efhn
+FnucKgNBFWNG5Nsv8j5t/nwgHp8CSKS8FUKm+DiG3Gt8TmejMYGOtjAa6z0IJRlf
+Qtw57HkdMAr7Fo89GRTM9a/XxnXPs5aispvZAwGjyogdcu1v0b9XVo65B5u5BBMe
+C1oGaytDotzVt/S6066drf3TinwvhzL6iYhYAK4WK5wdWIJN5SHa1Wz3qECLxwLV
+NjDvPwmbptIxo78g1KKeJsS0ww8LbADRLBaxKusG2dWYw83LIGitCiyhLydBXJHe
+SWLt2DrvaBxt/pTDKGgyYAhlzQKfl5YvD4cnPbkPhWLoK5q09NPXwZOWJyMpiLE5
+mVM6IKqIRDtKJCqL4LSN3WYw36Zut/whQxaePhIgyHowwT2rAgMBAAGjggH3MIIB
+8zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEu
+ZXhhbXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEG
+CWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwSQYJYIZIAYb4QgENBDwWOkRv
+bWFpbiBDb250cm9sbGVyIENlcnRpZmljYXRlIGFkZGMuYWRkb20uc2FtYmEuZXhh
+bXBsZS5jb20wHQYDVR0OBBYEFD28cAx01LiFSR0IhMQbJ/KvcjfTMB8GA1UdIwQY
+MBaAFKI+Aiqjp005tAhNmcwMdTbqJ8M+MEAGA1UdEQQ5MDeCHGFkZGMuYWRkb20u
+c2FtYmEuZXhhbXBsZS5jb22gFwYJKwYBBAGCNxkBoAoECAEjRWeJq83vMDEGA1Ud
+EgQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0G
+CWCGSAGG+EIBBARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMv
+Q0Etc2FtYmEuZXhhbXBsZS5jb20tY3JsLmNybDAmBgNVHSUEHzAdBggrBgEFBQcD
+AgYIKwYBBQUHAwEGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggQBAJ6Luwp63MCU
+M7wYpeZKH/+OIbGPM/A+i2xyVcRHcV/O5zHvW2IEt1ePqCef7WnS7KgN4nYzjUE6
+Z2FcU2DHU+3XmXIpHa7T7sl2HG0YR+mU3S6XP5mvtfShfJL2TbXBegw4utG2GZqf
+4gKE1FQBOHtVhkruPYVIAdo0CWlDJX5uBnPguXy1nE6ctVKFMmJiJTn6AktRLt+O
+UhcCUPSZKb9+l1OREoWaaWJFWcRbP68Y5nvkhl3xnlorPhRuftRHJO/ZqOzZpsu4
+TxqG2UMgQRYVX4EN/msxU8H2hEzzA2TS5kQ9emB51zdvM97AqLlu/rJ5rLRTkrgK
+WSvMazfEb8ZEAvd8xcamb8Kt3ngeSJbM/lkuU8401ujwVkMwMpBv+Ud2q5lj4+ij
+84OY6QUr6vn5nWZwxywAwp5XPjFDUFDI26gtIU5vOcK979hHmScNSLJY8b5Fvf7E
+olb8BgLcGTOFU+04WQEWvKrF00s3VIMb5cFL3TRr5dg1hpXmn9IihLHiT6cuTeac
+69vfQuG0ZuZY0ygQNJfznGtfBSxHLON16290CuzXHTCAVkQSJvZOX/+S9GICNpxi
+6zmYU2holfuUaGm4PGYaznjEz8RvIayopvSraSouAF33ZwaxT5dYiFXYbuulmFA2
+IXA9sKT1OyGzHPWp3cZKwom4WrO8HyHOTGhfmNg5cNJ+oJDfraMT6zyT9rj02adR
+sw3q7tRXqtvKfIqgCMOYmjq3uipQkibC4xG6EmAkuVnfYqjXTaPL6kboOfmDFKhc
+RHVxa3+ZvWhY2WvRzcdFlZ5EHoU1wDArGKrrL5PVvmZdcO0dBPLBHrXsRQwE9p2I
+0wwgXlsj3zSh9eq0oUTA2tXqiei1y9z4ku6sjWHtv3QrKHkf9Jr/Y73mqnkdLCZK
+siZTV7qIDusZV8AQoB6BKsBWLsMqgb/BWudIzsFquWxBzESmuHDiVw5tQdZh2r+s
+ICynKmcjmAC6zouowkVmpwjrfwq155vW9AfVs0PNJ9T6yUCPr7I2HOdEtE7MWitz
+rY/E2Uem+yx9GoAqVbOANG+OFyeTBSFA6Y+/R2pS9S61GNGMHYMEgFX9ISjcfL7I
+wV/kQNMT5Ga/rZJOm9vBvqNCdNrDLAraP5QUrX7egcYBavd6tCVRsKvNszp3v8Nr
+BEQwc0Gtk0ln7kPRlo42gysbbOfMPtYWuYhKq1bAdgD2mmqK4+BBdZ07Rw/JCo6f
+nACSu67YQlY1ZOtZE9osY4PD7GiRtfNxhUhUw52hyGPz3l2lNKkehSwstdipYo0m
+H7Kep4NN32ljtbfl3ec7GOWzd9/FR7P3jOdehy5G44+xK5vGJi0aKDATEIZbRoex
+LRLOtv4cTkQ=
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-key.pem
new file mode 100644
index 0000000..6f11ced
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-key.pem
@@ -0,0 +1,54 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIJjjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIpUlK4cdzu/UCAggA
+MBQGCCqGSIb3DQMHBAju3WkqK++BQgSCCUit3hNjGErKHafSn7CLnhKlNTzvtaAv
+PwTStReWMNULMJ6Z1Rhm0jO8x5BBStEHy3A4h1GmWNSyIzOhZqGi3K2SqpBa9+TP
+SSYzeNKCsv/06QeQ3GTJJF2GTKLw8I2tZOJnNy5wYprGDuz92AAncj645C8xBYb/
+RgN1YyHh3B2tkPlOVZZU8z8hH9iaDwKiXfY0+EgVDSCj1pHWKEzGzhx4UtyKhCc5
+1J4fyPA+8SzJ0tRAohLHdrm9KIn/tawbbS6Ce8iwLBad6A4k73WgYW4ZawMA+n1X
+OIhyCR/dfIlPRPcojyN4c2O5uPmGCDErt6awUY7LyctZPRAUBbk83i69HbRvK/kq
+JuyhTIWUbhVpvt6HZxCC0cFBy7tlSeOL3LXlu1JoWAEqCVm8vHQPs3WTwTTrShHP
+kauortTdLstddxqPwWKmUcSLcviK+IfD54y3fJGYMr5goLdXCGfb7XZQoXANIYKP
+di/jXOn6PTjKdC7/J8G0UZmRmjEvxp5CBPiNqr07YJUfu7IN4KxEKRf/aDyJ1npw
+JEaMFiBvFx0Vr5nm7trQ43TdkuHbn7MY6nkPMbzC8a8KcKFGbnU/n6TIyeGYo2o5
+2ICW3QmXjzhrWiDzU+cEbSEs77UAQJNrSxRVuKKuwLEnuy6/pRhlxex6Hp6nNCOd
+dTZKDeqHsntRa6zTuOleh+XOMHeSuHjhJdThxEszHPFsYzH/EtE8TaKiBQE9kecy
+M+nbxfMqRTYitsl8wTPiuoTgrzDjUJcAAsS/jDNYUA63NCG2BT9Gq9qY48DwfWGM
+YPMYj6CfRwsyAPSeC7hV31olnGAp15kBhM2TpxE6KqUnGuxL0ET9LJsHjaRsP+r1
+KMjNmibQSy948LIvHhEtdfg5/Jn5jv6JHmmSBktma4C+MUfQKBinzy6MM1IAaZlZ
+hUdL14VnERFh9OGLjZGBOBlk/9FU2Yf4lfAtLgT95GezlYQIOqpG/Pkm04wH71+W
+bfW+53gBQqcaSexM5QFsqRspq7yyLX0mElG6z5gOmEJN3rV+DZ2d+84dxKQ5rX++
++mLYlfQKe1K/1F8HVXH/1ZMeAkzvxk1Odlm6fhwcTHciX3CSESAtJeLSD3PNgSE1
+f0Lep/CteZecOnM63T454jC4V49qXYgQBD32WuOHIbFhHd/lQ5Zj+3T5LgKlE5H3
+5oTUU/+DFgqFrwHlM5f1Ha9G8rjuHucjHyQ7ix7jNjEIoG82It8ESisIOoOwb3bc
+Jjkfj3v7f5Axi0wyD94KLFntBCI64uhyTk+JuvagA2KnLQ5uWEFRgqhMXRNg3kbI
+STOAopjoB2bnIvQZxQ8hxOT67EjKd7iJJXh2zfBAQ7dvnVKznvdSamTcB/Uh3IQR
+RjOZE3ej3lEb4XCM2NCyqZvFgoU+Og4yg+4yainCE+6Jt1jYNvms2iabxC+ZQZ3t
+/vCgVDvnULX5FJvphGK/Idua5FFIeSNLOoK9qjfrBNL9kdFVMWCyMyK0cIdsZFRp
+2at32a9n8OU1rRYgFn8kaWK4JQqKelm1qVCixcHLUtI/cyp+t7vvjOGRnDrbfoK0
+ae+pt0De0aBsOMKmUetn3CXFXIyQa/FJ3W8X7yl82ctS3ZZmWcND0Lqhoa1JADdj
+vbxxGzh1rJPsuPePwIXAVqtbVJD84i+dP0+i1oR/e5jNgRKj0tJcfZnnsvmSIldY
+FvxDpIX2h/tDrTKfwQzFHBBuPA00ZuGfftGc4LD7SOVjVb6CF2GMX/0+zmKlPf56
+FvxvGl+GwLPz/BaSGlT/4DApF0HJEZ1AeSvzHGhdgWecbk4s/lMAnv17vH2YWql1
+uJ54FgDAT0ufzAb0aHAl3YO8pYDOOXGqHaqWRMJvtuh15FB52HYvt+Ojo2mzPu4j
+lvUcOBRMzgPl8zcs0L/WgE0SggC6DpXGU+rK1/J91qlNRBJ664R6j0iyskPvdzYN
+aJ8ZZSJ+yQPralfSD/Sd+RcRviP2draINoyVbFHSH2zvvhcZc0ETL24tNI/tSXpR
+Cw86CajiN7T691pC3eZyQLSQJnMSY/0F0i12KU3J+1kq6eeMSoPc5EKItfH5wxjw
+RPnJAU84HGIQEAhEn6Ht1XaZcMfo9xyr9WMpmyH4OoTLt1+gFGgSCfbjsusl9aNl
+EDhcYmav8OFHE48qvEoYyHD7S3fwsxKFSCJpYTRweBRQaEzpq1z90tVxzhLZFpJe
+A7sw/HpiOuty0hDHQ5JaiRBsQ+CiOsVdWZXzaI/H0aoaPbLbpursuTPPPG5OFqvL
+WIIDfFYZ9rhy8t/YaAeTyFoLx1VU7m88ZZndyaVXhnqp7iaU14NXlelPeyKJ3ZXc
+pd6gZ4l1XAJHbeyiBx+6khtZb6JTLbYpwfbjTqPmDtNw2PVb5rwF0ZSeP6LXKOEM
++WntayDMbWK67yUCBlkPTpY4k+8nV8pJ+th9sR8LlL7d9rZgbSjmxG8XgjC7HHg+
+4I2O7poGQMVgtMeIsGZRIS0cTpm1dpCRfFQPR0DOB6+wjDRPIRNNiTZQYdkpfHQ1
+QSpCskaWG9HzJQGSu+meN4LdaKEoXwNMMz77fCTWhXXkvy6Ujm44EpOOfaHXpg7T
+AQagXzyII0xXj+rAFkqmnyygWgxpou6f3MkoWxIC/qYocC4Ci3oWMAZVssWfnhoP
+T/ZormTZN3uQCZYtfwTjbjh5efFQc4I9THxkHV6eyhGE7MQO/D/5zjBzkwmNsU6b
+GttZyyHto+oKlXMF9dNKxLkQbtVO8ZDIDuNP+sb/m7wj3GG2MNoklp6Cd7lckimv
+PqkQP7PQa8h6EeFXmTKqi7vfgsQAEIzTfOLJDvfHhLC54pjbFPR8vY0T5Y2Dwe8w
+rMPwFenW1ae6DjeGDHij3+QbQmTYZeu8Hblhs5DNhy7wtZX05IUsioVfJLC9QngN
+Y5u7OuMGQLPdcPjWHBuZsl/lMdii1lOB/PrExrEIsybSGPQonDfK6x1pOeyIJsbr
+fDnevcamxLpG6BU8U7AqE1QHa/sJGNO/lgsHGLrb5A2id1J+VttSxSG09sML49uw
+T+vmgdVbVjsYRvMSjMfwRrVp4NARlXph5FUA2DxAKXvr1reicAleVgQDcokAHhLi
+vGZ34XFIZHB+YZvHxd3tZxLcKvAMZQJTPlO6RdD9cx+84DEfevaJilUjyu6Ga4ty
+HjA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-openssl.cnf b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-openssl.cnf
new file mode 100644
index 0000000..bdd0364
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-openssl.cnf
@@ -0,0 +1,250 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = CA-samba.example.com         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-samba.example.com-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-samba.example.com-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-samba.example.com-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-samba.example.com-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-samba.example.com-crl.pem           # The current CRL
+crl         = $dir/Public/CA-samba.example.com-crl.crl           # The current CRL
+private_key = $dir/Private/CA-samba.example.com-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-samba.example.com.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = 7300           # how long to certify for
+default_crl_days= 7300            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = 4096
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = US
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = SambaState
+
+localityName            = Locality Name (eg, city)
+localityName_default    = SambaCity
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = SambaSelfTesting
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Domain Controllers
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = addc.addom.samba.example.com
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = ca-samba.example.com at samba.example.com
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+#[ usr_cert_mskdc ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a domain controller certificate.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+nsCertType          = server
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Domain Controller Certificate addc.addom.samba.example.com"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=@dc_subjalt
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for our domain controller certs
+# serverAuth - says cert can be used to identify an ssl/tls server
+# msKDC - says cert can be used to identify a Kerberos Domain Controller.
+extendedKeyUsage = clientAuth,serverAuth,msKDC
+
+[dc_subjalt]
+DNS=addc.addom.samba.example.com
+otherName=msADGUID;FORMAT:HEX,OCTETSTRING:0123456789ABCDEF
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-private-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-private-key.pem
new file mode 100644
index 0000000..eec21e4
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-private-key.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJJwIBAAKCAgEApsSpv3XqTI07/YoPsKK2x6gf5A4+Qe/WEEh3e05MWeG/bccY
+e6gBp9XSLCE+0BraWAPoQvFTDqeRuSy553rJ3l7tTJNrzN0X0MfR8Xw9DW/fXVNa
+sR+je1tBZQx86lPfu9pBFdpJ47ktu7Wv74y4hHTQGBaOXOTC56GHj+OHiwu7kDDo
+4PPrwFBftX9Umhs0Q/2+WoBuD2Ois3lCSoXIB8eCVSOI1E4DL/GVve0VLT4Wzf/H
+mwMpNqZdyRoeiaW6ZoMPlqgHnyS5G48CmrhQKYu+Y0X6RcM4I6CYOrRrQpkTNkuE
+7yeJOTR5+GcWe5wqA0EVY0bk2y/yPm3+fCAenwJIpLwVQqb4OIbca3xOZ6MxgY62
+MBrrPQglGV9C3DnseR0wCvsWjz0ZFMz1r9fGdc+zlqKym9kDAaPKiB1y7W/Rv1dW
+jrkHm7kEEx4LWgZrK0Oi3NW39LrTrp2t/dOKfC+HMvqJiFgArhYrnB1Ygk3lIdrV
+bPeoQIvHAtU2MO8/CZum0jGjvyDUop4mxLTDDwtsANEsFrEq6wbZ1ZjDzcsgaK0K
+LKEvJ0Fckd5JYu3YOu9oHG3+lMMoaDJgCGXNAp+Xli8Phyc9uQ+FYugrmrT009fB
+k5YnIymIsTmZUzogqohEO0okKovgtI3dZjDfpm63/CFDFp4+EiDIejDBPasCAwEA
+AQKCAgAloAU0PyRHdS3tu/JiRbO7RAE98MC3G6dOMStT1IyBUt9foyWw8Gy/Mwyi
+DDYhuY09glQqlkvI6KGGB8NBqIBW/U/IkRInPFKdNhf1xbP4jh707VNu1taJhEMy
+yyh7rcSym0FH7uHw0NyylwFEqJkQuVIhvSUNbEdU/yqYmhsAkfsVQxOnfSDZWMjf
+KAUsZ6rZFCyYOpWaPz58A4WjTp+csbSEBOpgC+HINVc1bIH0nSeD/otIO+RWgh5y
+usPdBlkRu8wOj4Z4r05cG13ZDnB3jyG7QBSBHNRTpW3zALWaZvLgsxUg5+ib0W0b
+UBbQeKE57rsmlN4ZXa3ny+U4l/6QQDSMtrWPNBCMrkt1Q/52gQk1IGeONUAQdLQT
+uBx0Vdn5ZvIFRBnkQl2KWOBWTdD2v0qxIHhXlsWX7tGVU7eh3GIAPoFzQZFHpPhA
+RObE8fNg/3HMVGDUwXnd4k+6c1t+Ioa17FuLJE4lr5c55Klq2lJ4Oq2Jd6AfoGjv
+anA45ChI6lrg2Kt7OhUEHIIHyZmm7eNmBHoGA3r+YJyiQQIGSiNjH+Up54KWa88z
+p+ZY1u3VdOiNuKVlRn79q85Th4HyMlx7wuY+t8HAj42Vt03Uy7iDaaTfuPxehMyS
+MqcRWR5MhavR5ShTtsIXwvUgWj/YcqaOb9Zfe2Y1RgFURKN3YQKCAQEA0I1hTnGs
+KE5l9dGowKm2io6pZr8J2B8ITjp8pdAaY46Ws1tfcTkbbpBUvyrflCIgLIP9KTP3
+6cc4HrK11mf8rPD1pHNWJd7CjPTLQFMYu+h8YlBqKwrgA8owLzUWG4omS0vehCnG
+6OIPi8ceUc2u6XW+TGKP4n8GXJrrKaw9hw83u6h9YQCpgfwF4QpwX8LzTMKnI7te
+HxUQFlhKX3vci+dP4n29c6yGl57830E7LeQGRfjo/NAV3pAAcHk79cEzOJQCN1Wy
+bNU2kcoOA3tGTI8tCfBdwpN11Sz2/tu4ytJE2weP5S7r9xOTq8t+iKQ9+NLhAvJU
+8S2mIkyFAi8tWQKCAQEAzLWsJ3qxyaLHv4tOFTqenSj0CbB25OIzDQNLT++L4fYn
+YAqL6/G83bRVbdYvfJ3ZdZdnseluGrR8ZcxdqioLCws66+O1vC8GkHI5aBKZt4MD
+Um+SzD6ZnARYcTbtRmPUJHxIdny2dbYLe5dDlqTFIV+olWDR+1YMSzXt/VW+jx9I
+tHhw8LJAxhMhDt0Gh+CxNFHQYdkdK/OuNTBufT/rxeT3E5t3TbSG29pU/F2Rce1G
+CCy0nbFsTMjPusSzwFJILWHdvBAYJceOajvqZhlaTV11u/qrj9gb+nJkH+rKvJnA
+pK2YyFWqomnGCZB61Y5LOfjk2b1BfVGCdqpRrBCOowKCAQBun3/NB1jlbGiDEvor
+cBpmtrO+z3jeTd+u9zElFxTYWEsxyjb/LOaTKDX7zTcZMVzVoBGKaImJVOY8yljP
+6QrLhWkXGSLKJbYW5MZnUWyeR/yqfbNDL5qSCA61C7i1VPtpF05p1msvHrJWV4GK
+rMqqBY2yoNlnsC9ksbwpt7ZPTNAoV4BiEuLXEyLfMxVWhmdeASZ9Oqb7X8XPxHd2
+3JGpGEJ0hnQWxp4CERBbMBO/DOQS+6xCZfIjw0ioYHZgrmGIEmJ2jZt+RT6T6JS0
+XhB1DcE7M2fYjTWEpTxDBbOoyg5CDGnUjKYXwiejieaNfmls8hbu5DIQWEF2khY/
+iVzJAoIBAENOiGgCo2oUp3CHMQkx2Oz7hiGZb74Z0Yc5yg1iSa/l61Rco1zUgrCy
+llQi1EI49EMBoQqSIa2OIkimRTWp1S+wZZMhr6NMIvBjXhSl6Py5iuIT5URaYM83
+bozq7mDyedH1Oy4aGzPgwy3DsmlZi6dJeHiE+QWWaTxhYvqksp8EPjd4UkoRkdKO
+f5QPgBI1Ao6dR9KkPD8zQ9ghMHLmDXNnsQU1XKij7qNiygagDS5UQW52pHwk1eL5
+M7PI8QEPDMQ/JVSsRgRF9MFhKdSgCVzemdNQvA/zkl9qNRl5bWdNdlWu7kkQQaZc
++Mw0QO7udjV9bGFbJKk7n5W8slXMq9kCggEAJ2yzyZKdQZtuXpf6WN6sNqRJ6CHo
+k9en+acEg9Y+5lVt2CRblprQxhdUV2KyN7G8GxV0hMwmHtMTeB4j6jhdZrAAZGVW
+upqCfY2vSYQ/svCeB0Fs5DMEI4iCS5Drn8gKKi/zWAbox9sb+zaYT/Ot5p2Ki/HH
+YIh+p8EE6IFWE3jChabPQieXVOC7tg/qaxWVHTv7Qe2fdZTY3XifTcN7hVghf/bH
+Vn+VdU2u/7hE7X3y9YNETNSin5U3F0BSm1tUQimUzU50+9Nl2UGPBI39e+15qRz7
+JHocpq9h9+k3T7qWwJxX74YhcTqdb1pGsKUEmo7r6rPR4L5h5nCF3OgR9g==
+-----END RSA PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-req.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-req.pem
new file mode 100644
index 0000000..5b356fa
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-S02-req.pem
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIFEjCCAvoCAQAwgcwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTYW1iYVN0YXRl
+MRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNVBAoMEFNhbWJhU2VsZlRlc3Rpbmcx
+GzAZBgNVBAsMEkRvbWFpbiBDb250cm9sbGVyczElMCMGA1UEAwwcYWRkYy5hZGRv
+bS5zYW1iYS5leGFtcGxlLmNvbTE1MDMGCSqGSIb3DQEJARYmY2Etc2FtYmEuZXhh
+bXBsZS5jb21Ac2FtYmEuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCmxKm/depMjTv9ig+worbHqB/kDj5B79YQSHd7TkxZ4b9txxh7
+qAGn1dIsIT7QGtpYA+hC8VMOp5G5LLnnesneXu1Mk2vM3RfQx9HxfD0Nb99dU1qx
+H6N7W0FlDHzqU9+72kEV2knjuS27ta/vjLiEdNAYFo5c5MLnoYeP44eLC7uQMOjg
+8+vAUF+1f1SaGzRD/b5agG4PY6KzeUJKhcgHx4JVI4jUTgMv8ZW97RUtPhbN/8eb
+Ayk2pl3JGh6Jpbpmgw+WqAefJLkbjwKauFApi75jRfpFwzgjoJg6tGtCmRM2S4Tv
+J4k5NHn4ZxZ7nCoDQRVjRuTbL/I+bf58IB6fAkikvBVCpvg4htxrfE5nozGBjrYw
+Gus9CCUZX0LcOex5HTAK+xaPPRkUzPWv18Z1z7OWorKb2QMBo8qIHXLtb9G/V1aO
+uQebuQQTHgtaBmsrQ6Lc1bf0utOuna3904p8L4cy+omIWACuFiucHViCTeUh2tVs
+96hAi8cC1TYw7z8Jm6bSMaO/INSinibEtMMPC2wA0SwWsSrrBtnVmMPNyyBorQos
+oS8nQVyR3kli7dg672gcbf6UwyhoMmAIZc0Cn5eWLw+HJz25D4Vi6CuatPTT18GT
+licjKYixOZlTOiCqiEQ7SiQqi+C0jd1mMN+mbrf8IUMWnj4SIMh6MME9qwIDAQAB
+oAAwDQYJKoZIhvcNAQELBQADggIBADLgdZz1gvzpnZPwd5KCxjwKgiotlUGBh6t6
+cLhyomCN02adMr0PPJP/n3r1Zsaq2db/zktP8J5fUYqA9vJZzYukzkKRHbl+rdHS
+JVEvHmbsG3729V9cy40kuL0EAM0weBbfQZaeFxfcLxl5v14QOxvldrmYSK5GaLh8
+WSEz4uljrI8ee3q8Cn08xlZ2Dr3MoHI9unEcLJFXkpCwVBALFhw5dG8od3jl8AyS
+WeMVbdD9fm4jnHE/RDSPDqUqMCGIYmrB5amGO5rSLDTWxDxrcHFRM7sa359nW2IA
+GoZd+r8Vf2AZ8i/KRgH7uIFB2BJm4L0QiVlajy3odW3zhQIVXNh9p58aGzOFQGkq
+Gsld4WI3gZZeSvGgGIjoB2+AYRjxTzUn5qSFVev5sFLK3cNdPZo66xltuPBhfXB/
+v/+/TQC80oZ8oZGdgYvBBT1IEg4pwB5Myqeps9J7kbJVmtxR2EGlq/aGN0yE/fy9
+S8ners0iXBJP18suSwbjj2unZQMBYLIgHLkzztxAMGYBlfEljSAvDfFCsK5Rkmya
+soxd1qHHMG8Ap+WZagpkK9tv42HwmbYKVeDArGAHr53aC4ripgrSBnzpmkiSyi4p
+mb3L5K/ZSOxo3xrS0wERq3p6FalF8/AhctgzWOgMvikVoTUy0xPsG/hulXPyk2UG
+rYn+WPQz
+-----END CERTIFICATE REQUEST-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-cert.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-cert.pem
new file mode 120000
index 0000000..43b4b51
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-cert.pem
@@ -0,0 +1 @@
+DC-addc.addom.samba.example.com-S02-cert.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-private-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-private-key.pem
new file mode 120000
index 0000000..3170fe7
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/addc.addom.samba.example.com/DC-addc.addom.samba.example.com-private-key.pem
@@ -0,0 +1 @@
+DC-addc.addom.samba.example.com-S02-private-key.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-cert.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-cert.pem
new file mode 100644
index 0000000..7b1b6a1
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-cert.pem
@@ -0,0 +1,190 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:28:44 2016 GMT
+            Not After : Mar 11 23:28:44 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Domain Controllers, CN=localdc.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:e6:a4:76:ce:e8:63:fe:57:f9:a3:ae:e0:ad:4d:
+                    e2:15:8e:d8:27:c8:7d:7f:2b:b1:e8:aa:50:8f:94:
+                    f9:c7:71:3f:52:32:91:d1:6d:52:22:5f:cd:8d:cc:
+                    62:16:7a:8b:58:65:ed:07:f7:ea:24:d3:88:d8:26:
+                    ca:eb:ec:16:a7:84:1c:7e:15:46:64:09:22:46:b9:
+                    dd:5c:07:84:50:a7:4e:31:3f:01:23:d1:f8:36:04:
+                    1a:bb:d4:e5:b6:d4:1b:5c:16:c9:9e:37:8a:3e:a9:
+                    7d:30:24:40:b2:b5:44:40:fa:5c:6f:d5:3e:ff:32:
+                    c2:e7:24:0a:e4:e4:aa:9f:ff:4c:ac:be:37:58:22:
+                    08:16:0e:f6:a7:2f:b5:6c:4f:ac:7b:a4:82:a8:9f:
+                    38:64:17:6e:72:b6:7c:4c:c5:44:2a:0a:b4:25:0d:
+                    b0:0c:ab:98:4a:f9:1a:1a:c9:a6:59:f4:00:a5:0a:
+                    6f:0a:d0:a5:34:ca:0f:f4:0e:fb:ba:d7:bb:3e:2c:
+                    7c:0c:68:6b:26:ff:1c:29:fe:77:f9:30:85:0d:44:
+                    8c:af:90:8a:70:93:5d:3a:b6:18:8b:a5:85:11:5c:
+                    a3:5d:57:16:dd:c7:c8:00:f1:05:71:c2:6e:07:3c:
+                    37:69:36:7c:12:c5:9e:1b:69:11:45:44:1e:eb:b9:
+                    b2:96:b1:89:cd:4d:fa:89:eb:92:49:f2:46:35:f3:
+                    9d:87:3c:be:e4:f8:b7:31:a7:36:4b:81:76:9b:b2:
+                    04:d5:80:7d:4f:e6:02:ed:24:4c:a0:03:c4:9d:00:
+                    9f:9d:71:93:0d:a5:b8:37:62:2b:03:c3:bd:24:25:
+                    2c:c3:43:d4:c8:27:b0:6d:05:d4:c6:c5:d8:5b:09:
+                    94:e8:27:6b:d9:6d:b7:bc:de:76:bf:d5:9c:36:26:
+                    04:b9:97:1d:f0:c9:8d:91:93:82:32:0d:b7:16:97:
+                    41:31:9a:22:0b:2e:ba:99:51:28:6b:f5:04:ba:c9:
+                    3d:57:0c:72:e8:e1:24:1a:d4:2a:6a:e7:e3:b6:b9:
+                    94:61:e3:4e:42:81:e5:43:e4:1e:ef:6d:c4:5d:a4:
+                    f9:b4:ec:3a:8a:34:fe:b5:c7:a8:fe:19:8d:cf:7d:
+                    1b:60:21:ba:25:6f:35:cd:4f:72:28:42:7d:87:08:
+                    aa:da:33:7e:63:e6:5b:5f:e7:01:a8:e3:0b:d3:08:
+                    5a:a6:df:ea:e7:2b:13:48:a7:83:32:96:c4:ba:d1:
+                    ff:15:66:52:33:86:46:5f:c2:9f:59:4a:00:98:b7:
+                    1b:a1:87:25:df:ad:68:5b:f7:26:17:2b:eb:84:62:
+                    9d:c3:bd:99:67:6a:02:5d:70:72:3e:18:92:99:8c:
+                    bd:d9:4f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Domain Controller Certificate localdc.samba.example.com
+            X509v3 Subject Key Identifier: 
+                E1:DF:73:0B:F1:3E:86:43:A4:B3:E9:8D:44:7D:3C:B2:19:C1:BC:F2
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                DNS:localdc.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication, msKDC
+    Signature Algorithm: sha256WithRSAEncryption
+         89:2c:57:98:17:c1:73:a6:10:02:6f:a6:ac:47:1c:37:2d:1d:
+         a1:3c:c5:29:b6:3a:e6:e8:14:ec:3b:74:ee:da:db:2d:97:3e:
+         d3:8c:9d:42:7e:b0:46:e9:54:74:4f:34:df:9e:34:7f:9e:8a:
+         9d:4d:b2:cf:fb:71:3f:cb:32:e6:45:e7:b4:d3:9e:e8:ca:a5:
+         cf:16:7b:76:b5:4e:e0:b9:bb:79:b1:82:a7:d3:23:cb:3c:46:
+         63:63:96:b3:5b:62:9e:99:dc:02:17:f9:07:63:86:76:06:1a:
+         02:1b:9a:df:1d:cd:e7:46:fe:9a:13:87:47:dd:e2:77:58:50:
+         a2:6c:c9:a0:f8:14:1f:3b:d7:59:9c:89:bd:2e:2d:ce:60:f4:
+         c6:2c:e3:63:cf:34:84:61:d9:90:2e:90:fc:5b:4f:a2:00:87:
+         e7:40:e0:fc:d1:24:8b:d0:28:01:d3:53:ac:b1:58:7f:87:29:
+         38:56:93:dd:a2:14:4a:9a:94:b9:f8:94:b2:04:47:db:b8:38:
+         e6:85:2b:cf:d4:72:88:8b:0d:8e:a0:69:f9:9f:10:22:82:9c:
+         c5:ec:01:e3:07:a1:69:37:94:25:3a:cd:17:29:37:8d:24:d3:
+         27:0f:4d:bf:b0:31:36:b8:c6:a8:69:0b:df:28:f8:e2:dc:da:
+         95:3e:7f:d7:3f:a5:8f:92:6a:7d:ad:3a:ac:af:73:2b:5f:f1:
+         b3:22:92:ef:da:71:84:9e:4b:23:7b:69:b7:29:fc:c5:05:84:
+         4b:ff:06:92:ee:f5:9b:14:2a:af:be:ef:02:e1:e7:d0:e8:d0:
+         29:7c:48:40:f1:95:bb:08:b2:30:c5:81:80:a8:91:5b:2e:08:
+         3b:30:44:07:b5:c4:0b:07:74:ca:5d:37:3d:75:f9:bc:6d:21:
+         a6:e0:91:d8:f9:27:88:05:58:a7:f4:36:eb:ba:40:63:36:15:
+         42:98:0b:e2:d1:c9:11:0b:29:81:e1:c7:02:7e:fa:05:65:51:
+         7b:d6:1a:33:46:fc:a5:d4:fd:64:e8:c8:11:d4:d1:41:d9:39:
+         18:08:a3:ed:15:70:d9:14:f5:ba:c9:bb:3e:96:8d:5d:cc:c3:
+         5c:b6:c8:79:02:2e:e2:a1:06:ba:a5:21:1c:bf:16:7f:2d:d9:
+         93:07:92:b1:fa:ee:3f:e3:56:35:f3:30:aa:11:54:d3:71:cb:
+         29:d4:60:e1:6c:ae:c4:24:e3:00:4f:5f:52:b0:3f:f4:76:f3:
+         6d:db:bc:d8:65:c4:37:be:1a:87:9b:65:c4:20:dd:da:a9:4c:
+         9f:86:33:2b:49:a6:f7:aa:ce:da:98:3b:e3:5f:ac:b8:1b:45:
+         0e:56:59:fb:49:38:0f:b7:d4:49:f8:7b:ac:fa:d8:b8:1d:16:
+         db:b2:4c:15:d8:e7:eb:6b:38:ff:d2:69:26:a6:f6:50:15:45:
+         2f:12:b2:05:d4:bf:6f:53:79:64:9b:d5:8b:a1:08:3e:43:ee:
+         08:fe:9b:ea:83:89:8a:6a:53:98:1e:c5:91:4c:7a:99:2b:6d:
+         97:dc:96:1b:de:27:c5:af:0f:dd:42:5c:23:7d:bc:6b:5b:ab:
+         47:29:98:35:8f:9e:e6:e1:5f:96:6a:bd:cf:3c:47:89:8b:ad:
+         21:de:20:da:99:82:c1:0e:9b:7c:38:21:d8:b1:1c:34:c5:4e:
+         f7:fe:7d:5e:a4:2f:f8:7d:5c:30:2c:9e:e6:5a:4f:d3:15:90:
+         e6:6f:69:ea:51:93:8f:2c:dd:a7:c3:3c:50:a8:d1:ba:0b:5c:
+         cc:2e:4e:57:71:21:08:a1:2c:bd:a7:20:4b:ae:5c:02:7a:cd:
+         9a:fe:1e:db:ec:ce:3b:12:37:cb:96:20:7b:3b:b1:5a:2e:84:
+         03:f9:0b:32:43:c0:4e:e3:ea:79:e7:9a:13:54:e5:a8:1a:17:
+         c4:79:78:25:63:ab:67:39:39:a0:6c:c4:c5:94:ac:16:92:3d:
+         f0:1a:1a:9e:ca:7a:84:1b:c1:5a:5f:4c:65:8a:30:a6:5e:6c:
+         0e:ae:bf:ac:09:97:0f:83:5c:92:ce:e4:43:de:06:4b:96:f5:
+         46:3b:7d:a8:e3:0f:d3:fe:00:c7:d4:79:4e:5f:bd:ec:59:12:
+         f9:65:23:fa:e7:97:a2:a6:39:3b:a3:1e:da:47:c5:18:5b:8d:
+         a7:7b:29:1c:5a:7a:06:c6:92:9e:b7:3b:f0:c5:56:e8:cf:84:
+         cd:dd:61:0f:21:25:f4:1e:2b:40:b6:74:28:8d:41:f6:2c:1d:
+         ce:b4:39:d1:e1:be:15:78:c9:d7:99:a1:9d:50:43:da:ec:40:
+         69:6a:3b:17:af:28:22:09:e0:7d:38:9e:a7:ca:b7:f7:94:8a:
+         2a:1b:32:4e:28:6d:18:95:ca:42:67:c8:bb:13:24:31:43:84:
+         3e:95:66:08:5c:15:7f:6b:93:cc:8f:b8:76:7a:fd:74:4a:d6:
+         6f:64:74:df:72:f7:34:a3:50:f0:db:bf:0a:2b:1b:48:b7:c9:
+         c0:97:23:27:b1:56:5b:9e:10:12:5a:bf:ff:38:61:da:41:75:
+         15:c5:03:c2:20:fd:7f:84:c0:94:8e:11:ed:01:ba:f1:19:b5:
+         05:1d:bf:89:ea:c9:38:4e:d2:cf:5b:24:c6:37:a1:8e:60:89:
+         5c:52:ff:7d:5e:2d:c9:f8:b1:79:07:4c:2f:18:85:e8:ba:bf:
+         3e:da:59:43:df:29:79:7e:00:38:d2:fc:a9:8e:3b:9d
+-----BEGIN CERTIFICATE-----
+MIIJ6zCCBdOgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI4NDRaFw0zNjAzMTEyMzI4NDRaMIG1MQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEbMBkGA1UE
+CwwSRG9tYWluIENvbnRyb2xsZXJzMSIwIAYDVQQDDBlsb2NhbGRjLnNhbWJhLmV4
+YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkBFiZjYS1zYW1iYS5leGFtcGxlLmNvbUBz
+YW1iYS5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AOakds7oY/5X+aOu4K1N4hWO2CfIfX8rseiqUI+U+cdxP1IykdFtUiJfzY3MYhZ6
+i1hl7Qf36iTTiNgmyuvsFqeEHH4VRmQJIka53VwHhFCnTjE/ASPR+DYEGrvU5bbU
+G1wWyZ43ij6pfTAkQLK1RED6XG/VPv8ywuckCuTkqp//TKy+N1giCBYO9qcvtWxP
+rHukgqifOGQXbnK2fEzFRCoKtCUNsAyrmEr5GhrJpln0AKUKbwrQpTTKD/QO+7rX
+uz4sfAxoayb/HCn+d/kwhQ1EjK+QinCTXTq2GIulhRFco11XFt3HyADxBXHCbgc8
+N2k2fBLFnhtpEUVEHuu5spaxic1N+onrkknyRjXznYc8vuT4tzGnNkuBdpuyBNWA
+fU/mAu0kTKADxJ0An51xkw2luDdiKwPDvSQlLMND1MgnsG0F1MbF2FsJlOgna9lt
+t7zedr/VnDYmBLmXHfDJjZGTgjINtxaXQTGaIgsuuplRKGv1BLrJPVcMcujhJBrU
+Kmrn47a5lGHjTkKB5UPkHu9txF2k+bTsOoo0/rXHqP4Zjc99G2AhuiVvNc1PcihC
+fYcIqtozfmPmW1/nAajjC9MIWqbf6ucrE0ingzKWxLrR/xVmUjOGRl/Cn1lKAJi3
+G6GHJd+taFv3Jhcr64RincO9mWdqAl1wcj4YkpmMvdlPAgMBAAGjggHxMIIB7TAJ
+BgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEuZXhh
+bXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEGCWCG
+SAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwRgYJYIZIAYb4QgENBDkWN0RvbWFp
+biBDb250cm9sbGVyIENlcnRpZmljYXRlIGxvY2FsZGMuc2FtYmEuZXhhbXBsZS5j
+b20wHQYDVR0OBBYEFOHfcwvxPoZDpLPpjUR9PLIZwbzyMB8GA1UdIwQYMBaAFKI+
+Aiqjp005tAhNmcwMdTbqJ8M+MD0GA1UdEQQ2MDSCGWxvY2FsZGMuc2FtYmEuZXhh
+bXBsZS5jb22gFwYJKwYBBAGCNxkBoAoECAEjRWeJq83vMDEGA1UdEgQqMCiBJmNh
+LXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0GCWCGSAGG+EIB
+BARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMvQ0Etc2FtYmEu
+ZXhhbXBsZS5jb20tY3JsLmNybDAmBgNVHSUEHzAdBggrBgEFBQcDAgYIKwYBBQUH
+AwEGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggQBAIksV5gXwXOmEAJvpqxHHDct
+HaE8xSm2OuboFOw7dO7a2y2XPtOMnUJ+sEbpVHRPNN+eNH+eip1Nss/7cT/LMuZF
+57TTnujKpc8We3a1TuC5u3mxgqfTI8s8RmNjlrNbYp6Z3AIX+QdjhnYGGgIbmt8d
+zedG/poTh0fd4ndYUKJsyaD4FB8711mcib0uLc5g9MYs42PPNIRh2ZAukPxbT6IA
+h+dA4PzRJIvQKAHTU6yxWH+HKThWk92iFEqalLn4lLIER9u4OOaFK8/UcoiLDY6g
+afmfECKCnMXsAeMHoWk3lCU6zRcpN40k0ycPTb+wMTa4xqhpC98o+OLc2pU+f9c/
+pY+San2tOqyvcytf8bMiku/acYSeSyN7abcp/MUFhEv/BpLu9ZsUKq++7wLh59Do
+0Cl8SEDxlbsIsjDFgYCokVsuCDswRAe1xAsHdMpdNz11+bxtIabgkdj5J4gFWKf0
+Nuu6QGM2FUKYC+LRyRELKYHhxwJ++gVlUXvWGjNG/KXU/WToyBHU0UHZORgIo+0V
+cNkU9brJuz6WjV3Mw1y2yHkCLuKhBrqlIRy/Fn8t2ZMHkrH67j/jVjXzMKoRVNNx
+yynUYOFsrsQk4wBPX1KwP/R2823bvNhlxDe+GoebZcQg3dqpTJ+GMytJpveqztqY
+O+NfrLgbRQ5WWftJOA+31En4e6z62LgdFtuyTBXY5+trOP/SaSam9lAVRS8SsgXU
+v29TeWSb1YuhCD5D7gj+m+qDiYpqU5gexZFMepkrbZfclhveJ8WvD91CXCN9vGtb
+q0cpmDWPnubhX5Zqvc88R4mLrSHeINqZgsEOm3w4IdixHDTFTvf+fV6kL/h9XDAs
+nuZaT9MVkOZvaepRk48s3afDPFCo0boLXMwuTldxIQihLL2nIEuuXAJ6zZr+Htvs
+zjsSN8uWIHs7sVouhAP5CzJDwE7j6nnnmhNU5agaF8R5eCVjq2c5OaBsxMWUrBaS
+PfAaGp7KeoQbwVpfTGWKMKZebA6uv6wJlw+DXJLO5EPeBkuW9UY7fajjD9P+AMfU
+eU5fvexZEvllI/rnl6KmOTujHtpHxRhbjad7KRxaegbGkp63O/DFVujPhM3dYQ8h
+JfQeK0C2dCiNQfYsHc60OdHhvhV4ydeZoZ1QQ9rsQGlqOxevKCIJ4H04nqfKt/eU
+iiobMk4obRiVykJnyLsTJDFDhD6VZghcFX9rk8yPuHZ6/XRK1m9kdN9y9zSjUPDb
+vworG0i3ycCXIyexVlueEBJav/84YdpBdRXFA8Ig/X+EwJSOEe0BuvEZtQUdv4nq
+yThO0s9bJMY3oY5giVxS/31eLcn4sXkHTC8Yhei6vz7aWUPfKXl+ADjS/KmOO50=
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-key.pem
new file mode 100644
index 0000000..3443a50
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-key.pem
@@ -0,0 +1,54 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIJjjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIc8U9D3UAcEQCAggA
+MBQGCCqGSIb3DQMHBAiv8rBzGS//TQSCCUieV5YQyWsn3FFhKYI425pOXfnTsSUb
+VEe7wO2H7D/S0RFfT5gILYv57TTH8Z9uAeX/wU5msKA4PZt16aMutNl2NWell8hy
+IX5R4n6IzSP6IobZKsyFR5u/h683Eli1pBd4BbLJuYu94sxelB4HQdRp0QJIvIvO
+TWqTyD7UmqqG/IVhTMQpzcepY/S4SGI6GODJtDLPRgv3x5/Z0/NsxiMKrXMi7HKc
+Rzg8jm2mausukN+sSyPcvlEufQjRJgJXtCIX98FMLp0pkOq1rsVUSNg8Qza6tbyE
+XhweHWbV9YZCVfmnhUalLt7CIoA7QeOQZbwTNpTo/4mSEA7lv1knvFSdMc9JvR6J
+bZQOk5rPzuX2W84UQ3CkIwaRB2iFUv0gJy5Z2xbhWgAR5KZIhGTKupHBYOmD29QU
+whgjXq4McdYWKquxELzSW5jXVPNwvREhEuKR1mt6g0NqXCbCeQHw7DWH1OGPz7jM
+HXsCGVWpXqeWvRHhdF+NRfHa41hqGS3Onq29UJtgcMpNYpGQYY6Exq6hVVsmddwt
+QU4COPfozJzeAlkUEem5AKnuh1JUxo/RieNP99sv1/8g8icc+oPXOIu/6HI3JGYB
+4WTVBp1OccEcNlnUYhxcL3ODYXcLUhiLZh2DS+IDLS3Pbp0v1qz/JuzDxiYBnEYt
+4Q5NWdhPF/TSS7wQHRl35LAyHHhBIu1kuDhnXjdq87h7ioNiffZ0DgSW4HFUzslk
+4UZGFTKaDpepBfIp1qnYGPKCMv+MLaMWU3LOfVGT3ecntkMxUtntNMZ6qGaXhzda
+65LD9xYJUrbo+qQSBiTNAhMOy6lHlwIulmML0j1YEcVc2EwgqdfbBeT9v9gh6If4
+85ba1Wvy4W/FN/xo/ECflLAvozjyYND8LMcZ73eJs4ncZkMZAkjfP3sg/qvTAtbf
+D6c+SRQbxRJv0ZUb9NN7wx4flsyypscKNqk78mytUN7gGf2xJIOvMS/zH/Zf9EpD
+bEY+lOY2llYtXhoEj95tnRPFhKaQeGZdkISsmoU5olLsw/tRkquGdAokh+fl+NtZ
+WxgJF8Ft8NT4iXhEBRfgFO5ubGq565c66ayA6R6K00pg/IvS8OXPuxT+/e8EKqUO
+R9RyWR5n+W8hWw5+pQWGNvwhLFLJFfCxHw2ucSyNCvtcb6ijV5yvi4cI+UuVnh3s
+WW3mMaMOYIcbh/thp8wBs/dpAOGUWX7XBfaGsQ0D+ff0ufcUobhXVZgtC0LhgfrN
+ZeHQF4bUXycyaAGWvstNb6Xj2QFVDG98eNDGmYDTD+0XwpPc/6/Ge4BLPAVcBpQw
+DMCKUqSkPPWCqfipbQmpBxswhYmzx+DjdfRxHExWeGk1pwyfH4GBhO5fkcpYVtU+
+RyruFu0YNnQ+2Y4eg8+3IyJndxkUHmwsB1DB0P8XvJ0n/NnAnZ0sIpE0x3dOFhb+
+SK0dj8fo2aEHOimrTHc2EJ2ZscpSCVNQ1BsScM36FCWxRWbTr8rBFsdUJ5CMZ2hN
+qHBtf38SgNkD3qBUmiPetsYt6qTKY9Rv25D4zL5IR2ZnV99oW6MTDhc49cxYn8Dy
+MKlyzV3upykqGBMSKBKbafDI3sO8gB3upUetnogi1TMaNyu4qNzq8oNRfdf+RD1R
+Rg4++U14UbYNvWRQnCqjJGUXDnVc8Gp9K8Z6p5eXihsFfpol1OGu0td1e0FRi3AH
+INW9UEpfRbmbEPHhYQRNAyRlcQXJ1FBnxUCk6qgfkD0ziJk2VD4oFoaSlqy7l21z
+zoH0Vp6PZGZEIs/mAODvtH5jsTEMUE8uuRmPqgnFqbi/gfQ5FJLR6dfCb8MJ2iJM
+Hw4791wi7tS1aCYoHneDtxNFeWuuEmw1uMoA+C5euGNv86XAH5AV2OrTIt8SLFPN
+mLBLQ3J9Kkitsy1JFz9IdJ5uY3K2CvpOaP+sx3l1Q4YVuSza8r7zRfTC1wPfbsvk
+64zZQzA57WvRvpaZU49HbMV9/zDOlQfLtL7TdAbqLYjlVRpO5pHHEqLRR9eGQ2UY
+zhfMFfcJahH4lDbgHf6EVjHnEuoW9fU8hLRVzUcQCVDsf36Et+g5G1JMhFnlVzdv
+MaKiN9tzKeIqxUSlXMHYm+oIb849pshNo+KRzZ0K+r+wExnpIfCfVOjAvSQU+6y9
+1uIIQlJfk6uPFVriaooyUDrW9/83AgzJDrkpSMTnVmo/MTS8cAe8Ox5cr+mHqJko
+cnHzBNI9Q0z59SpJdXucPVyk5MYPUdfyI2ouicm+nKidNvlp36O7UHMw0pJdeqDg
+03vhaVif5uN8FNjBLp6xIipX6lor6XCOnkGR/zkis602sTAkE4nemOw9zy3rIBr+
+hYnSY7vMFCVYIERjqSOLE0k0d5RyOsGjSYr8yQMvpTGusla34qVPjrrpJ+OuczK/
+6KJeHV+WUw42g8JSs67j8YJ2ejc9gr9AVSRiES99QL+tlFnOTY28N40OjXqFJjYK
+A0x0By1O6h4PMKtYchTuJAoEOB2KOP1Ta+NlL80zM4nWwv7NdO0AR/ATfUfix1GS
+NiMC10C7eurYdAfxly3p9NgjQq+vaKsnSy0TbXPCgW8YTegnxKTUWJm+BEiYaE4M
+A0c1CySusV+JO1catlXSeCB6ajddi/SKXsW26lJ3Q+8QqhA3EMivCE3Zh2Q5c1yp
+gCV7IXtdryPdK16qmirO9LKkm6sCfBdhgBgi+IcyUhqxwHCwxrPqzEs75Sa3U/6k
+kV3AqFwhHYtUj2fBNlfJ1efV8fW+WLboJkHbi2LXmL4NBvHTNjK3NprffFrQ/QJU
+oYsMQdeWQZD+3p8w1fPb0sXEDL6LQgjAjyDaqOiX8XrQ8nr3n4FpTI38/OIIfS69
+IHtgo5yv0CMfN+C6LAHOE0aDHRoY6+TVVgr1Z/X2VqJQJONii0dQ5ttDHYnUpzu0
+vWsdvVjsyhkLa2yhUB7UyWusZo0HZRSAcf1pNlpp5rCtJad9to7OvOL3qb5GluAK
+/5eZE6RzgyGOjtOx0IgQ+l4ThQCTbkoVEtB59IEeP/+Sq2RmFfdGiGgC3Wnrga8b
+gkuXXbjZboptSku6N1ZO1r99wd0qIHzrtVCONGLGfVBy7X6nDO2pC9IUOXycMji7
+B5J0toyDWt6UzlLQasmz8Be7NZJCkDd2jlSKorZtdynsXbRkX1H4by9kI8kEcgK7
+ICE=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-openssl.cnf b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-openssl.cnf
new file mode 100644
index 0000000..bf4131f
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-openssl.cnf
@@ -0,0 +1,250 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = CA-samba.example.com         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-samba.example.com-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-samba.example.com-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-samba.example.com-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-samba.example.com-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-samba.example.com-crl.pem           # The current CRL
+crl         = $dir/Public/CA-samba.example.com-crl.crl           # The current CRL
+private_key = $dir/Private/CA-samba.example.com-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-samba.example.com.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = 7300           # how long to certify for
+default_crl_days= 7300            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = 4096
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = US
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = SambaState
+
+localityName            = Locality Name (eg, city)
+localityName_default    = SambaCity
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = SambaSelfTesting
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Domain Controllers
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = localdc.samba.example.com
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = ca-samba.example.com at samba.example.com
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+#[ usr_cert_mskdc ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a domain controller certificate.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+nsCertType          = server
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Domain Controller Certificate localdc.samba.example.com"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=@dc_subjalt
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for our domain controller certs
+# serverAuth - says cert can be used to identify an ssl/tls server
+# msKDC - says cert can be used to identify a Kerberos Domain Controller.
+extendedKeyUsage = clientAuth,serverAuth,msKDC
+
+[dc_subjalt]
+DNS=localdc.samba.example.com
+otherName=msADGUID;FORMAT:HEX,OCTETSTRING:0123456789ABCDEF
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-private-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-private-key.pem
new file mode 100644
index 0000000..546b292
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-private-key.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJJwIBAAKCAgEA5qR2zuhj/lf5o67grU3iFY7YJ8h9fyux6KpQj5T5x3E/UjKR
+0W1SIl/NjcxiFnqLWGXtB/fqJNOI2CbK6+wWp4QcfhVGZAkiRrndXAeEUKdOMT8B
+I9H4NgQau9TlttQbXBbJnjeKPql9MCRAsrVEQPpcb9U+/zLC5yQK5OSqn/9MrL43
+WCIIFg72py+1bE+se6SCqJ84ZBducrZ8TMVEKgq0JQ2wDKuYSvkaGsmmWfQApQpv
+CtClNMoP9A77ute7Pix8DGhrJv8cKf53+TCFDUSMr5CKcJNdOrYYi6WFEVyjXVcW
+3cfIAPEFccJuBzw3aTZ8EsWeG2kRRUQe67mylrGJzU36ieuSSfJGNfOdhzy+5Pi3
+Mac2S4F2m7IE1YB9T+YC7SRMoAPEnQCfnXGTDaW4N2IrA8O9JCUsw0PUyCewbQXU
+xsXYWwmU6Cdr2W23vN52v9WcNiYEuZcd8MmNkZOCMg23FpdBMZoiCy66mVEoa/UE
+usk9Vwxy6OEkGtQqaufjtrmUYeNOQoHlQ+Qe723EXaT5tOw6ijT+tceo/hmNz30b
+YCG6JW81zU9yKEJ9hwiq2jN+Y+ZbX+cBqOML0whapt/q5ysTSKeDMpbEutH/FWZS
+M4ZGX8KfWUoAmLcboYcl361oW/cmFyvrhGKdw72ZZ2oCXXByPhiSmYy92U8CAwEA
+AQKCAgBqVMxJW64t5lU69zax70QZ+D8DKFVjObvNridx6pa1MiqlNJcxXBsPqedU
+RjO6dUikumjq0Yrq63MdY9UNq0xOcoPIRPqsx+E7hhjdgsGnhVpxLcDSyMyL6pyA
+mAhHn8X1ULQm8ygS94S1myEQwqzy3/mZvVBLyxU8BsvW9u0K0mKBCTjustHTiZaB
+QWd8xcaZQiDSqIUQ8BSFYkgwBIoGb+TZaFQPo1SUy/8S9oBw3CMn84V6EPL5QWbV
+d8rqOuciJNQTzFgKJHbRjXW2Nn5Avae2kQaiG+5RUP5D801D0denAq2SFbbJaFTA
+O4kKYOKS6QGOjfj0Xh4ONveiaXxBSPpIJSvbjAV+Nq92NVkZ35jiPqGZzebhzzoD
+mU6mMvRoL/FHs9PKNZF1Cd4EP1SdLhiImj+1eajfYvHAlz6kIJxTue0BFkh13uwp
+amx48wB7e/W8t8lqixICf1HlCv+EQGN6aka5dHMqJobXhkt9npz53+AYdpc8Sjs9
+QlFplYoOgkaHvzLv9yeZPOT5Xr32weE6KpM+SwvpVxfttbkvqrWoOoEcDARuVqiS
+TRzS/ZDiEn+Kcgm7pJ3i2nTAIBzwC4z91HJbeVXNpptkZJEgjXM8XjSArHjDrkl1
+EGKARlkTn576XMGWSkF/bmEBiG0KIhTu+DmwsQvR+564tjV98QKCAQEA+aS7ygjL
+aRj5JZKMt3VWZRntK20m04iY0wGDNs+p+nFRJjCDAUhTTOl9++vlJYe8HO9iXzUv
+O51tGnzrck9+gUVlFghrw0dJ+mY0+1bSt2aLNUmlfvv1uRpm9Pd3xbQ6e3Kpf/r1
+ew6IpG8I6pvpVJXJ3FQZpSOlTP9dyRxMNzdILGzzPrb+2r0j6Oc/y3+adBiXB3Yg
+QPfFJRJZA4k2Wk/qSi9NR/yWHaY0krO68l8l2zn1AKaIoVVqtxVTQ7qUBWNXzVMe
+ULtAvO1Bonh+C+zYcNJjSBeYWeJ7pbp/ozDe6M2DuJMv4aW6oV6tGcMF9NOd1pFx
+qiC8vIVPZ3rJ9QKCAQEA7IPf9CAaDUScu2/Ry9z1RaISU4BMi/30poc80Zy2hC18
+vP8aiHVlQdkdzdKYGweaYNQpszGeBcHK51y6V11vwCNQRrCoUp9VbICp7ok2O4y8
+w9r+q4GcYthHeMhEnHDo4R/uHKEJCYS012RLlLSXMa0Dfl1sOv8mVuIEaZoRJrAq
+Xzxz9KX7MFv5Zb8TvVL6fHEXmdMmmoiZnyNplH+3LMj6duoNaxjtsoixCkuRTXE7
+Cav118q+QWae+yhIonF+HRIa/G0doqHa+P9rl18FUnxfAf91Z70SSJ2oOtuWjd1J
+37eG4d7skpAoWWdXNpCqpJnsPLlSlBqKmYrN5CM3swKCAQBAfV/Np0v00HC8Vgln
+8zXoVDRCfaYEC0t/ZuqgpDDC87cE6I9PK4HpYoAbLis58MCVsPl2ouSav+ZJa2/f
+Tc3eUzDz6iT8g1QHDZQuQZWZrzHTCD1qemhV8w4Zxjv4pMBe15YV65yyt2RxJgXl
+pXU3VqKY+ljNolG3fFib9WVy9iL85wBHeTqJA0ddiS+fwE0EJL4PPWLDpb4V/5Fj
+KnUSC4b4txN9vzCAZEk8hJWMuyuqYGR8UIkHNGum9ClYW8CVS76I2ioArP7iT2Af
+OoVFS1/2dUMUgpPm1G0guPb0D1HmTgDzE4LRBeEagryw5QKK5oflwBje3ColgUKr
+9rppAoIBAH9t9gXkHeU0KHXco16BaCziS5ltsNBkPaJTjvMoyjWhBGoX0EXhanL1
+9dblNkqp6AVviiAgBZH4fcf17/gOQZ116VSM7cPGURIqqGP6zZt8EmA756akKIwh
+FzD+Rek79F0HBRWrteDI/V5njUlLm4KKQy2cTCnlOtTo5ZO4DLGZjNrPCXKw0wuV
+ImQtdQc2Y/sUO7EHUO9F1e8l90apIRoiFsBnDl+7iKX+e9SeLmVZMoPdgJGJjMRT
+9ChB5hCPsXEcRinm6GataftqMp/V9Foi5FWBO9JuziENwIwlr5Izvg+pJCUiJLg6
+r2KsCRM/EpGo1N1KxDFDs5VScegPCX0CggEAWCJ0+KmHbA4F+vDjYW1wNE1MBKee
+4Q+nnX45oEHDM+J5da2Ov2IhblzVX/vJaVtI2rwSXCkM3x7ByAXwewNa4BA/eGG/
+v2MPs21f9GcLkpLv0xz+pILkeeNk+e0yIYE4jWQGFMlYh7cNLStDSw6XNU/9IKeO
+r2gQjAqS/pMGBMS3FOcd2S+/gMjJom2GaWLhGdJAGdmtGh2EbFku5+WDL76pyAaN
+BHEGD91PSER5nEGS9ho81IPDrIm0LVcp6xMRD6PWput/0gcC3Zun1ZDo9oJA1AsS
+NMnm6c14ASh/1KQUx9XkC1hUmBVhb4UA4EshT4oXffTHpDMlA6yWqlkReg==
+-----END RSA PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-req.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-req.pem
new file mode 100644
index 0000000..d2647cc
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-S00-req.pem
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIFDzCCAvcCAQAwgckxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTYW1iYVN0YXRl
+MRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNVBAoMEFNhbWJhU2VsZlRlc3Rpbmcx
+GzAZBgNVBAsMEkRvbWFpbiBDb250cm9sbGVyczEiMCAGA1UEAwwZbG9jYWxkYy5z
+YW1iYS5leGFtcGxlLmNvbTE1MDMGCSqGSIb3DQEJARYmY2Etc2FtYmEuZXhhbXBs
+ZS5jb21Ac2FtYmEuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDmpHbO6GP+V/mjruCtTeIVjtgnyH1/K7HoqlCPlPnHcT9SMpHRbVIi
+X82NzGIWeotYZe0H9+ok04jYJsrr7BanhBx+FUZkCSJGud1cB4RQp04xPwEj0fg2
+BBq71OW21BtcFsmeN4o+qX0wJECytURA+lxv1T7/MsLnJArk5Kqf/0ysvjdYIggW
+DvanL7VsT6x7pIKonzhkF25ytnxMxUQqCrQlDbAMq5hK+RoayaZZ9AClCm8K0KU0
+yg/0Dvu617s+LHwMaGsm/xwp/nf5MIUNRIyvkIpwk106thiLpYURXKNdVxbdx8gA
+8QVxwm4HPDdpNnwSxZ4baRFFRB7rubKWsYnNTfqJ65JJ8kY1852HPL7k+LcxpzZL
+gXabsgTVgH1P5gLtJEygA8SdAJ+dcZMNpbg3YisDw70kJSzDQ9TIJ7BtBdTGxdhb
+CZToJ2vZbbe83na/1Zw2JgS5lx3wyY2Rk4IyDbcWl0ExmiILLrqZUShr9QS6yT1X
+DHLo4SQa1Cpq5+O2uZRh405CgeVD5B7vbcRdpPm07DqKNP61x6j+GY3PfRtgIbol
+bzXNT3IoQn2HCKraM35j5ltf5wGo4wvTCFqm3+rnKxNIp4MylsS60f8VZlIzhkZf
+wp9ZSgCYtxuhhyXfrWhb9yYXK+uEYp3DvZlnagJdcHI+GJKZjL3ZTwIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAFRI0PRZO7XlWIpWUC0wc3KjVvTGxieaalJdPC/j
+dxT7lBkSTHGjbeLIkqjVAuhONziKT2RP9QxzK2sa9jxIi5zR1byZv500suTez+96
+KkqSnFTgM4nwJdv2S8x0uBPmlREL4K1I0FGZX29wd0bqFhBQqSzVQvQqGSiqSJfU
+KkIys1tAIrC7DfNvfhogIrupuN8clluLe0T25qxGeaqXN+EYB7U/O+4FZccpGoeP
+dHO2zYeRib0oGTlnk1noRmlqgXPEKfzoWMJ2cUkexlRy1ajW0r1rvcIgc1rPnB8h
+6c6YhFGwbYW54/I6tLxJc5pyWCQNH/uYEeFnGs/w85lPKvLM0RXsQ7rfnDRv3LOj
+Mex+3whmIs5dAVdQQMy0ngsbPpaR+5Ry8eWAPmwnRXwVaysGgmTysVCzFGqSO3ul
+7FgbKEEM1cNe4+Gvl2LEl+aJ5CB1DBslDjXMQVwLMpAU2sthJurhujx3/j598IUp
+why48F4056Uf33CncLSEriykIEFXUionXUxtDsCaS13+CfKw+gUJJRsg4ZWqrY6M
+b0KHAtzq4g7lFZ+XaXpGdxntqGOrgxfcgWBRhJnp35ILoMFNV2OHjySnF6SWDJvP
+AY9IQsUDiMruNjCS9s5zaH7KqmJJ+pgcjVSholozUEI2J3hUpq3KFsE20Cyi+YbO
+kTlo
+-----END CERTIFICATE REQUEST-----
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-cert.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-cert.pem
new file mode 120000
index 0000000..b7549bb
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-cert.pem
@@ -0,0 +1 @@
+DC-localdc.samba.example.com-S00-cert.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-private-key.pem b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-private-key.pem
new file mode 120000
index 0000000..21601b4
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/DCs/localdc.samba.example.com/DC-localdc.samba.example.com-private-key.pem
@@ -0,0 +1 @@
+DC-localdc.samba.example.com-S00-private-key.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/NewCerts/00.pem b/selftest/manage-ca/CA-samba.example.com/NewCerts/00.pem
new file mode 100644
index 0000000..7b1b6a1
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/NewCerts/00.pem
@@ -0,0 +1,190 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:28:44 2016 GMT
+            Not After : Mar 11 23:28:44 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Domain Controllers, CN=localdc.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:e6:a4:76:ce:e8:63:fe:57:f9:a3:ae:e0:ad:4d:
+                    e2:15:8e:d8:27:c8:7d:7f:2b:b1:e8:aa:50:8f:94:
+                    f9:c7:71:3f:52:32:91:d1:6d:52:22:5f:cd:8d:cc:
+                    62:16:7a:8b:58:65:ed:07:f7:ea:24:d3:88:d8:26:
+                    ca:eb:ec:16:a7:84:1c:7e:15:46:64:09:22:46:b9:
+                    dd:5c:07:84:50:a7:4e:31:3f:01:23:d1:f8:36:04:
+                    1a:bb:d4:e5:b6:d4:1b:5c:16:c9:9e:37:8a:3e:a9:
+                    7d:30:24:40:b2:b5:44:40:fa:5c:6f:d5:3e:ff:32:
+                    c2:e7:24:0a:e4:e4:aa:9f:ff:4c:ac:be:37:58:22:
+                    08:16:0e:f6:a7:2f:b5:6c:4f:ac:7b:a4:82:a8:9f:
+                    38:64:17:6e:72:b6:7c:4c:c5:44:2a:0a:b4:25:0d:
+                    b0:0c:ab:98:4a:f9:1a:1a:c9:a6:59:f4:00:a5:0a:
+                    6f:0a:d0:a5:34:ca:0f:f4:0e:fb:ba:d7:bb:3e:2c:
+                    7c:0c:68:6b:26:ff:1c:29:fe:77:f9:30:85:0d:44:
+                    8c:af:90:8a:70:93:5d:3a:b6:18:8b:a5:85:11:5c:
+                    a3:5d:57:16:dd:c7:c8:00:f1:05:71:c2:6e:07:3c:
+                    37:69:36:7c:12:c5:9e:1b:69:11:45:44:1e:eb:b9:
+                    b2:96:b1:89:cd:4d:fa:89:eb:92:49:f2:46:35:f3:
+                    9d:87:3c:be:e4:f8:b7:31:a7:36:4b:81:76:9b:b2:
+                    04:d5:80:7d:4f:e6:02:ed:24:4c:a0:03:c4:9d:00:
+                    9f:9d:71:93:0d:a5:b8:37:62:2b:03:c3:bd:24:25:
+                    2c:c3:43:d4:c8:27:b0:6d:05:d4:c6:c5:d8:5b:09:
+                    94:e8:27:6b:d9:6d:b7:bc:de:76:bf:d5:9c:36:26:
+                    04:b9:97:1d:f0:c9:8d:91:93:82:32:0d:b7:16:97:
+                    41:31:9a:22:0b:2e:ba:99:51:28:6b:f5:04:ba:c9:
+                    3d:57:0c:72:e8:e1:24:1a:d4:2a:6a:e7:e3:b6:b9:
+                    94:61:e3:4e:42:81:e5:43:e4:1e:ef:6d:c4:5d:a4:
+                    f9:b4:ec:3a:8a:34:fe:b5:c7:a8:fe:19:8d:cf:7d:
+                    1b:60:21:ba:25:6f:35:cd:4f:72:28:42:7d:87:08:
+                    aa:da:33:7e:63:e6:5b:5f:e7:01:a8:e3:0b:d3:08:
+                    5a:a6:df:ea:e7:2b:13:48:a7:83:32:96:c4:ba:d1:
+                    ff:15:66:52:33:86:46:5f:c2:9f:59:4a:00:98:b7:
+                    1b:a1:87:25:df:ad:68:5b:f7:26:17:2b:eb:84:62:
+                    9d:c3:bd:99:67:6a:02:5d:70:72:3e:18:92:99:8c:
+                    bd:d9:4f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Domain Controller Certificate localdc.samba.example.com
+            X509v3 Subject Key Identifier: 
+                E1:DF:73:0B:F1:3E:86:43:A4:B3:E9:8D:44:7D:3C:B2:19:C1:BC:F2
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                DNS:localdc.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication, msKDC
+    Signature Algorithm: sha256WithRSAEncryption
+         89:2c:57:98:17:c1:73:a6:10:02:6f:a6:ac:47:1c:37:2d:1d:
+         a1:3c:c5:29:b6:3a:e6:e8:14:ec:3b:74:ee:da:db:2d:97:3e:
+         d3:8c:9d:42:7e:b0:46:e9:54:74:4f:34:df:9e:34:7f:9e:8a:
+         9d:4d:b2:cf:fb:71:3f:cb:32:e6:45:e7:b4:d3:9e:e8:ca:a5:
+         cf:16:7b:76:b5:4e:e0:b9:bb:79:b1:82:a7:d3:23:cb:3c:46:
+         63:63:96:b3:5b:62:9e:99:dc:02:17:f9:07:63:86:76:06:1a:
+         02:1b:9a:df:1d:cd:e7:46:fe:9a:13:87:47:dd:e2:77:58:50:
+         a2:6c:c9:a0:f8:14:1f:3b:d7:59:9c:89:bd:2e:2d:ce:60:f4:
+         c6:2c:e3:63:cf:34:84:61:d9:90:2e:90:fc:5b:4f:a2:00:87:
+         e7:40:e0:fc:d1:24:8b:d0:28:01:d3:53:ac:b1:58:7f:87:29:
+         38:56:93:dd:a2:14:4a:9a:94:b9:f8:94:b2:04:47:db:b8:38:
+         e6:85:2b:cf:d4:72:88:8b:0d:8e:a0:69:f9:9f:10:22:82:9c:
+         c5:ec:01:e3:07:a1:69:37:94:25:3a:cd:17:29:37:8d:24:d3:
+         27:0f:4d:bf:b0:31:36:b8:c6:a8:69:0b:df:28:f8:e2:dc:da:
+         95:3e:7f:d7:3f:a5:8f:92:6a:7d:ad:3a:ac:af:73:2b:5f:f1:
+         b3:22:92:ef:da:71:84:9e:4b:23:7b:69:b7:29:fc:c5:05:84:
+         4b:ff:06:92:ee:f5:9b:14:2a:af:be:ef:02:e1:e7:d0:e8:d0:
+         29:7c:48:40:f1:95:bb:08:b2:30:c5:81:80:a8:91:5b:2e:08:
+         3b:30:44:07:b5:c4:0b:07:74:ca:5d:37:3d:75:f9:bc:6d:21:
+         a6:e0:91:d8:f9:27:88:05:58:a7:f4:36:eb:ba:40:63:36:15:
+         42:98:0b:e2:d1:c9:11:0b:29:81:e1:c7:02:7e:fa:05:65:51:
+         7b:d6:1a:33:46:fc:a5:d4:fd:64:e8:c8:11:d4:d1:41:d9:39:
+         18:08:a3:ed:15:70:d9:14:f5:ba:c9:bb:3e:96:8d:5d:cc:c3:
+         5c:b6:c8:79:02:2e:e2:a1:06:ba:a5:21:1c:bf:16:7f:2d:d9:
+         93:07:92:b1:fa:ee:3f:e3:56:35:f3:30:aa:11:54:d3:71:cb:
+         29:d4:60:e1:6c:ae:c4:24:e3:00:4f:5f:52:b0:3f:f4:76:f3:
+         6d:db:bc:d8:65:c4:37:be:1a:87:9b:65:c4:20:dd:da:a9:4c:
+         9f:86:33:2b:49:a6:f7:aa:ce:da:98:3b:e3:5f:ac:b8:1b:45:
+         0e:56:59:fb:49:38:0f:b7:d4:49:f8:7b:ac:fa:d8:b8:1d:16:
+         db:b2:4c:15:d8:e7:eb:6b:38:ff:d2:69:26:a6:f6:50:15:45:
+         2f:12:b2:05:d4:bf:6f:53:79:64:9b:d5:8b:a1:08:3e:43:ee:
+         08:fe:9b:ea:83:89:8a:6a:53:98:1e:c5:91:4c:7a:99:2b:6d:
+         97:dc:96:1b:de:27:c5:af:0f:dd:42:5c:23:7d:bc:6b:5b:ab:
+         47:29:98:35:8f:9e:e6:e1:5f:96:6a:bd:cf:3c:47:89:8b:ad:
+         21:de:20:da:99:82:c1:0e:9b:7c:38:21:d8:b1:1c:34:c5:4e:
+         f7:fe:7d:5e:a4:2f:f8:7d:5c:30:2c:9e:e6:5a:4f:d3:15:90:
+         e6:6f:69:ea:51:93:8f:2c:dd:a7:c3:3c:50:a8:d1:ba:0b:5c:
+         cc:2e:4e:57:71:21:08:a1:2c:bd:a7:20:4b:ae:5c:02:7a:cd:
+         9a:fe:1e:db:ec:ce:3b:12:37:cb:96:20:7b:3b:b1:5a:2e:84:
+         03:f9:0b:32:43:c0:4e:e3:ea:79:e7:9a:13:54:e5:a8:1a:17:
+         c4:79:78:25:63:ab:67:39:39:a0:6c:c4:c5:94:ac:16:92:3d:
+         f0:1a:1a:9e:ca:7a:84:1b:c1:5a:5f:4c:65:8a:30:a6:5e:6c:
+         0e:ae:bf:ac:09:97:0f:83:5c:92:ce:e4:43:de:06:4b:96:f5:
+         46:3b:7d:a8:e3:0f:d3:fe:00:c7:d4:79:4e:5f:bd:ec:59:12:
+         f9:65:23:fa:e7:97:a2:a6:39:3b:a3:1e:da:47:c5:18:5b:8d:
+         a7:7b:29:1c:5a:7a:06:c6:92:9e:b7:3b:f0:c5:56:e8:cf:84:
+         cd:dd:61:0f:21:25:f4:1e:2b:40:b6:74:28:8d:41:f6:2c:1d:
+         ce:b4:39:d1:e1:be:15:78:c9:d7:99:a1:9d:50:43:da:ec:40:
+         69:6a:3b:17:af:28:22:09:e0:7d:38:9e:a7:ca:b7:f7:94:8a:
+         2a:1b:32:4e:28:6d:18:95:ca:42:67:c8:bb:13:24:31:43:84:
+         3e:95:66:08:5c:15:7f:6b:93:cc:8f:b8:76:7a:fd:74:4a:d6:
+         6f:64:74:df:72:f7:34:a3:50:f0:db:bf:0a:2b:1b:48:b7:c9:
+         c0:97:23:27:b1:56:5b:9e:10:12:5a:bf:ff:38:61:da:41:75:
+         15:c5:03:c2:20:fd:7f:84:c0:94:8e:11:ed:01:ba:f1:19:b5:
+         05:1d:bf:89:ea:c9:38:4e:d2:cf:5b:24:c6:37:a1:8e:60:89:
+         5c:52:ff:7d:5e:2d:c9:f8:b1:79:07:4c:2f:18:85:e8:ba:bf:
+         3e:da:59:43:df:29:79:7e:00:38:d2:fc:a9:8e:3b:9d
+-----BEGIN CERTIFICATE-----
+MIIJ6zCCBdOgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI4NDRaFw0zNjAzMTEyMzI4NDRaMIG1MQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEbMBkGA1UE
+CwwSRG9tYWluIENvbnRyb2xsZXJzMSIwIAYDVQQDDBlsb2NhbGRjLnNhbWJhLmV4
+YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkBFiZjYS1zYW1iYS5leGFtcGxlLmNvbUBz
+YW1iYS5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AOakds7oY/5X+aOu4K1N4hWO2CfIfX8rseiqUI+U+cdxP1IykdFtUiJfzY3MYhZ6
+i1hl7Qf36iTTiNgmyuvsFqeEHH4VRmQJIka53VwHhFCnTjE/ASPR+DYEGrvU5bbU
+G1wWyZ43ij6pfTAkQLK1RED6XG/VPv8ywuckCuTkqp//TKy+N1giCBYO9qcvtWxP
+rHukgqifOGQXbnK2fEzFRCoKtCUNsAyrmEr5GhrJpln0AKUKbwrQpTTKD/QO+7rX
+uz4sfAxoayb/HCn+d/kwhQ1EjK+QinCTXTq2GIulhRFco11XFt3HyADxBXHCbgc8
+N2k2fBLFnhtpEUVEHuu5spaxic1N+onrkknyRjXznYc8vuT4tzGnNkuBdpuyBNWA
+fU/mAu0kTKADxJ0An51xkw2luDdiKwPDvSQlLMND1MgnsG0F1MbF2FsJlOgna9lt
+t7zedr/VnDYmBLmXHfDJjZGTgjINtxaXQTGaIgsuuplRKGv1BLrJPVcMcujhJBrU
+Kmrn47a5lGHjTkKB5UPkHu9txF2k+bTsOoo0/rXHqP4Zjc99G2AhuiVvNc1PcihC
+fYcIqtozfmPmW1/nAajjC9MIWqbf6ucrE0ingzKWxLrR/xVmUjOGRl/Cn1lKAJi3
+G6GHJd+taFv3Jhcr64RincO9mWdqAl1wcj4YkpmMvdlPAgMBAAGjggHxMIIB7TAJ
+BgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEuZXhh
+bXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEGCWCG
+SAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwRgYJYIZIAYb4QgENBDkWN0RvbWFp
+biBDb250cm9sbGVyIENlcnRpZmljYXRlIGxvY2FsZGMuc2FtYmEuZXhhbXBsZS5j
+b20wHQYDVR0OBBYEFOHfcwvxPoZDpLPpjUR9PLIZwbzyMB8GA1UdIwQYMBaAFKI+
+Aiqjp005tAhNmcwMdTbqJ8M+MD0GA1UdEQQ2MDSCGWxvY2FsZGMuc2FtYmEuZXhh
+bXBsZS5jb22gFwYJKwYBBAGCNxkBoAoECAEjRWeJq83vMDEGA1UdEgQqMCiBJmNh
+LXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0GCWCGSAGG+EIB
+BARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMvQ0Etc2FtYmEu
+ZXhhbXBsZS5jb20tY3JsLmNybDAmBgNVHSUEHzAdBggrBgEFBQcDAgYIKwYBBQUH
+AwEGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggQBAIksV5gXwXOmEAJvpqxHHDct
+HaE8xSm2OuboFOw7dO7a2y2XPtOMnUJ+sEbpVHRPNN+eNH+eip1Nss/7cT/LMuZF
+57TTnujKpc8We3a1TuC5u3mxgqfTI8s8RmNjlrNbYp6Z3AIX+QdjhnYGGgIbmt8d
+zedG/poTh0fd4ndYUKJsyaD4FB8711mcib0uLc5g9MYs42PPNIRh2ZAukPxbT6IA
+h+dA4PzRJIvQKAHTU6yxWH+HKThWk92iFEqalLn4lLIER9u4OOaFK8/UcoiLDY6g
+afmfECKCnMXsAeMHoWk3lCU6zRcpN40k0ycPTb+wMTa4xqhpC98o+OLc2pU+f9c/
+pY+San2tOqyvcytf8bMiku/acYSeSyN7abcp/MUFhEv/BpLu9ZsUKq++7wLh59Do
+0Cl8SEDxlbsIsjDFgYCokVsuCDswRAe1xAsHdMpdNz11+bxtIabgkdj5J4gFWKf0
+Nuu6QGM2FUKYC+LRyRELKYHhxwJ++gVlUXvWGjNG/KXU/WToyBHU0UHZORgIo+0V
+cNkU9brJuz6WjV3Mw1y2yHkCLuKhBrqlIRy/Fn8t2ZMHkrH67j/jVjXzMKoRVNNx
+yynUYOFsrsQk4wBPX1KwP/R2823bvNhlxDe+GoebZcQg3dqpTJ+GMytJpveqztqY
+O+NfrLgbRQ5WWftJOA+31En4e6z62LgdFtuyTBXY5+trOP/SaSam9lAVRS8SsgXU
+v29TeWSb1YuhCD5D7gj+m+qDiYpqU5gexZFMepkrbZfclhveJ8WvD91CXCN9vGtb
+q0cpmDWPnubhX5Zqvc88R4mLrSHeINqZgsEOm3w4IdixHDTFTvf+fV6kL/h9XDAs
+nuZaT9MVkOZvaepRk48s3afDPFCo0boLXMwuTldxIQihLL2nIEuuXAJ6zZr+Htvs
+zjsSN8uWIHs7sVouhAP5CzJDwE7j6nnnmhNU5agaF8R5eCVjq2c5OaBsxMWUrBaS
+PfAaGp7KeoQbwVpfTGWKMKZebA6uv6wJlw+DXJLO5EPeBkuW9UY7fajjD9P+AMfU
+eU5fvexZEvllI/rnl6KmOTujHtpHxRhbjad7KRxaegbGkp63O/DFVujPhM3dYQ8h
+JfQeK0C2dCiNQfYsHc60OdHhvhV4ydeZoZ1QQ9rsQGlqOxevKCIJ4H04nqfKt/eU
+iiobMk4obRiVykJnyLsTJDFDhD6VZghcFX9rk8yPuHZ6/XRK1m9kdN9y9zSjUPDb
+vworG0i3ycCXIyexVlueEBJav/84YdpBdRXFA8Ig/X+EwJSOEe0BuvEZtQUdv4nq
+yThO0s9bJMY3oY5giVxS/31eLcn4sXkHTC8Yhei6vz7aWUPfKXl+ADjS/KmOO50=
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/NewCerts/01.pem b/selftest/manage-ca/CA-samba.example.com/NewCerts/01.pem
new file mode 100644
index 0000000..4ab5d5a
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/NewCerts/01.pem
@@ -0,0 +1,169 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:04 2016 GMT
+            Not After : Mar 11 23:29:04 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Users, CN=administrator at samba.example.com/emailAddress=administrator at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:af:87:9e:1e:7f:c0:ab:da:47:22:74:d0:df:01:
+                    f1:67:6c:ac:c4:b7:d9:18:97:e5:7a:62:76:33:b6:
+                    52:f2:92:90:75:ac:a3:94:7e:0c:29:75:c9:83:2f:
+                    19:66:60:84:45:ff:d5:a9:bd:c5:3a:a2:d8:25:cf:
+                    15:8a:23:3e:09:73:2f:99:1d:24:1f:e6:96:7e:7b:
+                    c4:1e:8d:55:5b:c1:18:69:cd:1d:b4:22:d5:7b:db:
+                    5e:7c:91:f2:8e:c1:03:30:ee:63:46:5a:54:d5:40:
+                    ac:79:55:00:71:07:8d:3e:0e:ed:ff:93:6c:f1:2d:
+                    84:c1:51:a3:7c:49:cf:ff:85:7b:c0:64:c1:ba:c8:
+                    66:7a:ff:17:2a:74:ea:16:6a:1d:97:c0:27:57:10:
+                    be:76:f5:9a:63:56:c7:25:c6:fc:a7:5e:00:a6:1a:
+                    3d:21:bd:7a:f9:e3:03:60:ce:df:16:06:fc:05:bc:
+                    d1:c8:5d:e7:33:ed:52:8b:60:5b:60:c5:70:13:1d:
+                    c1:b3:08:13:09:3b:05:e8:02:40:12:45:89:af:87:
+                    1f:6a:8f:62:ce:1e:17:13:34:82:81:86:e9:bb:85:
+                    5b:75:1d:f4:3a:02:b4:a6:58:23:fe:c3:3a:35:09:
+                    95:bb:f7:79:bc:e3:97:e6:6d:77:24:aa:2d:51:50:
+                    37:69
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Client, S/MIME
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Smart Card Login Certificate for administrator at samba.example.com
+            X509v3 Subject Key Identifier: 
+                45:DA:4B:8D:05:9C:62:4E:62:C3:D7:5C:5F:D3:D9:85:B4:9B:F2:2C
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                email:administrator at samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, scardLogin
+    Signature Algorithm: sha256WithRSAEncryption
+         a2:bb:e6:97:67:3c:b6:6e:6e:dd:34:99:16:c6:80:91:08:bf:
+         91:ba:51:62:5d:76:2f:e5:53:91:3d:99:03:18:a9:84:69:73:
+         76:66:c3:eb:56:d7:c5:40:91:15:da:de:b2:76:48:7d:8a:8c:
+         80:79:3c:e6:da:0e:a6:c3:53:d6:74:ee:5f:29:b7:03:46:de:
+         89:32:14:22:03:30:68:2e:7e:06:d4:ac:9e:82:c0:02:16:7f:
+         81:ba:ee:7a:e7:8b:f7:fb:99:7f:8c:eb:78:54:97:4e:28:44:
+         da:f4:e2:1b:f8:3e:ac:ca:cc:e3:e3:71:90:91:47:9c:78:ed:
+         6f:bc:b7:98:12:ea:75:e5:15:f7:26:56:a7:5c:d6:74:a8:13:
+         7b:23:35:4e:6a:01:f6:a9:f5:5b:9b:d0:ea:ba:0f:c3:c4:1a:
+         e0:b9:a3:ed:5d:28:cb:7f:1d:3e:8a:9a:af:4c:88:00:3c:10:
+         f0:49:85:24:60:e6:cb:d6:9e:00:46:78:4d:90:22:68:4f:10:
+         39:84:3b:e2:7c:3d:ed:23:41:19:7e:6f:45:59:89:a9:9f:26:
+         c1:f9:7d:4d:0a:b4:10:f9:31:7d:cc:87:d0:4b:62:14:70:86:
+         c8:7d:14:ff:e4:68:e2:de:42:ca:01:c7:aa:2d:5a:a5:72:64:
+         f1:4c:fa:6e:60:15:22:08:68:e6:c6:6a:75:63:24:b5:54:76:
+         d1:97:4f:e0:e8:bc:eb:d0:62:84:4a:b4:3a:07:38:5f:b9:a6:
+         6a:31:14:47:33:81:bd:d0:a4:a2:da:2b:92:0d:dc:42:c4:0f:
+         28:0d:b6:1b:33:b5:88:df:1b:a8:d8:90:9a:11:ce:df:d4:14:
+         e9:ac:94:94:95:bb:bc:6e:f1:be:85:29:3f:17:ab:41:14:d8:
+         20:ba:e0:a2:a3:d3:d4:8b:1e:4b:32:22:8d:0d:c1:e6:39:1a:
+         ce:cd:f3:1d:f1:82:85:d5:e7:80:34:90:a4:0e:d4:af:32:c8:
+         79:4e:25:32:b6:1e:06:3a:26:42:38:47:1a:32:96:71:5b:fe:
+         5b:b0:ef:7d:fe:58:ca:eb:b5:c9:4b:2f:12:cb:89:36:22:7c:
+         a6:39:ab:20:c1:2d:cd:6b:34:e1:cd:bc:ed:45:45:12:4a:65:
+         4b:ab:45:f2:6d:7a:9d:f8:b5:52:78:1b:da:2f:e0:ce:f7:e2:
+         b0:fa:6f:40:3d:dd:e9:39:c3:63:68:ab:77:53:be:3b:dd:9a:
+         bc:d7:d7:fa:6a:bf:bf:74:f7:11:80:87:f9:d3:45:eb:1e:8e:
+         d1:a9:a0:2e:66:e7:20:67:1c:4c:22:43:77:85:ff:1a:23:37:
+         cc:49:de:51:ee:f2:04:2f:a8:98:88:0f:b6:18:53:eb:e2:49:
+         15:5e:02:8b:1e:7b:e6:c5:d1:0c:df:84:4e:d9:bd:fe:21:48:
+         d4:a4:11:01:27:57:51:d6:c1:b2:a1:1c:11:9a:a7:d1:ab:f0:
+         99:16:b2:c8:3f:74:25:68:0b:1a:cf:58:0d:cd:cc:1a:6d:8b:
+         ec:1f:70:82:02:40:97:0f:75:2c:53:87:c1:42:5c:d1:7e:19:
+         78:2c:2c:88:73:33:81:63:38:84:07:0f:16:bb:7c:54:59:03:
+         94:e7:b8:85:d7:f8:5e:53:35:65:2e:e5:27:65:be:f0:89:65:
+         f6:ab:3f:6e:a5:bd:c1:1a:9e:31:30:68:6e:50:af:54:4c:33:
+         f8:73:2f:41:60:4f:4c:85:1b:ad:7d:db:62:42:dc:87:96:b4:
+         cf:ce:12:50:ed:6c:01:5f:e2:f9:03:f5:f7:4c:6c:8f:2b:5b:
+         7a:64:7d:19:e8:20:f2:e9:10:58:f3:71:0e:1e:58:68:f2:59:
+         3c:06:53:7a:f3:60:62:5b:c7:b7:83:58:1d:3d:a6:17:db:33:
+         cc:91:14:af:d6:b9:08:bf:60:af:ac:3e:fe:8b:74:71:20:c7:
+         e7:31:5e:26:6c:28:52:67:12:1e:c3:9b:89:23:5d:88:ee:b0:
+         6b:db:cc:94:8b:9b:1b:40:b7:66:bc:7d:1d:e1:08:00:20:ba:
+         41:cd:17:d6:4c:7b:c4:5a:fd:cf:6b:20:e2:b8:86:9c:31:17:
+         c2:d7:7f:1c:3a:d0:fc:1d:f5:7f:c9:96:04:27:de:b8:ef:8d:
+         38:9a:b3:56:60:ac:c2:07:38:64:19:39:9e:73:6f:ba:59:15:
+         ac:45:42:4d:bb:79:60:7f:ae:c3:8d:63:4a:27:16:0a:ca:92:
+         7f:f7:a2:02:76:f5:e6:7c:ec:ba:ea:18:cd:9c:3b:ee:37:2c:
+         9d:78:4e:c9:40:6d:94:cc:ce:ca:f4:33:fc:a4:dd:05:62:d6:
+         0f:1e:19:63:af:10:c3:ff:02:1a:0a:48:fd:af:f2:a4:0e:64:
+         dd:90:f4:4f:14:1b:90:1f:9e:29:b0:0b:94:a4:d1:2a:87:b9:
+         3a:76:c2:b6:af:c3:d4:84:6e:85:1c:64:73:46:d0:df:72:c0:
+         3c:42:91:c4:30:10:11:18:36:bc:e5:17:36:22:5f:c2:3f:ac:
+         1d:2e:9d:87:11:be:a7:ac:b2:62:35:74:b9:27:27:95:bc:c1:
+         11:44:f8:64:36:60:74:06:a2:e7:e9:76:be:a7:86:5e:18:1e:
+         bd:dc:b0:aa:ae:92:d6:dd:d6:25:80:d6:c1:be:c1:21:1c:01:
+         6f:83:20:ae:b7:54:4f:3d:2d:12:fc:a2:cc:49:fd:59
+-----BEGIN CERTIFICATE-----
+MIII/TCCBOWgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5MDRaFw0zNjAzMTEyMzI5MDRaMIGnMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEOMAwGA1UE
+CwwFVXNlcnMxKDAmBgNVBAMMH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5j
+b20xLjAsBgkqhkiG9w0BCQEWH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5j
+b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvh54ef8Cr2kcidNDf
+AfFnbKzEt9kYl+V6YnYztlLykpB1rKOUfgwpdcmDLxlmYIRF/9WpvcU6otglzxWK
+Iz4Jcy+ZHSQf5pZ+e8QejVVbwRhpzR20ItV72158kfKOwQMw7mNGWlTVQKx5VQBx
+B40+Du3/k2zxLYTBUaN8Sc//hXvAZMG6yGZ6/xcqdOoWah2XwCdXEL529ZpjVscl
+xvynXgCmGj0hvXr54wNgzt8WBvwFvNHIXecz7VKLYFtgxXATHcGzCBMJOwXoAkAS
+RYmvhx9qj2LOHhcTNIKBhum7hVt1HfQ6ArSmWCP+wzo1CZW793m845fmbXckqi1R
+UDdpAgMBAAGjggIRMIICDTAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0
+dHA6Ly93d3cuc2FtYmEuZXhhbXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxl
+LmNvbS1jcmwuY3JsMBEGCWCGSAGG+EIBAQQEAwIFoDALBgNVHQ8EBAMCBeAwTwYJ
+YIZIAYb4QgENBEIWQFNtYXJ0IENhcmQgTG9naW4gQ2VydGlmaWNhdGUgZm9yIGFk
+bWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5jb20wHQYDVR0OBBYEFEXaS40FnGJO
+YsPXXF/T2YW0m/IsMB8GA1UdIwQYMBaAFKI+Aiqjp005tAhNmcwMdTbqJ8M+MFsG
+A1UdEQRUMFKBH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5jb22gLwYKKwYB
+BAGCNxQCA6AhDB9hZG1pbmlzdHJhdG9yQHNhbWJhLmV4YW1wbGUuY29tMDEGA1Ud
+EgQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0G
+CWCGSAGG+EIBBARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMv
+Q0Etc2FtYmEuZXhhbXBsZS5jb20tY3JsLmNybDAfBgNVHSUEGDAWBggrBgEFBQcD
+AgYKKwYBBAGCNxQCAjANBgkqhkiG9w0BAQsFAAOCBAEAorvml2c8tm5u3TSZFsaA
+kQi/kbpRYl12L+VTkT2ZAxiphGlzdmbD61bXxUCRFdresnZIfYqMgHk85toOpsNT
+1nTuXym3A0beiTIUIgMwaC5+BtSsnoLAAhZ/gbrueueL9/uZf4zreFSXTihE2vTi
+G/g+rMrM4+NxkJFHnHjtb7y3mBLqdeUV9yZWp1zWdKgTeyM1TmoB9qn1W5vQ6roP
+w8Qa4Lmj7V0oy38dPoqar0yIADwQ8EmFJGDmy9aeAEZ4TZAiaE8QOYQ74nw97SNB
+GX5vRVmJqZ8mwfl9TQq0EPkxfcyH0EtiFHCGyH0U/+Ro4t5CygHHqi1apXJk8Uz6
+bmAVIgho5sZqdWMktVR20ZdP4Oi869BihEq0Ogc4X7mmajEURzOBvdCkotorkg3c
+QsQPKA22GzO1iN8bqNiQmhHO39QU6ayUlJW7vG7xvoUpPxerQRTYILrgoqPT1Ise
+SzIijQ3B5jkazs3zHfGChdXngDSQpA7UrzLIeU4lMrYeBjomQjhHGjKWcVv+W7Dv
+ff5Yyuu1yUsvEsuJNiJ8pjmrIMEtzWs04c287UVFEkplS6tF8m16nfi1Ungb2i/g
+zvfisPpvQD3d6TnDY2ird1O+O92avNfX+mq/v3T3EYCH+dNF6x6O0amgLmbnIGcc
+TCJDd4X/GiM3zEneUe7yBC+omIgPthhT6+JJFV4Cix575sXRDN+ETtm9/iFI1KQR
+ASdXUdbBsqEcEZqn0avwmRayyD90JWgLGs9YDc3MGm2L7B9wggJAlw91LFOHwUJc
+0X4ZeCwsiHMzgWM4hAcPFrt8VFkDlOe4hdf4XlM1ZS7lJ2W+8Ill9qs/bqW9wRqe
+MTBoblCvVEwz+HMvQWBPTIUbrX3bYkLch5a0z84SUO1sAV/i+QP190xsjytbemR9
+Gegg8ukQWPNxDh5YaPJZPAZTevNgYlvHt4NYHT2mF9szzJEUr9a5CL9gr6w+/ot0
+cSDH5zFeJmwoUmcSHsObiSNdiO6wa9vMlIubG0C3Zrx9HeEIACC6Qc0X1kx7xFr9
+z2sg4riGnDEXwtd/HDrQ/B31f8mWBCfeuO+NOJqzVmCswgc4ZBk5nnNvulkVrEVC
+Tbt5YH+uw41jSicWCsqSf/eiAnb15nzsuuoYzZw77jcsnXhOyUBtlMzOyvQz/KTd
+BWLWDx4ZY68Qw/8CGgpI/a/ypA5k3ZD0TxQbkB+eKbALlKTRKoe5OnbCtq/D1IRu
+hRxkc0bQ33LAPEKRxDAQERg2vOUXNiJfwj+sHS6dhxG+p6yyYjV0uScnlbzBEUT4
+ZDZgdAai5+l2vqeGXhgevdywqq6S1t3WJYDWwb7BIRwBb4MgrrdUTz0tEvyizEn9
+WQ==
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/NewCerts/02.pem b/selftest/manage-ca/CA-samba.example.com/NewCerts/02.pem
new file mode 100644
index 0000000..2e2a8b9
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/NewCerts/02.pem
@@ -0,0 +1,191 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:25 2016 GMT
+            Not After : Mar 11 23:29:25 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Domain Controllers, CN=addc.addom.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:a6:c4:a9:bf:75:ea:4c:8d:3b:fd:8a:0f:b0:a2:
+                    b6:c7:a8:1f:e4:0e:3e:41:ef:d6:10:48:77:7b:4e:
+                    4c:59:e1:bf:6d:c7:18:7b:a8:01:a7:d5:d2:2c:21:
+                    3e:d0:1a:da:58:03:e8:42:f1:53:0e:a7:91:b9:2c:
+                    b9:e7:7a:c9:de:5e:ed:4c:93:6b:cc:dd:17:d0:c7:
+                    d1:f1:7c:3d:0d:6f:df:5d:53:5a:b1:1f:a3:7b:5b:
+                    41:65:0c:7c:ea:53:df:bb:da:41:15:da:49:e3:b9:
+                    2d:bb:b5:af:ef:8c:b8:84:74:d0:18:16:8e:5c:e4:
+                    c2:e7:a1:87:8f:e3:87:8b:0b:bb:90:30:e8:e0:f3:
+                    eb:c0:50:5f:b5:7f:54:9a:1b:34:43:fd:be:5a:80:
+                    6e:0f:63:a2:b3:79:42:4a:85:c8:07:c7:82:55:23:
+                    88:d4:4e:03:2f:f1:95:bd:ed:15:2d:3e:16:cd:ff:
+                    c7:9b:03:29:36:a6:5d:c9:1a:1e:89:a5:ba:66:83:
+                    0f:96:a8:07:9f:24:b9:1b:8f:02:9a:b8:50:29:8b:
+                    be:63:45:fa:45:c3:38:23:a0:98:3a:b4:6b:42:99:
+                    13:36:4b:84:ef:27:89:39:34:79:f8:67:16:7b:9c:
+                    2a:03:41:15:63:46:e4:db:2f:f2:3e:6d:fe:7c:20:
+                    1e:9f:02:48:a4:bc:15:42:a6:f8:38:86:dc:6b:7c:
+                    4e:67:a3:31:81:8e:b6:30:1a:eb:3d:08:25:19:5f:
+                    42:dc:39:ec:79:1d:30:0a:fb:16:8f:3d:19:14:cc:
+                    f5:af:d7:c6:75:cf:b3:96:a2:b2:9b:d9:03:01:a3:
+                    ca:88:1d:72:ed:6f:d1:bf:57:56:8e:b9:07:9b:b9:
+                    04:13:1e:0b:5a:06:6b:2b:43:a2:dc:d5:b7:f4:ba:
+                    d3:ae:9d:ad:fd:d3:8a:7c:2f:87:32:fa:89:88:58:
+                    00:ae:16:2b:9c:1d:58:82:4d:e5:21:da:d5:6c:f7:
+                    a8:40:8b:c7:02:d5:36:30:ef:3f:09:9b:a6:d2:31:
+                    a3:bf:20:d4:a2:9e:26:c4:b4:c3:0f:0b:6c:00:d1:
+                    2c:16:b1:2a:eb:06:d9:d5:98:c3:cd:cb:20:68:ad:
+                    0a:2c:a1:2f:27:41:5c:91:de:49:62:ed:d8:3a:ef:
+                    68:1c:6d:fe:94:c3:28:68:32:60:08:65:cd:02:9f:
+                    97:96:2f:0f:87:27:3d:b9:0f:85:62:e8:2b:9a:b4:
+                    f4:d3:d7:c1:93:96:27:23:29:88:b1:39:99:53:3a:
+                    20:aa:88:44:3b:4a:24:2a:8b:e0:b4:8d:dd:66:30:
+                    df:a6:6e:b7:fc:21:43:16:9e:3e:12:20:c8:7a:30:
+                    c1:3d:ab
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Domain Controller Certificate addc.addom.samba.example.com
+            X509v3 Subject Key Identifier: 
+                3D:BC:70:0C:74:D4:B8:85:49:1D:08:84:C4:1B:27:F2:AF:72:37:D3
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                DNS:addc.addom.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, TLS Web Server Authentication, msKDC
+    Signature Algorithm: sha256WithRSAEncryption
+         9e:8b:bb:0a:7a:dc:c0:94:33:bc:18:a5:e6:4a:1f:ff:8e:21:
+         b1:8f:33:f0:3e:8b:6c:72:55:c4:47:71:5f:ce:e7:31:ef:5b:
+         62:04:b7:57:8f:a8:27:9f:ed:69:d2:ec:a8:0d:e2:76:33:8d:
+         41:3a:67:61:5c:53:60:c7:53:ed:d7:99:72:29:1d:ae:d3:ee:
+         c9:76:1c:6d:18:47:e9:94:dd:2e:97:3f:99:af:b5:f4:a1:7c:
+         92:f6:4d:b5:c1:7a:0c:38:ba:d1:b6:19:9a:9f:e2:02:84:d4:
+         54:01:38:7b:55:86:4a:ee:3d:85:48:01:da:34:09:69:43:25:
+         7e:6e:06:73:e0:b9:7c:b5:9c:4e:9c:b5:52:85:32:62:62:25:
+         39:fa:02:4b:51:2e:df:8e:52:17:02:50:f4:99:29:bf:7e:97:
+         53:91:12:85:9a:69:62:45:59:c4:5b:3f:af:18:e6:7b:e4:86:
+         5d:f1:9e:5a:2b:3e:14:6e:7e:d4:47:24:ef:d9:a8:ec:d9:a6:
+         cb:b8:4f:1a:86:d9:43:20:41:16:15:5f:81:0d:fe:6b:31:53:
+         c1:f6:84:4c:f3:03:64:d2:e6:44:3d:7a:60:79:d7:37:6f:33:
+         de:c0:a8:b9:6e:fe:b2:79:ac:b4:53:92:b8:0a:59:2b:cc:6b:
+         37:c4:6f:c6:44:02:f7:7c:c5:c6:a6:6f:c2:ad:de:78:1e:48:
+         96:cc:fe:59:2e:53:ce:34:d6:e8:f0:56:43:30:32:90:6f:f9:
+         47:76:ab:99:63:e3:e8:a3:f3:83:98:e9:05:2b:ea:f9:f9:9d:
+         66:70:c7:2c:00:c2:9e:57:3e:31:43:50:50:c8:db:a8:2d:21:
+         4e:6f:39:c2:bd:ef:d8:47:99:27:0d:48:b2:58:f1:be:45:bd:
+         fe:c4:a2:56:fc:06:02:dc:19:33:85:53:ed:38:59:01:16:bc:
+         aa:c5:d3:4b:37:54:83:1b:e5:c1:4b:dd:34:6b:e5:d8:35:86:
+         95:e6:9f:d2:22:84:b1:e2:4f:a7:2e:4d:e6:9c:eb:db:df:42:
+         e1:b4:66:e6:58:d3:28:10:34:97:f3:9c:6b:5f:05:2c:47:2c:
+         e3:75:eb:6f:74:0a:ec:d7:1d:30:80:56:44:12:26:f6:4e:5f:
+         ff:92:f4:62:02:36:9c:62:eb:39:98:53:68:68:95:fb:94:68:
+         69:b8:3c:66:1a:ce:78:c4:cf:c4:6f:21:ac:a8:a6:f4:ab:69:
+         2a:2e:00:5d:f7:67:06:b1:4f:97:58:88:55:d8:6e:eb:a5:98:
+         50:36:21:70:3d:b0:a4:f5:3b:21:b3:1c:f5:a9:dd:c6:4a:c2:
+         89:b8:5a:b3:bc:1f:21:ce:4c:68:5f:98:d8:39:70:d2:7e:a0:
+         90:df:ad:a3:13:eb:3c:93:f6:b8:f4:d9:a7:51:b3:0d:ea:ee:
+         d4:57:aa:db:ca:7c:8a:a0:08:c3:98:9a:3a:b7:ba:2a:50:92:
+         26:c2:e3:11:ba:12:60:24:b9:59:df:62:a8:d7:4d:a3:cb:ea:
+         46:e8:39:f9:83:14:a8:5c:44:75:71:6b:7f:99:bd:68:58:d9:
+         6b:d1:cd:c7:45:95:9e:44:1e:85:35:c0:30:2b:18:aa:eb:2f:
+         93:d5:be:66:5d:70:ed:1d:04:f2:c1:1e:b5:ec:45:0c:04:f6:
+         9d:88:d3:0c:20:5e:5b:23:df:34:a1:f5:ea:b4:a1:44:c0:da:
+         d5:ea:89:e8:b5:cb:dc:f8:92:ee:ac:8d:61:ed:bf:74:2b:28:
+         79:1f:f4:9a:ff:63:bd:e6:aa:79:1d:2c:26:4a:b2:26:53:57:
+         ba:88:0e:eb:19:57:c0:10:a0:1e:81:2a:c0:56:2e:c3:2a:81:
+         bf:c1:5a:e7:48:ce:c1:6a:b9:6c:41:cc:44:a6:b8:70:e2:57:
+         0e:6d:41:d6:61:da:bf:ac:20:2c:a7:2a:67:23:98:00:ba:ce:
+         8b:a8:c2:45:66:a7:08:eb:7f:0a:b5:e7:9b:d6:f4:07:d5:b3:
+         43:cd:27:d4:fa:c9:40:8f:af:b2:36:1c:e7:44:b4:4e:cc:5a:
+         2b:73:ad:8f:c4:d9:47:a6:fb:2c:7d:1a:80:2a:55:b3:80:34:
+         6f:8e:17:27:93:05:21:40:e9:8f:bf:47:6a:52:f5:2e:b5:18:
+         d1:8c:1d:83:04:80:55:fd:21:28:dc:7c:be:c8:c1:5f:e4:40:
+         d3:13:e4:66:bf:ad:92:4e:9b:db:c1:be:a3:42:74:da:c3:2c:
+         0a:da:3f:94:14:ad:7e:de:81:c6:01:6a:f7:7a:b4:25:51:b0:
+         ab:cd:b3:3a:77:bf:c3:6b:04:44:30:73:41:ad:93:49:67:ee:
+         43:d1:96:8e:36:83:2b:1b:6c:e7:cc:3e:d6:16:b9:88:4a:ab:
+         56:c0:76:00:f6:9a:6a:8a:e3:e0:41:75:9d:3b:47:0f:c9:0a:
+         8e:9f:9c:00:92:bb:ae:d8:42:56:35:64:eb:59:13:da:2c:63:
+         83:c3:ec:68:91:b5:f3:71:85:48:54:c3:9d:a1:c8:63:f3:de:
+         5d:a5:34:a9:1e:85:2c:2c:b5:d8:a9:62:8d:26:1f:b2:9e:a7:
+         83:4d:df:69:63:b5:b7:e5:dd:e7:3b:18:e5:b3:77:df:c5:47:
+         b3:f7:8c:e7:5e:87:2e:46:e3:8f:b1:2b:9b:c6:26:2d:1a:28:
+         30:13:10:86:5b:46:87:b1:2d:12:ce:b6:fe:1c:4e:44
+-----BEGIN CERTIFICATE-----
+MIIJ9DCCBdygAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5MjVaFw0zNjAzMTEyMzI5MjVaMIG4MQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEbMBkGA1UE
+CwwSRG9tYWluIENvbnRyb2xsZXJzMSUwIwYDVQQDDBxhZGRjLmFkZG9tLnNhbWJh
+LmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkBFiZjYS1zYW1iYS5leGFtcGxlLmNv
+bUBzYW1iYS5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAKbEqb916kyNO/2KD7CitseoH+QOPkHv1hBId3tOTFnhv23HGHuoAafV0iwh
+PtAa2lgD6ELxUw6nkbksued6yd5e7UyTa8zdF9DH0fF8PQ1v311TWrEfo3tbQWUM
+fOpT37vaQRXaSeO5Lbu1r++MuIR00BgWjlzkwuehh4/jh4sLu5Aw6ODz68BQX7V/
+VJobNEP9vlqAbg9jorN5QkqFyAfHglUjiNROAy/xlb3tFS0+Fs3/x5sDKTamXcka
+HomlumaDD5aoB58kuRuPApq4UCmLvmNF+kXDOCOgmDq0a0KZEzZLhO8niTk0efhn
+FnucKgNBFWNG5Nsv8j5t/nwgHp8CSKS8FUKm+DiG3Gt8TmejMYGOtjAa6z0IJRlf
+Qtw57HkdMAr7Fo89GRTM9a/XxnXPs5aispvZAwGjyogdcu1v0b9XVo65B5u5BBMe
+C1oGaytDotzVt/S6066drf3TinwvhzL6iYhYAK4WK5wdWIJN5SHa1Wz3qECLxwLV
+NjDvPwmbptIxo78g1KKeJsS0ww8LbADRLBaxKusG2dWYw83LIGitCiyhLydBXJHe
+SWLt2DrvaBxt/pTDKGgyYAhlzQKfl5YvD4cnPbkPhWLoK5q09NPXwZOWJyMpiLE5
+mVM6IKqIRDtKJCqL4LSN3WYw36Zut/whQxaePhIgyHowwT2rAgMBAAGjggH3MIIB
+8zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEu
+ZXhhbXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEG
+CWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwSQYJYIZIAYb4QgENBDwWOkRv
+bWFpbiBDb250cm9sbGVyIENlcnRpZmljYXRlIGFkZGMuYWRkb20uc2FtYmEuZXhh
+bXBsZS5jb20wHQYDVR0OBBYEFD28cAx01LiFSR0IhMQbJ/KvcjfTMB8GA1UdIwQY
+MBaAFKI+Aiqjp005tAhNmcwMdTbqJ8M+MEAGA1UdEQQ5MDeCHGFkZGMuYWRkb20u
+c2FtYmEuZXhhbXBsZS5jb22gFwYJKwYBBAGCNxkBoAoECAEjRWeJq83vMDEGA1Ud
+EgQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0G
+CWCGSAGG+EIBBARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMv
+Q0Etc2FtYmEuZXhhbXBsZS5jb20tY3JsLmNybDAmBgNVHSUEHzAdBggrBgEFBQcD
+AgYIKwYBBQUHAwEGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggQBAJ6Luwp63MCU
+M7wYpeZKH/+OIbGPM/A+i2xyVcRHcV/O5zHvW2IEt1ePqCef7WnS7KgN4nYzjUE6
+Z2FcU2DHU+3XmXIpHa7T7sl2HG0YR+mU3S6XP5mvtfShfJL2TbXBegw4utG2GZqf
+4gKE1FQBOHtVhkruPYVIAdo0CWlDJX5uBnPguXy1nE6ctVKFMmJiJTn6AktRLt+O
+UhcCUPSZKb9+l1OREoWaaWJFWcRbP68Y5nvkhl3xnlorPhRuftRHJO/ZqOzZpsu4
+TxqG2UMgQRYVX4EN/msxU8H2hEzzA2TS5kQ9emB51zdvM97AqLlu/rJ5rLRTkrgK
+WSvMazfEb8ZEAvd8xcamb8Kt3ngeSJbM/lkuU8401ujwVkMwMpBv+Ud2q5lj4+ij
+84OY6QUr6vn5nWZwxywAwp5XPjFDUFDI26gtIU5vOcK979hHmScNSLJY8b5Fvf7E
+olb8BgLcGTOFU+04WQEWvKrF00s3VIMb5cFL3TRr5dg1hpXmn9IihLHiT6cuTeac
+69vfQuG0ZuZY0ygQNJfznGtfBSxHLON16290CuzXHTCAVkQSJvZOX/+S9GICNpxi
+6zmYU2holfuUaGm4PGYaznjEz8RvIayopvSraSouAF33ZwaxT5dYiFXYbuulmFA2
+IXA9sKT1OyGzHPWp3cZKwom4WrO8HyHOTGhfmNg5cNJ+oJDfraMT6zyT9rj02adR
+sw3q7tRXqtvKfIqgCMOYmjq3uipQkibC4xG6EmAkuVnfYqjXTaPL6kboOfmDFKhc
+RHVxa3+ZvWhY2WvRzcdFlZ5EHoU1wDArGKrrL5PVvmZdcO0dBPLBHrXsRQwE9p2I
+0wwgXlsj3zSh9eq0oUTA2tXqiei1y9z4ku6sjWHtv3QrKHkf9Jr/Y73mqnkdLCZK
+siZTV7qIDusZV8AQoB6BKsBWLsMqgb/BWudIzsFquWxBzESmuHDiVw5tQdZh2r+s
+ICynKmcjmAC6zouowkVmpwjrfwq155vW9AfVs0PNJ9T6yUCPr7I2HOdEtE7MWitz
+rY/E2Uem+yx9GoAqVbOANG+OFyeTBSFA6Y+/R2pS9S61GNGMHYMEgFX9ISjcfL7I
+wV/kQNMT5Ga/rZJOm9vBvqNCdNrDLAraP5QUrX7egcYBavd6tCVRsKvNszp3v8Nr
+BEQwc0Gtk0ln7kPRlo42gysbbOfMPtYWuYhKq1bAdgD2mmqK4+BBdZ07Rw/JCo6f
+nACSu67YQlY1ZOtZE9osY4PD7GiRtfNxhUhUw52hyGPz3l2lNKkehSwstdipYo0m
+H7Kep4NN32ljtbfl3ec7GOWzd9/FR7P3jOdehy5G44+xK5vGJi0aKDATEIZbRoex
+LRLOtv4cTkQ=
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/NewCerts/03.pem b/selftest/manage-ca/CA-samba.example.com/NewCerts/03.pem
new file mode 100644
index 0000000..7486a63
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/NewCerts/03.pem
@@ -0,0 +1,169 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:41 2016 GMT
+            Not After : Mar 11 23:29:41 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Users, CN=administrator at addom.samba.example.com/emailAddress=administrator at addom.samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:be:91:64:f2:1b:2b:ed:9b:40:bc:0d:46:23:49:
+                    77:32:74:fe:cb:9a:46:86:33:1e:56:bd:c8:da:dd:
+                    e6:2a:07:34:61:1c:f0:b8:71:29:24:2b:90:f3:43:
+                    99:6f:69:f6:ff:8d:b9:b7:3f:f3:36:6a:99:90:90:
+                    d6:95:63:4e:88:5a:d7:41:89:7f:73:13:64:49:c7:
+                    de:42:65:08:5d:ca:04:b2:68:3a:40:7f:6a:05:df:
+                    56:30:2f:ac:1b:8b:0f:c3:15:3c:38:0f:90:50:44:
+                    00:bb:59:40:f6:d2:e8:5b:73:03:0d:f6:7d:38:5d:
+                    2f:99:c3:0d:13:0f:74:d0:9e:ef:1e:92:42:c4:46:
+                    7c:dc:85:7e:e9:af:91:4e:9d:5f:82:af:58:60:18:
+                    a5:ac:91:6e:dd:cf:a7:32:3c:d2:f4:e9:81:be:80:
+                    9e:0c:ca:1f:1a:be:98:c4:fe:e6:25:c1:89:fe:16:
+                    0a:30:90:d3:d4:e5:af:89:24:64:12:d0:4f:19:e2:
+                    1b:86:fb:06:a9:63:d1:47:10:89:dc:2b:52:24:dc:
+                    66:a9:56:c2:cb:f4:ec:35:12:f4:ad:5e:fc:ff:86:
+                    e9:b1:f9:1f:b3:ce:44:fb:be:04:af:8d:42:9b:56:
+                    a5:02:7f:c5:cf:5f:23:41:1c:69:ee:33:97:7a:81:
+                    50:8b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Client, S/MIME
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Smart Card Login Certificate for administrator at addom.samba.example.com
+            X509v3 Subject Key Identifier: 
+                30:10:6E:1F:7E:52:33:8C:C8:85:E5:92:74:5D:76:7E:E9:33:5B:36
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                email:administrator at addom.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, scardLogin
+    Signature Algorithm: sha256WithRSAEncryption
+         53:3e:51:d2:5d:2c:69:23:5b:dd:05:1a:23:ff:39:5d:54:63:
+         e5:da:e1:4b:60:8c:09:7c:4e:8e:da:8a:bb:63:5d:bc:2d:a0:
+         d4:ce:9e:d2:ce:38:d7:32:67:ba:4a:a6:d1:1d:c4:c7:50:e8:
+         9a:9e:44:56:1a:9c:f4:8f:b9:8e:39:84:21:db:0f:60:8a:60:
+         b4:0f:4f:3c:35:a0:d2:37:3d:88:e8:0a:18:a7:a7:2d:19:e3:
+         aa:d3:8e:18:8f:35:ef:3e:4a:95:c4:d3:9b:f4:cf:89:c2:70:
+         b9:8c:5c:ef:8a:9e:7a:56:73:13:eb:8b:b7:d9:e1:88:5b:c4:
+         62:47:42:45:8d:7b:2d:cf:71:83:1b:48:9d:84:8f:65:66:97:
+         61:fc:f6:30:34:e8:88:2a:34:91:48:dc:7a:b7:65:bc:9c:98:
+         00:4c:e7:49:fe:4d:a9:56:ea:87:d6:6c:46:39:f2:98:5b:56:
+         14:82:f2:9e:b8:ad:fd:89:36:48:87:4e:5c:ef:3f:e0:35:ff:
+         72:5f:5b:e1:c2:fd:d9:6e:40:2b:35:ad:50:08:74:94:87:89:
+         c4:cd:c7:ab:a7:19:4e:ba:f2:1d:83:0f:b0:cf:9c:e6:df:73:
+         36:88:cf:42:9c:a3:72:27:0f:f7:bf:5b:cc:6b:e5:20:03:b5:
+         4a:1c:f3:7d:ae:92:43:aa:bb:13:07:a4:3a:77:3d:34:01:00:
+         f1:89:aa:e8:1b:09:7b:b8:b0:e1:54:03:ff:3d:8d:be:35:b9:
+         13:b2:59:58:32:48:93:f8:e7:d7:3d:49:70:01:44:e6:2b:21:
+         b3:75:49:ae:44:7a:50:15:b8:65:f3:c3:48:96:df:c8:d9:2a:
+         f7:c5:2a:7e:2c:68:77:af:2d:78:1b:fc:1a:d8:f4:8b:a6:86:
+         35:d2:f0:87:e9:d6:30:0a:76:65:f8:71:e9:80:0d:1f:16:86:
+         89:92:81:34:d9:be:9b:41:25:ec:65:a9:0a:56:b2:03:91:54:
+         02:21:97:99:74:61:8c:4a:2e:f4:d0:b1:8b:f1:e6:26:52:bc:
+         f6:f2:e0:bd:96:66:22:c3:4e:51:2f:c3:c4:65:65:c7:97:b5:
+         1b:29:23:7a:c0:7b:fb:49:33:a0:a9:6a:b7:2f:f3:44:6b:5b:
+         0c:2c:0d:75:f2:50:d5:82:ba:9a:ab:e0:89:0a:b6:b5:8a:5e:
+         1a:67:ab:d9:a7:21:22:75:61:1e:d7:21:36:15:6a:da:a8:39:
+         4d:95:50:2b:e6:ac:c4:f6:38:74:c9:c5:ac:ce:2f:b3:c8:d4:
+         ad:18:a7:93:d4:1a:be:c2:be:9e:39:e6:a7:b1:0e:93:d0:9e:
+         cf:b0:ac:53:7d:08:1f:9d:a5:98:2b:4e:f6:80:e4:df:ea:43:
+         a2:f9:64:bf:84:b2:ff:1c:93:36:60:74:08:4e:5b:d6:24:9a:
+         f8:ac:c7:81:f9:2a:a9:00:28:44:15:6a:31:b9:b5:08:89:c8:
+         31:15:1e:8f:9d:2c:d0:e3:a8:32:2c:68:42:41:19:6c:43:8e:
+         69:c0:44:01:ba:1c:c4:ea:f4:ff:c8:57:03:ba:df:3f:5e:a5:
+         03:da:75:31:2e:07:67:a7:5c:02:55:c3:6f:8f:11:f5:8c:56:
+         a1:f7:4b:bb:46:d0:e5:ff:68:c1:77:3d:0d:35:12:f5:40:af:
+         cd:05:5c:53:74:ff:54:e0:c0:c6:10:5c:e8:33:06:0a:50:47:
+         7e:71:3a:36:66:aa:f8:de:97:2a:ae:bf:8d:6d:d4:39:c4:fd:
+         b3:03:1d:a5:9c:47:39:8c:c0:b3:73:f8:3a:d6:34:ac:49:4f:
+         b3:87:74:11:20:8f:c0:aa:24:a7:30:20:0c:c0:d9:1c:44:ee:
+         ae:c8:b8:13:63:e5:f8:5e:8f:b0:5a:46:c5:83:3d:41:62:06:
+         e4:62:a6:0a:40:cc:8e:59:ad:8a:36:4e:20:e6:f2:32:04:6e:
+         ee:4e:7d:97:88:dc:ea:74:90:c4:ab:a8:b5:bc:6c:81:b1:64:
+         77:a6:93:34:44:e4:60:38:b1:0c:2b:29:3a:4a:f7:17:d7:3a:
+         c8:42:7e:db:4d:5f:09:92:ae:6c:90:e1:7d:9f:96:9c:1a:82:
+         bd:45:02:76:29:62:e5:b9:14:53:01:53:c0:5a:d5:34:53:7a:
+         25:49:3e:3d:db:19:7e:29:57:80:78:67:ea:21:3e:3d:59:36:
+         e0:8b:da:75:57:9b:c8:9d:a1:18:18:e2:5c:35:35:9e:62:2c:
+         f5:0f:c0:8f:55:16:a5:d4:9e:cd:0e:78:87:9d:53:d3:01:e1:
+         18:61:36:1c:06:c3:3a:43:f3:8a:13:e6:4e:52:32:fd:46:21:
+         cd:62:18:1f:ae:f5:f2:1a:ea:7a:01:3b:a1:3f:1d:16:00:91:
+         5e:94:78:f4:60:33:54:a9:fc:1c:0a:75:f9:17:aa:dd:12:91:
+         66:4b:f0:d1:60:25:d4:06:d1:99:9c:c5:64:01:4b:ba:d9:66:
+         ba:9c:f7:68:75:fd:11:3a:eb:6e:fb:8f:a6:17:8a:cd:bc:1a:
+         59:f9:a9:cd:33:db:7d:71:26:7d:c7:be:de:eb:2e:c0:7e:db:
+         29:08:0e:82:63:1e:8c:8f:e6:21:1c:b1:49:13:9e:df:78:3b:
+         68:01:17:0f:df:97:96:58:32:48:1e:5c:ff:fa:db:90:b5:05:
+         84:68:fd:7c:c0:a5:35:d9:75:1e:ea:cc:25:25:3f:6e
+-----BEGIN CERTIFICATE-----
+MIIJGzCCBQOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5NDFaFw0zNjAzMTEyMzI5NDFaMIGzMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEOMAwGA1UE
+CwwFVXNlcnMxLjAsBgNVBAMMJWFkbWluaXN0cmF0b3JAYWRkb20uc2FtYmEuZXhh
+bXBsZS5jb20xNDAyBgkqhkiG9w0BCQEWJWFkbWluaXN0cmF0b3JAYWRkb20uc2Ft
+YmEuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+
+kWTyGyvtm0C8DUYjSXcydP7LmkaGMx5Wvcja3eYqBzRhHPC4cSkkK5DzQ5lvafb/
+jbm3P/M2apmQkNaVY06IWtdBiX9zE2RJx95CZQhdygSyaDpAf2oF31YwL6wbiw/D
+FTw4D5BQRAC7WUD20uhbcwMN9n04XS+Zww0TD3TQnu8ekkLERnzchX7pr5FOnV+C
+r1hgGKWskW7dz6cyPNL06YG+gJ4Myh8avpjE/uYlwYn+FgowkNPU5a+JJGQS0E8Z
+4huG+wapY9FHEIncK1Ik3GapVsLL9Ow1EvStXvz/humx+R+zzkT7vgSvjUKbVqUC
+f8XPXyNBHGnuM5d6gVCLAgMBAAGjggIjMIICHzAJBgNVHRMEAjAAME8GA1UdHwRI
+MEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEuZXhhbXBsZS5jb20vY3Jscy9DQS1z
+YW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEGCWCGSAGG+EIBAQQEAwIFoDALBgNV
+HQ8EBAMCBeAwVQYJYIZIAYb4QgENBEgWRlNtYXJ0IENhcmQgTG9naW4gQ2VydGlm
+aWNhdGUgZm9yIGFkbWluaXN0cmF0b3JAYWRkb20uc2FtYmEuZXhhbXBsZS5jb20w
+HQYDVR0OBBYEFDAQbh9+UjOMyIXlknRddn7pM1s2MB8GA1UdIwQYMBaAFKI+Aiqj
+p005tAhNmcwMdTbqJ8M+MGcGA1UdEQRgMF6BJWFkbWluaXN0cmF0b3JAYWRkb20u
+c2FtYmEuZXhhbXBsZS5jb22gNQYKKwYBBAGCNxQCA6AnDCVhZG1pbmlzdHJhdG9y
+QGFkZG9tLnNhbWJhLmV4YW1wbGUuY29tMDEGA1UdEgQqMCiBJmNhLXNhbWJhLmV4
+YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0GCWCGSAGG+EIBBARAFj5odHRw
+Oi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMvQ0Etc2FtYmEuZXhhbXBsZS5j
+b20tY3JsLmNybDAfBgNVHSUEGDAWBggrBgEFBQcDAgYKKwYBBAGCNxQCAjANBgkq
+hkiG9w0BAQsFAAOCBAEAUz5R0l0saSNb3QUaI/85XVRj5drhS2CMCXxOjtqKu2Nd
+vC2g1M6e0s441zJnukqm0R3Ex1Domp5EVhqc9I+5jjmEIdsPYIpgtA9PPDWg0jc9
+iOgKGKenLRnjqtOOGI817z5KlcTTm/TPicJwuYxc74qeelZzE+uLt9nhiFvEYkdC
+RY17Lc9xgxtInYSPZWaXYfz2MDToiCo0kUjcerdlvJyYAEznSf5NqVbqh9ZsRjny
+mFtWFILynrit/Yk2SIdOXO8/4DX/cl9b4cL92W5AKzWtUAh0lIeJxM3Hq6cZTrry
+HYMPsM+c5t9zNojPQpyjcicP979bzGvlIAO1Shzzfa6SQ6q7EwekOnc9NAEA8Ymq
+6BsJe7iw4VQD/z2NvjW5E7JZWDJIk/jn1z1JcAFE5ishs3VJrkR6UBW4ZfPDSJbf
+yNkq98Uqfixod68teBv8Gtj0i6aGNdLwh+nWMAp2Zfhx6YANHxaGiZKBNNm+m0El
+7GWpClayA5FUAiGXmXRhjEou9NCxi/HmJlK89vLgvZZmIsNOUS/DxGVlx5e1Gykj
+esB7+0kzoKlqty/zRGtbDCwNdfJQ1YK6mqvgiQq2tYpeGmer2achInVhHtchNhVq
+2qg5TZVQK+asxPY4dMnFrM4vs8jUrRink9QavsK+njnmp7EOk9Cez7CsU30IH52l
+mCtO9oDk3+pDovlkv4Sy/xyTNmB0CE5b1iSa+KzHgfkqqQAoRBVqMbm1CInIMRUe
+j50s0OOoMixoQkEZbEOOacBEAbocxOr0/8hXA7rfP16lA9p1MS4HZ6dcAlXDb48R
+9YxWofdLu0bQ5f9owXc9DTUS9UCvzQVcU3T/VODAxhBc6DMGClBHfnE6Nmaq+N6X
+Kq6/jW3UOcT9swMdpZxHOYzAs3P4OtY0rElPs4d0ESCPwKokpzAgDMDZHETursi4
+E2Pl+F6PsFpGxYM9QWIG5GKmCkDMjlmtijZOIObyMgRu7k59l4jc6nSQxKuotbxs
+gbFkd6aTNETkYDixDCspOkr3F9c6yEJ+201fCZKubJDhfZ+WnBqCvUUCdili5bkU
+UwFTwFrVNFN6JUk+PdsZfilXgHhn6iE+PVk24IvadVebyJ2hGBjiXDU1nmIs9Q/A
+j1UWpdSezQ54h51T0wHhGGE2HAbDOkPzihPmTlIy/UYhzWIYH6718hrqegE7oT8d
+FgCRXpR49GAzVKn8HAp1+Req3RKRZkvw0WAl1AbRmZzFZAFLutlmupz3aHX9ETrr
+bvuPpheKzbwaWfmpzTPbfXEmfce+3usuwH7bKQgOgmMejI/mIRyxSROe33g7aAEX
+D9+XllgySB5c//rbkLUFhGj9fMClNdl1HurMJSU/bg==
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt
new file mode 100644
index 0000000..8a0f05e
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt
@@ -0,0 +1 @@
+01
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt.old b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt.old
new file mode 100644
index 0000000..4daddb7
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-crlnumber.txt.old
@@ -0,0 +1 @@
+00
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt
new file mode 100644
index 0000000..fb3c34a
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt
@@ -0,0 +1,4 @@
+V	360311232844Z		00	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Domain Controllers/CN=localdc.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+V	360311232904Z		01	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Users/CN=administrator at samba.example.com/emailAddress=administrator at samba.example.com
+V	360311232925Z		02	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Domain Controllers/CN=addc.addom.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+V	360311232941Z		03	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Users/CN=administrator at addom.samba.example.com/emailAddress=administrator at addom.samba.example.com
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr.old b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr.old
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.attr.old
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.old b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.old
new file mode 100644
index 0000000..9b973d4
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-index.txt.old
@@ -0,0 +1,3 @@
+V	360311232844Z		00	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Domain Controllers/CN=localdc.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+V	360311232904Z		01	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Users/CN=administrator at samba.example.com/emailAddress=administrator at samba.example.com
+V	360311232925Z		02	unknown	/C=US/ST=SambaState/O=SambaSelfTesting/OU=Domain Controllers/CN=addc.addom.samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-openssl.cnf b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-openssl.cnf
new file mode 100644
index 0000000..17a5571
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-openssl.cnf
@@ -0,0 +1,203 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = CA-samba.example.com         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-samba.example.com-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-samba.example.com-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-samba.example.com-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-samba.example.com-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-samba.example.com-crl.pem           # The current CRL
+crl         = $dir/Public/CA-samba.example.com-crl.crl           # The current CRL
+private_key = $dir/Private/CA-samba.example.com-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-samba.example.com.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = 1           # how long to certify for
+default_crl_days= 7300            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = 8192
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = US
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = SambaState
+
+localityName            = Locality Name (eg, city)
+localityName_default    = SambaCity
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = SambaSelfTesting
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = CA Administration
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = CA of samba.example.com
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = ca-samba.example.com at samba.example.com
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+[ template_x509_extensions ]
+
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-private-key.pem b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-private-key.pem
new file mode 100644
index 0000000..930b870
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-private-key.pem
@@ -0,0 +1,102 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIISljBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI8gnWGjK+GVYCAggA
+MBQGCCqGSIb3DQMHBAjV6Im8e0V05wSCElCDz2WaJB4sMLy3WQI/JoMnq+DDjyNC
+7+9th9jeu0Nzcax9NqQ2pKWav2eIwhjS61AM7Zw4+SIqV6mJmuv1IVohHgxAx+nN
+1Poq6bAbgbxk0uwS4nSYXQWOA6xhmjLuZcQcl8bZ6c50Vvc1GLkKiJ7T2x0xr2qt
+pkw86WzbBtrUDbg5IHR3AsgTpyg1Lhs/E1ZCJ3Kd5qXpJwoejvjMCeCqroEzEfo0
+TzIRQS3R/hbnsAzwP03p4HyNs7rY8qGY0K+xv6fTHHiiw+0KbJK0w8KLi7ru0pp8
+YPTTSWBLd96ws0nlhY0aVQzDhlbXSXtqMSQNgZYln7CcH2R8dycwcjDhX0JsPAql
+tIzvkl2goYU7jNI5QnpGPA9VH2U2ipMaEhiaY4yfDolnRaueo3YdmigFz7I4Tanx
+kB3BaF0WrUkIk9oXXH2yIbRm6UAgYhGvNkTcifu6Iv+xfxn2JPulNGWcsJlVsRof
+Hrdy3ZzcDp3bYDoA7gVWQgQKoz3ngIhrgH98zSiNCpKvjWXYx+oWYKHtxVFtFwij
+Pc6+AUdTTjVfQsfNBkE9B2sjmvif6lnKWaMS349zodVCjWQrjsUITJV9Hbqv/8lw
+GrCTFS4R1Wt+ABQDZXZDj4qXQ3Y8NhNI4Z/rkGN9rdaNJuDoyDYzm0tGvoRBP2uV
+GJrAWKt6amx0oSI18L1cqm2hoY7wiZSYFqdXbZm5fbhoELfeak0tMPkHEXx1HtCu
+cVQjcbHTakHcc1cW5TFRlmWZwar4RC//6YO5PENhMacPuW1ld0qF5AbwH303Gw1/
+k4+sYBe0IxiFQWnIFyfCoZI9swTojuUU/p+wxHjwCoxLoiYDN8EOCkHvgcgu7ddQ
+WVHpWyhcNeKcYH71PvyPXjJufbaBouMHrGAodAQXYuRZCwpXvfRG6rqs3yPYkFYn
+dBRdUKDIj2KBLg5n2ssy7ENpRcygUwfgK4H7Qn1yHmDMuq9VjgWNSn1ufCQa+M2L
+CAOMrzX6uRuzw04K2vvv9xhC/Vrr+ISbOL9CDJyvyD4Xzk09JXV9CL8zTDzlJf6s
+DnGhd4F/ejKn8MiOTOYuKugqoFDIw0D3WtbiAHYkXyB1Q13JXjc+N5E74xtGPVUW
+IezrC9yEnQWrrtCBFbAtAKehphfZrvseAB4tBSyToio9wXBVKupa/ghoKEuBIQtE
+OAsBY5Vd8JwZyaLFLBzkPfDqZE6mNSQuSm/x4HjciToQBYicNoGApRH0qneHXdUU
+YUA5QeRp/HRL+yawNPq47HgvmbJh1cpyOsBOGjwqo0Tf0Q6WcqhrZmceHJbpxFeR
+ySDEsuqdSp0prk5CCJ6HO3gsrE6DFLmLNNkZACycIndKO/I98ORY4dmR+zGUoMTS
+Y5Gqpxhuh2LleiquFv3c/mrXVRA4Vl6F43H8isv+7/avhoSkBdoVi17wCR3pdk9F
+naPHRqv6O+VT82S8BqYLR0xk3or+0wzFuaGkh6zPjlYr+DGrTr9qSW34+hJAUsSh
+pcmePlS4A08sM2aZ/z4NSBzGrtSAI0KaeZOZMEyHL7MwZGHvQYz4WbekZJMZR33L
+51ia/VkA2rMw6fgV/HYA3Zwd3NSTQ9jvwP8oAYmjrIbkApQTZQdbGQIh+8kcA4QE
+3seLJAQQ3/reJvkc4jzwbF+A6K53iu23s/FhP89fK93xz+2zxt4bfMb0RQYWSb4u
+aMsTHMC+Aenx93KrVYHvBi/O3PRxPUZQaPPQ+GQVerpmqhnrAtPh8xMjtxRpF3mI
+Hff9RJTCi9jAQWDYAuuWNo1nFi4q6tQU8vCX2T5o+AsvwIrRDxz9E3ELqwPD1Zl8
+YRSBVgQPpy9xS/eHCgBOa7Lch2/gmew0pE6JgHmGSAZbZGVa7QxIsWvrgvNwuDmQ
+pV9xVWttK5dup1un9Z9fiuozO+Iu6a8x0ECCxsUEO2C9bh+Qt1EzjirVy+1WWnKc
+fW2XrFHwQMqIMTjM8JOuWgL2R+YjhFFge0h8CGiXk4f6mnuuGfHhP858Mmxuw0rZ
+bdwwyBq1eiXPrkxm88yo8FYmLXCQExlyFsLbFZ+kJVhZbxeP9siedP14Tgqy2FC0
+2A+tcmypVLu5Vthu66I3wUvmgi9hucwe/s8qCRQwYciN1wzHH6f+uDz//kQIgA75
+AuNAHJYV3uWCKUESpnDL/9W2O6FvWY/j24QG0AkXsl+peovo8CucGUZxphLfsua6
+4x2WrTLehObG+G54CHdOLTrFQDIDRL9Kvmrw8/TGkXEles+WNnB8HxiUQKokA3ld
+fhXy+e/yjaGzwoNY84CV1WXowWJ2vA1Z9gdr1mFpl2uJm1s+RRquuyRI/yXBvGQ4
+x0pPSe8vbQ2OlCzuVMjFpG4dx4oqBwXUR69YigpsVi1A3n23qAPUSjJBflgPLWdG
+x/T+NiQ9TVhFKHqkgiL7e5s5VWaYREXjfDeiVowst/7vJdX3RugJTlVfnmPJ/pJZ
+JnObpWxm7jmJu72fek0bmNaOMvMf4YVB5G/z2gQ0bpwSbl91kxJvTJ6DG9Kb10h9
+ekfffdFdiZHD5V7BUibmt3aYAZSPRG3Scurrv/kKzkH1/cEMnMDb2ppxsfT+LrLu
+92P/7sCxqGJtk6JNiV9MhY3c9gBHsWTIbcJG/wZHzXhwZphoPyFf21I3x11jzQ86
+D3WTC4UQ8ez+PgMvl1ifP0wC0e7ANs8GsDZg9GEI+tBxx4GsAP1dcpr8c+v/wEDF
+/a2fXqtymxWUDc4qCcrE5Az/U7k4tMSIvOiH/QVBsYOybcuvHd4E+Yrx7bXapk0V
+KIgFQm8kVftR32h7KDx55Vcv5a11dEp4TUF1k1MH36GVxMzfqQnnTnwDs67Q2FCs
+YAGt9jF0imAU3KZUwHbJvPYpjNEV9g3pkd4shyB7ZqNXjOFG+rU7F6xOVcf33lBu
+yP653eMJjLR7hKrQ1UiWhgosc9zSUhl+Er6EqV0OoNtXzDI0uHsCzJ4BuLeKzOga
+wXS8JjzHR9Qb+Nf0OljkNgmfCUBk7BDGuvt6ZQwP4pift9+YKJQ9dTLz0QZxeEoA
+Ky9BOkhF4Q9cYACZiSnZGWq5Y+5I+zIPr1LxGfu8gOqhkvne5wAHmC97YbSXaHXI
+rHvFhAzbwdsX2Crgvgd+feIP3LU5T7YhGW3nZMbigaDsBOTUQQW0f8tXygc1QjzT
+dV/mbpoIDz/39PIYKC0BlQQ2S3clfr8SoRWR0bKEypPd7CZXAH4zAdPjKJih3yV/
+SqWxvMKuZFpSu3BJTcrXvN7nvKBzW17VGI0eSE9+SwrsMHZVUjXUolarSYczdC6v
+QKkNV7+Uu04GCNivnE6sYs3M0n5ZSvvBha1/8kUDIi1k6QhvtEauA3WuoMp8/iU2
+mlvT5Kev96glUo1SdCQRLZFh1HXtvKgYiqEZ8FVW3kHMrvDF3Nxh4XDGvuQ6nO8O
+w8TfE56kZVot8KTcYkOBDiyVX/qGLYNNvW2WHm+zygHKVQRkxnL5Y1/GOU10Wr2i
+7ynFFYyjHwj5vkKsqLytQmuIxig2L8eW2WSx74WyWJPLbeHUSVweHjO9DTh9TgUZ
+QEqPRuhTJMXq6VYpMWq9CUYAF/nal1vTab3Q7BbKcDFma89d4m+yv6FTnOnswS5q
+r22NvQwl+09grdVYaL14a+BtkkCYH+SL30B54Vws5W7JS+34OSkMzDZtwwuGUqC3
+P61oG3jsGyJt6knWTgnp83GHKo1jsrP6IooatP4BaPf7PmKcftPuzies10G7MGHm
+h7gAAYVrAW9lDvKKYc7UC/rgf4kJpkqcM6d3eU+9+ccVfmCIbHN4dEE/+VGKMHAA
+qKQS9j5dyoCZH14PXAotyHCmvst08pkKG9Oj7VPG/+rX6tBD3y1LOlMbMKet9Owy
+WA0yTBYXHxr22zcJD6k/7AgkBKbdkJPMR+X9IyINQojpvXJZIKZkVhoSCa4d9DYF
+2xLKo3W3Mqoi3U7sQ42mQsdaozlql+CBYqd3wq1bkGyyqZ4zgm+D9VI+mZ6hZGt/
+77Qlp2j8JeCdsPDy+igzCpz6fkVaQum5fZlg1II5uYR+4EOvn33LbCT+kcqp+YC8
+m32umo2Eg1In2xgfqCpPTEDIjLSxgvC+NtJ/CmGVo6gYebyFLXZlnDbzAhxaOIDO
+p59Tm9K3+wL31FnQOlXtkO9VihN9k5W1qR/MjPH3LaWCFSgMjed3LlOPEFBYmzeV
+oz1oBZcJGVA0aEMA/Oh8hqMjVjz3vaIQfCuJ6eTLob7RDfmnhVaCPHMT9sJDCqKU
+j4r1P0SRj+SRt+tO3kPD3dz8ejXRUb/lTLTSx3fQK0sB7XWu/LJpP3jGgoES6W/t
+Fj6Eai8LXjqr+1rMnc0NKCLlWZakYp8snikOI5b/+t4WsOwhKVFiMbMdtkf5u7J8
+yKLPpkUS/YBxk4Uhv7srkITCzGpE9keV9umQImwPKAtb25DcAXPp5IXuJViHtu6Y
+rKYYlmWgjobgCDvP7NFGKv+7hszZpWmSg/AS13QtPUZ9Fn9mM/Af8Swu5pp2HGUp
+Zme8CjltYjtAk5ChNL+9C5AlVEZoD0x1ag16Gp09ODzEjQ0JebojJuw1X4+q3syD
+BodCMFhwiO2nsnHrr5PALdoAy4YYmQop31HwjhsDShCuSc+8kWnvWRlzyVSI8/vV
+jD8TV68QBeKyU8PDhC2Bmogy/xVYAJthgfK9LYD619Xz8+0h0cTFSwK/WAO4C38l
+WV9SASyAj0O+JMUWheq/Qh4gP2NRDL2fyMFpf8uflwTjmg3Mu39oqcI3SQYk6ViI
+Mq+ClfbU1hYZrakAN8pt8HUM1XbXJRDXnE3hmrTiU+jdNucuunHDjkf9ZaRNgBWW
+yV309Ua9O91EEG0iGjkQ9Sy3ChscBolfvMpayzGtQRFDYWDX6UZnV5zI4ir21ikQ
+A04zphPlCdOWelU8Qs8GuYX8HeXCzc1hUKffARtY2DQqiQ6lmh4YXHM0ILK/kDYo
+ftmcBWpAZEntVRlnrCbPz29cwltn6DHQC6HWKGQyRxafp8fINUOINNMui+W4UR5f
+tNn9IederuOpDvgYDMAzEt59BT8QgRggJl+hlXjRxOXANLTOHWqWKejk8+LAAH3+
+DjBFTX84cfrbbLgrK57E9afEN84KM2EJCCGFXYvc5qBPgrS9oYQwIErvpy89k8fW
+bR7pU41CrHYZG2am774H80FCfofzzAFoJ2pZdPF2Lo95cLxNENy8RjYfePJR2tcf
+vlqNynUvBjabCW6XhtmRK8/fsakfqfaQkZfpHqtA+qAweLh1bcirz3rBeNvwsO3G
+JBxUgNkMel2F78Lg/EfMQL/hxeajDV+LilJkeZeRbHNL18M8dzzJaZkBm2oGylc5
+AS5r4r1EvSINjf1uXDA9CMBNydf6n62VPnDKrk1WK2R+pzFeeVvRayx7PVWacP3N
+JnKPY+t2eIq5JlNCfIHcL8MDHaau4ck/f2lnUJm1OfqhdfAf6wsf+XuEhfkzqsV/
+gRjrumWsuMs7B15eIZNoyP+x9XPfTXvKXtNpWaUbq2iC/rxgMzqzDN0XvHSr8eTL
+I5sg9nlAiezZYcDsGcjpK5EUY3/3zmZtO+OvXg2kA0dQx8QWg51B8MI/f9EprAAp
+O4ypSjvH+Hthnq4Cr1dXtJzOJru3wz0N37Hy/EhMrDYP3XJUjkYJqTrxM8dsT7TD
+RwvRjbJaZYi1mmIakXbHAhEAcIg/Z7hueIYHrOzYaW6akPdxy0yS252mZ83KtUC9
+oxNzYQdMi43bxbWgcTu5RxGPZ99IYUdKziBJiJlOpWFSzPwKcD0bkHeDAbWZ4Aex
+msyzLubI3nPnuszVWgG8cUP1w1HbCC5KAWIOSoRYS6SzcirAZAXuqvoBGGSCiKdJ
+kMIXRjSHgTfNPE0zSkuoYognqtPBQB+tCmEYUwmIidzp7iVe3muLJj1qHRcUNx1g
+XzbpRMOGRUSgMJJlcba5BRNmFnSEjgnFx+v/NEiMhjacOiDDypi58eYPvgLZ0v8I
+UlI0napiKxX1XS9XZE7SI8xXn5zte2de36xAfZTm1gMEYG/sOUndKUUrmsG4ag+u
+ttyW6veD/LMXzYX/vP6zBe8l2RkZp15xMPMSTovij4ELLOAsWmAB8MAQ7p2TThOa
+gmFx0AnWZ55GAXcM6/2dK54ZQjm12KgRz2uZD6RpHgxDlErzHBVY8VFWPHx4b60M
++BVqk94uAsprvWczcuowZwF41MsJ7wm3a1Jtd104mx1/0GokF6EG+NjpSFvHiDN8
+JVlZ24lBIBv/7Q==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt
new file mode 100644
index 0000000..6496923
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt
@@ -0,0 +1 @@
+04
diff --git a/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt.old b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt.old
new file mode 100644
index 0000000..75016ea
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Private/CA-samba.example.com-serial.txt.old
@@ -0,0 +1 @@
+03
diff --git a/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-cert.pem b/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-cert.pem
new file mode 100644
index 0000000..d6a1577
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-cert.pem
@@ -0,0 +1,62 @@
+-----BEGIN CERTIFICATE-----
+MIILPDCCBySgAwIBAgIJAM6BrnFPnFmXMA0GCSqGSIb3DQEBCwUAMIHGMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKU2FtYmFTdGF0ZTESMBAGA1UEBwwJU2FtYmFDaXR5
+MRkwFwYDVQQKDBBTYW1iYVNlbGZUZXN0aW5nMRowGAYDVQQLDBFDQSBBZG1pbmlz
+dHJhdGlvbjEgMB4GA1UEAwwXQ0Egb2Ygc2FtYmEuZXhhbXBsZS5jb20xNTAzBgkq
+hkiG9w0BCQEWJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29t
+MB4XDTE2MDMxNjIzMjgzMVoXDTM2MDMxMTIzMjgzMVowgcYxCzAJBgNVBAYTAlVT
+MRMwEQYDVQQIDApTYW1iYVN0YXRlMRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNV
+BAoMEFNhbWJhU2VsZlRlc3RpbmcxGjAYBgNVBAsMEUNBIEFkbWluaXN0cmF0aW9u
+MSAwHgYDVQQDDBdDQSBvZiBzYW1iYS5leGFtcGxlLmNvbTE1MDMGCSqGSIb3DQEJ
+ARYmY2Etc2FtYmEuZXhhbXBsZS5jb21Ac2FtYmEuZXhhbXBsZS5jb20wggQiMA0G
+CSqGSIb3DQEBAQUAA4IEDwAwggQKAoIEAQC3qPlXMRW0bS5QonEW4MMRiZlgWRc3
+DLtA1hSg0a0POKXIBTTb26kVWwJkdLdLPf9POdAWa+PtEDcgiTKeNeh3hdCaKQiR
+LGtmR2Ncy5jcLyAaJPHL3ZrYCzKPyfhVLtZqrS+5CmJRs1Ar1zEpRPIcT0Qdb6Jp
+gu43msIQnULTZPatF4Oi847jb/JIXnTYxto7cuk1I/2VFJ8OD2cYypNbCkthwAga
+ftJ0GNsM2Ii0q5aFnrHpCh/UhvQ1XGZfGVgBRrFjQQ75GlSCFXuwLLiyXwpj6c/p
+QPTQuWLe+21rnizpxmXBvP6d2LaX2Vsq/XP9iVN/jVigY4swgk61Z6XFkmsVJErB
++JEOrjdcO0kkkqlSY0aqqpoXgtV8lNxTeKrNllRmW/i/Wz174PPdvR6QQFMG0X/W
+NOtqwBGZqiafHlu1xrtC/RnzC2S3ygKssP9463bO8IDvhv2I3QnbsuQdKhQSE5rr
+VDJcSI1DHe+tGsko4QA2RBFvgO8+877K9qnBXpnVdYrnEk4UlZVk8L7TIngbA7RR
+bZ7j1mE28PIzcGN2ps1IY80CbO6V+60YegT2F7smjRAS9YJyfqM0fs4yoRuT5Day
+BHN9asy//gEVfebXytzfvZvh0Y+XTlxsXbZ24IsaW1IhsLNvny9BX2Ygrv5wnf7i
+zvEGf4rnO4v+d4mn2HrkkYLfIJe/iQAY3c8uABbEZgzrTHqC+oyRE4MQUtjQR+10
+8IOvbVeU716Q3SxyiGlq0Dici84J2izArVuZBGVoS2pytwbNFU7eL5SeirL1Xy/E
+3siV+y6Oxr3sigrAmMQbzr0YQT7yDjVaP61ct8krc5N4Z95SciIlvmEIzKkV8kql
+Uiom+XWP8aRnZmiuvfGnvEyB67MmggEkG1LGIhsp+ZsnTfo4nU716Djlq5pOZHY2
+VTiOLET7Omo/a+RmHwrog4hRm2BYifyt3RGmzoWF77klbow13ov0UrsTF7Sw6Uft
+EnaklsZU9cfFyNLsDjEwRTWQ4QMdq3dI6WSOYN9EWFtxLGY8FypH2QkTOOPsqgXY
+/SxZUBqa3r+MrGRJ2NCF6kr1/yanLicVzNSR4tymEFDfF2FJVOtQqbO370JGIrJE
+3kq89zUUMH9xNP6IJu+N11Xe63028KlJomWq6my8AUk7a0sk8z75FIa5PvUSYhQ8
+gbTYXM2AyYLTYxkLt+OzLLyvQI1l6KX3PWLaa94lqxkjGQWIt/ViL1OTineiTbYJ
+YR2SB4R3S3Y6N3AAT6l7D1/lxThrqzmWAAkbElBTZZrXGybjL3I9q8lzVt98X9HY
+LrVClydpw42drOIX5PQ68+s8lYNBA1/uYim3IgTjDPIqsNIkBOjreYnPAgMBAAGj
+ggEpMIIBJTAdBgNVHQ4EFgQUoj4CKqOnTTm0CE2ZzAx1Nuonwz4wHwYDVR0jBBgw
+FoAUoj4CKqOnTTm0CE2ZzAx1Nuonwz4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMC
+AQYwTwYDVR0fBEgwRjBEoEKgQIY+aHR0cDovL3d3dy5zYW1iYS5leGFtcGxlLmNv
+bS9jcmxzL0NBLXNhbWJhLmV4YW1wbGUuY29tLWNybC5jcmwwEQYJYIZIAYb4QgEB
+BAQDAgEGMDEGA1UdEQQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4
+YW1wbGUuY29tMDEGA1UdEgQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJh
+LmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IEAQCa8zKgFnArq4GM+OJfiK95
+fYuTgbO+PaH19GWCyNkNCrtasxt6BIdxKYW+rC6VxXBRXSvaPLbiRCDhD9hL03IR
+daQ+R9JanYzoloN7m5q+mSdJpfsIfdlvqKr4hyti6sfC3jnQC1Tp696KrW1P1Ymi
+kOOxksmngZzTYr2q+JhydYsNAdpxeAIAILDZI0F4VzOVPXRy2+Gop+lwWYvtRjjn
+Z8HemYJ8jIGUlldMVInd5+XmS4/+kFLB6Ly+JAoqC9PBUfWiwXIFIPOIM5ia4sNH
+ZeViTG5Kw7MO/esPs7J8VKB6La4v+CYCT4ngT0ekRLXhRi/Dwa8Ok+hFmRtrikvU
+TEqZPOQT3sRqGdlongAZ1kmCkU4n4RhwbMh6WitDKJf7YToMsyrm6LQvGo4Bf1Ns
+mqnY93OSTyOblNGYwq45BMQbGhW21uW93SQg938ojuw4366KeGnHCD3zvyfWh6Yh
+duAWNQb8TNDqhik0lLNVMyrEPpk0f24XrVC2LBia3Z4hQvep/pI8tg1656XbI6/J
+GubM9KW6o0ndZLnMzFFga3JqztzL/Ooqu+yVaA9q89GlN2zv3hafXaC/AChG1b8k
+Esx37mA68jVaTh/1hX8T2hz14EV3LUB2N21W228HuUhZ33PEcR10XMJNJsOOwHUn
+5I902kznpUs3VTVvbWBsEfhZAD9uns07Z5b0b8UN3fZyNmXeE7gObt10obSFzoPt
+yhnTCULNJ0K3cwuQDAC4Y6HQK5hvLBazdvnYT5rZqGneG9ALdQqr9if2gZFeUPQv
+a63VZFwfyx5wQlFwLVbaH3tTl1dweJkZYjUC3BL1rngHNNvD1t//ERXqL2ngOe4C
+1xNNOBAC2Q4upBYAuH+zoT8KMRCxEh22SPNGrlmN+9MwY+ceP1Dxa97vY9FtSMIB
+dYEvoI8TyFhAjC6t4HOUxT4lvpc7Hma+1AlG5x/aSCY2A9ONdLLo5DyXSuLFHgtc
+gh0dJygZ85sd90k8hl+73muHHofG6HuzMNaQhN8sFoaiedhIHa5+Lv6FVyd7Y0dy
+QVHiPVcf5KG3o0y6OnXdfsGNUsak01fqQhIewVghdTU9liGW8PH1UVWO310q1K46
+U46Hp/JBamvvW5B2ZSg8Dj4arS7/TxxNqbIPAtNxtN7Hwg1dubGWMatCv2A8Cx29
+oWIeUG2HKY4XvbdOnpWvCGx+sUqBiK6Sf5zvJF+UigmZPKrZgbrFWSC1tf0RYn9d
+IyH4JGo4uP5OCxBWFvtj2d51qJJvdnlegKkPd9E0vzIZRHJsSoAx54MmqRZQkPzV
+56iQXA4iTfhv2sF7Uer379OV//ML5xIjsV+IkJepTUtAgimqkKKRktCPfFT6mOtw
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-crl.pem b/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-crl.pem
new file mode 100644
index 0000000..73b10cb
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Public/CA-samba.example.com-crl.pem
@@ -0,0 +1,32 @@
+-----BEGIN X509 CRL-----
+MIIFdTCCAV0CAQEwDQYJKoZIhvcNAQELBQAwgcYxCzAJBgNVBAYTAlVTMRMwEQYD
+VQQIDApTYW1iYVN0YXRlMRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNVBAoMEFNh
+bWJhU2VsZlRlc3RpbmcxGjAYBgNVBAsMEUNBIEFkbWluaXN0cmF0aW9uMSAwHgYD
+VQQDDBdDQSBvZiBzYW1iYS5leGFtcGxlLmNvbTE1MDMGCSqGSIb3DQEJARYmY2Et
+c2FtYmEuZXhhbXBsZS5jb21Ac2FtYmEuZXhhbXBsZS5jb20XDTE2MDMxNjIzMjgz
+NFoXDTM2MDMxMTIzMjgzNFqgYjBgMDEGA1UdEgQqMCiBJmNhLXNhbWJhLmV4YW1w
+bGUuY29tQHNhbWJhLmV4YW1wbGUuY29tMB8GA1UdIwQYMBaAFKI+Aiqjp005tAhN
+mcwMdTbqJ8M+MAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IEAQA13bwPRi4+
+CaG7MSTVA4Z4JZIU1CQagBJCah0XPXl+xIs/aWCxS3jdFnCUNLOxrKk5Onrsv0z7
+YWQJHsH2Lu0I38SPyWhftmhrqn74QQyfbGMGblDufbfJsHNyeME2z0ZtCoHUgaz2
+kMatR7ys6uvOY4Moghr/xNK2QYSzCFsetF/5ua2h547GK+VMqb4wH14WIx0ljVO0
+knpqT+uX5b+3KX2QcUFDIzRJZWBj0gDWzNxL5PSbZbcxtpUpUIgbFHD8HGRAu3R3
+MCJE3mKuKyaRKqLaF/qOWnskkHnIV3gObeKIgWFNLiyQKUAvu0m3QO7b5zqUeOep
+JMy/3dwixIoDU5QU1O7TAvJQhVscjt0baQaklqlI7jKwdd1xk6brIXKqLa55ALd2
+RIs7I01X/ZyukrY+NbvQOGh/Weqnxe2IM91DkVQGYNxaa52Fqlrop3U4qdZRgtuL
+Ye8RP3IPcVEoH/t/fW6IBTEN1uG9vVvyUUW2H4lI44yeNt2Pd+6qXXFyKZ9pfctx
+7zCOdo9/ikSzCddLFKL6bgJ4vxNuSt+4csq79BytK+69SrsGP/R87154uqA8nMPm
+TXpFhL3YBqOklphc1JVCccTp/824vkrgrEOSB7uIZOtdTpTuRabo6R5yv2pjC5GR
+om3sI8c7xKeUUsfxDF2jt4vJHlKgYEx8YgbAdKq3As0fkpsY0IcMSNR1KMq8H4ia
+0eNWy1YmkvcZzZTL1GBtL1XNPHkvmuBHV2rglBg7PAklr/9WX7IM6AZh2WKP0Spe
+ih1C7YlVzCgQgOaGEe28jegtgkr3I84j34GJmK5WO5fa7/au8wzUDEyGTJE1wZxv
+k1s4TKiNuCSiH26qVUKfwpzrqhiW/ElAeKsXxjg/V7anhPbQsd+sz4RNFi9RldlY
+tdXkPmKBTvupJkVa3ZUxl8gyXNW8t8bSpW2kYFOorxnEkvhwIxMhwSC9pyEyNFXa
+sxsMZ/BcvFBcJYORhxMYVNksCriyWRuYsNORC8s9wnygbQ2n3TuoloZ9rR8mc6XK
+3EgLwhOyENWToRurBdN7Vq6BuNtnl5P/Rd2WBTy62EcXkrnJCCUK4ouP3o0MRt/V
+LdQiCVf9nnHdkiWMQMH4pkgrEJb70IvS/MAAee3SFuMNa72zgD9Pgk4NX6upqt8s
+3+wo0gqmg1gJ9RQUyk/TuYMgdBVg68B6G1C8RifxffhZMj/rOm1xdXXwRfmDyrHZ
+aaNZv3VHTEIJjSCHMkDV7SD9d36gdX0F1lLP5HIu0QTWJeyE/fFTD+hQMY5Ryk+c
+nzW2ZYuTp14xWD3NTQzq/NS+BPpOcAtL3hSpyvP4UkIFGZc7OUPPBBwR2xTVLQfZ
+YqKrAHJKgPXZ
+-----END X509 CRL-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-cert.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-cert.pem
new file mode 100644
index 0000000..7486a63
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-cert.pem
@@ -0,0 +1,169 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:41 2016 GMT
+            Not After : Mar 11 23:29:41 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Users, CN=administrator at addom.samba.example.com/emailAddress=administrator at addom.samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:be:91:64:f2:1b:2b:ed:9b:40:bc:0d:46:23:49:
+                    77:32:74:fe:cb:9a:46:86:33:1e:56:bd:c8:da:dd:
+                    e6:2a:07:34:61:1c:f0:b8:71:29:24:2b:90:f3:43:
+                    99:6f:69:f6:ff:8d:b9:b7:3f:f3:36:6a:99:90:90:
+                    d6:95:63:4e:88:5a:d7:41:89:7f:73:13:64:49:c7:
+                    de:42:65:08:5d:ca:04:b2:68:3a:40:7f:6a:05:df:
+                    56:30:2f:ac:1b:8b:0f:c3:15:3c:38:0f:90:50:44:
+                    00:bb:59:40:f6:d2:e8:5b:73:03:0d:f6:7d:38:5d:
+                    2f:99:c3:0d:13:0f:74:d0:9e:ef:1e:92:42:c4:46:
+                    7c:dc:85:7e:e9:af:91:4e:9d:5f:82:af:58:60:18:
+                    a5:ac:91:6e:dd:cf:a7:32:3c:d2:f4:e9:81:be:80:
+                    9e:0c:ca:1f:1a:be:98:c4:fe:e6:25:c1:89:fe:16:
+                    0a:30:90:d3:d4:e5:af:89:24:64:12:d0:4f:19:e2:
+                    1b:86:fb:06:a9:63:d1:47:10:89:dc:2b:52:24:dc:
+                    66:a9:56:c2:cb:f4:ec:35:12:f4:ad:5e:fc:ff:86:
+                    e9:b1:f9:1f:b3:ce:44:fb:be:04:af:8d:42:9b:56:
+                    a5:02:7f:c5:cf:5f:23:41:1c:69:ee:33:97:7a:81:
+                    50:8b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Client, S/MIME
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Smart Card Login Certificate for administrator at addom.samba.example.com
+            X509v3 Subject Key Identifier: 
+                30:10:6E:1F:7E:52:33:8C:C8:85:E5:92:74:5D:76:7E:E9:33:5B:36
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                email:administrator at addom.samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, scardLogin
+    Signature Algorithm: sha256WithRSAEncryption
+         53:3e:51:d2:5d:2c:69:23:5b:dd:05:1a:23:ff:39:5d:54:63:
+         e5:da:e1:4b:60:8c:09:7c:4e:8e:da:8a:bb:63:5d:bc:2d:a0:
+         d4:ce:9e:d2:ce:38:d7:32:67:ba:4a:a6:d1:1d:c4:c7:50:e8:
+         9a:9e:44:56:1a:9c:f4:8f:b9:8e:39:84:21:db:0f:60:8a:60:
+         b4:0f:4f:3c:35:a0:d2:37:3d:88:e8:0a:18:a7:a7:2d:19:e3:
+         aa:d3:8e:18:8f:35:ef:3e:4a:95:c4:d3:9b:f4:cf:89:c2:70:
+         b9:8c:5c:ef:8a:9e:7a:56:73:13:eb:8b:b7:d9:e1:88:5b:c4:
+         62:47:42:45:8d:7b:2d:cf:71:83:1b:48:9d:84:8f:65:66:97:
+         61:fc:f6:30:34:e8:88:2a:34:91:48:dc:7a:b7:65:bc:9c:98:
+         00:4c:e7:49:fe:4d:a9:56:ea:87:d6:6c:46:39:f2:98:5b:56:
+         14:82:f2:9e:b8:ad:fd:89:36:48:87:4e:5c:ef:3f:e0:35:ff:
+         72:5f:5b:e1:c2:fd:d9:6e:40:2b:35:ad:50:08:74:94:87:89:
+         c4:cd:c7:ab:a7:19:4e:ba:f2:1d:83:0f:b0:cf:9c:e6:df:73:
+         36:88:cf:42:9c:a3:72:27:0f:f7:bf:5b:cc:6b:e5:20:03:b5:
+         4a:1c:f3:7d:ae:92:43:aa:bb:13:07:a4:3a:77:3d:34:01:00:
+         f1:89:aa:e8:1b:09:7b:b8:b0:e1:54:03:ff:3d:8d:be:35:b9:
+         13:b2:59:58:32:48:93:f8:e7:d7:3d:49:70:01:44:e6:2b:21:
+         b3:75:49:ae:44:7a:50:15:b8:65:f3:c3:48:96:df:c8:d9:2a:
+         f7:c5:2a:7e:2c:68:77:af:2d:78:1b:fc:1a:d8:f4:8b:a6:86:
+         35:d2:f0:87:e9:d6:30:0a:76:65:f8:71:e9:80:0d:1f:16:86:
+         89:92:81:34:d9:be:9b:41:25:ec:65:a9:0a:56:b2:03:91:54:
+         02:21:97:99:74:61:8c:4a:2e:f4:d0:b1:8b:f1:e6:26:52:bc:
+         f6:f2:e0:bd:96:66:22:c3:4e:51:2f:c3:c4:65:65:c7:97:b5:
+         1b:29:23:7a:c0:7b:fb:49:33:a0:a9:6a:b7:2f:f3:44:6b:5b:
+         0c:2c:0d:75:f2:50:d5:82:ba:9a:ab:e0:89:0a:b6:b5:8a:5e:
+         1a:67:ab:d9:a7:21:22:75:61:1e:d7:21:36:15:6a:da:a8:39:
+         4d:95:50:2b:e6:ac:c4:f6:38:74:c9:c5:ac:ce:2f:b3:c8:d4:
+         ad:18:a7:93:d4:1a:be:c2:be:9e:39:e6:a7:b1:0e:93:d0:9e:
+         cf:b0:ac:53:7d:08:1f:9d:a5:98:2b:4e:f6:80:e4:df:ea:43:
+         a2:f9:64:bf:84:b2:ff:1c:93:36:60:74:08:4e:5b:d6:24:9a:
+         f8:ac:c7:81:f9:2a:a9:00:28:44:15:6a:31:b9:b5:08:89:c8:
+         31:15:1e:8f:9d:2c:d0:e3:a8:32:2c:68:42:41:19:6c:43:8e:
+         69:c0:44:01:ba:1c:c4:ea:f4:ff:c8:57:03:ba:df:3f:5e:a5:
+         03:da:75:31:2e:07:67:a7:5c:02:55:c3:6f:8f:11:f5:8c:56:
+         a1:f7:4b:bb:46:d0:e5:ff:68:c1:77:3d:0d:35:12:f5:40:af:
+         cd:05:5c:53:74:ff:54:e0:c0:c6:10:5c:e8:33:06:0a:50:47:
+         7e:71:3a:36:66:aa:f8:de:97:2a:ae:bf:8d:6d:d4:39:c4:fd:
+         b3:03:1d:a5:9c:47:39:8c:c0:b3:73:f8:3a:d6:34:ac:49:4f:
+         b3:87:74:11:20:8f:c0:aa:24:a7:30:20:0c:c0:d9:1c:44:ee:
+         ae:c8:b8:13:63:e5:f8:5e:8f:b0:5a:46:c5:83:3d:41:62:06:
+         e4:62:a6:0a:40:cc:8e:59:ad:8a:36:4e:20:e6:f2:32:04:6e:
+         ee:4e:7d:97:88:dc:ea:74:90:c4:ab:a8:b5:bc:6c:81:b1:64:
+         77:a6:93:34:44:e4:60:38:b1:0c:2b:29:3a:4a:f7:17:d7:3a:
+         c8:42:7e:db:4d:5f:09:92:ae:6c:90:e1:7d:9f:96:9c:1a:82:
+         bd:45:02:76:29:62:e5:b9:14:53:01:53:c0:5a:d5:34:53:7a:
+         25:49:3e:3d:db:19:7e:29:57:80:78:67:ea:21:3e:3d:59:36:
+         e0:8b:da:75:57:9b:c8:9d:a1:18:18:e2:5c:35:35:9e:62:2c:
+         f5:0f:c0:8f:55:16:a5:d4:9e:cd:0e:78:87:9d:53:d3:01:e1:
+         18:61:36:1c:06:c3:3a:43:f3:8a:13:e6:4e:52:32:fd:46:21:
+         cd:62:18:1f:ae:f5:f2:1a:ea:7a:01:3b:a1:3f:1d:16:00:91:
+         5e:94:78:f4:60:33:54:a9:fc:1c:0a:75:f9:17:aa:dd:12:91:
+         66:4b:f0:d1:60:25:d4:06:d1:99:9c:c5:64:01:4b:ba:d9:66:
+         ba:9c:f7:68:75:fd:11:3a:eb:6e:fb:8f:a6:17:8a:cd:bc:1a:
+         59:f9:a9:cd:33:db:7d:71:26:7d:c7:be:de:eb:2e:c0:7e:db:
+         29:08:0e:82:63:1e:8c:8f:e6:21:1c:b1:49:13:9e:df:78:3b:
+         68:01:17:0f:df:97:96:58:32:48:1e:5c:ff:fa:db:90:b5:05:
+         84:68:fd:7c:c0:a5:35:d9:75:1e:ea:cc:25:25:3f:6e
+-----BEGIN CERTIFICATE-----
+MIIJGzCCBQOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5NDFaFw0zNjAzMTEyMzI5NDFaMIGzMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEOMAwGA1UE
+CwwFVXNlcnMxLjAsBgNVBAMMJWFkbWluaXN0cmF0b3JAYWRkb20uc2FtYmEuZXhh
+bXBsZS5jb20xNDAyBgkqhkiG9w0BCQEWJWFkbWluaXN0cmF0b3JAYWRkb20uc2Ft
+YmEuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+
+kWTyGyvtm0C8DUYjSXcydP7LmkaGMx5Wvcja3eYqBzRhHPC4cSkkK5DzQ5lvafb/
+jbm3P/M2apmQkNaVY06IWtdBiX9zE2RJx95CZQhdygSyaDpAf2oF31YwL6wbiw/D
+FTw4D5BQRAC7WUD20uhbcwMN9n04XS+Zww0TD3TQnu8ekkLERnzchX7pr5FOnV+C
+r1hgGKWskW7dz6cyPNL06YG+gJ4Myh8avpjE/uYlwYn+FgowkNPU5a+JJGQS0E8Z
+4huG+wapY9FHEIncK1Ik3GapVsLL9Ow1EvStXvz/humx+R+zzkT7vgSvjUKbVqUC
+f8XPXyNBHGnuM5d6gVCLAgMBAAGjggIjMIICHzAJBgNVHRMEAjAAME8GA1UdHwRI
+MEYwRKBCoECGPmh0dHA6Ly93d3cuc2FtYmEuZXhhbXBsZS5jb20vY3Jscy9DQS1z
+YW1iYS5leGFtcGxlLmNvbS1jcmwuY3JsMBEGCWCGSAGG+EIBAQQEAwIFoDALBgNV
+HQ8EBAMCBeAwVQYJYIZIAYb4QgENBEgWRlNtYXJ0IENhcmQgTG9naW4gQ2VydGlm
+aWNhdGUgZm9yIGFkbWluaXN0cmF0b3JAYWRkb20uc2FtYmEuZXhhbXBsZS5jb20w
+HQYDVR0OBBYEFDAQbh9+UjOMyIXlknRddn7pM1s2MB8GA1UdIwQYMBaAFKI+Aiqj
+p005tAhNmcwMdTbqJ8M+MGcGA1UdEQRgMF6BJWFkbWluaXN0cmF0b3JAYWRkb20u
+c2FtYmEuZXhhbXBsZS5jb22gNQYKKwYBBAGCNxQCA6AnDCVhZG1pbmlzdHJhdG9y
+QGFkZG9tLnNhbWJhLmV4YW1wbGUuY29tMDEGA1UdEgQqMCiBJmNhLXNhbWJhLmV4
+YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0GCWCGSAGG+EIBBARAFj5odHRw
+Oi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMvQ0Etc2FtYmEuZXhhbXBsZS5j
+b20tY3JsLmNybDAfBgNVHSUEGDAWBggrBgEFBQcDAgYKKwYBBAGCNxQCAjANBgkq
+hkiG9w0BAQsFAAOCBAEAUz5R0l0saSNb3QUaI/85XVRj5drhS2CMCXxOjtqKu2Nd
+vC2g1M6e0s441zJnukqm0R3Ex1Domp5EVhqc9I+5jjmEIdsPYIpgtA9PPDWg0jc9
+iOgKGKenLRnjqtOOGI817z5KlcTTm/TPicJwuYxc74qeelZzE+uLt9nhiFvEYkdC
+RY17Lc9xgxtInYSPZWaXYfz2MDToiCo0kUjcerdlvJyYAEznSf5NqVbqh9ZsRjny
+mFtWFILynrit/Yk2SIdOXO8/4DX/cl9b4cL92W5AKzWtUAh0lIeJxM3Hq6cZTrry
+HYMPsM+c5t9zNojPQpyjcicP979bzGvlIAO1Shzzfa6SQ6q7EwekOnc9NAEA8Ymq
+6BsJe7iw4VQD/z2NvjW5E7JZWDJIk/jn1z1JcAFE5ishs3VJrkR6UBW4ZfPDSJbf
+yNkq98Uqfixod68teBv8Gtj0i6aGNdLwh+nWMAp2Zfhx6YANHxaGiZKBNNm+m0El
+7GWpClayA5FUAiGXmXRhjEou9NCxi/HmJlK89vLgvZZmIsNOUS/DxGVlx5e1Gykj
+esB7+0kzoKlqty/zRGtbDCwNdfJQ1YK6mqvgiQq2tYpeGmer2achInVhHtchNhVq
+2qg5TZVQK+asxPY4dMnFrM4vs8jUrRink9QavsK+njnmp7EOk9Cez7CsU30IH52l
+mCtO9oDk3+pDovlkv4Sy/xyTNmB0CE5b1iSa+KzHgfkqqQAoRBVqMbm1CInIMRUe
+j50s0OOoMixoQkEZbEOOacBEAbocxOr0/8hXA7rfP16lA9p1MS4HZ6dcAlXDb48R
+9YxWofdLu0bQ5f9owXc9DTUS9UCvzQVcU3T/VODAxhBc6DMGClBHfnE6Nmaq+N6X
+Kq6/jW3UOcT9swMdpZxHOYzAs3P4OtY0rElPs4d0ESCPwKokpzAgDMDZHETursi4
+E2Pl+F6PsFpGxYM9QWIG5GKmCkDMjlmtijZOIObyMgRu7k59l4jc6nSQxKuotbxs
+gbFkd6aTNETkYDixDCspOkr3F9c6yEJ+201fCZKubJDhfZ+WnBqCvUUCdili5bkU
+UwFTwFrVNFN6JUk+PdsZfilXgHhn6iE+PVk24IvadVebyJ2hGBjiXDU1nmIs9Q/A
+j1UWpdSezQ54h51T0wHhGGE2HAbDOkPzihPmTlIy/UYhzWIYH6718hrqegE7oT8d
+FgCRXpR49GAzVKn8HAp1+Req3RKRZkvw0WAl1AbRmZzFZAFLutlmupz3aHX9ETrr
+bvuPpheKzbwaWfmpzTPbfXEmfce+3usuwH7bKQgOgmMejI/mIRyxSROe33g7aAEX
+D9+XllgySB5c//rbkLUFhGj9fMClNdl1HurMJSU/bg==
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-key.pem
new file mode 100644
index 0000000..0d33211
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI06+E0Qn55PYCAggA
+MBQGCCqGSIb3DQMHBAgRIdE1BfEflgSCBMgjWcKNk0gmS+OepxYA2tMjMir2YwFb
+ht/PFx0llj4Zt2U2TgvSFhm7JcsNPXqqqElIvEeNrY5BTB6Jbkd5pt1EpKcBlgHQ
+cPtjslAxo5C5FgvLuzaFd1tRhHm7UWygTRcI+79zRmypOm0v57ZdS6Z218sJc0gk
+re7tBT+lF+S5uCRAUmWBgdVjEFjW+1r0dhVJWYftB8JoE4zW+B0wEz6PIv0cTt7K
+cnjHVMFKWPJStAbJ98RWchF0KWeu+cuWAWt/rJ2QrM+q1bBP4Mgn6XfRnKbcJofk
+BG5v4oo8B/TSe3woBMtf2BheaeXDa96D7lxF7gELTkdodNfJd9s66GLSRKCk6amk
+eJKO8fLZbXpiT0/TGeFvrihWa/ZpVG4I94KDn2a+U8Agq+B1WA6MqCt6txK6GFIN
+okCRyRUYb6TFDI2JA+jeEX+0tStVGp+qNyk4PT4tZOG2BJ2dq5F6+KF0VzE8I7V0
+zIFWQvvwO8N+osvmJgQgxI6JOq0ubiHEEiSrd4lKVO7NJ223I9GXao/z+0l5ywYn
+SL0LEsw2adblRDgzBnsLCqWEeC3Oczg790AaNkqWPolGKBEpOXlCPCjILJfG/7Ii
+GGvuAQaXOOM3fnxb2oTOpFMn6BQDmX77hiCKGTB4VCgTIhwBOpwLDeDxjyUjCp2C
+PPtped8Dne+kK9iGuHyu45sXrVtxfigfKh9+ncCsFVQfpmcYXDiUhn/RUP4qezco
+jkKeC+S4lM9mG/KzWeDUtMlYkEqFA6yxs05VzpxR3h7sizV0YAE2evSxn3w4aYWY
+GGKtVG4h30f7YbxI1N9+2iBTToAejF5gF5/WDPn8N+voohQCIQ6iAZ48vUDuQGme
+mzi73xu774u7M/BnmgtTr1ZG9gvT+F6q6rnJFAqj3k8j+mv2w4XCqytZJ4OGTijo
+j/s/eZDWmo4t/WXUMjePDzXl96hjBq4bZOpqNwKDLsqbVwQrhFzXTkGLhGQAyKb4
+wZywUkYfTdWa9f+A2NmWqry9Ef5KcOJTSHt6FeY5kwcY56iZT+cD4V2pgxTqQBGt
+YUy/j0V35l41OTKZ6x5P3ZSk45w6RPY3/BqcnfvhSFxON3jFivg1DKIcB8WaWjss
+40vP+TthOR2X4FQ/OHKwjs+tC6JpwDuSNCVwj9VBGSgjeXK/aV9BG1A0m4R7qxTV
+aT4tjSSfPfkOf16hTW2ncHTr9rvY3XcYm8eC5E/IEQ7gxpG/JI0+xK2tel0bochs
+aSBP+qGP85Sib3pcnepG6Zhkx4KgTvhbWRAfNS5rB1jLGSpeWQkMZmun91tTuVLK
+fRyfQZ2gkr2ixX/zlPb1bhIXHUBgnoUyUHwZ2lNCDp/dm+nGYqXeeg9lZfD3dYpQ
+Yd1zdR7Faj8aOsC9T4DRUDzgUIUCdvd2wdmnXF1YB43VgXjsAkfZkEVve1ltv4iG
+OAtp0n9aUz+4yS4kBLWEQfNsK7Tz5zjN2BJmm5qQWARxVbR/shhYKqXuY9HbmB95
+sGc1d37pK+n4HvXqQ701zEuvtwyP/P4gg7HjBI2pauuKfT+eVK+xpTBx4W8imY7j
+8IhJ4IBBUWzoMoADD132fVW7f3vpp1XGjvbq5fgDlU6beVsWS9KXBD2Wsl7FDkJ5
+49U=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-openssl.cnf b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-openssl.cnf
new file mode 100644
index 0000000..da136b8
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-openssl.cnf
@@ -0,0 +1,242 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = CA-samba.example.com         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-samba.example.com-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-samba.example.com-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-samba.example.com-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-samba.example.com-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-samba.example.com-crl.pem           # The current CRL
+crl         = $dir/Public/CA-samba.example.com-crl.crl           # The current CRL
+private_key = $dir/Private/CA-samba.example.com-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-samba.example.com.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = 7300           # how long to certify for
+default_crl_days= 7300            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = 2048
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = US
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = SambaState
+
+localityName            = Locality Name (eg, city)
+localityName_default    = SambaCity
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = SambaSelfTesting
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Users
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = administrator at addom.samba.example.com
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = administrator at addom.samba.example.com
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+#[ usr_cert_scarduser ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a certificate that will be used to login from a smart card
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# For normal client use this is typical
+nsCertType = client, email
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Smart Card Login Certificate for administrator at addom.samba.example.com"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=email:copy,otherName:msUPN;UTF8:administrator at addom.samba.example.com
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for client certs
+extendedKeyUsage = clientAuth,scardLogin
+
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-private-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-private-key.pem
new file mode 100644
index 0000000..1510760
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-private-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAvpFk8hsr7ZtAvA1GI0l3MnT+y5pGhjMeVr3I2t3mKgc0YRzw
+uHEpJCuQ80OZb2n2/425tz/zNmqZkJDWlWNOiFrXQYl/cxNkScfeQmUIXcoEsmg6
+QH9qBd9WMC+sG4sPwxU8OA+QUEQAu1lA9tLoW3MDDfZ9OF0vmcMNEw900J7vHpJC
+xEZ83IV+6a+RTp1fgq9YYBilrJFu3c+nMjzS9OmBvoCeDMofGr6YxP7mJcGJ/hYK
+MJDT1OWviSRkEtBPGeIbhvsGqWPRRxCJ3CtSJNxmqVbCy/TsNRL0rV78/4bpsfkf
+s85E+74Er41Cm1alAn/Fz18jQRxp7jOXeoFQiwIDAQABAoIBADkGUvmrrdJ1IcLk
+CffnNPbxUYllifMAevSj5+WufwBWlZL10QawPgpnywEwWkqfn9zK8SbnyQSgk4FS
+BhQ/2jEtVbpzxaKOy/TUDSs7BmziVdN5Iu1H81b8hNL4gPzg+P98bD+uUJXkM3/c
+bnctl4A+A0z7VG84W1Ucq93nQyJl18E64i57JMb3tI+423FM3sJBk2FUj64Mwg8r
+0p88gccSieB3GusffHazlJDKrlHdFyClLBnW3OQHegv42JOKZErIMHwlaV8fhF21
+GAARx/pDgnvIYUaGhLrf2pCyIkOZIdUedA84rLwAZT9akOtxpNCAxlVUn4xcpAC1
+EAKzGbECgYEA99Hzh3vDNGINYJjqsw01E71DelNTeUmBOuJKqdOG0YLHiG0tERcx
+9KLv+7Uo/qtuRzpkMHao7+zC4spQBk1yYkjVtPkXhWdgVUOztkkza72jlwtVu0eK
+VYfB7eubOMnSsPtVeYyyM6DFKBRUxo0VKsvvjD/84WdCGsgy+jDRDUkCgYEAxNur
+XMStYOnxdebOGFs5U8jc+/HNNuaCpSkk98uQ0/VfWp8TXA508FYnT6/BcoH+3hHy
+7W/7aMv//0IWgNQk8m1w33svDdq7jRJXrIpyb7QaX2OW8IfTfIMKVXOgxPvD/4IK
+lvmvf8T7K0W7rDYdcfy9bsDb0RQcH0Z3cp4lUzMCgYEAmLjmX6RB1FJo9BLI8Lc+
+8n88ynH3i1NlNKioYqhc+VijJsxBbbrhqmWPh4tJTEjRmUu+2q8FxXYfVCxhzMCF
+sVQ5f2HSwP/IOkOSyM+rxMYFvtvZZaTc94DGXp1H92NJWJBLSLEQUQjO97gv1nyz
+gsBTTBdS/IXqEx81a0ISUyECgYA80saClj4fmIjDbfm1qtHuojwtGAvY76XkE+9Z
+JKtt4f2BSW843TqiW2wwAdTaZXHy+Ua+t//M5GMHYksDqQh1Yv0h/7SNKk0SjF1M
+cUZkXxha6rFjRgRBD1ftCRneYw+u7WYKOcFQz/Lu7s/KqLm2U2nQQ4RneDgsLaCQ
+aG6N4wKBgArI0d3MlNFXLU7bT+q/2BaZ5VBwaF/6DlI4m1hDT8dKtOTja+y6vAm/
+aH82uJyoom8R/w2H/ICe3NuwYgTo/7Vy6xMt1TnskGOc0yjTZBMMU1nN8zrxlgD1
+1Xr8TzGOf//mK4H54B/POSq6WZ0PSXDVGToVWMdif+2Rq16+CcKp
+-----END RSA PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-req.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-req.pem
new file mode 100644
index 0000000..fbaf0fc
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-S03-req.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIDDTCCAfUCAQAwgccxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTYW1iYVN0YXRl
+MRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNVBAoMEFNhbWJhU2VsZlRlc3Rpbmcx
+DjAMBgNVBAsMBVVzZXJzMS4wLAYDVQQDDCVhZG1pbmlzdHJhdG9yQGFkZG9tLnNh
+bWJhLmV4YW1wbGUuY29tMTQwMgYJKoZIhvcNAQkBFiVhZG1pbmlzdHJhdG9yQGFk
+ZG9tLnNhbWJhLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvpFk8hsr7ZtAvA1GI0l3MnT+y5pGhjMeVr3I2t3mKgc0YRzwuHEpJCuQ
+80OZb2n2/425tz/zNmqZkJDWlWNOiFrXQYl/cxNkScfeQmUIXcoEsmg6QH9qBd9W
+MC+sG4sPwxU8OA+QUEQAu1lA9tLoW3MDDfZ9OF0vmcMNEw900J7vHpJCxEZ83IV+
+6a+RTp1fgq9YYBilrJFu3c+nMjzS9OmBvoCeDMofGr6YxP7mJcGJ/hYKMJDT1OWv
+iSRkEtBPGeIbhvsGqWPRRxCJ3CtSJNxmqVbCy/TsNRL0rV78/4bpsfkfs85E+74E
+r41Cm1alAn/Fz18jQRxp7jOXeoFQiwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEB
+ALQr9rGYIkhd/AXeVoFHs/66rwaq3GccdnJpi023/5LhOlRmMa2BWTuQm3jW/3Oc
+HgQOx9G0GTDpaBtAjOCGDCygw/k23oekVTQtDPiGigMnpuY2vnrjAeUFJo3us5pA
+9eVPzKTzJf5ftc/aoVC39t/1Uks103M8t5vJCcexBTYQONe56XC1krY50PHZNI/u
+stjOmleHZclLBU/BplId43nRlvvdkXihPiEbdV4XvhHRs/6w52DkQst6NH6jzeWk
+anYEP2Oo1ROX5v201414ZaWm7oDxtNuL8NzDt+DUGISwC/9ZcqadzlaoI9XVhOb2
+AfbQMY1Q/3OeR8uRROpnHjE=
+-----END CERTIFICATE REQUEST-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-cert.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-cert.pem
new file mode 120000
index 0000000..a2eb210
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-cert.pem
@@ -0,0 +1 @@
+USER-administrator at addom.samba.example.com-S03-cert.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-private-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-private-key.pem
new file mode 120000
index 0000000..afbf12e
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at addom.samba.example.com/USER-administrator at addom.samba.example.com-private-key.pem
@@ -0,0 +1 @@
+USER-administrator at addom.samba.example.com-S03-private-key.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-cert.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-cert.pem
new file mode 100644
index 0000000..4ab5d5a
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-cert.pem
@@ -0,0 +1,169 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=SambaState, L=SambaCity, O=SambaSelfTesting, OU=CA Administration, CN=CA of samba.example.com/emailAddress=ca-samba.example.com at samba.example.com
+        Validity
+            Not Before: Mar 16 23:29:04 2016 GMT
+            Not After : Mar 11 23:29:04 2036 GMT
+        Subject: C=US, ST=SambaState, O=SambaSelfTesting, OU=Users, CN=administrator at samba.example.com/emailAddress=administrator at samba.example.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:af:87:9e:1e:7f:c0:ab:da:47:22:74:d0:df:01:
+                    f1:67:6c:ac:c4:b7:d9:18:97:e5:7a:62:76:33:b6:
+                    52:f2:92:90:75:ac:a3:94:7e:0c:29:75:c9:83:2f:
+                    19:66:60:84:45:ff:d5:a9:bd:c5:3a:a2:d8:25:cf:
+                    15:8a:23:3e:09:73:2f:99:1d:24:1f:e6:96:7e:7b:
+                    c4:1e:8d:55:5b:c1:18:69:cd:1d:b4:22:d5:7b:db:
+                    5e:7c:91:f2:8e:c1:03:30:ee:63:46:5a:54:d5:40:
+                    ac:79:55:00:71:07:8d:3e:0e:ed:ff:93:6c:f1:2d:
+                    84:c1:51:a3:7c:49:cf:ff:85:7b:c0:64:c1:ba:c8:
+                    66:7a:ff:17:2a:74:ea:16:6a:1d:97:c0:27:57:10:
+                    be:76:f5:9a:63:56:c7:25:c6:fc:a7:5e:00:a6:1a:
+                    3d:21:bd:7a:f9:e3:03:60:ce:df:16:06:fc:05:bc:
+                    d1:c8:5d:e7:33:ed:52:8b:60:5b:60:c5:70:13:1d:
+                    c1:b3:08:13:09:3b:05:e8:02:40:12:45:89:af:87:
+                    1f:6a:8f:62:ce:1e:17:13:34:82:81:86:e9:bb:85:
+                    5b:75:1d:f4:3a:02:b4:a6:58:23:fe:c3:3a:35:09:
+                    95:bb:f7:79:bc:e3:97:e6:6d:77:24:aa:2d:51:50:
+                    37:69
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+            Netscape Cert Type: 
+                SSL Client, S/MIME
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                Smart Card Login Certificate for administrator at samba.example.com
+            X509v3 Subject Key Identifier: 
+                45:DA:4B:8D:05:9C:62:4E:62:C3:D7:5C:5F:D3:D9:85:B4:9B:F2:2C
+            X509v3 Authority Key Identifier: 
+                keyid:A2:3E:02:2A:A3:A7:4D:39:B4:08:4D:99:CC:0C:75:36:EA:27:C3:3E
+
+            X509v3 Subject Alternative Name: 
+                email:administrator at samba.example.com, othername:<unsupported>
+            X509v3 Issuer Alternative Name: 
+                email:ca-samba.example.com at samba.example.com
+            Netscape CA Revocation Url: 
+                http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+            X509v3 Extended Key Usage: 
+                TLS Web Client Authentication, scardLogin
+    Signature Algorithm: sha256WithRSAEncryption
+         a2:bb:e6:97:67:3c:b6:6e:6e:dd:34:99:16:c6:80:91:08:bf:
+         91:ba:51:62:5d:76:2f:e5:53:91:3d:99:03:18:a9:84:69:73:
+         76:66:c3:eb:56:d7:c5:40:91:15:da:de:b2:76:48:7d:8a:8c:
+         80:79:3c:e6:da:0e:a6:c3:53:d6:74:ee:5f:29:b7:03:46:de:
+         89:32:14:22:03:30:68:2e:7e:06:d4:ac:9e:82:c0:02:16:7f:
+         81:ba:ee:7a:e7:8b:f7:fb:99:7f:8c:eb:78:54:97:4e:28:44:
+         da:f4:e2:1b:f8:3e:ac:ca:cc:e3:e3:71:90:91:47:9c:78:ed:
+         6f:bc:b7:98:12:ea:75:e5:15:f7:26:56:a7:5c:d6:74:a8:13:
+         7b:23:35:4e:6a:01:f6:a9:f5:5b:9b:d0:ea:ba:0f:c3:c4:1a:
+         e0:b9:a3:ed:5d:28:cb:7f:1d:3e:8a:9a:af:4c:88:00:3c:10:
+         f0:49:85:24:60:e6:cb:d6:9e:00:46:78:4d:90:22:68:4f:10:
+         39:84:3b:e2:7c:3d:ed:23:41:19:7e:6f:45:59:89:a9:9f:26:
+         c1:f9:7d:4d:0a:b4:10:f9:31:7d:cc:87:d0:4b:62:14:70:86:
+         c8:7d:14:ff:e4:68:e2:de:42:ca:01:c7:aa:2d:5a:a5:72:64:
+         f1:4c:fa:6e:60:15:22:08:68:e6:c6:6a:75:63:24:b5:54:76:
+         d1:97:4f:e0:e8:bc:eb:d0:62:84:4a:b4:3a:07:38:5f:b9:a6:
+         6a:31:14:47:33:81:bd:d0:a4:a2:da:2b:92:0d:dc:42:c4:0f:
+         28:0d:b6:1b:33:b5:88:df:1b:a8:d8:90:9a:11:ce:df:d4:14:
+         e9:ac:94:94:95:bb:bc:6e:f1:be:85:29:3f:17:ab:41:14:d8:
+         20:ba:e0:a2:a3:d3:d4:8b:1e:4b:32:22:8d:0d:c1:e6:39:1a:
+         ce:cd:f3:1d:f1:82:85:d5:e7:80:34:90:a4:0e:d4:af:32:c8:
+         79:4e:25:32:b6:1e:06:3a:26:42:38:47:1a:32:96:71:5b:fe:
+         5b:b0:ef:7d:fe:58:ca:eb:b5:c9:4b:2f:12:cb:89:36:22:7c:
+         a6:39:ab:20:c1:2d:cd:6b:34:e1:cd:bc:ed:45:45:12:4a:65:
+         4b:ab:45:f2:6d:7a:9d:f8:b5:52:78:1b:da:2f:e0:ce:f7:e2:
+         b0:fa:6f:40:3d:dd:e9:39:c3:63:68:ab:77:53:be:3b:dd:9a:
+         bc:d7:d7:fa:6a:bf:bf:74:f7:11:80:87:f9:d3:45:eb:1e:8e:
+         d1:a9:a0:2e:66:e7:20:67:1c:4c:22:43:77:85:ff:1a:23:37:
+         cc:49:de:51:ee:f2:04:2f:a8:98:88:0f:b6:18:53:eb:e2:49:
+         15:5e:02:8b:1e:7b:e6:c5:d1:0c:df:84:4e:d9:bd:fe:21:48:
+         d4:a4:11:01:27:57:51:d6:c1:b2:a1:1c:11:9a:a7:d1:ab:f0:
+         99:16:b2:c8:3f:74:25:68:0b:1a:cf:58:0d:cd:cc:1a:6d:8b:
+         ec:1f:70:82:02:40:97:0f:75:2c:53:87:c1:42:5c:d1:7e:19:
+         78:2c:2c:88:73:33:81:63:38:84:07:0f:16:bb:7c:54:59:03:
+         94:e7:b8:85:d7:f8:5e:53:35:65:2e:e5:27:65:be:f0:89:65:
+         f6:ab:3f:6e:a5:bd:c1:1a:9e:31:30:68:6e:50:af:54:4c:33:
+         f8:73:2f:41:60:4f:4c:85:1b:ad:7d:db:62:42:dc:87:96:b4:
+         cf:ce:12:50:ed:6c:01:5f:e2:f9:03:f5:f7:4c:6c:8f:2b:5b:
+         7a:64:7d:19:e8:20:f2:e9:10:58:f3:71:0e:1e:58:68:f2:59:
+         3c:06:53:7a:f3:60:62:5b:c7:b7:83:58:1d:3d:a6:17:db:33:
+         cc:91:14:af:d6:b9:08:bf:60:af:ac:3e:fe:8b:74:71:20:c7:
+         e7:31:5e:26:6c:28:52:67:12:1e:c3:9b:89:23:5d:88:ee:b0:
+         6b:db:cc:94:8b:9b:1b:40:b7:66:bc:7d:1d:e1:08:00:20:ba:
+         41:cd:17:d6:4c:7b:c4:5a:fd:cf:6b:20:e2:b8:86:9c:31:17:
+         c2:d7:7f:1c:3a:d0:fc:1d:f5:7f:c9:96:04:27:de:b8:ef:8d:
+         38:9a:b3:56:60:ac:c2:07:38:64:19:39:9e:73:6f:ba:59:15:
+         ac:45:42:4d:bb:79:60:7f:ae:c3:8d:63:4a:27:16:0a:ca:92:
+         7f:f7:a2:02:76:f5:e6:7c:ec:ba:ea:18:cd:9c:3b:ee:37:2c:
+         9d:78:4e:c9:40:6d:94:cc:ce:ca:f4:33:fc:a4:dd:05:62:d6:
+         0f:1e:19:63:af:10:c3:ff:02:1a:0a:48:fd:af:f2:a4:0e:64:
+         dd:90:f4:4f:14:1b:90:1f:9e:29:b0:0b:94:a4:d1:2a:87:b9:
+         3a:76:c2:b6:af:c3:d4:84:6e:85:1c:64:73:46:d0:df:72:c0:
+         3c:42:91:c4:30:10:11:18:36:bc:e5:17:36:22:5f:c2:3f:ac:
+         1d:2e:9d:87:11:be:a7:ac:b2:62:35:74:b9:27:27:95:bc:c1:
+         11:44:f8:64:36:60:74:06:a2:e7:e9:76:be:a7:86:5e:18:1e:
+         bd:dc:b0:aa:ae:92:d6:dd:d6:25:80:d6:c1:be:c1:21:1c:01:
+         6f:83:20:ae:b7:54:4f:3d:2d:12:fc:a2:cc:49:fd:59
+-----BEGIN CERTIFICATE-----
+MIII/TCCBOWgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBxjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMClNhbWJhU3RhdGUxEjAQBgNVBAcMCVNhbWJhQ2l0eTEZMBcGA1UE
+CgwQU2FtYmFTZWxmVGVzdGluZzEaMBgGA1UECwwRQ0EgQWRtaW5pc3RyYXRpb24x
+IDAeBgNVBAMMF0NBIG9mIHNhbWJhLmV4YW1wbGUuY29tMTUwMwYJKoZIhvcNAQkB
+FiZjYS1zYW1iYS5leGFtcGxlLmNvbUBzYW1iYS5leGFtcGxlLmNvbTAeFw0xNjAz
+MTYyMzI5MDRaFw0zNjAzMTEyMzI5MDRaMIGnMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKU2FtYmFTdGF0ZTEZMBcGA1UECgwQU2FtYmFTZWxmVGVzdGluZzEOMAwGA1UE
+CwwFVXNlcnMxKDAmBgNVBAMMH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5j
+b20xLjAsBgkqhkiG9w0BCQEWH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5j
+b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvh54ef8Cr2kcidNDf
+AfFnbKzEt9kYl+V6YnYztlLykpB1rKOUfgwpdcmDLxlmYIRF/9WpvcU6otglzxWK
+Iz4Jcy+ZHSQf5pZ+e8QejVVbwRhpzR20ItV72158kfKOwQMw7mNGWlTVQKx5VQBx
+B40+Du3/k2zxLYTBUaN8Sc//hXvAZMG6yGZ6/xcqdOoWah2XwCdXEL529ZpjVscl
+xvynXgCmGj0hvXr54wNgzt8WBvwFvNHIXecz7VKLYFtgxXATHcGzCBMJOwXoAkAS
+RYmvhx9qj2LOHhcTNIKBhum7hVt1HfQ6ArSmWCP+wzo1CZW793m845fmbXckqi1R
+UDdpAgMBAAGjggIRMIICDTAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECGPmh0
+dHA6Ly93d3cuc2FtYmEuZXhhbXBsZS5jb20vY3Jscy9DQS1zYW1iYS5leGFtcGxl
+LmNvbS1jcmwuY3JsMBEGCWCGSAGG+EIBAQQEAwIFoDALBgNVHQ8EBAMCBeAwTwYJ
+YIZIAYb4QgENBEIWQFNtYXJ0IENhcmQgTG9naW4gQ2VydGlmaWNhdGUgZm9yIGFk
+bWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5jb20wHQYDVR0OBBYEFEXaS40FnGJO
+YsPXXF/T2YW0m/IsMB8GA1UdIwQYMBaAFKI+Aiqjp005tAhNmcwMdTbqJ8M+MFsG
+A1UdEQRUMFKBH2FkbWluaXN0cmF0b3JAc2FtYmEuZXhhbXBsZS5jb22gLwYKKwYB
+BAGCNxQCA6AhDB9hZG1pbmlzdHJhdG9yQHNhbWJhLmV4YW1wbGUuY29tMDEGA1Ud
+EgQqMCiBJmNhLXNhbWJhLmV4YW1wbGUuY29tQHNhbWJhLmV4YW1wbGUuY29tME0G
+CWCGSAGG+EIBBARAFj5odHRwOi8vd3d3LnNhbWJhLmV4YW1wbGUuY29tL2NybHMv
+Q0Etc2FtYmEuZXhhbXBsZS5jb20tY3JsLmNybDAfBgNVHSUEGDAWBggrBgEFBQcD
+AgYKKwYBBAGCNxQCAjANBgkqhkiG9w0BAQsFAAOCBAEAorvml2c8tm5u3TSZFsaA
+kQi/kbpRYl12L+VTkT2ZAxiphGlzdmbD61bXxUCRFdresnZIfYqMgHk85toOpsNT
+1nTuXym3A0beiTIUIgMwaC5+BtSsnoLAAhZ/gbrueueL9/uZf4zreFSXTihE2vTi
+G/g+rMrM4+NxkJFHnHjtb7y3mBLqdeUV9yZWp1zWdKgTeyM1TmoB9qn1W5vQ6roP
+w8Qa4Lmj7V0oy38dPoqar0yIADwQ8EmFJGDmy9aeAEZ4TZAiaE8QOYQ74nw97SNB
+GX5vRVmJqZ8mwfl9TQq0EPkxfcyH0EtiFHCGyH0U/+Ro4t5CygHHqi1apXJk8Uz6
+bmAVIgho5sZqdWMktVR20ZdP4Oi869BihEq0Ogc4X7mmajEURzOBvdCkotorkg3c
+QsQPKA22GzO1iN8bqNiQmhHO39QU6ayUlJW7vG7xvoUpPxerQRTYILrgoqPT1Ise
+SzIijQ3B5jkazs3zHfGChdXngDSQpA7UrzLIeU4lMrYeBjomQjhHGjKWcVv+W7Dv
+ff5Yyuu1yUsvEsuJNiJ8pjmrIMEtzWs04c287UVFEkplS6tF8m16nfi1Ungb2i/g
+zvfisPpvQD3d6TnDY2ird1O+O92avNfX+mq/v3T3EYCH+dNF6x6O0amgLmbnIGcc
+TCJDd4X/GiM3zEneUe7yBC+omIgPthhT6+JJFV4Cix575sXRDN+ETtm9/iFI1KQR
+ASdXUdbBsqEcEZqn0avwmRayyD90JWgLGs9YDc3MGm2L7B9wggJAlw91LFOHwUJc
+0X4ZeCwsiHMzgWM4hAcPFrt8VFkDlOe4hdf4XlM1ZS7lJ2W+8Ill9qs/bqW9wRqe
+MTBoblCvVEwz+HMvQWBPTIUbrX3bYkLch5a0z84SUO1sAV/i+QP190xsjytbemR9
+Gegg8ukQWPNxDh5YaPJZPAZTevNgYlvHt4NYHT2mF9szzJEUr9a5CL9gr6w+/ot0
+cSDH5zFeJmwoUmcSHsObiSNdiO6wa9vMlIubG0C3Zrx9HeEIACC6Qc0X1kx7xFr9
+z2sg4riGnDEXwtd/HDrQ/B31f8mWBCfeuO+NOJqzVmCswgc4ZBk5nnNvulkVrEVC
+Tbt5YH+uw41jSicWCsqSf/eiAnb15nzsuuoYzZw77jcsnXhOyUBtlMzOyvQz/KTd
+BWLWDx4ZY68Qw/8CGgpI/a/ypA5k3ZD0TxQbkB+eKbALlKTRKoe5OnbCtq/D1IRu
+hRxkc0bQ33LAPEKRxDAQERg2vOUXNiJfwj+sHS6dhxG+p6yyYjV0uScnlbzBEUT4
+ZDZgdAai5+l2vqeGXhgevdywqq6S1t3WJYDWwb7BIRwBb4MgrrdUTz0tEvyizEn9
+WQ==
+-----END CERTIFICATE-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-key.pem
new file mode 100644
index 0000000..652e3bd
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI7Afo/WihRO4CAggA
+MBQGCCqGSIb3DQMHBAiyzMez8ikVKgSCBMikJkx4Qhm0cLRQXJfIPsHX0YQfinoJ
+qLGWMQ5KWTpwFZHoeqarmCVLJwReF75E8nD5tJdKt5J+lN0gBQMbppAzlSOJvMne
+1E5sDoBHY3jYUViF3p+ZZt4YoDxaGFYxcGL9M6Uo/Yb1791riMisQjgn7inpRe0i
+JuHngJH9Dblg0+vGM3JkMKdizWHSW4RyeYXa8d3rh62Y5RD7exUHKkz3pPucSsyy
+dnkhvbhdXSYzPxcUarrjx3pNMzWhamLWP3V6UwupCB8dygLm4QV+Fc3Jw7wR3Efj
+cewWjmXHuHzAGfDhr1r6yeWaAQCYezSp18UwMRv9AWgiTAayxDI+IroBigvU3PfA
+KE0RlWBnvoy2ggNEsCvk2QXYpQiIJMTS9u1oi2aOdvXaaVxuKBPJGgzAFGSnM44k
+gE1Pe+snVxzRuzHCNXnWoCxSa9xAvRt/dnQ9n1p2m3lwlt+kP0kO4ieMhT+SnBNh
+QY/WRfJ8E5ldYyfJ0y2eRd1hCu+42tj72rAuQkhPEUJzWuU6N1xzChXPwXVnhIh4
+HS4bpd9uL1wA5sNw2zfXdanagmSrXC5EFVdj4rJzHWzkalg0GTMhYd4QsbqI5d8O
+lO5ECnZUJwIcYa5Hy7OVDymRh3BxPMDGYqiO1+6QHUrqRm/XiSDUSaBfLat9ckHY
+0JT5nbBMg0TJ3VIhUbsZaQ4fwZNr9zgeS+yoFuLcPYPCHBz2fDNq6MFb0BqbHcYY
+qmf++nxF/jW21UKTryBeiLdkq1TjExOEXdmjSL4vwmUjyx+ycM4w8GvdU4xkdkQl
+1jNlx20WSocZ0hzreCMXglUb1q7tzZvaVJrSS9TX2PV38Fcz6jpmOeKtnkRBMUis
+Ge20QO7D8zCJM0jL+mNAnuZCA7zHc8aenbR6hK8i3Kd8G0XhWLNVWI5KfFtgrRaW
+UCM8mSdEIvWZfPrdvxo/kYEXBBA8i+3oO0nSUTyHpqmsIH3nYvaWnVmibnKMigO3
++3d+6Db5R117EbXDdRWm85jiN7PQ1SdNVxtKN4Wu188r/KfchXAeBQcBy9Kh1vVY
+qYTqP4Mp7dbm864iiZQZwTLJeq346+xUze5NY7nFHWl0ps7ujk+i9WA9I+M2TAj9
+Zmywy4Xvjwpj7PO5zA9O5TRxnnBbz7VrTcxBLK+6T/2yZZceJ29Bv7wy61eK9LNk
+AYy+MFXlY64L6HauTk9Ne/VnNnTvYYqrqPNy6CehQc0+LKvmYLCHUZabhWi7P1rj
+gUkkypfBH0j8k1lDnjnYu5bml32GK7eBix9C+5kNDadnvCEVDiYFT59SDyKCUHMZ
+19EKywqkWVPu5ez+60zSEJACpvIqDxlamusN3O9tQZD/t2c2lJiBeBPszXgj8Gin
+++tuCwkz/3KNy+u3SCZg9SUk5+XVZDOQOMh9EmUT5oqoPUTm9pblU2B8lRZaw/wl
+B97E4q4TUOtXZXHJdCkU8Sxr8/l8fOFYqIeiFx8PhSHaFgpEKgs89G9AefIb+l1u
+Z36bqMs0y4rIiSHR++0ZO5NJIi33zhPHvifmPzBTDXRn9cWdfqwetq1ts9ZD27oE
+4UhJyRU0gprmtpQWoVnd6ghiM1zk7lZmRQEDDXy4+puztzgZNLKJbSeXbufe49nX
+DcU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-openssl.cnf b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-openssl.cnf
new file mode 100644
index 0000000..db72360
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-openssl.cnf
@@ -0,0 +1,242 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = http://www.samba.example.com/crls/CA-samba.example.com-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = CA-samba.example.com         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-samba.example.com-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-samba.example.com-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-samba.example.com-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-samba.example.com-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-samba.example.com-crl.pem           # The current CRL
+crl         = $dir/Public/CA-samba.example.com-crl.crl           # The current CRL
+private_key = $dir/Private/CA-samba.example.com-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-samba.example.com.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = 7300           # how long to certify for
+default_crl_days= 7300            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = 2048
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = US
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = SambaState
+
+localityName            = Locality Name (eg, city)
+localityName_default    = SambaCity
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = SambaSelfTesting
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Users
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = administrator at samba.example.com
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = administrator at samba.example.com
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+#[ usr_cert_scarduser ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a certificate that will be used to login from a smart card
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# For normal client use this is typical
+nsCertType = client, email
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Smart Card Login Certificate for administrator at samba.example.com"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=email:copy,otherName:msUPN;UTF8:administrator at samba.example.com
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for client certs
+extendedKeyUsage = clientAuth,scardLogin
+
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-private-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-private-key.pem
new file mode 100644
index 0000000..cc8f150
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-private-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAr4eeHn/Aq9pHInTQ3wHxZ2ysxLfZGJflemJ2M7ZS8pKQdayj
+lH4MKXXJgy8ZZmCERf/Vqb3FOqLYJc8ViiM+CXMvmR0kH+aWfnvEHo1VW8EYac0d
+tCLVe9tefJHyjsEDMO5jRlpU1UCseVUAcQeNPg7t/5Ns8S2EwVGjfEnP/4V7wGTB
+ushmev8XKnTqFmodl8AnVxC+dvWaY1bHJcb8p14Apho9Ib16+eMDYM7fFgb8BbzR
+yF3nM+1Si2BbYMVwEx3BswgTCTsF6AJAEkWJr4cfao9izh4XEzSCgYbpu4VbdR30
+OgK0plgj/sM6NQmVu/d5vOOX5m13JKotUVA3aQIDAQABAoIBAQCEj7E0a1rA7ooG
+VZ5grQD5ELOxpP7Jef2OXcnS6ADgvRtoI0cun7rjnNbgwbM3A/EhRELCfFT1IYKH
+m0szFcaGMH1j7wQXK3fAcgv83tP2BXBAhu3F2wDLFzLWdQpwEQgt7fr/aLzkiIE4
+6J76va9HjNLkzxvZUH0P2m3TMZNp7s2NLjxNQwivNXSgKXcT9fPX7IaBd063W41I
+iYQZ7M8Q3C1vk34uC9V1LxjFxOAe42G/ITkjt3CJbg0CjMXG3P3TKIXG94ufpFQO
+mkEzUSGxTCkwlqHKcxsa+7f72TocuhLuwpFBSeRmiIsa5ZHxJiC6XOkz2CAboNkI
+UMSVjoxZAoGBAOlOGjiF7ChheDLhtj3/VcxfyHkcNoUFAtKuoT/FD8JMQiEUTifr
+V7eA8pfAQubVVRNLmZEA40gsJsTPbCRQymwcYDFRATlTd6nZ1s53z99E/v/1QjIa
+ZpQXRD+Nt1xmID/MuX34qpIA6ZEE2zTFoMo1STeNf4eC9mESW9DkA05rAoGBAMCa
+wrvLa5whtXbhdoWfCMYKtSQuGTEKslb4Ec97sKIdZXloGnH0eyiwnynCDhX2wPJt
+gnQtVxNXb9+MFxh+6bnX5rMyB+myXszpPNBCbLO0FU3+vfIEmOoULqU1Xn7Eu97m
+LGoR6G9cN7p8RuX7zp5ROKGfDg77oW8XhVah2x57AoGAY1BmBQ2tW/sx6ab/pyCc
+a2WSt0t1QebCLuE7ryO586H2vJIiOwgJzQnNOyAS2qSRlKcn9fwExGJXFoydok/p
++1+Q6y1qcfbAB8O9lyKVkJuUWW0UArQOWpgU62DuXxzyOXZyt9c09PYCd0Mz9SDz
+s2A/jLBlS1BKhUQFZcTKS4UCgYBaT7cD66x3t26pYar7mMi6ZAbwAhWZ41QgZ42i
+ZnM6cOJF/UR5LpQZTkgzgmSsc9mhUywaYbA0x4kTn1KtD8V0eQIaAFmpgRPmrW7w
+kFT8JnLe8ZYLR5CUIgaFPPMkKgeVywQEcIU2wlz3OpLcACiwH5GYZ0ZmTCM0Pikt
+qBNgxQKBgEVgpIHZi2xdfvwtCrEfomnlImj94HySKIFenCRoc/d34+KO4jKho1zN
+dqbSDqz/lB/7GWFjRszTMZMVJkl8TbE050UEe8EDPt93BSeGHNCUXUesZQVddGhn
+iH8OLIkoW3xIlNgflwi4+7gLjWrAHHPwEG3Iys83DVCA5D/4C02m
+-----END RSA PRIVATE KEY-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-req.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-req.pem
new file mode 100644
index 0000000..72cd979
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-S01-req.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIDATCCAekCAQAwgbsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTYW1iYVN0YXRl
+MRIwEAYDVQQHDAlTYW1iYUNpdHkxGTAXBgNVBAoMEFNhbWJhU2VsZlRlc3Rpbmcx
+DjAMBgNVBAsMBVVzZXJzMSgwJgYDVQQDDB9hZG1pbmlzdHJhdG9yQHNhbWJhLmV4
+YW1wbGUuY29tMS4wLAYJKoZIhvcNAQkBFh9hZG1pbmlzdHJhdG9yQHNhbWJhLmV4
+YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4eeHn/A
+q9pHInTQ3wHxZ2ysxLfZGJflemJ2M7ZS8pKQdayjlH4MKXXJgy8ZZmCERf/Vqb3F
+OqLYJc8ViiM+CXMvmR0kH+aWfnvEHo1VW8EYac0dtCLVe9tefJHyjsEDMO5jRlpU
+1UCseVUAcQeNPg7t/5Ns8S2EwVGjfEnP/4V7wGTBushmev8XKnTqFmodl8AnVxC+
+dvWaY1bHJcb8p14Apho9Ib16+eMDYM7fFgb8BbzRyF3nM+1Si2BbYMVwEx3BswgT
+CTsF6AJAEkWJr4cfao9izh4XEzSCgYbpu4VbdR30OgK0plgj/sM6NQmVu/d5vOOX
+5m13JKotUVA3aQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAGrgBV0TkeQ3fHEJ
+vTabQG/aKSgzkkzaiBdY5GBX3FGtmKl0E9DNImc3bcw4QBC8GDObGoqct31QpHnT
+H51MN/Vix3YAUsKbGtvopGygn22sLtm21Iy1lOS2QsEikPxrDedmKjGzsyi8fWFF
+fWOEW1+mhS7L6oiNDm18MbAaYN6wdgkPVW0Uc+P/ftRZ1y2T2mli+99IgNQQW9Rb
+7ZrHBTyCq9IK73UniVCA3yEN2ibHxaZQsvl3DpUfkKdPV1FOsvj33nTMtcubY7/P
+c4n3w2M0HVSu6Ch+cJj0dy3FzYU76eInzT6B+hs2lGCIm6H4pUH8Vjx9dNMjcC4d
+vctx/Mw=
+-----END CERTIFICATE REQUEST-----
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-cert.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-cert.pem
new file mode 120000
index 0000000..3b134b6
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-cert.pem
@@ -0,0 +1 @@
+USER-administrator at samba.example.com-S01-cert.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-private-key.pem b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-private-key.pem
new file mode 120000
index 0000000..964892e
--- /dev/null
+++ b/selftest/manage-ca/CA-samba.example.com/Users/administrator at samba.example.com/USER-administrator at samba.example.com-private-key.pem
@@ -0,0 +1 @@
+USER-administrator at samba.example.com-S01-private-key.pem
\ No newline at end of file
diff --git a/selftest/manage-ca/manage-CA-samba.example.com.cnf b/selftest/manage-ca/manage-CA-samba.example.com.cnf
new file mode 100644
index 0000000..65c9b95
--- /dev/null
+++ b/selftest/manage-ca/manage-CA-samba.example.com.cnf
@@ -0,0 +1,21 @@
+#
+# All passwords are "1234"
+#
+
+CRL_HTTP_BASE="http://www.samba.example.com/crls"
+CRL_SSH_BASE="none at samba.example.com:/none/crls"
+DNS_DOMAIN="samba.example.com"
+
+CA_BITS="8192"
+DC_BITS="4096"
+USER_BITS="2048"
+# 20 years should be enough
+CA_DAYS="7300"
+CRL_DAYS="7300"
+DC_DAYS="7300"
+USER_DAYS="7300"
+
+COUNTRY_NAME="US"
+STATE_NAME="SambaState"
+LOCALITY_NAME="SambaCity"
+ORGANIZATION_NAME="SambaSelfTesting"
diff --git a/selftest/manage-ca/manage-CA-samba.example.com.sh b/selftest/manage-ca/manage-CA-samba.example.com.sh
new file mode 100644
index 0000000..187ea4b
--- /dev/null
+++ b/selftest/manage-ca/manage-CA-samba.example.com.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+
+set -e
+set -u
+set -x
+
+#
+# All passwords are "1234"
+#
+
+# DONE # ./manage-ca.sh manage-CA-samba.example.com.cnf init_ca
+# DONE #
+# DONE # ./manage-ca.sh manage-CA-samba.example.com.cnf create_dc localdc.samba.example.com 0123456789ABCDEF
+# DONE # ./manage-ca.sh manage-CA-samba.example.com.cnf create_user administrator at samba.example.com
+# DONE #
+# DONE # ./manage-ca.sh manage-CA-samba.example.com.cnf create_dc addc.addom.samba.example.com 0123456789ABCDEF
+# DONE # ./manage-ca.sh manage-CA-samba.example.com.cnf create_user administrator at addom.samba.example.com
diff --git a/selftest/manage-ca/manage-ca.sh b/selftest/manage-ca/manage-ca.sh
new file mode 100755
index 0000000..ab796b7
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.sh
@@ -0,0 +1,387 @@
+#!/bin/bash
+#
+
+set -e
+set -u
+#set -x
+
+umask 022
+
+function print_usage()
+{
+	echo "Usage:"
+	echo ""
+	echo "${0} <CNF_FILE> <CMD> [<ARG1> [<ARG2>]]"
+	echo ""
+	echo "${0} <CNF_FILE> init_ca"
+	echo "${0} <CNF_FILE> update_crl"
+	echo "${0} <CNF_FILE> publish_crl"
+	echo "${0} <CNF_FILE> create_dc <DC_DNS_NAME> <DC_OBJECTGUID_HEX>"
+	echo "${0} <CNF_FILE> revoke_dc <DC_DNS_NAME> <REVOKE_RESON>"
+	echo "${0} <CNF_FILE> create_user <USER_PRINCIPAL_NAME>"
+	echo "${0} <CNF_FILE> revoke_user <USER_PRINCIPAL_NAME> <REVOKE_RESON>"
+	echo ""
+}
+
+function check_arg()
+{
+	local k="${1}"
+	local v="${2}"
+
+	test -n "${v}" || {
+		print_usage
+		echo "ERROR: CMD[${CMD}] argument <${k}> missing"
+		return 1
+	}
+
+	return 0
+}
+CNF="${1-}"
+test -n "${CNF}" || {
+	print_usage
+	echo "ERROR: speficy <CNF_FILE> see manage-ca.templates.d/manage-CA-example.com.cnf"
+	exit 1
+}
+test -e "${CNF}" || {
+	print_usage
+	echo "ERROR: CNF_FILE[${CNF}] does not exist"
+	exit 1
+}
+CMD="${2-}"
+CMDARG1="${3-}"
+CMDARG2="${4-}"
+
+TEMPLATE_DIR="manage-ca.templates.d"
+DEFAULT_VARS=""
+DEFAULT_VARS="${DEFAULT_VARS} CRL_HTTP_BASE DNS_DOMAIN DEFAULT_BITS"
+DEFAULT_VARS="${DEFAULT_VARS} DEFAULT_BITS DEFAULT_DAYS DEFAULT_CRL_DAYS"
+DEFAULT_VARS="${DEFAULT_VARS} COUNTRY_NAME STATE_NAME LOCALITY_NAME ORGANIZATION_NAME"
+DEFAULT_VARS="${DEFAULT_VARS} ORGANIZATIONAL_UNIT_NAME COMMON_NAME EMAIL_ADDRESS"
+
+source "${CNF}"
+
+DEFAULT_BITS=${DEFAULT_BITS:=8192}
+CA_BITS=${CA_BITS:=${DEFAULT_BITS}}
+DC_BITS=${DC_BITS:=${DEFAULT_BITS}}
+USER_BITS=${USER_BITS:=${DEFAULT_BITS}}
+
+CA_DAYS=${CA_DAYS:=3650}
+CRL_DAYS=${CRL_DAYS:=30}
+DC_DAYS=${DC_DAYS:=730}
+USER_DAYS=${USER_DAYS:=730}
+
+CA_DIR="CA-${DNS_DOMAIN}"
+DEFAULT_VARS="${DEFAULT_VARS} CA_DIR"
+
+CACERT_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.pem"
+CACERT_CER="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.cer"
+CACRL_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.pem"
+CACRL_CRL="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.crl"
+CA_SERIAL="${CA_DIR}/Private/CA-${DNS_DOMAIN}-serial.txt"
+
+function generate_from_template()
+{
+	local base_template="${TEMPLATE_DIR}/$1"
+	local cmd_template="${TEMPLATE_DIR}/$2"
+	local cnf_file="$3"
+	shift 3
+	local vars="$@"
+
+	test -f "${base_template}" || {
+		echo "base_template[${base_template}] does not exists"
+		return 1
+	}
+	test -f "${cmd_template}" || {
+		echo "cmd_template[${cmd_template}] does not exists"
+		return 1
+	}
+	test -e "${cnf_file}" && {
+		echo "cnf_file[${cnf_file}] already exists"
+		return 1
+	}
+
+	local sedargs=""
+	for k in $vars; do
+		v=$(eval echo "\${${k}}")
+		sedargs="${sedargs} -e 's!@@${k}@@!${v}!g'"
+	done
+
+	#echo "sedargs[${sedargs}]"
+	cat "${base_template}" "${cmd_template}" | eval sed ${sedargs} > "${cnf_file}"
+	grep '@@'  "${cnf_file}" | wc -l | grep -q '^0' || {
+		echo "invalid context in cnf_file[${cnf_file}]"
+		grep '@@' "${cnf_file}"
+		return 1
+	}
+
+	return 0
+}
+
+case "${CMD}" in
+init_ca)
+	test -e "${CA_DIR}" && {
+		echo "CA with CA_DIR[${CA_DIR}] already exists"
+		exit 1
+	}
+
+	OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+	CA_INDEX="${CA_DIR}/Private/CA-${DNS_DOMAIN}-index.txt"
+	CA_CRLNUMBER="${CA_DIR}/Private/CA-${DNS_DOMAIN}-crlnumber.txt"
+	PRIVATEKEY="${CA_DIR}/Private/CA-${DNS_DOMAIN}-private-key.pem"
+
+	ORGANIZATIONAL_UNIT_NAME="CA Administration"
+	COMMON_NAME="CA of ${DNS_DOMAIN}"
+	EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
+
+	DEFAULT_BITS="${CA_BITS}"
+	DEFAULT_DAYS="1"
+	DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+	mkdir -p "${CA_DIR}/"{,Public}
+	umask 077
+	mkdir -p "${CA_DIR}/"{,Private,NewCerts,DCs,Users}
+	umask 022
+	touch "${CA_INDEX}"
+	echo "00" > "${CA_SERIAL}"
+	echo "00" > "${CA_CRLNUMBER}"
+
+	generate_from_template \
+		"openssl-BASE-template.cnf" \
+		"openssl-CA-template.cnf" \
+		"${OPENSSLCNF}" \
+		${DEFAULT_VARS}
+	openssl req -new -x509 -sha256 -extensions v3_ca -days "${CA_DAYS}" -keyout "${PRIVATEKEY}" -out "${CACERT_PEM}" -config "${OPENSSLCNF}"
+	openssl x509 -in "${CACERT_PEM}" -inform PEM -out "${CACERT_CER}" -outform DER
+	echo -n "Generate CRL [ENTER] to continue"
+	read
+	openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+	openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+	ls -la "${CA_DIR}"/Public/CA-*
+	echo "Please run: '${0} ${CNF} publish_crl'"
+	exit 0
+	;;
+update_crl)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+
+	OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+	openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+	openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+	ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+	echo "Please run: '${0} ${CNF} publish_crl'"
+	exit 0
+	;;
+publish_crl)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+
+	echo "Upload ${CACRL_CRL} to ${CRL_SSH_BASE}/"
+	rsync -a -P "${CACRL_CRL}" "${CRL_SSH_BASE}/"
+	echo "Check ${CRL_HTTP_BASE}/CA-${DNS_DOMAIN}-crl.crl"
+	exit 0
+	;;
+create_dc)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+	#
+	#
+	# ldbsearch -H ldap://DC_DNS_NAME '(dnsHostName=DC_DNS_NAME)' distinguishedName --controls=search_options:1:1 --controls=extended_dn:1:0
+	DC_DNS_NAME="${CMDARG1}"
+	check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
+	DC_OBJECTGUID_HEX=$(echo "${CMDARG2}" | tr a-z A-Z)
+	check_arg "DC_OBJECTGUID_HEX" "${DC_OBJECTGUID_HEX}"
+
+	DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
+	test -e "${DC_DIR}" && {
+		echo "DC with DC_DIR[${DC_DIR}] already exists"
+		exit 1
+	}
+
+	NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
+	DCFILE_BASE="DC-${DC_DNS_NAME}-S${NEXT_SERIAL}"
+	OPENSSLCNF="${DC_DIR}/${DCFILE_BASE}-openssl.cnf"
+	DCKEY_PEM="${DC_DIR}/${DCFILE_BASE}-key.pem"
+	DCKEY_PRIVATE_PEM="${DC_DIR}/${DCFILE_BASE}-private-key.pem"
+	DCKEY_PRIVATE_PEM_BASE="${DCFILE_BASE}-private-key.pem"
+	DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
+	DCREQ_PEM="${DC_DIR}/${DCFILE_BASE}-req.pem"
+	DCCERT_PEM="${DC_DIR}/${DCFILE_BASE}-cert.pem"
+	DCCERT_PEM_BASE="${DCFILE_BASE}-cert.pem"
+	DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
+	DCCERT_CER="${DC_DIR}/${DCFILE_BASE}-cert.cer"
+	DCCERT_P12="${DC_DIR}/${DCFILE_BASE}-private.p12"
+
+	ORGANIZATIONAL_UNIT_NAME="Domain Controllers"
+	COMMON_NAME="${DC_DNS_NAME}"
+	EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
+
+	DEFAULT_BITS="${DC_BITS}"
+	DEFAULT_DAYS="${DC_DAYS}"
+	DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+	umask 077
+	mkdir -p "${DC_DIR}/"
+
+	generate_from_template \
+		"openssl-BASE-template.cnf" \
+		"openssl-DC-template.cnf" \
+		"${OPENSSLCNF}" \
+		${DEFAULT_VARS} DC_DNS_NAME DC_OBJECTGUID_HEX
+
+	openssl req -new -newkey rsa -keyout "${DCKEY_PEM}" -out "${DCREQ_PEM}" -config "${OPENSSLCNF}"
+	openssl rsa -in "${DCKEY_PEM}" -inform PEM -out "${DCKEY_PRIVATE_PEM}" -outform PEM
+	openssl ca -config "${OPENSSLCNF}" -in "${DCREQ_PEM}" -out "${DCCERT_PEM}"
+	ln -s "${DCKEY_PRIVATE_PEM_BASE}" "${DCKEY_PRIVATE_PEM_LINK}"
+	ln -s "${DCCERT_PEM_BASE}" "${DCCERT_PEM_LINK}"
+	openssl x509 -in "${DCCERT_PEM}"  -inform PEM -out "${DCCERT_CER}" -outform DER
+	echo "Generate ${DCCERT_P12}"
+	openssl pkcs12 -in "${DCCERT_PEM}" -inkey "${DCKEY_PRIVATE_PEM}" -export -out "${DCCERT_P12}"
+	ls -la "${DC_DIR}"/*.*
+	exit 0
+	;;
+revoke_dc)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+	DC_DNS_NAME="${CMDARG1}"
+	check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
+	REVOKE_REASON="${CMDARG2}"
+	check_arg "REVOKE_REASON" "${REVOKE_REASON}"
+
+	DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
+	test -e "${DC_DIR}" || {
+		echo "DC with DC_DIR[${DC_DIR}] does not exists"
+		exit 1
+	}
+
+	OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+	DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
+	DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
+
+	REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
+	REVOKE_DC_DIR="${DC_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
+
+	openssl ca -config "${OPENSSLCNF}" -revoke "${DCCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
+
+	mv "${DCKEY_PRIVATE_PEM_LINK}" "${DCKEY_PRIVATE_PEM_LINK}.revoked"
+	mv "${DCCERT_PEM_LINK}" "${DCCERT_PEM_LINK}.revoked"
+	mv "${DC_DIR}" "${REVOKE_DC_DIR}"
+	echo "${REVOKE_DC_DIR}"
+
+	openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+	openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+	ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+	echo "Please run: '${0} ${CNF} publish_crl'"
+	exit 0
+	;;
+create_user)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+	USER_PRINCIPAL_NAME="${CMDARG1}"
+	check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
+
+	USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
+	test -e "${USER_DIR}" && {
+		echo "USER with USER_DIR[${USER_DIR}] already exists"
+		exit 1
+	}
+
+	NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
+	USERFILE_BASE="USER-${USER_PRINCIPAL_NAME}-S${NEXT_SERIAL}"
+	OPENSSLCNF="${USER_DIR}/${USERFILE_BASE}-openssl.cnf"
+	USERKEY_PEM="${USER_DIR}/${USERFILE_BASE}-key.pem"
+	USERKEY_PRIVATE_PEM="${USER_DIR}/${USERFILE_BASE}-private-key.pem"
+	USERKEY_PRIVATE_PEM_BASE="${USERFILE_BASE}-private-key.pem"
+	USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
+	USERREQ_PEM="${USER_DIR}/${USERFILE_BASE}-req.pem"
+	USERCERT_PEM="${USER_DIR}/${USERFILE_BASE}-cert.pem"
+	USERCERT_PEM_BASE="${USERFILE_BASE}-cert.pem"
+	USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
+	USERCERT_CER="${USER_DIR}/${USERFILE_BASE}-cert.cer"
+	USERCERT_P12="${USER_DIR}/${USERFILE_BASE}-private.p12"
+
+	ORGANIZATIONAL_UNIT_NAME="Users"
+	COMMON_NAME="${USER_PRINCIPAL_NAME}"
+	EMAIL_ADDRESS="${USER_PRINCIPAL_NAME}"
+
+	DEFAULT_BITS="${USER_BITS}"
+	DEFAULT_DAYS="${USER_DAYS}"
+	DEFAULT_CRL_DAYS="${CRL_DAYS}"
+
+	umask 077
+	mkdir -p "${USER_DIR}/"
+
+	generate_from_template \
+		"openssl-BASE-template.cnf" \
+		"openssl-USER-template.cnf" \
+		"${OPENSSLCNF}" \
+		${DEFAULT_VARS} USER_PRINCIPAL_NAME
+
+	openssl req -new -newkey rsa -keyout "${USERKEY_PEM}" -out "${USERREQ_PEM}" -config "${OPENSSLCNF}"
+	openssl rsa -in "${USERKEY_PEM}" -inform PEM -out "${USERKEY_PRIVATE_PEM}" -outform PEM
+	openssl ca -config "${OPENSSLCNF}" -in "${USERREQ_PEM}" -out "${USERCERT_PEM}"
+	ln -s "${USERKEY_PRIVATE_PEM_BASE}" "${USERKEY_PRIVATE_PEM_LINK}"
+	ln -s "${USERCERT_PEM_BASE}" "${USERCERT_PEM_LINK}"
+	openssl x509 -in "${USERCERT_PEM}"  -inform PEM -out "${USERCERT_CER}" -outform DER
+	echo "Generate ${USERCERT_P12}"
+	openssl pkcs12 -in "${USERCERT_PEM}" -inkey "${USERKEY_PRIVATE_PEM}" -export -out "${USERCERT_P12}"
+	ls -la "${USER_DIR}"/*.*
+	exit 0
+	;;
+revoke_user)
+	test -e "${CA_DIR}" || {
+		echo "CA with CA_DIR[${CA_DIR}] does not exists"
+		exit 1
+	}
+	USER_PRINCIPAL_NAME="${CMDARG1}"
+	check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
+	REVOKE_REASON="${CMDARG2}"
+	check_arg "REVOKE_REASON" "${REVOKE_REASON}"
+
+	USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
+	test -e "${USER_DIR}" || {
+		echo "USER with USER_DIR[${USER_DIR}] does not exists"
+		exit 1
+	}
+
+	OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
+	USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
+	USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
+
+	REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
+	REVOKE_USER_DIR="${USER_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
+
+	openssl ca -config "${OPENSSLCNF}" -revoke "${USERCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
+
+	mv "${USERKEY_PRIVATE_PEM_LINK}" "${USERKEY_PRIVATE_PEM_LINK}.revoked"
+	mv "${USERCERT_PEM_LINK}" "${USERCERT_PEM_LINK}.revoked"
+	mv "${USER_DIR}" "${REVOKE_USER_DIR}.revoked"
+	echo "${REVOKE_USER_DIR}"
+
+	openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
+	openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
+	ls -la "${CACRL_PEM}" "${CACRL_CRL}"
+	echo "Please run: '${0} ${CNF} publish_crl'"
+	exit 0
+	;;
+usage)
+	print_usage
+	exit 1
+	;;
+*)
+	print_usage
+	echo "ERROR: CMD[${CMD}] - unknown"
+	exit 1
+	;;
+esac
+
+exit 1
diff --git a/selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf b/selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf
new file mode 100644
index 0000000..1f3d24e
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.templates.d/manage-CA-example.com.cnf
@@ -0,0 +1,17 @@
+
+CRL_HTTP_BASE="http://www.example.com/crls"
+CRL_SSH_BASE="www.example.com:/path/to/crls"
+DNS_DOMAIN="example.com"
+
+#CA_BITS="8192"
+#DC_BITS="8192"
+#USER_BITS="8192"
+#CA_DAYS="3650"
+#CRL_DAYS="30"
+#DC_DAYS="730"
+#USER_DAYS="730"
+
+COUNTRY_NAME="US"
+STATE_NAME="ExampleState"
+LOCALITY_NAME="ExampleCity"
+ORGANIZATION_NAME="ExampleOrganization"
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf
new file mode 100644
index 0000000..ca8415b
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.templates.d/openssl-BASE-template.cnf
@@ -0,0 +1,201 @@
+#
+# Based on the OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME            = .
+RANDFILE        = $ENV::HOME/.rnd
+
+#CRLDISTPT       = [CRL Distribution Point; e.g., http://crl-list.base/w4edom-l4.base.crl]
+CRLDISTPT       = @@CRL_HTTP_BASE@@/CA-@@DNS_DOMAIN@@-crl.crl
+
+# Extra OBJECT IDENTIFIER info:
+oid_section     = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions        = 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used as a login credential
+scardLogin=1.3.6.1.4.1.311.20.2.2
+# Used in a smart card login certificate's subject alternative name
+msUPN=1.3.6.1.4.1.311.20.2.3
+# Ordinarily, certificates must have this oid as an enhanced key usage in order for Windows to allow them to be used to identify a domain controller
+msKDC=1.3.6.1.5.2.3.5
+# Identifies the AD GUID
+msADGUID=1.3.6.1.4.1.311.25.1
+
+####################################################################
+[ ca ]
+default_ca  = CA_default        # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir         = @@CA_DIR@@         # Where everything is kept
+certs       = $dir/_none_certs        # Where the issued certs are kept
+crl_dir     = $dir/_none_crl          # Where the issued crl are kept
+database    = $dir/Private/CA-@@DNS_DOMAIN@@-index.txt    # database index file.
+unique_subject  = yes           # Set to 'no' to allow creation of
+                                # several certificates with same subject.
+new_certs_dir   = $dir/NewCerts     # default place for new certs.
+
+certificate = $dir/Public/CA-@@DNS_DOMAIN@@-cert.pem   # The CA certificate
+serial      = $dir/Private/CA-@@DNS_DOMAIN@@-serial.txt       # The current serial number
+crlnumber   = $dir/Private/CA-@@DNS_DOMAIN@@-crlnumber.txt    # the current crl number
+                                # must be commented out to leave a V1 CRL
+
+#crl         = $dir/Public/CA-@@DNS_DOMAIN@@-crl.pem           # The current CRL
+crl         = $dir/Public/CA-@@DNS_DOMAIN@@-crl.crl           # The current CRL
+private_key = $dir/Private/CA-@@DNS_DOMAIN@@-private-key.pem    # The private key
+RANDFILE    = $dir/Private/CA-@@DNS_DOMAIN@@.rand        # private random number file
+
+#x509_extensions    =   # The extensions to add to the cert
+x509_extensions = template_x509_extensions
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt    = ca_default        # Subject Name options
+cert_opt    = ca_default        # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions  = crl_ext
+
+default_days    = @@DEFAULT_DAYS@@           # how long to certify for
+default_crl_days= @@DEFAULT_CRL_DAYS@@            # how long before next CRL
+default_md  = sha256            # use public key default MD
+preserve    = no                # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy      = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName     = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName      = supplied
+emailAddress        = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName     = match
+stateOrProvinceName = match
+localityName        = match
+organizationName    = match
+organizationalUnitName  = match
+commonName      = supplied
+emailAddress        = supplied
+
+####################################################################
+[ req ]
+default_bits        = @@DEFAULT_BITS@@
+distinguished_name  = req_distinguished_name
+attributes      = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix   : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default     = @@COUNTRY_NAME@@
+countryName_min         = 2
+countryName_max         = 2
+
+stateOrProvinceName     = State or Province Name (full name)
+stateOrProvinceName_default = @@STATE_NAME@@
+
+localityName            = Locality Name (eg, city)
+localityName_default    = @@LOCALITY_NAME@@
+
+organizationName        = Organization Name (eg, company)
+organizationName_default    = @@ORGANIZATION_NAME@@
+
+organizationalUnitName      = Organizational Unit Name (eg, section)
+organizationalUnitName_default = @@ORGANIZATIONAL_UNIT_NAME@@
+
+commonName          = Common Name (eg, YOUR name)
+commonName_default  = @@COMMON_NAME@@
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_default    = @@EMAIL_ADDRESS@@
+emailAddress_max        = 64
+
+# SET-ex3           = SET extension number 3
+
+[ req_attributes ]
+#challengePassword       = A challenge password
+#challengePassword_min       = 4
+#challengePassword_max       = 20
+#
+#unstructuredName        = An optional company name
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+# Extensions for a typical CA
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. 
+keyUsage = cRLSign, keyCertSign
+
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Some might want this also
+nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf
new file mode 100644
index 0000000..4c6bb4a
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.templates.d/openssl-CA-template.cnf
@@ -0,0 +1,2 @@
+[ template_x509_extensions ]
+
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf
new file mode 100644
index 0000000..0b0424d
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.templates.d/openssl-DC-template.cnf
@@ -0,0 +1,49 @@
+#[ usr_cert_mskdc ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a domain controller certificate.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+nsCertType          = server
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Domain Controller Certificate @@DC_DNS_NAME@@"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=@dc_subjalt
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for our domain controller certs
+# serverAuth - says cert can be used to identify an ssl/tls server
+# msKDC - says cert can be used to identify a Kerberos Domain Controller.
+extendedKeyUsage = clientAuth,serverAuth,msKDC
+
+[dc_subjalt]
+DNS=@@DC_DNS_NAME@@
+otherName=msADGUID;FORMAT:HEX,OCTETSTRING:@@DC_OBJECTGUID_HEX@@
diff --git a/selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf b/selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf
new file mode 100644
index 0000000..71674b9
--- /dev/null
+++ b/selftest/manage-ca/manage-ca.templates.d/openssl-USER-template.cnf
@@ -0,0 +1,41 @@
+#[ usr_cert_scarduser ]
+[ template_x509_extensions ]
+
+# These extensions are added when 'ca' signs a request for a certificate that will be used to login from a smart card
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+crlDistributionPoints=URI:$CRLDISTPT
+
+# For normal client use this is typical
+nsCertType = client, email
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment           = "Smart Card Login Certificate for @@USER_PRINCIPAL_NAME@@"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+
+subjectAltName=email:copy,otherName:msUPN;UTF8:@@USER_PRINCIPAL_NAME@@
+
+# Copy subject details
+issuerAltName=issuer:copy
+
+nsCaRevocationUrl       = $CRLDISTPT
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+#Extended Key requirements for client certs
+extendedKeyUsage = clientAuth,scardLogin
+
diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index db5da05..f7b7f95 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -27,6 +27,7 @@ use Cwd qw(abs_path);
 use lib "$RealBin";
 use Subunit;
 use SocketWrapper;
+use target::Samba;
 
 eval {
 require Time::HiRes;
@@ -516,6 +517,42 @@ sub write_clientconf($$$)
 	mkdir("$clientdir/ncalrpcdir", 0755);
 	umask $mask;
 
+	my $cadir = "$ENV{SRCDIR_ABS}/selftest/manage-ca/CA-samba.example.com";
+	my $cacert = "$cadir/Public/CA-samba.example.com-cert.pem";
+	my $cacrl_pem = "$cadir/Public/CA-samba.example.com-crl.pem";
+	my $ca_users_dir = "$cadir/Users";
+
+	if ( -d "$clientdir/pkinit" ) {
+	        unlink <$clientdir/pkinit/*>;
+	} else {
+	        mkdir("$clientdir/pkinit", 0700);
+	}
+
+	# each user has a USER-${USER_PRINCIPAL_NAME}-cert.pem and
+	# USER-${USER_PRINCIPAL_NAME}-private-key.pem symlink
+	# We make a copy here and make the certificated easily
+	# accessable in the client environment.
+	my $mask = umask;
+	umask 0077;
+	opendir USERS, "${ca_users_dir}" or die "Could not open dir '${ca_users_dir}': $!";
+	for my $d (readdir USERS) {
+		my $user_dir = "${ca_users_dir}/${d}";
+		next if ${d} =~ /^\./;
+		next if (! -d "${user_dir}");
+		opendir USER, "${user_dir}" or die "Could not open dir '${user_dir}': $!";
+		for my $l (readdir USER) {
+			my $user_link = "${user_dir}/${l}";
+			next if ${l} =~ /^\./;
+			next if (! -l "${user_link}");
+
+			my $dest = "${clientdir}/pkinit/${l}";
+			Samba::copy_file_content(${user_link}, ${dest});
+		}
+		closedir USER;
+	}
+	closedir USERS;
+	umask $mask;
+
 	open(CF, ">$conffile");
 	print CF "[global]\n";
 	print CF "\tnetbios name = client\n";
@@ -547,6 +584,9 @@ sub write_clientconf($$$)
 #We don't want to run 'speed' tests for very long
         torture:timelimit = 1
         winbind separator = /
+	tls cafile = ${cacert}
+	tls crlfile = ${cacrl_pem}
+	tls verify peer = no_check
 ";
 	close(CF);
 }
diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index 9937203..e87acd3 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -71,6 +71,111 @@ sub nss_wrapper_winbind_so_path($) {
 	return $ret;
 }
 
+sub copy_file_content($$)
+{
+	my ($in, $out) = @_;
+	open(IN, "${in}") or die("failed to open in[${in}] for reading: $!");
+	open(OUT, ">${out}") or die("failed to open out[${out}] for writing: $!");
+	while(<IN>) {
+		print OUT $_;
+	}
+	close(OUT);
+	close(IN);
+}
+
+sub prepare_keyblobs($)
+{
+	my ($ctx) = @_;
+
+	my $cadir = "$ENV{SRCDIR_ABS}/selftest/manage-ca/CA-samba.example.com";
+	my $cacert = "$cadir/Public/CA-samba.example.com-cert.pem";
+	my $cacrl_pem = "$cadir/Public/CA-samba.example.com-crl.pem";
+	my $dcdnsname = "$ctx->{hostname}.$ctx->{dnsname}";
+	my $dcdir = "$cadir/DCs/$dcdnsname";
+	my $dccert = "$dcdir/DC-$dcdnsname-cert.pem";
+	my $dckey_private = "$dcdir/DC-$dcdnsname-private-key.pem";
+	my $userprincipalname = "administrator\@$ctx->{dnsname}";
+	my $userdir = "$cadir/Users/$userprincipalname";
+	my $usercert = "$userdir/USER-$userprincipalname-cert.pem";
+	my $userkey_private = "$userdir/USER-$userprincipalname-private-key.pem";
+
+	my $tlsdir = "$ctx->{tlsdir}";
+	my $pkinitdir = "$ctx->{prefix_abs}/pkinit";
+	#TLS and PKINIT crypto blobs
+	my $dhfile = "$tlsdir/dhparms.pem";
+	my $cafile = "$tlsdir/ca.pem";
+	my $crlfile = "$tlsdir/crl.pem";
+	my $certfile = "$tlsdir/cert.pem";
+	my $keyfile = "$tlsdir/key.pem";
+	my $usercertfile = "$pkinitdir/USER-$userprincipalname-cert.pem";
+	my $userkeyfile = "$pkinitdir/USER-$userprincipalname-private-key.pem";
+
+	mkdir($tlsdir, 0700);
+	mkdir($pkinitdir, 0700);
+	my $oldumask = umask;
+	umask 0077;
+
+	# This is specified here to avoid draining entropy on every run
+	# generate by
+	# openssl dhparam -out dhparms.pem -text -2 8192
+	open(DHFILE, ">$dhfile");
+	print DHFILE <<EOF;
+-----BEGIN DH PARAMETERS-----
+MIIECAKCBAEAlcpjuJptCzC2bIIApLuyFLw2nODQUztqs/peysY9e3LgWh/xrc87
+SWJNSUrqFJFh2m357WH0XGcTdTk0b/8aIYIWjbwEhWR/5hZ+1x2TDrX1awkYayAe
+pr0arycmWHaAmhw+m+dBdj2O2jRMe7gn0ha85JALNl+Z3wv2q2eys8TIiQ2dbHPx
+XvpMmlAv7QHZnpSpX/XgueQr6T3EYggljppZwk1fe4W2cxBjCv9w/Q83pJXMEVVB
+WESEQPZC38v6hVIXIlF4J7jXjV3+NtCLL4nvsy0jrLEntyKz5OB8sNPRzJr0Ju2Y
+yXORCSMMXMygP+dxJtQ6txzQYWyaCYN1HqHDZy3cFL9Qy8kTFqIcW56Lti2GsW/p
+jSMzEOa1NevhKNFL3dSZJx5m+5ZeMvWXlCqXSptmVdbs5wz5jkMUm/E6pVfM5lyb
+Ttlcq2iYPqnJz1jcL5xwhoufID8zSJCPJ7C0jb0Ngy5wLIUZfjXJUXxUyxTnNR9i
+N9Sc+UkDvLxnCW+qzjyPXGlQU1SsJwMLWa2ZecL/uYE4bOdcN3g+5WHkevyDnXqR
++yy9x7sGXjBT3bRWK5tVHJWOi6eBu1hp39U6aK8oOJWiUt3vmC2qEdIsT6JaLNNi
+YKrSfRGBf19IJBaagen1S19bb3dnmwoU1RaWM0EeJQW1oXOBg7zLisB2yuu5azBn
+tse00+0nc+GbH2y+jP0sE7xil1QeilZl+aQ3tX9vL0cnCa+8602kXxU7P5HaX2+d
+05pvoHmeZbDV85io36oF976gBYeYN+qAkTUMsIZhuLQDuyn0963XOLyn1Pm6SBrU
+OkIZXW7WoKEuO/YSfizUIqXwmAMJjnEMJCWG51MZZKx//9Hsdp1RXSm/bRSbvXB7
+MscjvQYWmfCFnIk8LYnEt3Yey40srEiS9xyZqdrvobxz+sU1XcqR38kpVf4gKASL
+xURia64s4emuJF+YHIObyydazQ+6/wX/C+m+nyfhuxSO6j1janPwtYbU+Uj3TzeM
+04K1mpPQpZcaMdZZiNiu7i8VJlOPKAz7aJT8TnMMF5GMyzyLpSMpc+NF9L/BSocV
+/cUM4wQT2PTHrcyYzmTVH7c9bzBkuxqrwVB1BY1jitDV9LIYIVBglKcX88qrfHIM
+XiXPAIwGclD59qm2cG8OdM9NA5pNMI119KuUAIJsUdgPbR1LkT2XTT15YVoHmFSQ
+DlaWOXn4td031jr0EisX8QtFR7+/0Nfoni6ydFGs5fNH/L1ckq6FEO4OhgucJw9H
+YRmiFlsQBQNny78vNchwZne3ZixkShtGW0hWDdi2n+h7St1peNJCNJjMbEhRsPRx
+RmNGWh4AL8rho4RO9OBao0MnUdjbbffD+wIBAg==
+-----END DH PARAMETERS-----
+EOF
+	close(DHFILE);
+
+	if (! -e ${dckey_private}) {
+		umask $oldumask;
+		return;
+	}
+
+	copy_file_content(${cacert}, ${cafile});
+	copy_file_content(${cacrl_pem}, ${crlfile});
+	copy_file_content(${dccert}, ${certfile});
+	copy_file_content(${dckey_private}, ${keyfile});
+	if (-e ${userkey_private}) {
+		copy_file_content(${usercert}, ${usercertfile});
+		copy_file_content(${userkey_private}, ${userkeyfile});
+	}
+
+	# COMPAT stuff to be removed in a later commit
+	my $kdccertfile = "$tlsdir/kdc.pem";
+	copy_file_content(${dccert}, ${kdccertfile});
+	if (-e ${userkey_private}) {
+		my $adminkeyfile = "$tlsdir/adminkey.pem";
+		my $admincertfile = "$tlsdir/admincert.pem";
+		my $admincertupnfile = "$tlsdir/admincertupn.pem";
+		copy_file_content(${userkey_private}, ${adminkeyfile});
+		copy_file_content(${usercert}, ${admincertfile});
+		copy_file_content(${usercert}, ${admincertupnfile});
+	}
+
+	umask $oldumask;
+}
+
 sub mk_krb5_conf($$)
 {
 	my ($ctx) = @_;
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index d16c440..24a9e24 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -213,6 +213,7 @@ sub setup_nt4_dc($$)
 	domain master = yes
 	domain logons = yes
 	lanman auth = yes
+	raw NTLMv2 auth = yes
 
 	rpc_server:epmapper = external
 	rpc_server:spoolss = external
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 65308e2..f8db618 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -257,219 +257,6 @@ sub mk_openldap($$)
 	return ($slapd_conf_d, $pidfile);
 }
 
-sub mk_keyblobs($$)
-{
-	my ($self, $tlsdir) = @_;
-
-	#TLS and PKINIT crypto blobs
-	my $dhfile = "$tlsdir/dhparms.pem";
-	my $cafile = "$tlsdir/ca.pem";
-	my $certfile = "$tlsdir/cert.pem";
-	my $reqkdc = "$tlsdir/req-kdc.der";
-	my $kdccertfile = "$tlsdir/kdc.pem";
-	my $keyfile = "$tlsdir/key.pem";
-	my $adminkeyfile = "$tlsdir/adminkey.pem";
-	my $reqadmin = "$tlsdir/req-admin.der";
-	my $admincertfile = "$tlsdir/admincert.pem";
-	my $admincertupnfile = "$tlsdir/admincertupn.pem";
-
-	mkdir($tlsdir, 0700);
-	my $oldumask = umask;
-	umask 0077;
-
-	#This is specified here to avoid draining entropy on every run
-	open(DHFILE, ">$dhfile");
-	print DHFILE <<EOF;
------BEGIN DH PARAMETERS-----
-MGYCYQC/eWD2xkb7uELmqLi+ygPMKyVcpHUo2yCluwnbPutEueuxrG/Cys8j8wLO
-svCN/jYNyR2NszOmg7ZWcOC/4z/4pWDVPUZr8qrkhj5MRKJc52MncfaDglvEdJrv
-YX70obsCAQI=
------END DH PARAMETERS-----
-EOF
-	close(DHFILE);
-
-	#Likewise, we pregenerate the key material.  This allows the
-	#other certificates to be pre-generated
-	open(KEYFILE, ">$keyfile");
-	print KEYFILE <<EOF;
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpc
-ol3+S9/6I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H
-6H+pPqVIRLOmrWImai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQAB
-AoGAAqDLzFRR/BF1kpsiUfL4WFvTarCe9duhwj7ORc6fs785qAXuwUYAJ0Uvzmy6
-HqoGv3t3RfmeHDmjcpPHsbOKnsOQn2MgmthidQlPBMWtQMff5zdoYNUFiPS0XQBq
-szNW4PRjaA9KkLQVTwnzdXGkBSkn/nGxkaVu7OR3vJOBoo0CQQDO4upypesnbe6p
-9/xqfZ2uim8IwV1fLlFClV7WlCaER8tsQF4lEi0XSzRdXGUD/dilpY88Nb+xok/X
-8Z8OvgAXAkEA+pcLsx1gN7kxnARxv54jdzQjC31uesJgMKQXjJ0h75aUZwTNHmZQ
-vPxi6u62YiObrN5oivkixwFNncT9MxTxVQJBAMaWUm2SjlLe10UX4Zdm1MEB6OsC
-kVoX37CGKO7YbtBzCfTzJGt5Mwc1DSLA2cYnGJqIfSFShptALlwedot0HikCQAJu
-jNKEKnbf+TdGY8Q0SKvTebOW2Aeg80YFkaTvsXCdyXrmdQcifw4WdO9KucJiDhSz
-Y9hVapz7ykEJtFtWjLECQQDIlfc63I5ZpXfg4/nN4IJXUW6AmPVOYIA5215itgki
-cSlMYli1H9MEXH0pQMGv5Qyd0OYIx2DDg96mZ+aFvqSG
------END RSA PRIVATE KEY-----
-EOF
-	close(KEYFILE);
-
-	open(ADMINKEYFILE, ">$adminkeyfile");
-
-	print ADMINKEYFILE <<EOF;
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQD0+OL7TQBj0RejbIH1+g5GeRaWaM9xF43uE5y7jUHEsi5owhZF
-5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMFxB6esnXhl0Jpip1JkUMM
-XLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xdl3JRlwIDAQAB
-AoGAP8mjCP628Ebc2eACQzOWjgEvwYCPK4qPmYOf1zJkArzG2t5XAGJ5WGrENRuB
-cm3XFh1lpmaADl982UdW3gul4gXUy6w4XjKK4vVfhyHj0kZ/LgaXUK9BAGhroJ2L
-osIOUsaC6jdx9EwSRctwdlF3wWJ8NK0g28AkvIk+FlolW4ECQQD7w5ouCDnf58CN
-u4nARx4xv5XJXekBvOomkCQAmuOsdOb6b9wn3mm2E3au9fueITjb3soMR31AF6O4
-eAY126rXAkEA+RgHzybzZEP8jCuznMqoN2fq/Vrs6+W3M8/G9mzGEMgLLpaf2Jiz
-I9tLZ0+OFk9tkRaoCHPfUOCrVWJZ7Y53QQJBAMhoA6rw0WDyUcyApD5yXg6rusf4
-ASpo/tqDkqUIpoL464Qe1tjFqtBM3gSXuhs9xsz+o0bzATirmJ+WqxrkKTECQHt2
-OLCpKqwAspU7N+w32kaUADoRLisCEdrhWklbwpQgwsIVsCaoEOpt0CLloJRYTANE
-yoZeAErTALjyZYZEPcECQQDlUi0N8DFxQ/lOwWyR3Hailft+mPqoPCa8QHlQZnlG
-+cfgNl57YHMTZFwgUVFRdJNpjH/WdZ5QxDcIVli0q+Ko
------END RSA PRIVATE KEY-----
-EOF
-
-	#generated with
-	# hxtool issue-certificate --self-signed --issue-ca \
-	# --ca-private-key="FILE:$KEYFILE" \
-	# --subject="CN=CA,DC=samba,DC=example,DC=com" \
-	# --certificate="FILE:$CAFILE" --lifetime="25 years"
-
-	open(CAFILE, ">$cafile");
-	print CAFILE <<EOF;
------BEGIN CERTIFICATE-----
-MIICcTCCAdqgAwIBAgIUaBPmjnPVqyFqR5foICmLmikJTzgwCwYJKoZIhvcNAQEFMFIxEzAR
-BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDgwMzAxMTIyMzEyWhgPMjAzMzAyMjQx
-MjIzMTJaMFIxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
-MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMIGfMA0GCSqGSIb3DQEBAQUA
-A4GNADCBiQKBgQDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpcol3+S9/6
-I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H6H+pPqVIRLOmrWIm
-ai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
-AaYwHQYDVR0OBBYEFMLZufegDKLZs0VOyFXYK1L6M8oyMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADgYEAAZJbCAAkaqgFJ0xgNovn8Ydd0KswQPjicwiODPgw9ZPoD2HiOUVO
-yYDRg/dhFF9y656OpcHk4N7qZ2sl3RlHkzDu+dseETW+CnKvQIoXNyeARRJSsSlwrwcoD4JR
-HTLk2sGigsWwrJ2N99sG/cqSJLJ1MFwLrs6koweBnYU0f/g=
------END CERTIFICATE-----
-EOF
-
-	#generated with GNUTLS internally in Samba.
-
-	open(CERTFILE, ">$certfile");
-	print CERTFILE <<EOF;
------BEGIN CERTIFICATE-----
-MIICYTCCAcygAwIBAgIE5M7SRDALBgkqhkiG9w0BAQUwZTEdMBsGA1UEChMUU2Ft
-YmEgQWRtaW5pc3RyYXRpb24xNDAyBgNVBAsTK1NhbWJhIC0gdGVtcG9yYXJ5IGF1
-dG9nZW5lcmF0ZWQgY2VydGlmaWNhdGUxDjAMBgNVBAMTBVNhbWJhMB4XDTA2MDgw
-NDA0MzY1MloXDTA4MDcwNDA0MzY1MlowZTEdMBsGA1UEChMUU2FtYmEgQWRtaW5p
-c3RyYXRpb24xNDAyBgNVBAsTK1NhbWJhIC0gdGVtcG9yYXJ5IGF1dG9nZW5lcmF0
-ZWQgY2VydGlmaWNhdGUxDjAMBgNVBAMTBVNhbWJhMIGcMAsGCSqGSIb3DQEBAQOB
-jAAwgYgCgYDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpcol3+
-S9/6I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H6H+p
-PqVIRLOmrWImai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABoyUw
-IzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAsGCSqGSIb3DQEB
-BQOBgQAmkN6XxvDnoMkGcWLCTwzxGfNNSVcYr7TtL2aJh285Xw9zaxcm/SAZBFyG
-LYOChvh6hPU7joMdDwGfbiLrBnMag+BtGlmPLWwp/Kt1wNmrRhduyTQFhN3PP6fz
-nBr9vVny2FewB2gHmelaPS//tXdxivSXKz3NFqqXLDJjq7P8wA==
------END CERTIFICATE-----
-EOF
-	close(CERTFILE);
-
-	#KDC certificate
-	# hxtool request-create \
-	# --subject="CN=krbtgt,CN=users,DC=samba,DC=example,DC=com" \
-	# --key="FILE:$KEYFILE" $KDCREQ
-
-	# hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE \
-	# --type="pkinit-kdc" \
-	# --pk-init-principal="krbtgt/SAMBA.EXAMPLE.COM at SAMBA.EXAMPLE.COM" \
-	# --req="PKCS10:$KDCREQ" --certificate="FILE:$KDCCERTFILE" \
-	# --lifetime="25 years"
-
-	open(KDCCERTFILE, ">$kdccertfile");
-	print KDCCERTFILE <<EOF;
------BEGIN CERTIFICATE-----
-MIIDDDCCAnWgAwIBAgIUI2Tzj+JnMzMcdeabcNo30rovzFAwCwYJKoZIhvcNAQEFMFIxEzAR
-BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDgwMzAxMTMxOTIzWhgPMjAzMzAyMjQx
-MzE5MjNaMGYxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
-MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMQ8wDQYDVQQDDAZrcmJ0
-Z3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMqDqkDAIdQwDUN8cOZaFl934XQL70nF
-yq+nD2KL0SfcTW5+WlyiXf5L3/oj+5pOYkdmt74MXd1PNv9Q5mjRl6bw34jPOSCgaQVp+Ne5
-PcEvlQ9jb8fof6k+pUhEs6atYiZqLfn1jKgqEXKjftjoc95TxBxn67atL2B5qkhZ966jAgMB
-AAGjgcgwgcUwDgYDVR0PAQH/BAQDAgWgMBIGA1UdJQQLMAkGBysGAQUCAwUwVAYDVR0RBE0w
-S6BJBgYrBgEFAgKgPzA9oBMbEVNBTUJBLkVYQU1QTEUuQ09NoSYwJKADAgEBoR0wGxsGa3Ji
-dGd0GxFTQU1CQS5FWEFNUExFLkNPTTAfBgNVHSMEGDAWgBTC2bn3oAyi2bNFTshV2CtS+jPK
-MjAdBgNVHQ4EFgQUwtm596AMotmzRU7IVdgrUvozyjIwCQYDVR0TBAIwADANBgkqhkiG9w0B
-AQUFAAOBgQBmrVD5MCmZjfHp1nEnHqTIh8r7lSmVtDx4s9MMjxm9oNrzbKXynvdhwQYFVarc
-ge4yRRDXtSebErOl71zVJI9CVeQQpwcH+tA85oGA7oeFtO/S7ls581RUU6tGgyxV4veD+lJv
-KPH5LevUtgD+q9H4LU4Sq5N3iFwBaeryB0g2wg==
------END CERTIFICATE-----
-EOF
-
-	# hxtool request-create \
-	# --subject="CN=Administrator,CN=users,DC=samba,DC=example,DC=com" \
-	# --key="FILE:$ADMINKEYFILE" $ADMINREQFILE
-
-	# hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE \
-	# --type="pkinit-client" \
-	# --pk-init-principal="administrator at SAMBA.EXAMPLE.COM" \
-	# --req="PKCS10:$ADMINREQFILE" --certificate="FILE:$ADMINCERTFILE" \
-	# --lifetime="25 years"
-	
-	open(ADMINCERTFILE, ">$admincertfile");
-	print ADMINCERTFILE <<EOF;
------BEGIN CERTIFICATE-----
-MIIDHTCCAoagAwIBAgIUUggzW4lLRkMKe1DAR2NKatkMDYwwCwYJKoZIhvcNAQELMFIxEzAR
-BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDkwNzI3MDMzMjE1WhgPMjAzNDA3MjIw
-MzMyMTVaMG0xEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
-MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMRYwFAYDVQQDDA1BZG1p
-bmlzdHJhdG9yMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0+OL7TQBj0RejbIH1+g5G
-eRaWaM9xF43uE5y7jUHEsi5owhZF5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMF
-xB6esnXhl0Jpip1JkUMMXLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xd
-l3JRlwIDAQABo4HSMIHPMA4GA1UdDwEB/wQEAwIFoDAoBgNVHSUEITAfBgcrBgEFAgMEBggr
-BgEFBQcDAgYKKwYBBAGCNxQCAjBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgExsRU0FNQkEu
-RVhBTVBMRS5DT02hGjAYoAMCAQGhETAPGw1BZG1pbmlzdHJhdG9yMB8GA1UdIwQYMBaAFMLZ
-ufegDKLZs0VOyFXYK1L6M8oyMB0GA1UdDgQWBBQg81bLyfCA88C2B/BDjXlGuaFaxjAJBgNV
-HRMEAjAAMA0GCSqGSIb3DQEBCwUAA4GBAEf/OSHUDJaGdtWGNuJeqcVYVMwrfBAc0OSwVhz1
-7/xqKHWo8wIMPkYRtaRHKLNDsF8GkhQPCpVsa6mX/Nt7YQnNvwd+1SBP5E8GvwWw9ZzLJvma
-nk2n89emuayLpVtp00PymrDLRBcNaRjFReQU8f0o509kiVPHduAp3jOiy13l
------END CERTIFICATE-----
-EOF
-	close(ADMINCERTFILE);
-
-	# hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE \
-	# --type="pkinit-client" \
-	# --ms-upn="administrator at samba.example.com" \
-	# --req="PKCS10:$ADMINREQFILE" --certificate="FILE:$ADMINCERTUPNFILE" \
-	# --lifetime="25 years"
-	
-	open(ADMINCERTUPNFILE, ">$admincertupnfile");
-	print ADMINCERTUPNFILE <<EOF;
------BEGIN CERTIFICATE-----
-MIIDDzCCAnigAwIBAgIUUp3CJMuNaEaAdPKp3QdNIwG7a4wwCwYJKoZIhvcNAQELMFIxEzAR
-BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy
-LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDkwNzI3MDMzMzA1WhgPMjAzNDA3MjIw
-MzMzMDVaMG0xEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl
-MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMRYwFAYDVQQDDA1BZG1p
-bmlzdHJhdG9yMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0+OL7TQBj0RejbIH1+g5G
-eRaWaM9xF43uE5y7jUHEsi5owhZF5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMF
-xB6esnXhl0Jpip1JkUMMXLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xd
-l3JRlwIDAQABo4HEMIHBMA4GA1UdDwEB/wQEAwIFoDAoBgNVHSUEITAfBgcrBgEFAgMEBggr
-BgEFBQcDAgYKKwYBBAGCNxQCAjA6BgNVHREEMzAxoC8GCisGAQQBgjcUAgOgIQwfYWRtaW5p
-c3RyYXRvckBzYW1iYS5leGFtcGxlLmNvbTAfBgNVHSMEGDAWgBTC2bn3oAyi2bNFTshV2CtS
-+jPKMjAdBgNVHQ4EFgQUIPNWy8nwgPPAtgfwQ415RrmhWsYwCQYDVR0TBAIwADANBgkqhkiG
-9w0BAQsFAAOBgQBk42+egeUB3Ji2PC55fbt3FNKxvmm2xUUFkV9POK/YR9rajKOwk5jtYSeS
-Zd7J9s//rNFNa7waklFkDaY56+QWTFtdvxfE+KoHaqt6X8u6pqi7p3M4wDKQox+9Dx8yWFyq
-Wfz/8alZ5aMezCQzXJyIaJsCLeKABosSwHcpAFmxlQ==
------END CERTIFICATE-----
-EOF
-
-	umask $oldumask;
-}
-
 sub setup_namespaces($$:$$)
 {
 	my ($self, $localenv, $upn_array, $spn_array) = @_;
@@ -712,6 +499,11 @@ sub provision_raw_step1($$)
 		warn("can't open $ctx->{smb_conf}$?");
 		return undef;
 	}
+
+	Samba::prepare_keyblobs($ctx);
+	my $crlfile = "$ctx->{tlsdir}/crl.pem";
+	$crlfile = "" unless -e ${crlfile};
+
 	print CONFFILE "
 [global]
 	netbios name = $ctx->{netbiosname}
@@ -730,6 +522,8 @@ sub provision_raw_step1($$)
 	winbind separator = /
 	interfaces = $ctx->{interfaces}
 	tls dh params file = $ctx->{tlsdir}/dhparms.pem
+	tls crlfile = ${crlfile}
+	tls verify peer = no_check
 	panic action = $RealBin/gdb_backtrace \%d
 	wins support = yes
 	server role = $ctx->{server_role}
@@ -737,6 +531,7 @@ sub provision_raw_step1($$)
         dcerpc endpoint servers = +winreg +srvsvc
 	notify:inotify = false
 	ldb:nosync = true
+	ldap server require strong auth = yes
 #We don't want to pass our self-tests if the PAC code is wrong
 	gensec:require_pac = true
 	log file = $ctx->{logdir}/log.\%m
@@ -767,8 +562,6 @@ sub provision_raw_step1($$)
 ";
 	close(CONFFILE);
 
-	$self->mk_keyblobs($ctx->{tlsdir});
-
         #Default the KDC IP to the server's IP
 	if (not defined($ctx->{kdc_ipv4})) {
 		$ctx->{kdc_ipv4} = $ctx->{ipv4};
@@ -1528,7 +1321,9 @@ sub provision_ad_dc_ntvfs($$)
 
 	print "PROVISIONING AD DC (NTVFS)...";
         my $extra_conf_options = "netbios aliases = localDC1-a
-        server services = +winbind -winbindd";
+        server services = +winbind -winbindd
+	ldap server require strong auth = allow_sasl_over_tls
+	";
 	my $ret = $self->provision($prefix,
 				   "domain controller",
 				   "localdc",
@@ -1646,6 +1441,7 @@ sub provision_fl2008r2dc($$$)
 	my ($self, $prefix, $dcvars) = @_;
 
 	print "PROVISIONING DC WITH FOREST LEVEL 2008r2...";
+        my $extra_conf_options = "ldap server require strong auth = no";
 	my $ret = $self->provision($prefix,
 				   "domain controller",
 				   "dc7",
@@ -1655,7 +1451,7 @@ sub provision_fl2008r2dc($$$)
 				   "locDCpass7",
 				   undef,
 				   undef,
-				   "",
+				   $extra_conf_options,
 				   "",
 				   undef);
 
@@ -1864,7 +1660,7 @@ sub provision_ad_dc($$)
 				   "domain controller",
 				   "addc",
 				   "ADDOMAIN",
-				   "addc.samba.example.com",
+				   "addom.samba.example.com",
 				   "2008",
 				   "locDCpass1",
 				   undef,
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 0dc6657..1a8cd91 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -89,7 +89,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
 
 	/* Attempt connection */
 	result = cli_full_connection(&cli, lp_netbios_name(), dc_name, dc_ss, 0,
-		"IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT);
+		"IPC$", "IPC", "", "", "", 0, SMB_SIGNING_IPC_DEFAULT);
 
 	if (!NT_STATUS_IS_OK(result)) {
 		/* map to something more useful */
diff --git a/source3/auth/auth_samba4.c b/source3/auth/auth_samba4.c
index 0a80d17..4f37fea 100644
--- a/source3/auth/auth_samba4.c
+++ b/source3/auth/auth_samba4.c
@@ -245,8 +245,8 @@ static NTSTATUS prepare_gensec(const struct auth_context *auth_context,
 	status = cli_credentials_set_machine_account(server_credentials, lp_ctx);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
-		talloc_free(server_credentials);
-		server_credentials = NULL;
+		TALLOC_FREE(frame);
+		return status;
 	}
 
 	status = samba_server_gensec_start(mem_ctx,
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index b079d04..c23de7e 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -34,6 +34,7 @@
 #include "../auth/auth_sam_reply.h"
 #include "../librpc/gen_ndr/idmap.h"
 #include "lib/param/loadparm.h"
+#include "../lib/tsocket/tsocket.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -353,6 +354,20 @@ NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
 				      const struct tsocket_address *remote_address,
                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
 {
+	bool allow_raw = lp_raw_ntlmv2_auth();
+
+	if (!allow_raw && nt_resp.length >= 48) {
+		/*
+		 * NTLMv2_RESPONSE has at least 48 bytes
+		 * and should only be supported via NTLMSSP.
+		 */
+		DEBUG(2,("Rejecting raw NTLMv2 authentication with "
+			 "user [%s\\%s] from[%s]\n",
+			 client_domain, smb_name,
+			 tsocket_address_string(remote_address, mem_ctx)));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	return make_user_info(mem_ctx,
 			      user_info, smb_name, smb_name,
 			      client_domain, client_domain, 
diff --git a/source3/include/auth_generic.h b/source3/include/auth_generic.h
index 07df62a..0911182 100644
--- a/source3/include/auth_generic.h
+++ b/source3/include/auth_generic.h
@@ -42,11 +42,12 @@ NTSTATUS auth_generic_set_creds(struct auth_generic_state *ans,
 NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx,
 				     struct auth_generic_state **_ans);
 NTSTATUS auth_generic_client_start(struct auth_generic_state *ans, const char *oid);
-
+NTSTATUS auth_generic_client_start_by_name(struct auth_generic_state *ans,
+					   const char *name);
 NTSTATUS auth_generic_client_start_by_authtype(struct auth_generic_state *ans,
 					       uint8_t auth_type,
 					       uint8_t auth_level);
-
-extern const struct gensec_security_ops gensec_ntlmssp3_client_ops;
+NTSTATUS auth_generic_client_start_by_sasl(struct auth_generic_state *ans,
+					   const char **sasl_list);
 
 #endif /* _AUTH_GENERIC_ */
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 4b86db0..88be15a 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -729,13 +729,6 @@ bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx,
 			 struct in_addr **pservers, int *pnum_servers);
 unsigned wins_srv_count_tag(const char *tag);
 
-/* The following definitions come from libsmb/clispnego.c  */
-
-DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
-				  const char *OIDs[],
-				  DATA_BLOB *psecblob,
-				  const char *principal);
-
 #ifndef ASN1_MAX_OIDS
 #define ASN1_MAX_OIDS 20
 #endif
@@ -745,18 +738,6 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 			       char **principal,
 			       DATA_BLOB *secblob);
 DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8_t tok_id[2]);
-int spnego_gen_krb5_negTokenInit(TALLOC_CTX *ctx,
-			    const char *principal, int time_offset,
-			    DATA_BLOB *targ,
-			    DATA_BLOB *session_key_krb5, uint32_t extra_ap_opts,
-			    const char *ccname, time_t *expire_time);
-bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
-			    DATA_BLOB *chal1, DATA_BLOB *chal2);
-DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob);
-bool spnego_parse_auth_response(TALLOC_CTX *ctx,
-				DATA_BLOB blob, NTSTATUS nt_status,
-				const char *mechOID,
-				DATA_BLOB *auth);
 
 /* The following definitions come from libsmb/conncache.c  */
 
@@ -899,31 +880,6 @@ bool get_dc_name(const char *domain,
 		fstring srv_name,
 		struct sockaddr_storage *ss_out);
 
-/* The following definitions come from libsmb/ntlmssp.c  */
-struct ntlmssp_state;
-NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user) ;
-NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password) ;
-NTSTATUS ntlmssp_set_password_hash(struct ntlmssp_state *ntlmssp_state,
-				   const char *hash);
-NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain) ;
-void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list);
-void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature);
-NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
-			const DATA_BLOB in, DATA_BLOB *out) ;
-bool ntlmssp_is_anonymous(struct ntlmssp_state *ntlmssp_state);
-NTSTATUS ntlmssp_server_start(TALLOC_CTX *mem_ctx,
-			      bool is_standalone,
-			      const char *netbios_name,
-			      const char *netbios_domain,
-			      const char *dns_name,
-			      const char *dns_domain,
-			      struct ntlmssp_state **ntlmssp_state);
-NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
-			      const char *netbios_name,
-			      const char *netbios_domain,
-			      bool use_ntlmv2,
-			      struct ntlmssp_state **_ntlmssp_state);
-
 /* The following definitions come from libsmb/passchange.c  */
 
 NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
@@ -984,7 +940,9 @@ const char *lp_idmap_backend(const char *domain_name);
 const char *lp_idmap_default_backend (void);
 int lp_security(void);
 int lp_client_max_protocol(void);
-int lp_winbindd_max_protocol(void);
+int lp_client_ipc_min_protocol(void);
+int lp_client_ipc_max_protocol(void);
+int lp_client_ipc_signing(void);
 int lp_smb2_max_credits(void);
 int lp_cups_encrypt(void);
 bool lp_widelinks(int );
diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c
index 0e05af8..37632af 100644
--- a/source3/lib/netapi/cm.c
+++ b/source3/lib/netapi/cm.c
@@ -88,7 +88,7 @@ static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
 	if (!auth_info) {
 		return WERR_NOMEM;
 	}
-	auth_info->signing_state = SMB_SIGNING_DEFAULT;
+	auth_info->signing_state = SMB_SIGNING_IPC_DEFAULT;
 	set_cmdline_auth_info_use_kerberos(auth_info, ctx->use_kerberos);
 	set_cmdline_auth_info_username(auth_info, ctx->username);
 	if (ctx->password) {
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index 5d3773e..17238a5 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -1315,7 +1315,7 @@ done:
 	}
 	s++;
 
-	if (data->has_error) {
+	if (asn1_has_error(data)) {
 		return false;
 	}
 
@@ -1529,7 +1529,7 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 		if (!asn1_write_OctetString(data, uval, uval_len)) return false;
 	}
 
-	if (data->has_error) {
+	if (asn1_has_error(data)) {
 		return false;
 	}
 	return asn1_pop_tag(data);
@@ -2019,7 +2019,7 @@ static bool tldap_decode_controls(struct tldap_req_state *state)
 
 		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto out;
 		if (!asn1_read_OctetString_talloc(msg, data, &oid)) goto out;
-		if ((data->has_error) || (oid == NULL)) {
+		if (asn1_has_error(data) || (oid == NULL)) {
 			goto out;
 		}
 		c->oid = oid;
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 224d992..1399f41 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -66,7 +66,6 @@ bool ads_sitename_match(ADS_STRUCT *ads);
 bool ads_closest_dc(ADS_STRUCT *ads);
 ADS_STATUS ads_connect(ADS_STRUCT *ads);
 ADS_STATUS ads_connect_user_creds(ADS_STRUCT *ads);
-ADS_STATUS ads_connect_gc(ADS_STRUCT *ads);
 void ads_disconnect(ADS_STRUCT *ads);
 ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
 				int scope, const char *expr, const char **attrs,
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 2e38df1..bc6c060 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -552,140 +552,6 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 		  c_realm, c_domain, nt_errstr(status)));
 	return status;
 }
-
-/*********************************************************************
- *********************************************************************/
-
-static NTSTATUS ads_lookup_site(void)
-{
-	ADS_STRUCT *ads = NULL;
-	ADS_STATUS ads_status;
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
-	ads = ads_init(lp_realm(), NULL, NULL);
-	if (!ads) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	/* The NO_BIND here will find a DC and set the client site
-	   but not establish the TCP connection */
-
-	ads->auth.flags = ADS_AUTH_NO_BIND;
-	ads_status = ads_connect(ads);
-	if (!ADS_ERR_OK(ads_status)) {
-		DEBUG(4, ("ads_lookup_site: ads_connect to our realm failed! (%s)\n",
-			  ads_errstr(ads_status)));
-	}
-	nt_status = ads_ntstatus(ads_status);
-
-	if (ads) {
-		ads_destroy(&ads);
-	}
-
-	return nt_status;
-}
-
-/*********************************************************************
- *********************************************************************/
-
-static const char* host_dns_domain(const char *fqdn)
-{
-	const char *p = fqdn;
-
-	/* go to next char following '.' */
-
-	if ((p = strchr_m(fqdn, '.')) != NULL) {
-		p++;
-	}
-
-	return p;
-}
-
-
-/**
- * Connect to the Global Catalog server
- * @param ads Pointer to an existing ADS_STRUCT
- * @return status of connection
- *
- * Simple wrapper around ads_connect() that fills in the
- * GC ldap server information
- **/
-
-ADS_STATUS ads_connect_gc(ADS_STRUCT *ads)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct dns_rr_srv *gcs_list;
-	int num_gcs;
-	const char *realm = ads->server.realm;
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-	ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
-	int i;
-	bool done = false;
-	char *sitename = NULL;
-
-	if (!realm)
-		realm = lp_realm();
-
-	if ((sitename = sitename_fetch(frame, realm)) == NULL) {
-		ads_lookup_site();
-		sitename = sitename_fetch(frame, realm);
-	}
-
-	do {
-		/* We try once with a sitename and once without
-		   (unless we don't have a sitename and then we're
-		   done */
-
-		if (sitename == NULL)
-			done = true;
-
-		nt_status = ads_dns_query_gcs(frame,
-					      realm,
-					      sitename,
-					      &gcs_list,
-					      &num_gcs);
-
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			ads_status = ADS_ERROR_NT(nt_status);
-			goto done;
-		}
-
-		/* Loop until we get a successful connection or have gone
-		   through them all.  When connecting a GC server, make sure that
-		   the realm is the server's DNS name and not the forest root */
-
-		for (i=0; i<num_gcs; i++) {
-			ads->server.gc = true;
-			ads->server.ldap_server = SMB_STRDUP(gcs_list[i].hostname);
-			ads->server.realm = SMB_STRDUP(host_dns_domain(ads->server.ldap_server));
-			ads_status = ads_connect(ads);
-			if (ADS_ERR_OK(ads_status)) {
-				/* Reset the bind_dn to "".  A Global Catalog server
-				   may host  multiple domain trees in a forest.
-				   Windows 2003 GC server will accept "" as the search
-				   path to imply search all domain trees in the forest */
-
-				SAFE_FREE(ads->config.bind_path);
-				ads->config.bind_path = SMB_STRDUP("");
-
-
-				goto done;
-			}
-			SAFE_FREE(ads->server.ldap_server);
-			SAFE_FREE(ads->server.realm);
-		}
-
-	        TALLOC_FREE(gcs_list);
-		num_gcs = 0;
-	} while (!done);
-
-done:
-	talloc_destroy(frame);
-
-	return ads_status;
-}
-
-
 /**
  * Connect to the LDAP server
  * @param ads Pointer to an existing ADS_STRUCT
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 720ee78..4fcd733 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -19,6 +19,7 @@
 
 #include "includes.h"
 #include "../libcli/auth/spnego.h"
+#include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
 #include "auth_generic.h"
 #include "ads.h"
@@ -28,7 +29,7 @@
 
 #ifdef HAVE_LDAP
 
-static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
+static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
 {
 	struct gensec_security *gensec_security =
 		talloc_get_type_abort(ads->ldap.wrap_private_data,
@@ -46,6 +47,7 @@ static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t
 	}
 
 	if ((ads->ldap.out.size - 4) < wrapped.length) {
+		TALLOC_FREE(frame);
 		return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
 	}
 
@@ -60,7 +62,7 @@ static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t
 	return ADS_SUCCESS;
 }
 
-static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
+static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads)
 {
 	struct gensec_security *gensec_security =
 		talloc_get_type_abort(ads->ldap.wrap_private_data,
@@ -94,7 +96,7 @@ static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
 	return ADS_SUCCESS;
 }
 
-static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
+static void ads_sasl_gensec_disconnect(ADS_STRUCT *ads)
 {
 	struct gensec_security *gensec_security =
 		talloc_get_type_abort(ads->ldap.wrap_private_data,
@@ -106,30 +108,32 @@ static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
 	ads->ldap.wrap_private_data = NULL;
 }
 
-static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
-	.name		= "ntlmssp",
-	.wrap		= ads_sasl_ntlmssp_wrap,
-	.unwrap		= ads_sasl_ntlmssp_unwrap,
-	.disconnect	= ads_sasl_ntlmssp_disconnect
+static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
+	.name		= "gensec",
+	.wrap		= ads_sasl_gensec_wrap,
+	.unwrap		= ads_sasl_gensec_unwrap,
+	.disconnect	= ads_sasl_gensec_disconnect
 };
 
 /* 
-   perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
+   perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
    we fit on one socket??)
 */
-static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
+static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
+				const char *sasl,
+				enum credentials_use_kerberos krb5_state,
+				const char *target_service,
+				const char *target_hostname,
+				const DATA_BLOB server_blob)
 {
-	DATA_BLOB msg1 = data_blob_null;
-	DATA_BLOB blob = data_blob_null;
 	DATA_BLOB blob_in = data_blob_null;
 	DATA_BLOB blob_out = data_blob_null;
-	struct berval cred, *scred = NULL;
 	int rc;
 	NTSTATUS nt_status;
 	ADS_STATUS status;
-	int turn = 1;
-
 	struct auth_generic_state *auth_generic_state;
+	bool use_spnego_principal = lp_client_use_spnego_principal();
+	const char *sasl_list[] = { sasl, NULL };
 
 	nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
 	if (!NT_STATUS_IS_OK(nt_status)) {
@@ -146,6 +150,39 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
 		return ADS_ERROR_NT(nt_status);
 	}
 
+	if (server_blob.length == 0) {
+		use_spnego_principal = false;
+	}
+
+	if (krb5_state == CRED_DONT_USE_KERBEROS) {
+		use_spnego_principal = false;
+	}
+
+	cli_credentials_set_kerberos_state(auth_generic_state->credentials,
+					   krb5_state);
+
+	if (target_service != NULL) {
+		nt_status = gensec_set_target_service(
+					auth_generic_state->gensec_security,
+					target_service);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return ADS_ERROR_NT(nt_status);
+		}
+	}
+
+	if (target_hostname != NULL) {
+		nt_status = gensec_set_target_hostname(
+					auth_generic_state->gensec_security,
+					target_hostname);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return ADS_ERROR_NT(nt_status);
+		}
+	}
+
+	if (target_service != NULL && target_hostname != NULL) {
+		use_spnego_principal = false;
+	}
+
 	switch (ads->ldap.wrap_type) {
 	case ADS_SASLWRAP_TYPE_SEAL:
 		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
@@ -157,98 +194,119 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
 		} else {
 			/*
 			 * windows servers are broken with sign only,
-			 * so we need to use seal here too
+			 * so we let the NTLMSSP backend to seal here,
+			 * via GENSEC_FEATURE_LDAP_STYLE.
 			 */
 			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
-			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
-			ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
+			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
 		}
 		break;
 	case ADS_SASLWRAP_TYPE_PLAIN:
 		break;
 	}
 
-	nt_status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
+	nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
+						      sasl_list);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		return ADS_ERROR_NT(nt_status);
 	}
 
-	blob_in = data_blob_null;
+	rc = LDAP_SASL_BIND_IN_PROGRESS;
+	nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+	if (use_spnego_principal) {
+		blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
+		if (blob_in.length == 0) {
+			TALLOC_FREE(auth_generic_state);
+			return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+		}
+	} else {
+		blob_in = data_blob_null;
+	}
+	blob_out = data_blob_null;
+
+	while (true) {
+		struct berval cred, *scred = NULL;
 
-	do {
 		nt_status = gensec_update(auth_generic_state->gensec_security,
 					  talloc_tos(), blob_in, &blob_out);
 		data_blob_free(&blob_in);
-		if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) 
-		     || NT_STATUS_IS_OK(nt_status))
-		    && blob_out.length) {
-			if (turn == 1) {
-				const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
-				/* and wrap it in a SPNEGO wrapper */
-				msg1 = spnego_gen_negTokenInit(talloc_tos(),
-						OIDs_ntlm, &blob_out, NULL);
-			} else {
-				/* wrap it in SPNEGO */
-				msg1 = spnego_gen_auth(talloc_tos(), blob_out);
-			}
-
+		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
+		    && !NT_STATUS_IS_OK(nt_status))
+		{
+			TALLOC_FREE(auth_generic_state);
 			data_blob_free(&blob_out);
+			return ADS_ERROR_NT(nt_status);
+		}
 
-			cred.bv_val = (char *)msg1.data;
-			cred.bv_len = msg1.length;
-			scred = NULL;
-			rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
-			data_blob_free(&msg1);
-			if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
-				if (scred) {
-					ber_bvfree(scred);
-				}
+		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
+			break;
+		}
 
-				TALLOC_FREE(auth_generic_state);
-				return ADS_ERROR(rc);
-			}
+		cred.bv_val = (char *)blob_out.data;
+		cred.bv_len = blob_out.length;
+		scred = NULL;
+		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
+		data_blob_free(&blob_out);
+		if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
 			if (scred) {
-				blob = data_blob(scred->bv_val, scred->bv_len);
 				ber_bvfree(scred);
-			} else {
-				blob = data_blob_null;
 			}
 
+			TALLOC_FREE(auth_generic_state);
+			return ADS_ERROR(rc);
+		}
+		if (scred) {
+			blob_in = data_blob_talloc(talloc_tos(),
+						   scred->bv_val,
+						   scred->bv_len);
+			if (blob_in.length != scred->bv_len) {
+				ber_bvfree(scred);
+				TALLOC_FREE(auth_generic_state);
+				return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+			}
+			ber_bvfree(scred);
 		} else {
+			blob_in = data_blob_null;
+		}
+		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
+			break;
+		}
+	}
+
+	data_blob_free(&blob_in);
+	data_blob_free(&blob_out);
 
+	if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
+		bool ok;
+
+		ok = gensec_have_feature(auth_generic_state->gensec_security,
+					 GENSEC_FEATURE_SEAL);
+		if (!ok) {
+			DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
 			TALLOC_FREE(auth_generic_state);
-			data_blob_free(&blob_out);
-			return ADS_ERROR_NT(nt_status);
+			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
 		}
-		
-		if ((turn == 1) && 
-		    (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
-			DATA_BLOB tmp_blob = data_blob_null;
-			/* the server might give us back two challenges */
-			if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in, 
-						    &tmp_blob)) {
 
-				TALLOC_FREE(auth_generic_state);
-				data_blob_free(&blob);
-				DEBUG(3,("Failed to parse challenges\n"));
-				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-			}
-			data_blob_free(&tmp_blob);
-		} else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
-			if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP, 
-							&blob_in)) {
+		ok = gensec_have_feature(auth_generic_state->gensec_security,
+					 GENSEC_FEATURE_SIGN);
+		if (!ok) {
+			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
+			TALLOC_FREE(auth_generic_state);
+			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
+		}
 
-				TALLOC_FREE(auth_generic_state);
-				data_blob_free(&blob);
-				DEBUG(3,("Failed to parse auth response\n"));
-				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-			}
+	} else if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
+		bool ok;
+
+		ok = gensec_have_feature(auth_generic_state->gensec_security,
+					 GENSEC_FEATURE_SIGN);
+		if (!ok) {
+			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
+			TALLOC_FREE(auth_generic_state);
+			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
 		}
-		data_blob_free(&blob);
-		data_blob_free(&blob_out);
-		turn++;
-	} while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
-	
+	}
+
 	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
 		size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
 		ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);
@@ -256,7 +314,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
 		ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
 		ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
 		ads->ldap.in.max_wrapped = max_wrapped;
-		status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, auth_generic_state->gensec_security);
+		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security);
 		if (!ADS_ERR_OK(status)) {
 			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
 				ads_errstr(status)));
@@ -437,292 +495,22 @@ static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
 	.disconnect	= ads_sasl_gssapi_disconnect
 };
 
-/* 
-   perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
-*/
-static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
-{
-	ADS_STATUS status;
-	bool ok;
-	uint32_t minor_status;
-	int gss_rc, rc;
-	gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
-	gss_OID_desc krb5_mech_type =
-	{9, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
-	gss_OID mech_type = &krb5_mech_type;
-	gss_OID actual_mech_type = GSS_C_NULL_OID;
-	const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
-	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
-	gss_buffer_desc input_token, output_token;
-	uint32_t req_flags, ret_flags;
-	uint32_t req_tmp, ret_tmp;
-	DATA_BLOB unwrapped;
-	DATA_BLOB wrapped;
-	struct berval cred, *scred = NULL;
-	uint32_t context_validity = 0;
-	time_t context_endtime = 0;
-
-	status = ads_init_gssapi_cred(ads, &gss_cred);
-	if (!ADS_ERR_OK(status)) {
-		goto failed;
-	}
-
-	input_token.value = NULL;
-	input_token.length = 0;
-
-	req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
-	switch (ads->ldap.wrap_type) {
-	case ADS_SASLWRAP_TYPE_SEAL:
-		req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
-		break;
-	case ADS_SASLWRAP_TYPE_SIGN:
-		req_flags |= GSS_C_INTEG_FLAG;
-		break;
-	case ADS_SASLWRAP_TYPE_PLAIN:
-		break;
-	}
-
-	/* Note: here we explicit ask for the krb5 mech_type */
-	gss_rc = gss_init_sec_context(&minor_status,
-				      gss_cred,
-				      &context_handle,
-				      serv_name,
-				      mech_type,
-				      req_flags,
-				      0,
-				      NULL,
-				      &input_token,
-				      &actual_mech_type,
-				      &output_token,
-				      &ret_flags,
-				      NULL);
-	if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
-		status = ADS_ERROR_GSS(gss_rc, minor_status);
-		goto failed;
-	}
-
-	/*
-	 * As some gssapi krb5 mech implementations
-	 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
-	 * to req_flags internaly, it's not possible to
-	 * use plain or signing only connection via
-	 * the gssapi interface.
-	 *
-	 * Because of this we need to check it the ret_flags
-	 * has more flags as req_flags and correct the value
-	 * of ads->ldap.wrap_type.
-	 *
-	 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
-	 * we need to give an error.
-	 */
-	req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
-	ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
-
-	if (req_tmp == ret_tmp) {
-		/* everythings fine... */
-
-	} else if (req_flags & GSS_C_CONF_FLAG) {
-		/*
-		 * here we wanted sealing but didn't got it
-		 * from the gssapi library
-		 */
-		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-		goto failed;
-
-	} else if ((req_flags & GSS_C_INTEG_FLAG) &&
-		   !(ret_flags & GSS_C_INTEG_FLAG)) {
-		/*
-		 * here we wanted siging but didn't got it
-		 * from the gssapi library
-		 */
-		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-		goto failed;
-
-	} else if (ret_flags & GSS_C_CONF_FLAG) {
-		/*
-		 * here we didn't want sealing
-		 * but the gssapi library forces it
-		 * so correct the needed wrap_type if
-		 * the caller didn't forced siging only
-		 */
-		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
-			status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-			goto failed;
-		}
-
-		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
-		req_flags = ret_flags;
-
-	} else if (ret_flags & GSS_C_INTEG_FLAG) {
-		/*
-		 * here we didn't want signing
-		 * but the gssapi library forces it
-		 * so correct the needed wrap_type if
-		 * the caller didn't forced plain
-		 */
-		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
-			status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-			goto failed;
-		}
-
-		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
-		req_flags = ret_flags;
-	} else {
-		/*
-		 * This could (should?) not happen
-		 */
-		status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
-		goto failed;
-	
-	}
-
-	/* and wrap that in a shiny SPNEGO wrapper */
-	unwrapped = data_blob_const(output_token.value, output_token.length);
-	wrapped = spnego_gen_negTokenInit(talloc_tos(),
-			spnego_mechs, &unwrapped, NULL);
-	gss_release_buffer(&minor_status, &output_token);
-	if (unwrapped.length > wrapped.length) {
-		status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-		goto failed;
-	}
-
-	cred.bv_val = (char *)wrapped.data;
-	cred.bv_len = wrapped.length;
-
-	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, 
-			      &scred);
-	data_blob_free(&wrapped);
-	if (rc != LDAP_SUCCESS) {
-		status = ADS_ERROR(rc);
-		goto failed;
-	}
-
-	if (scred) {
-		wrapped = data_blob_const(scred->bv_val, scred->bv_len);
-	} else {
-		wrapped = data_blob_null;
-	}
-
-	ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK,
-					OID_KERBEROS5_OLD,
-					&unwrapped);
-	if (scred) ber_bvfree(scred);
-	if (!ok) {
-		status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
-		goto failed;
-	}
-
-	input_token.value	= unwrapped.data;
-	input_token.length	= unwrapped.length;
-
-	/* 
-	 * As we asked for mutal authentication
-	 * we need to pass the servers response
-	 * to gssapi
-	 */
-	gss_rc = gss_init_sec_context(&minor_status,
-				      gss_cred,
-				      &context_handle,
-				      serv_name,
-				      mech_type,
-				      req_flags,
-				      0,
-				      NULL,
-				      &input_token,
-				      &actual_mech_type,
-				      &output_token,
-				      &ret_flags,
-				      NULL);
-	data_blob_free(&unwrapped);
-	if (gss_rc) {
-		status = ADS_ERROR_GSS(gss_rc, minor_status);
-		goto failed;
-	}
-
-	gss_release_buffer(&minor_status, &output_token);
-
-	/*
-	 * If we the sign and seal options
-	 * doesn't match after getting the response
-	 * from the server, we don't want to use the connection
-	 */
-	req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
-	ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
-
-	if (req_tmp != ret_tmp) {
-		/* everythings fine... */
-		status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
-		goto failed;
-	}
-
-	gss_rc =
-	    gss_context_time(&minor_status, context_handle, &context_validity);
-	if (gss_rc == GSS_S_COMPLETE) {
-		if (context_validity != 0) {
-			context_endtime = time(NULL) + context_validity;
-			DEBUG(10, ("context (service ticket) valid for "
-				"%u seconds\n",
-				context_validity));
-		} else {
-			DEBUG(10, ("context (service ticket) expired\n"));
-		}
-	} else {
-		DEBUG(1, ("gss_context_time failed (%d,%u) -"
-			" this will be a one-time context\n",
-			gss_rc, minor_status));
-		if (gss_rc == GSS_S_CONTEXT_EXPIRED) {
-			DEBUG(10, ("context (service ticket) expired\n"));
-		}
-	}
-
-	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
-		uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
-
-		gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
-					     (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
-					     GSS_C_QOP_DEFAULT,
-					     max_msg_size, &ads->ldap.out.max_unwrapped);
-		if (gss_rc) {
-			status = ADS_ERROR_GSS(gss_rc, minor_status);
-			goto failed;
-		}
-
-		ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
-		ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
-		ads->ldap.in.max_wrapped = max_msg_size;
-		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
-		if (!ADS_ERR_OK(status)) {
-			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
-				ads_errstr(status)));
-			goto failed;
-		}
-		/* make sure we don't free context_handle */
-		context_handle = GSS_C_NO_CONTEXT;
-	}
-
-	ads->auth.tgs_expire = context_endtime;
-	status = ADS_SUCCESS;
-
-failed:
-	if (gss_cred != GSS_C_NO_CREDENTIAL)
-		gss_release_cred(&minor_status, &gss_cred);
-	if (context_handle != GSS_C_NO_CONTEXT)
-		gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
-	return status;
-}
-
 #endif /* HAVE_KRB5 */
 
 #ifdef HAVE_KRB5
 struct ads_service_principal {
-	 char *string;
+	char *service;
+	char *hostname;
+	char *string;
 #ifdef HAVE_KRB5
-	 gss_name_t name;
+	gss_name_t name;
 #endif
 };
 
 static void ads_free_service_principal(struct ads_service_principal *p)
 {
+	SAFE_FREE(p->service);
+	SAFE_FREE(p->hostname);
 	SAFE_FREE(p->string);
 
 #ifdef HAVE_KRB5
@@ -734,9 +522,10 @@ static void ads_free_service_principal(struct ads_service_principal *p)
 	ZERO_STRUCTP(p);
 }
 
-
-static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
-					      char **returned_principal)
+static ADS_STATUS ads_guess_target(ADS_STRUCT *ads,
+				   char **service,
+				   char **hostname,
+				   char **principal)
 {
 	ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
 	char *princ = NULL;
@@ -816,13 +605,26 @@ static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
 		goto out;
 	}
 
+	*service = SMB_STRDUP("ldap");
+	if (*service == NULL) {
+		status = ADS_ERROR(LDAP_PARAM_ERROR);
+		goto out;
+	}
+	*hostname = SMB_STRDUP(server);
+	if (*hostname == NULL) {
+		SAFE_FREE(*service);
+		status = ADS_ERROR(LDAP_PARAM_ERROR);
+		goto out;
+	}
 	rc = asprintf(&princ, "ldap/%s@%s", server, realm);
 	if (rc == -1 || princ == NULL) {
+		SAFE_FREE(*service);
+		SAFE_FREE(*hostname);
 		status = ADS_ERROR(LDAP_PARAM_ERROR);
 		goto out;
 	}
 
-	*returned_principal = princ;
+	*principal = princ;
 
 	status = ADS_SUCCESS;
 out:
@@ -831,7 +633,6 @@ out:
 }
 
 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
-						 const char *given_principal,
 						 struct ads_service_principal *p)
 {
 	ADS_STATUS status;
@@ -846,27 +647,12 @@ static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
 
 	ZERO_STRUCTP(p);
 
-	/* I've seen a child Windows 2000 domain not send
-	   the principal name back in the first round of
-	   the SASL bind reply.  So we guess based on server
-	   name and realm.  --jerry  */
-	/* Also try best guess when we get the w2k8 ignore principal
-	   back, or when we are configured to ignore it - gd,
-	   abartlet */
-
-	if (!lp_client_use_spnego_principal() ||
-	    !given_principal ||
-	    strequal(given_principal, ADS_IGNORE_PRINCIPAL)) {
-
-		status = ads_guess_service_principal(ads, &p->string);
-		if (!ADS_ERR_OK(status)) {
-			return status;
-		}
-	} else {
-		p->string = SMB_STRDUP(given_principal);
-		if (!p->string) {
-			return ADS_ERROR(LDAP_NO_MEMORY);
-		}
+	status = ads_guess_target(ads,
+				  &p->service,
+				  &p->hostname,
+				  &p->string);
+	if (!ADS_ERR_OK(status)) {
+		return status;
 	}
 
 #ifdef HAVE_KRB5
@@ -883,63 +669,6 @@ static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
 	return ADS_SUCCESS;
 }
 
-/* 
-   perform a LDAP/SASL/SPNEGO/KRB5 bind
-*/
-static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
-{
-	DATA_BLOB blob = data_blob_null;
-	struct berval cred, *scred = NULL;
-	DATA_BLOB session_key = data_blob_null;
-	int rc;
-
-	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
-		return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-	}
-
-	rc = spnego_gen_krb5_negTokenInit(talloc_tos(), principal,
-				     ads->auth.time_offset, &blob, &session_key, 0,
-				     ads->auth.ccache_name,
-				     &ads->auth.tgs_expire);
-
-	if (rc) {
-		return ADS_ERROR_KRB5(rc);
-	}
-
-	/* now send the auth packet and we should be done */
-	cred.bv_val = (char *)blob.data;
-	cred.bv_len = blob.length;
-
-	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
-
-	data_blob_free(&blob);
-	data_blob_free(&session_key);
-	if(scred)
-		ber_bvfree(scred);
-
-	return ADS_ERROR(rc);
-}
-
-static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
-					    struct ads_service_principal *p)
-{
-#ifdef HAVE_KRB5
-	/*
-	 * we only use the gsskrb5 based implementation
-	 * when sasl sign or seal is requested.
-	 *
-	 * This has the following reasons:
-	 * - it's likely that the gssapi krb5 mech implementation
-	 *   doesn't support to negotiate plain connections
-	 * - the ads_sasl_spnego_rawkrb5_bind is more robust
-	 *   against clock skew errors
-	 */
-	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
-		return ads_sasl_spnego_gsskrb5_bind(ads, p->name);
-	}
-#endif
-	return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
-}
 #endif /* HAVE_KRB5 */
 
 /* 
@@ -947,6 +676,8 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
 */
 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct ads_service_principal p = {0};
 	struct berval *scred=NULL;
 	int rc, i;
 	ADS_STATUS status;
@@ -961,7 +692,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
 	if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
 		status = ADS_ERROR(rc);
-		goto failed;
+		goto done;
 	}
 
 	blob = data_blob(scred->bv_val, scred->bv_len);
@@ -976,11 +707,10 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 	   reply */
 	if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
 			OIDs[0] == NULL) {
-		data_blob_free(&blob);
 		status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
-		goto failed;
+		goto done;
 	}
-	data_blob_free(&blob);
+	TALLOC_FREE(given_principal);
 
 	/* make sure the server understands kerberos */
 	for (i=0;OIDs[i];i++) {
@@ -993,59 +723,60 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 #endif
 		talloc_free(OIDs[i]);
 	}
-	DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));
+
+	status = ads_generate_service_principal(ads, &p);
+	if (!ADS_ERR_OK(status)) {
+		goto done;
+	}
 
 #ifdef HAVE_KRB5
 	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
 	    got_kerberos_mechanism) 
 	{
-		struct ads_service_principal p;
-
-		status = ads_generate_service_principal(ads, given_principal, &p);
-		TALLOC_FREE(given_principal);
-		if (!ADS_ERR_OK(status)) {
-			return status;
-		}
-
-		status = ads_sasl_spnego_krb5_bind(ads, &p);
+		status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
+						     CRED_MUST_USE_KERBEROS,
+						     p.service, p.hostname,
+						     blob);
 		if (ADS_ERR_OK(status)) {
 			ads_free_service_principal(&p);
-			return status;
+			goto done;
 		}
 
-		DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
+		DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
 			  "calling kinit\n", ads_errstr(status)));
 
 		status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 
 
 		if (ADS_ERR_OK(status)) {
-			status = ads_sasl_spnego_krb5_bind(ads, &p);
+			status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
+							CRED_MUST_USE_KERBEROS,
+							p.service, p.hostname,
+							blob);
 			if (!ADS_ERR_OK(status)) {
 				DEBUG(0,("kinit succeeded but "
-					"ads_sasl_spnego_krb5_bind failed: %s\n",
+					"ads_sasl_spnego_gensec_bind(KRB5) failed: %s\n",
 					ads_errstr(status)));
 			}
 		}
 
-		ads_free_service_principal(&p);
-
 		/* only fallback to NTLMSSP if allowed */
 		if (ADS_ERR_OK(status) || 
 		    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
-			return status;
+			goto done;
 		}
-	} else
-#endif
-	{
-		TALLOC_FREE(given_principal);
 	}
+#endif
 
 	/* lets do NTLMSSP ... this has the big advantage that we don't need
 	   to sync clocks, and we don't rely on special versions of the krb5 
 	   library for HMAC_MD4 encryption */
-	return ads_sasl_spnego_ntlmssp_bind(ads);
-
-failed:
+	status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
+					     CRED_DONT_USE_KERBEROS,
+					     p.service, p.hostname,
+					     data_blob_null);
+done:
+	ads_free_service_principal(&p);
+	TALLOC_FREE(frame);
 	return status;
 }
 
@@ -1267,7 +998,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
 	ADS_STATUS status;
 	struct ads_service_principal p;
 
-	status = ads_generate_service_principal(ads, NULL, &p);
+	status = ads_generate_service_principal(ads, &p);
 	if (!ADS_ERR_OK(status)) {
 		return status;
 	}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 3e58b18..aab2d29 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -857,7 +857,7 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
 				   domain,
 				   pass,
 				   flags,
-				   SMB_SIGNING_DEFAULT);
+				   SMB_SIGNING_IPC_DEFAULT);
 }
 
 /****************************************************************
@@ -1412,7 +1412,7 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
 				     machine_domain,
 				     machine_password,
 				     flags,
-				     SMB_SIGNING_DEFAULT);
+				     SMB_SIGNING_IPC_DEFAULT);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		status = cli_full_connection(&cli, NULL,
@@ -1423,7 +1423,7 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
 					     NULL,
 					     "",
 					     0,
-					     SMB_SIGNING_DEFAULT);
+					     SMB_SIGNING_IPC_DEFAULT);
 	}
 
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index 33a32c3..6ea2c4a 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -45,6 +45,7 @@ struct gse_context {
 	gss_name_t server_name;
 	gss_name_t client_name;
 	OM_uint32 gss_want_flags, gss_got_flags;
+	size_t max_wrap_buf_size;
 	size_t sig_size;
 
 	gss_cred_id_t delegated_cred_handle;
@@ -136,6 +137,7 @@ static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
 	talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
 
 	gse_ctx->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
+	gse_ctx->max_wrap_buf_size = UINT16_MAX;
 
 	memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
 
@@ -201,8 +203,11 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 {
 	struct gse_context *gse_ctx;
 	OM_uint32 gss_maj, gss_min;
-	gss_buffer_desc name_buffer = {0, NULL};
+	gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER;
 	gss_OID_set_desc mech_set;
+#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
+	gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
+#endif
 	NTSTATUS status;
 
 	if (!server || !service) {
@@ -255,12 +260,34 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 				   &gse_ctx->creds,
 				   NULL, NULL);
 	if (gss_maj) {
-		DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
-			  (char *)name_buffer.value,
+		DEBUG(5, ("gss_acquire_creds failed for GSS_C_NO_NAME with [%s] -"
+			  "the caller may retry after a kinit.\n",
+			  gse_errstr(gse_ctx, gss_maj, gss_min)));
+		status = NT_STATUS_INTERNAL_ERROR;
+		goto err_out;
+	}
+
+#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
+	/*
+	 * Don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG.
+	 *
+	 * This allows us to disable SIGN and SEAL for
+	 * AUTH_LEVEL_CONNECT and AUTH_LEVEL_INTEGRITY.
+	 *
+	 * https://groups.yahoo.com/neo/groups/cat-ietf/conversations/topics/575
+	 * http://krbdev.mit.edu/rt/Ticket/Display.html?id=6938
+	 */
+	gss_maj = gss_set_cred_option(&gss_min, &gse_ctx->creds,
+				      GSS_KRB5_CRED_NO_CI_FLAGS_X,
+				      &empty_buffer);
+	if (gss_maj) {
+		DEBUG(0, ("gss_set_cred_option(GSS_KRB5_CRED_NO_CI_FLAGS_X), "
+			  "failed with [%s]\n",
 			  gse_errstr(gse_ctx, gss_maj, gss_min)));
 		status = NT_STATUS_INTERNAL_ERROR;
 		goto err_out;
 	}
+#endif
 
 	*_gse_ctx = gse_ctx;
 	TALLOC_FREE(name_buffer.value);
@@ -570,6 +597,9 @@ static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
+		do_sign = true;
+	}
 	if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 		do_sign = true;
 	}
@@ -870,18 +900,15 @@ static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
 		talloc_get_type_abort(gensec_security->private_data,
 		struct gse_context);
 
+	if (feature & GENSEC_FEATURE_SESSION_KEY) {
+		return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
+	}
 	if (feature & GENSEC_FEATURE_SIGN) {
 		return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
 	}
 	if (feature & GENSEC_FEATURE_SEAL) {
 		return gse_ctx->gss_got_flags & GSS_C_CONF_FLAG;
 	}
-	if (feature & GENSEC_FEATURE_SESSION_KEY) {
-		/* Only for GSE/Krb5 */
-		if (smb_gss_oid_equal(gse_ctx->ret_mech, gss_mech_krb5)) {
-			return true;
-		}
-	}
 	if (feature & GENSEC_FEATURE_DCE_STYLE) {
 		return gse_ctx->gss_got_flags & GSS_C_DCE_STYLE;
 	}
@@ -1037,6 +1064,40 @@ static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security,
 	return NT_STATUS_OK;
 }
 
+static size_t gensec_gse_max_input_size(struct gensec_security *gensec_security)
+{
+	struct gse_context *gse_ctx =
+		talloc_get_type_abort(gensec_security->private_data,
+		struct gse_context);
+	OM_uint32 maj_stat, min_stat;
+	OM_uint32 max_input_size;
+
+	maj_stat = gss_wrap_size_limit(&min_stat,
+				       gse_ctx->gssapi_context,
+				       gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
+				       GSS_C_QOP_DEFAULT,
+				       gse_ctx->max_wrap_buf_size,
+				       &max_input_size);
+	if (GSS_ERROR(maj_stat)) {
+		TALLOC_CTX *mem_ctx = talloc_new(NULL);
+		DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
+			  gse_errstr(mem_ctx, maj_stat, min_stat)));
+		talloc_free(mem_ctx);
+		return 0;
+	}
+
+	return max_input_size;
+}
+
+/* Find out the maximum output size negotiated on this connection */
+static size_t gensec_gse_max_wrapped_size(struct gensec_security *gensec_security)
+{
+	struct gse_context *gse_ctx =
+		talloc_get_type_abort(gensec_security->private_data,
+		struct gse_context);
+	return gse_ctx->max_wrap_buf_size;
+}
+
 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
 				  size_t data_size)
 {
@@ -1076,6 +1137,8 @@ const struct gensec_security_ops gensec_gse_krb5_security_ops = {
 	.check_packet	= gensec_gse_check_packet,
 	.seal_packet	= gensec_gse_seal_packet,
 	.unseal_packet	= gensec_gse_unseal_packet,
+	.max_input_size	  = gensec_gse_max_input_size,
+	.max_wrapped_size = gensec_gse_max_wrapped_size,
 	.wrap           = gensec_gse_wrap,
 	.unwrap         = gensec_gse_unwrap,
 	.have_feature   = gensec_gse_have_feature,
diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h
index e7d66b7..1838012 100644
--- a/source3/librpc/rpc/dcerpc.h
+++ b/source3/librpc/rpc/dcerpc.h
@@ -40,6 +40,7 @@ struct gensec_security;
 struct pipe_auth_data {
 	enum dcerpc_AuthType auth_type;
 	enum dcerpc_AuthLevel auth_level;
+	uint32_t auth_context_id;
 	bool client_hdr_signing;
 	bool hdr_signing;
 	bool verified_bitmask1;
@@ -69,10 +70,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
 				 uint32_t auth_context_id,
 				 const DATA_BLOB *credentials,
 				 DATA_BLOB *blob);
-NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
-				 const DATA_BLOB *blob,
-				 struct dcerpc_auth *r,
-				 bool bigendian);
 NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
 			    size_t header_len, size_t data_left,
 			    size_t max_xmit_frag,
@@ -83,8 +80,7 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 			   struct ncacn_packet *pkt,
 			   DATA_BLOB *pkt_trailer,
-			   size_t header_size,
-			   DATA_BLOB *raw_pkt,
-			   size_t *pad_len);
+			   uint8_t header_size,
+			   DATA_BLOB *raw_pkt);
 
 #endif /* __S3_DCERPC_H__ */
diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c
index 1193baa..aab43a1 100644
--- a/source3/librpc/rpc/dcerpc_helpers.c
+++ b/source3/librpc/rpc/dcerpc_helpers.c
@@ -177,47 +177,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
 }
 
 /**
-* @brief Decodes a dcerpc_auth blob
-*
-* @param mem_ctx	The memory context on which to allocate the packet
-*			elements
-* @param blob		The blob of data to decode
-* @param r		An empty dcerpc_auth structure, must not be NULL
-*
-* @return a NTSTATUS error code
-*/
-NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
-				 const DATA_BLOB *blob,
-				 struct dcerpc_auth *r,
-				 bool bigendian)
-{
-	enum ndr_err_code ndr_err;
-	struct ndr_pull *ndr;
-
-	ndr = ndr_pull_init_blob(blob, mem_ctx);
-	if (!ndr) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	if (bigendian) {
-		ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
-	}
-
-	ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
-
-	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		talloc_free(ndr);
-		return ndr_map_error2ntstatus(ndr_err);
-	}
-	talloc_free(ndr);
-
-	if (DEBUGLEVEL >= 10) {
-		NDR_PRINT_DEBUG(dcerpc_auth, r);
-	}
-
-	return NT_STATUS_OK;
-}
-
-/**
 * @brief Calculate how much data we can in a packet, including calculating
 *	 auth token and pad lengths.
 *
@@ -444,7 +403,7 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
 					 auth->auth_type,
 					 auth->auth_level,
 					 pad_len,
-					 1 /* context id. */,
+					 auth->auth_context_id,
 					 &auth_blob,
 					 &auth_info);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -481,19 +440,18 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
 *
 * @param auth		The auth data for the connection
 * @param pkt		The actual ncacn_packet
-* @param pkt_trailer	The stub_and_verifier part of the packet
+* @param pkt_trailer [in][out]	The stub_and_verifier part of the packet,
+* 			the auth_trailer and padding will be removed.
 * @param header_size	The header size
 * @param raw_pkt	The whole raw packet data blob
-* @param pad_len	[out] The padding length used in the packet
 *
 * @return A NTSTATUS error code
 */
 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 			   struct ncacn_packet *pkt,
 			   DATA_BLOB *pkt_trailer,
-			   size_t header_size,
-			   DATA_BLOB *raw_pkt,
-			   size_t *pad_len)
+			   uint8_t header_size,
+			   DATA_BLOB *raw_pkt)
 {
 	struct gensec_security *gensec_security;
 	NTSTATUS status;
@@ -502,6 +460,14 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 	DATA_BLOB full_pkt;
 	DATA_BLOB data;
 
+	/*
+	 * These check should be done in the caller.
+	 */
+	SMB_ASSERT(raw_pkt->length == pkt->frag_length);
+	SMB_ASSERT(header_size <= pkt->frag_length);
+	SMB_ASSERT(pkt_trailer->length < pkt->frag_length);
+	SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length);
+
 	switch (auth->auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		DEBUG(10, ("Requested Privacy.\n"));
@@ -515,7 +481,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 		if (pkt->auth_length != 0) {
 			break;
 		}
-		*pad_len = 0;
 		return NT_STATUS_OK;
 
 	case DCERPC_AUTH_LEVEL_NONE:
@@ -524,7 +489,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 				  "authenticated connection!\n"));
 			return NT_STATUS_INVALID_PARAMETER;
 		}
-		*pad_len = 0;
 		return NT_STATUS_OK;
 
 	default:
@@ -533,16 +497,8 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	/* Paranioa checks for auth_length. */
-	if (pkt->auth_length > pkt->frag_length) {
-		return NT_STATUS_INFO_LENGTH_MISMATCH;
-	}
-	if (((unsigned int)pkt->auth_length
-	     + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
-	    ((unsigned int)pkt->auth_length
-	     + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
-		/* Integer wrap attempt. */
-		return NT_STATUS_INFO_LENGTH_MISMATCH;
+	if (pkt->auth_length == 0) {
+		return NT_STATUS_INVALID_PARAMETER;
 	}
 
 	status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
@@ -551,10 +507,23 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 		return status;
 	}
 
+	if (auth_info.auth_type != auth->auth_type) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (auth_info.auth_level != auth->auth_level) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (auth_info.auth_context_id != auth->auth_context_id) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	pkt_trailer->length -= auth_length;
 	data = data_blob_const(raw_pkt->data + header_size,
-				pkt_trailer->length - auth_length);
-	full_pkt = data_blob_const(raw_pkt->data,
-				raw_pkt->length - auth_info.credentials.length);
+			       pkt_trailer->length);
+	full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length);
+	full_pkt.length -= auth_info.credentials.length;
 
 	switch (auth->auth_type) {
 	case DCERPC_AUTH_TYPE_NONE:
@@ -579,10 +548,13 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
 	 * pkt_trailer actually has a copy of the raw data, and they
 	 * are still both used in later calls */
 	if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+		if (pkt_trailer->length != data.length) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
 		memcpy(pkt_trailer->data, data.data, data.length);
 	}
 
-	*pad_len = auth_info.auth_pad_length;
+	pkt_trailer->length -= auth_info.auth_pad_length;
 	data_blob_free(&auth_info.credentials);
 	return NT_STATUS_OK;
 }
diff --git a/source3/libsmb/auth_generic.c b/source3/libsmb/auth_generic.c
index 68d1451..59560d6 100644
--- a/source3/libsmb/auth_generic.c
+++ b/source3/libsmb/auth_generic.c
@@ -86,7 +86,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st
 	}
 
 	backends = talloc_zero_array(gensec_settings,
-				     const struct gensec_security_ops *, 6);
+				     const struct gensec_security_ops *, 7);
 	if (backends == NULL) {
 		TALLOC_FREE(ans);
 		return NT_STATUS_NO_MEMORY;
@@ -100,7 +100,8 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st
 	backends[idx++] = &gensec_gse_krb5_security_ops;
 #endif
 
-	backends[idx++] = &gensec_ntlmssp3_client_ops;
+	backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
+	backends[idx++] = gensec_security_by_name(NULL, "ntlmssp_resume_ccache");
 
 	backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO);
 	backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL);
@@ -151,6 +152,29 @@ NTSTATUS auth_generic_client_start(struct auth_generic_state *ans, const char *o
 	return NT_STATUS_OK;
 }
 
+NTSTATUS auth_generic_client_start_by_name(struct auth_generic_state *ans,
+					   const char *name)
+{
+	NTSTATUS status;
+
+	/* Transfer the credentials to gensec */
+	status = gensec_set_credentials(ans->gensec_security, ans->credentials);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
+			  nt_errstr(status)));
+		return status;
+	}
+	talloc_unlink(ans, ans->credentials);
+	ans->credentials = NULL;
+
+	status = gensec_start_mech_by_name(ans->gensec_security, name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
 NTSTATUS auth_generic_client_start_by_authtype(struct auth_generic_state *ans,
 					       uint8_t auth_type,
 					       uint8_t auth_level)
@@ -175,3 +199,26 @@ NTSTATUS auth_generic_client_start_by_authtype(struct auth_generic_state *ans,
 
 	return NT_STATUS_OK;
 }
+
+NTSTATUS auth_generic_client_start_by_sasl(struct auth_generic_state *ans,
+					   const char **sasl_list)
+{
+	NTSTATUS status;
+
+	/* Transfer the credentials to gensec */
+	status = gensec_set_credentials(ans->gensec_security, ans->credentials);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
+			  nt_errstr(status)));
+		return status;
+	}
+	talloc_unlink(ans, ans->credentials);
+	ans->credentials = NULL;
+
+	status = gensec_start_mech_by_sasl_list(ans->gensec_security, sasl_list);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 530f5c3..2c351dd 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -26,7 +26,10 @@
 #include "../libcli/auth/libcli_auth.h"
 #include "../libcli/auth/spnego.h"
 #include "smb_krb5.h"
-#include "../auth/ntlmssp/ntlmssp.h"
+#include "auth/credentials/credentials.h"
+#include "auth/gensec/gensec.h"
+#include "auth/ntlmssp/ntlmssp.h"
+#include "auth_generic.h"
 #include "libads/kerberos_proto.h"
 #include "krb5_env.h"
 #include "../lib/util/tevent_ntstatus.h"
@@ -1264,386 +1267,407 @@ static void use_in_memory_ccache(void) {
 	setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
 }
 
+#endif	/* HAVE_KRB5 */
+
 /****************************************************************************
- Do a spnego/kerberos encrypted session setup.
+ Do a spnego/NTLMSSP encrypted session setup.
 ****************************************************************************/
 
-struct cli_session_setup_kerberos_state {
+struct cli_session_setup_gensec_state {
+	struct tevent_context *ev;
 	struct cli_state *cli;
-	DATA_BLOB negTokenTarg;
-	DATA_BLOB session_key_krb5;
-	ADS_STATUS ads_status;
+	struct auth_generic_state *auth_generic;
+	bool is_anonymous;
+	DATA_BLOB blob_in;
+	uint8_t *inbuf;
+	struct iovec *recv_iov;
+	DATA_BLOB blob_out;
+	bool local_ready;
+	bool remote_ready;
+	DATA_BLOB session_key;
 };
 
-static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
+static int cli_session_setup_gensec_state_destructor(
+	struct cli_session_setup_gensec_state *state)
+{
+	TALLOC_FREE(state->auth_generic);
+	data_blob_clear_free(&state->session_key);
+	return 0;
+}
 
-static struct tevent_req *cli_session_setup_kerberos_send(
+static void cli_session_setup_gensec_local_next(struct tevent_req *req);
+static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
+static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
+static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
+static void cli_session_setup_gensec_ready(struct tevent_req *req);
+
+static struct tevent_req *cli_session_setup_gensec_send(
 	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
-	const char *principal)
+	const char *user, const char *pass, const char *domain,
+	enum credentials_use_kerberos krb5_state,
+	const char *target_service,
+	const char *target_hostname,
+	const char *target_principal)
 {
-	struct tevent_req *req, *subreq;
-	struct cli_session_setup_kerberos_state *state;
-	int rc;
-
-	DEBUG(2,("Doing kerberos session setup\n"));
+	struct tevent_req *req;
+	struct cli_session_setup_gensec_state *state;
+	NTSTATUS status;
+	bool use_spnego_principal = lp_client_use_spnego_principal();
 
 	req = tevent_req_create(mem_ctx, &state,
-				struct cli_session_setup_kerberos_state);
+				struct cli_session_setup_gensec_state);
 	if (req == NULL) {
 		return NULL;
 	}
+	state->ev = ev;
 	state->cli = cli;
-	state->ads_status = ADS_SUCCESS;
 
-	/*
-	 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
-	 * we have to acquire a ticket. To be fixed later :-)
-	 */
-	rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
-				     &state->session_key_krb5, 0, NULL, NULL);
-	if (rc) {
-		NTSTATUS status;
-
-		state->ads_status = ADS_ERROR_KRB5(rc);
-		status = ads_ntstatus(state->ads_status);
-		if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
-			status = NT_STATUS_LOGON_FAILURE;
-			state->ads_status = ADS_ERROR_NT(status);
+	talloc_set_destructor(
+		state, cli_session_setup_gensec_state_destructor);
+
+	status = auth_generic_client_prepare(state, &state->auth_generic);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	gensec_want_feature(state->auth_generic->gensec_security,
+			    GENSEC_FEATURE_SESSION_KEY);
+	if (cli->use_ccache) {
+		gensec_want_feature(state->auth_generic->gensec_security,
+				    GENSEC_FEATURE_NTLM_CCACHE);
+		if (pass != NULL && strlen(pass) == 0) {
+			/*
+			 * some callers pass "" as no password
+			 *
+			 * GENSEC_FEATURE_NTLM_CCACHE only handles
+			 * NULL as no password.
+			 */
+			pass = NULL;
 		}
-		DEBUG(1, ("cli_session_setup_kerberos: "
-			  "spnego_gen_krb5_negTokenInit failed: %s - %s\n",
-			  error_message(rc), nt_errstr(status)));
-		tevent_req_nterror(req, status);
+	}
+
+	status = auth_generic_set_username(state->auth_generic, user);
+	if (tevent_req_nterror(req, status)) {
 		return tevent_req_post(req, ev);
 	}
 
-#if 0
-	file_save("negTokenTarg.dat", state->negTokenTarg.data,
-		  state->negTokenTarg.length);
-#endif
+	status = auth_generic_set_domain(state->auth_generic, domain);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
 
-	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		state->cli->smb2.session = smbXcli_session_create(cli,
-								  cli->conn);
-		if (tevent_req_nomem(state->cli->smb2.session, req)) {
+	if (cli->pw_nt_hash) {
+		struct samr_Password nt_hash;
+		size_t converted;
+		bool ok;
+
+		if (pass == NULL) {
+			tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
 			return tevent_req_post(req, ev);
 		}
-	}
 
-	subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
-	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, ev);
+		converted = strhex_to_str((char *)nt_hash.hash,
+					  sizeof(nt_hash.hash),
+					  pass, strlen(pass));
+		if (converted != sizeof(nt_hash.hash)) {
+			tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+			return tevent_req_post(req, ev);
+		}
+
+		ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
+						 &nt_hash, CRED_SPECIFIED);
+		if (!ok) {
+			tevent_req_oom(req);
+			return tevent_req_post(req, ev);
+		}
+	} else {
+		status = auth_generic_set_password(state->auth_generic, pass);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
 	}
-	tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
-	return req;
-}
 
-static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
-{
-	struct tevent_req *req = tevent_req_callback_data(
-		subreq, struct tevent_req);
-	struct cli_session_setup_kerberos_state *state = tevent_req_data(
-		req, struct cli_session_setup_kerberos_state);
-	uint8_t *inbuf = NULL;
-	struct iovec *recv_iov = NULL;
-	NTSTATUS status;
+	cli_credentials_set_kerberos_state(state->auth_generic->credentials,
+					   krb5_state);
 
-	status = cli_sesssetup_blob_recv(subreq, state,
-					 NULL, &inbuf, &recv_iov);
-	TALLOC_FREE(subreq);
-	if (!NT_STATUS_IS_OK(status)) {
-		tevent_req_nterror(req, status);
-		return;
+	if (krb5_state == CRED_DONT_USE_KERBEROS) {
+		use_spnego_principal = false;
 	}
 
-	if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
-		struct smbXcli_session *session = state->cli->smb2.session;
-		status = smb2cli_session_set_session_key(session,
-						state->session_key_krb5,
-						recv_iov);
+	if (target_service != NULL) {
+		status = gensec_set_target_service(
+				state->auth_generic->gensec_security,
+				target_service);
 		if (tevent_req_nterror(req, status)) {
-			return;
+			return tevent_req_post(req, ev);
 		}
-	} else {
-		struct smbXcli_session *session = state->cli->smb1.session;
+	}
 
-		status = smb1cli_session_set_session_key(session,
-							 state->session_key_krb5);
+	if (target_hostname != NULL) {
+		status = gensec_set_target_hostname(
+				state->auth_generic->gensec_security,
+				target_hostname);
 		if (tevent_req_nterror(req, status)) {
-			return;
+			return tevent_req_post(req, ev);
 		}
+	}
 
-		if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
-					   data_blob_null)
-		    && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
-			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-			return;
+	if (target_principal != NULL) {
+		status = gensec_set_target_principal(
+				state->auth_generic->gensec_security,
+				target_principal);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
 		}
+		use_spnego_principal = false;
+	} else if (target_service != NULL && target_hostname != NULL) {
+		use_spnego_principal = false;
 	}
 
-	tevent_req_done(req);
-}
+	if (use_spnego_principal) {
+		const DATA_BLOB *b;
+		b = smbXcli_conn_server_gss_blob(cli->conn);
+		if (b != NULL) {
+			state->blob_in = *b;
+		}
+	}
 
-static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
-{
-	struct cli_session_setup_kerberos_state *state = tevent_req_data(
-		req, struct cli_session_setup_kerberos_state);
-	NTSTATUS status;
+	state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
 
-	if (tevent_req_is_nterror(req, &status)) {
-		ADS_STATUS ads = state->ads_status;
+	status = auth_generic_client_start(state->auth_generic,
+					   GENSEC_OID_SPNEGO);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
 
-		if (!ADS_ERR_OK(state->ads_status)) {
-			ads = state->ads_status;
-		} else {
-			ads = ADS_ERROR_NT(status);
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		state->cli->smb2.session = smbXcli_session_create(cli,
+								  cli->conn);
+		if (tevent_req_nomem(state->cli->smb2.session, req)) {
+			return tevent_req_post(req, ev);
 		}
-		tevent_req_received(req);
-		return ads;
 	}
-	tevent_req_received(req);
-	return ADS_SUCCESS;
-}
-
-#endif	/* HAVE_KRB5 */
 
-/****************************************************************************
- Do a spnego/NTLMSSP encrypted session setup.
-****************************************************************************/
+	cli_session_setup_gensec_local_next(req);
+	if (!tevent_req_is_in_progress(req)) {
+		return tevent_req_post(req, ev);
+	}
 
-struct cli_session_setup_ntlmssp_state {
-	struct tevent_context *ev;
-	struct cli_state *cli;
-	struct ntlmssp_state *ntlmssp_state;
-	int turn;
-	DATA_BLOB blob_out;
-};
+	return req;
+}
 
-static int cli_session_setup_ntlmssp_state_destructor(
-	struct cli_session_setup_ntlmssp_state *state)
+static void cli_session_setup_gensec_local_next(struct tevent_req *req)
 {
-	if (state->ntlmssp_state != NULL) {
-		TALLOC_FREE(state->ntlmssp_state);
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
+	struct tevent_req *subreq = NULL;
+
+	if (state->local_ready) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
 	}
-	return 0;
-}
 
-static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
+	subreq = gensec_update_send(state, state->ev,
+			state->auth_generic->gensec_security,
+			state->blob_in);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
+}
 
-static struct tevent_req *cli_session_setup_ntlmssp_send(
-	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
-	const char *user, const char *pass, const char *domain)
+static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
 {
-	struct tevent_req *req, *subreq;
-	struct cli_session_setup_ntlmssp_state *state;
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
 	NTSTATUS status;
-	DATA_BLOB blob_out;
-	const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
 
-	req = tevent_req_create(mem_ctx, &state,
-				struct cli_session_setup_ntlmssp_state);
-	if (req == NULL) {
-		return NULL;
+	status = gensec_update_recv(subreq, state, &state->blob_out);
+	TALLOC_FREE(subreq);
+	state->blob_in = data_blob_null;
+	if (!NT_STATUS_IS_OK(status) &&
+	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
+	{
+		tevent_req_nterror(req, status);
+		return;
 	}
-	state->ev = ev;
-	state->cli = cli;
-	state->turn = 1;
 
-	state->ntlmssp_state = NULL;
-	talloc_set_destructor(
-		state, cli_session_setup_ntlmssp_state_destructor);
-
-	status = ntlmssp_client_start(state,
-				      lp_netbios_name(),
-				      lp_workgroup(),
-				      lp_client_ntlmv2_auth(),
-				      &state->ntlmssp_state);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-	ntlmssp_want_feature(state->ntlmssp_state,
-			     NTLMSSP_FEATURE_SESSION_KEY);
-	if (cli->use_ccache) {
-		ntlmssp_want_feature(state->ntlmssp_state,
-				     NTLMSSP_FEATURE_CCACHE);
-	}
-	status = ntlmssp_set_username(state->ntlmssp_state, user);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-	status = ntlmssp_set_domain(state->ntlmssp_state, domain);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-	if (cli->pw_nt_hash) {
-		status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
-	} else {
-		status = ntlmssp_set_password(state->ntlmssp_state, pass);
-	}
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
+	if (NT_STATUS_IS_OK(status)) {
+		state->local_ready = true;
 	}
-	status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
-				&blob_out);
-	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		goto fail;
+
+	if (state->local_ready && state->remote_ready) {
+		cli_session_setup_gensec_ready(req);
+		return;
 	}
 
-	state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
-	data_blob_free(&blob_out);
+	cli_session_setup_gensec_remote_next(req);
+}
 
-	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		state->cli->smb2.session = smbXcli_session_create(cli,
-								  cli->conn);
-		if (tevent_req_nomem(state->cli->smb2.session, req)) {
-			return tevent_req_post(req, ev);
-		}
+static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
+{
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
+	struct tevent_req *subreq = NULL;
+
+	if (state->remote_ready) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
 	}
 
-	subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
+	subreq = cli_sesssetup_blob_send(state, state->ev,
+					 state->cli, state->blob_out);
 	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, ev);
+		return;
 	}
-	tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
-	return req;
-fail:
-	tevent_req_nterror(req, status);
-	return tevent_req_post(req, ev);
+	tevent_req_set_callback(subreq,
+				cli_session_setup_gensec_remote_done,
+				req);
 }
 
-static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
+static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
 {
-	struct tevent_req *req = tevent_req_callback_data(
-		subreq, struct tevent_req);
-	struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
-		req, struct cli_session_setup_ntlmssp_state);
-	DATA_BLOB blob_in, msg_in, blob_out;
-	uint8_t *inbuf = NULL;
-	struct iovec *recv_iov = NULL;
-	bool parse_ret;
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
 	NTSTATUS status;
 
-	status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
-					 &inbuf, &recv_iov);
+	TALLOC_FREE(state->inbuf);
+	TALLOC_FREE(state->recv_iov);
+
+	status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
+					 &state->inbuf, &state->recv_iov);
 	TALLOC_FREE(subreq);
 	data_blob_free(&state->blob_out);
+	if (!NT_STATUS_IS_OK(status) &&
+	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
+	{
+		tevent_req_nterror(req, status);
+		return;
+	}
 
 	if (NT_STATUS_IS_OK(status)) {
-		if (state->cli->server_domain[0] == '\0') {
-			TALLOC_FREE(state->cli->server_domain);
-			state->cli->server_domain = talloc_strdup(state->cli,
-						state->ntlmssp_state->server.netbios_domain);
-			if (state->cli->server_domain == NULL) {
-				tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-				return;
-			}
-		}
-
-		if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
-			struct smbXcli_session *session = state->cli->smb2.session;
+		state->remote_ready = true;
+	}
 
-			if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
-				/*
-				 * Windows server does not set the
-				 * SMB2_SESSION_FLAG_IS_GUEST nor
-				 * SMB2_SESSION_FLAG_IS_NULL flag.
-				 *
-				 * This fix makes sure we do not try
-				 * to verify a signature on the final
-				 * session setup response.
-				 */
-				TALLOC_FREE(state->ntlmssp_state);
-				tevent_req_done(req);
-				return;
-			}
+	if (state->local_ready && state->remote_ready) {
+		cli_session_setup_gensec_ready(req);
+		return;
+	}
 
-			status = smb2cli_session_set_session_key(session,
-						state->ntlmssp_state->session_key,
-						recv_iov);
-			if (tevent_req_nterror(req, status)) {
-				return;
-			}
-		} else {
-			struct smbXcli_session *session = state->cli->smb1.session;
+	cli_session_setup_gensec_local_next(req);
+}
 
-			status = smb1cli_session_set_session_key(session,
-					state->ntlmssp_state->session_key);
-			if (tevent_req_nterror(req, status)) {
-				return;
-			}
+static void cli_session_setup_gensec_ready(struct tevent_req *req)
+{
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
+	const char *server_domain = NULL;
+	NTSTATUS status;
 
-			if (smb1cli_conn_activate_signing(
-				    state->cli->conn, state->ntlmssp_state->session_key,
-				    data_blob_null)
-			    && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
-				tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
-				return;
-			}
-		}
-		TALLOC_FREE(state->ntlmssp_state);
-		tevent_req_done(req);
-		return;
-	}
-	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		tevent_req_nterror(req, status);
+	if (state->blob_in.length != 0) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
 	}
 
-	if (blob_in.length == 0) {
-		tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+	if (state->blob_out.length != 0) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
 		return;
 	}
 
-	if ((state->turn == 1)
-	    && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		DATA_BLOB tmp_blob = data_blob_null;
-		/* the server might give us back two challenges */
-		parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
-						   &tmp_blob);
-		data_blob_free(&tmp_blob);
-	} else {
-		parse_ret = spnego_parse_auth_response(state, blob_in, status,
-						       OID_NTLMSSP, &msg_in);
-	}
-	state->turn += 1;
-
-	if (!parse_ret) {
-		DEBUG(3,("Failed to parse auth response\n"));
-		if (NT_STATUS_IS_OK(status)
-		    || NT_STATUS_EQUAL(status,
-				       NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-			tevent_req_nterror(
-				req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+	/*
+	 * gensec_ntlmssp_server_domain() returns NULL
+	 * if NTLMSSP is not used.
+	 *
+	 * We can remove this later
+	 * and leave the server domain empty for SMB2 and above
+	 * in future releases.
+	 */
+	server_domain = gensec_ntlmssp_server_domain(
+				state->auth_generic->gensec_security);
+
+	if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
+		TALLOC_FREE(state->cli->server_domain);
+		state->cli->server_domain = talloc_strdup(state->cli,
+					server_domain);
+		if (state->cli->server_domain == NULL) {
+			tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
 			return;
 		}
 	}
 
-	status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
-
-	if (!NT_STATUS_IS_OK(status)
-	    && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		TALLOC_FREE(state->ntlmssp_state);
-		tevent_req_nterror(req, status);
+	status = gensec_session_key(state->auth_generic->gensec_security,
+				    state, &state->session_key);
+	if (tevent_req_nterror(req, status)) {
 		return;
 	}
 
-	state->blob_out = spnego_gen_auth(state, blob_out);
-	if (tevent_req_nomem(state->blob_out.data, req)) {
-		return;
-	}
+	if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+		struct smbXcli_session *session = state->cli->smb2.session;
 
-	subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
-					 state->blob_out);
-	if (tevent_req_nomem(subreq, req)) {
-		return;
+		if (state->is_anonymous) {
+			/*
+			 * Windows server does not set the
+			 * SMB2_SESSION_FLAG_IS_GUEST nor
+			 * SMB2_SESSION_FLAG_IS_NULL flag.
+			 *
+			 * This fix makes sure we do not try
+			 * to verify a signature on the final
+			 * session setup response.
+			 */
+			tevent_req_done(req);
+			return;
+		}
+
+		status = smb2cli_session_set_session_key(session,
+							 state->session_key,
+							 state->recv_iov);
+		if (tevent_req_nterror(req, status)) {
+			return;
+		}
+	} else {
+		struct smbXcli_session *session = state->cli->smb1.session;
+		bool active;
+
+		status = smb1cli_session_set_session_key(session,
+							 state->session_key);
+		if (tevent_req_nterror(req, status)) {
+			return;
+		}
+
+		active = smb1cli_conn_activate_signing(state->cli->conn,
+						       state->session_key,
+						       data_blob_null);
+		if (active) {
+			bool ok;
+
+			ok = smb1cli_conn_check_signing(state->cli->conn,
+							state->inbuf, 1);
+			if (!ok) {
+				tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+				return;
+			}
+		}
 	}
-	tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
+
+	tevent_req_done(req);
 }
 
-static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
+static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
 {
-	struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
-		req, struct cli_session_setup_ntlmssp_state);
+	struct cli_session_setup_gensec_state *state =
+		tevent_req_data(req,
+		struct cli_session_setup_gensec_state);
 	NTSTATUS status;
 
 	if (tevent_req_is_nterror(req, &status)) {
@@ -1723,6 +1747,7 @@ static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
 struct cli_session_setup_spnego_state {
 	struct tevent_context *ev;
 	struct cli_state *cli;
+	const char *target_hostname;
 	const char *user;
 	const char *account;
 	const char *pass;
@@ -1739,14 +1764,14 @@ static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
 
 static struct tevent_req *cli_session_setup_spnego_send(
 	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
-	const char *user, const char *pass, const char *user_domain,
-	const char *dest_realm)
+	const char *user, const char *pass, const char *user_domain)
 {
 	struct tevent_req *req, *subreq;
 	struct cli_session_setup_spnego_state *state;
 	char *principal = NULL;
 	char *OIDs[ASN1_MAX_OIDS];
 	int i;
+	const char *dest_realm = cli_state_remote_realm(cli);
 	const DATA_BLOB *server_blob;
 
 	req = tevent_req_create(mem_ctx, &state,
@@ -1766,6 +1791,7 @@ static struct tevent_req *cli_session_setup_spnego_send(
 		return tevent_req_post(req, ev);
 	}
 
+	state->target_hostname = smbXcli_conn_remote_name(cli->conn);
 	server_blob = smbXcli_conn_server_gss_blob(cli->conn);
 
 	DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
@@ -1813,12 +1839,10 @@ static struct tevent_req *cli_session_setup_spnego_send(
 	 * and do not store results */
 
 	if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
-		const char *remote_name = smbXcli_conn_remote_name(cli->conn);
 		char *tmp;
 
-
 		tmp = cli_session_setup_get_principal(
-			talloc_tos(), principal, remote_name, dest_realm);
+			talloc_tos(), principal, state->target_hostname, dest_realm);
 		TALLOC_FREE(principal);
 		principal = tmp;
 
@@ -1840,8 +1864,11 @@ static struct tevent_req *cli_session_setup_spnego_send(
 		}
 
 		if (principal) {
-			subreq = cli_session_setup_kerberos_send(
-				state, ev, cli, principal);
+			subreq = cli_session_setup_gensec_send(
+				state, ev, cli,
+				state->account, pass, user_domain,
+				CRED_MUST_USE_KERBEROS,
+				"cifs", state->target_hostname, principal);
 			if (tevent_req_nomem(subreq, req)) {
 				return tevent_req_post(req, ev);
 			}
@@ -1854,8 +1881,11 @@ static struct tevent_req *cli_session_setup_spnego_send(
 #endif
 
 ntlmssp:
-	subreq = cli_session_setup_ntlmssp_send(
-		state, ev, cli, state->account, pass, user_domain);
+	subreq = cli_session_setup_gensec_send(
+		state, state->ev, state->cli,
+		state->account, state->pass, state->user_domain,
+		CRED_DONT_USE_KERBEROS,
+		"cifs", state->target_hostname, NULL);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -1871,9 +1901,11 @@ static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct cli_session_setup_spnego_state *state = tevent_req_data(
 		req, struct cli_session_setup_spnego_state);
+	NTSTATUS status;
 
-	state->result = cli_session_setup_kerberos_recv(subreq);
+	status = cli_session_setup_gensec_recv(subreq);
 	TALLOC_FREE(subreq);
+	state->result = ADS_ERROR_NT(status);
 
 	if (ADS_ERR_OK(state->result) ||
 	    !state->cli->fallback_after_kerberos) {
@@ -1881,9 +1913,11 @@ static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
 		return;
 	}
 
-	subreq = cli_session_setup_ntlmssp_send(
-		state, state->ev, state->cli, state->account, state->pass,
-		state->user_domain);
+	subreq = cli_session_setup_gensec_send(
+		state, state->ev, state->cli,
+		state->account, state->pass, state->user_domain,
+		CRED_DONT_USE_KERBEROS,
+		"cifs", state->target_hostname, NULL);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
@@ -1900,7 +1934,7 @@ static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
 		req, struct cli_session_setup_spnego_state);
 	NTSTATUS status;
 
-	status = cli_session_setup_ntlmssp_recv(subreq);
+	status = cli_session_setup_gensec_recv(subreq);
 	TALLOC_FREE(subreq);
 	state->result = ADS_ERROR_NT(status);
 	tevent_req_done(req);
@@ -2014,10 +2048,8 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
 	}
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		const char *remote_realm = cli_state_remote_realm(cli);
-
 		subreq = cli_session_setup_spnego_send(
-			state, ev, cli, user, pass, workgroup, remote_realm);
+			state, ev, cli, user, pass, workgroup);
 		if (tevent_req_nomem(subreq, req)) {
 			return tevent_req_post(req, ev);
 		}
@@ -2077,10 +2109,8 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
 	/* if the server supports extended security then use SPNEGO */
 
 	if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
-		const char *remote_realm = cli_state_remote_realm(cli);
-
 		subreq = cli_session_setup_spnego_send(
-			state, ev, cli, user, pass, workgroup, remote_realm);
+			state, ev, cli, user, pass, workgroup);
 		if (tevent_req_nomem(subreq, req)) {
 			return tevent_req_post(req, ev);
 		}
@@ -2089,6 +2119,17 @@ struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
 		return req;
 	} else {
 		/* otherwise do a NT1 style session setup */
+		if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
+			/*
+			 * Don't send an NTLMv2 response without NTLMSSP
+			 * if we want to use spnego support
+			 */
+			DEBUG(1, ("Server does not support EXTENDED_SECURITY "
+				  " but 'client use spnego = yes"
+				  " and 'client ntlmv2 auth = yes'\n"));
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return tevent_req_post(req, ev);
+		}
 
 		subreq = cli_session_setup_nt1_send(
 			state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
@@ -3111,6 +3152,8 @@ fail:
 struct cli_start_connection_state {
 	struct tevent_context *ev;
 	struct cli_state *cli;
+	int min_protocol;
+	int max_protocol;
 };
 
 static void cli_start_connection_connected(struct tevent_req *subreq);
@@ -3140,6 +3183,14 @@ static struct tevent_req *cli_start_connection_send(
 	}
 	state->ev = ev;
 
+	if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
+		state->min_protocol = lp_client_ipc_min_protocol();
+		state->max_protocol = lp_client_ipc_max_protocol();
+	} else {
+		state->min_protocol = lp_client_min_protocol();
+		state->max_protocol = lp_client_max_protocol();
+	}
+
 	subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
 				     0x20, my_name, signing_state, flags);
 	if (tevent_req_nomem(subreq, req)) {
@@ -3165,8 +3216,8 @@ static void cli_start_connection_connected(struct tevent_req *subreq)
 
 	subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
 				      state->cli->timeout,
-				      lp_client_min_protocol(),
-				      lp_client_max_protocol());
+				      state->min_protocol,
+				      state->max_protocol);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 6f28dfa..cfb3b16 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -170,6 +170,15 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
 		use_level_II_oplocks = true;
 	}
 
+	if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
+		/*
+		 * Ensure for IPC/RPC the default is to require
+		 * signing unless explicitly turned off by the
+		 * administrator.
+		 */
+		signing_state = lp_client_ipc_signing();
+	}
+
 	if (signing_state == SMB_SIGNING_DEFAULT) {
 		signing_state = lp_client_signing();
 	}
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 52c19a9..4a0fbcd 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -26,73 +26,6 @@
 #include "../lib/util/asn1.h"
 
 /*
-  generate a negTokenInit packet given a list of supported
-  OIDs (the mechanisms) a blob, and a principal name string
-*/
-
-DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
-				  const char *OIDs[],
-				  DATA_BLOB *psecblob,
-				  const char *principal)
-{
-	int i;
-	ASN1_DATA *data;
-	DATA_BLOB ret = data_blob_null;
-
-	data = asn1_init(talloc_tos());
-	if (data == NULL) {
-		return data_blob_null;
-	}
-
-	if (!asn1_push_tag(data,ASN1_APPLICATION(0))) goto err;
-	if (!asn1_write_OID(data,OID_SPNEGO)) goto err;
-	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
-	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;
-
-	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
-	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;
-	for (i=0; OIDs[i]; i++) {
-		if (!asn1_write_OID(data,OIDs[i])) goto err;
-	}
-	if (!asn1_pop_tag(data)) goto err;
-	if (!asn1_pop_tag(data)) goto err;
-
-	if (psecblob && psecblob->length && psecblob->data) {
-		if (!asn1_push_tag(data, ASN1_CONTEXT(2))) goto err;
-		if (!asn1_write_OctetString(data,psecblob->data,
-			psecblob->length)) goto err;
-		if (!asn1_pop_tag(data)) goto err;
-	}
-
-	if (principal) {
-		if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
-		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
-		if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
-		if (!asn1_write_GeneralString(data,principal)) goto err;
-		if (!asn1_pop_tag(data)) goto err;
-		if (!asn1_pop_tag(data)) goto err;
-		if (!asn1_pop_tag(data)) goto err;
-	}
-
-	if (!asn1_pop_tag(data)) goto err;
-	if (!asn1_pop_tag(data)) goto err;
-
-	if (!asn1_pop_tag(data)) goto err;
-
-	ret = data_blob_talloc(ctx, data->data, data->length);
-
-  err:
-
-	if (data->has_error) {
-		DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data->ofs));
-	}
-
-	asn1_free(data);
-
-	return ret;
-}
-
-/*
   parse a negTokenInit packet giving a GUID, a list of supported
   OIDs (the mechanisms) and a principal name string 
 */
@@ -143,7 +76,7 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 		if (!asn1_read_OID(data,ctx, &OIDs[i])) {
 			goto err;
 		}
-		if (data->has_error) {
+		if (asn1_has_error(data)) {
 			goto err;
 		}
 	}
@@ -209,11 +142,11 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 
 	if (!asn1_end_tag(data)) goto err;
 
-	ret = !data->has_error;
+	ret = !asn1_has_error(data);
 
   err:
 
-	if (data->has_error) {
+	if (asn1_has_error(data)) {
 		int j;
 		if (principal) {
 			TALLOC_FREE(*principal);
@@ -250,219 +183,23 @@ DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const ui
 	if (!asn1_write(data, ticket.data, ticket.length)) goto err;
 	if (!asn1_pop_tag(data)) goto err;
 
-	ret = data_blob_talloc(ctx, data->data, data->length);
-
-  err:
-
-	if (data->has_error) {
-		DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
+	if (!asn1_extract_blob(data, ctx, &ret)) {
+		goto err;
 	}
 
 	asn1_free(data);
-
-	return ret;
-}
-
-/* 
-   generate a SPNEGO krb5 negTokenInit packet, ready for a EXTENDED_SECURITY
-   kerberos session setup
-*/
-int spnego_gen_krb5_negTokenInit(TALLOC_CTX *ctx,
-			    const char *principal, int time_offset,
-			    DATA_BLOB *targ,
-			    DATA_BLOB *session_key_krb5, uint32_t extra_ap_opts,
-			    const char *ccname, time_t *expire_time)
-{
-	int retval;
-	DATA_BLOB tkt, tkt_wrapped;
-	const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
-
-	/* get a kerberos ticket for the service and extract the session key */
-	retval = cli_krb5_get_ticket(ctx, principal, time_offset,
-					  &tkt, session_key_krb5,
-					  extra_ap_opts, ccname,
-					  expire_time, NULL);
-	if (retval) {
-		return retval;
-	}
-
-	/* wrap that up in a nice GSS-API wrapping */
-	tkt_wrapped = spnego_gen_krb5_wrap(ctx, tkt, TOK_ID_KRB_AP_REQ);
-
-	/* and wrap that in a shiny SPNEGO wrapper */
-	*targ = spnego_gen_negTokenInit(ctx, krb_mechs, &tkt_wrapped, NULL);
-
-	data_blob_free(&tkt_wrapped);
-	data_blob_free(&tkt);
-
-	return retval;
-}
-
-
-/*
-  parse a spnego NTLMSSP challenge packet giving two security blobs
-*/
-bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
-			    DATA_BLOB *chal1, DATA_BLOB *chal2)
-{
-	bool ret = false;
-	ASN1_DATA *data;
-
-	ZERO_STRUCTP(chal1);
-	ZERO_STRUCTP(chal2);
-
-	data = asn1_init(talloc_tos());
-	if (data == NULL) {
-		return false;
-	}
-
-	if (!asn1_load(data, blob)) goto err;
-	if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
-	if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
-
-	if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
-	if (!asn1_check_enumerated(data,1)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
-	if (!asn1_check_OID(data, OID_NTLMSSP)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	if (!asn1_start_tag(data,ASN1_CONTEXT(2))) goto err;
-	if (!asn1_read_OctetString(data, ctx, chal1)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	/* the second challenge is optional (XP doesn't send it) */
-	if (asn1_tag_remaining(data)) {
-		if (!asn1_start_tag(data,ASN1_CONTEXT(3))) goto err;
-		if (!asn1_read_OctetString(data, ctx, chal2)) goto err;
-		if (!asn1_end_tag(data)) goto err;
-	}
-
-	if (!asn1_end_tag(data)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	ret = !data->has_error;
+	data = NULL;
 
   err:
 
-	if (data->has_error) {
-		data_blob_free(chal1);
-		data_blob_free(chal2);
-	}
-
-	asn1_free(data);
-	return ret;
-}
-
-
-/*
- generate a SPNEGO auth packet. This will contain the encrypted passwords
-*/
-DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob)
-{
-	ASN1_DATA *data;
-	DATA_BLOB ret = data_blob_null;
-
-	data = asn1_init(talloc_tos());
-	if (data == NULL) {
-		return data_blob_null;
-	}
-
-	if (!asn1_push_tag(data, ASN1_CONTEXT(1))) goto err;
-	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
-	if (!asn1_push_tag(data, ASN1_CONTEXT(2))) goto err;
-	if (!asn1_write_OctetString(data,blob.data,blob.length)) goto err;
-	if (!asn1_pop_tag(data)) goto err;
-	if (!asn1_pop_tag(data)) goto err;
-	if (!asn1_pop_tag(data)) goto err;
-
-	ret = data_blob_talloc(ctx, data->data, data->length);
-
- err:
-
-	asn1_free(data);
-
-	return ret;
-}
-
-/*
- parse a SPNEGO auth packet. This contains the encrypted passwords
-*/
-bool spnego_parse_auth_response(TALLOC_CTX *ctx,
-			        DATA_BLOB blob, NTSTATUS nt_status,
-				const char *mechOID,
-				DATA_BLOB *auth)
-{
-	ASN1_DATA *data;
-	uint8_t negResult;
-	bool ret = false;
-
-	if (NT_STATUS_IS_OK(nt_status)) {
-		negResult = SPNEGO_ACCEPT_COMPLETED;
-	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		negResult = SPNEGO_ACCEPT_INCOMPLETE;
-	} else {
-		negResult = SPNEGO_REJECT;
-	}
-
-	data = asn1_init(talloc_tos());
-	if (data == NULL) {
-		return false;
-	}
-
-	*auth = data_blob_null;
-
-	if (!asn1_load(data, blob)) goto err;
-	if (!asn1_start_tag(data, ASN1_CONTEXT(1))) goto err;
-	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto err;
-	if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto err;
-	if (!asn1_check_enumerated(data, negResult)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	if (asn1_tag_remaining(data)) {
-		if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
-		if (!asn1_check_OID(data, mechOID)) goto err;
-		if (!asn1_end_tag(data)) goto err;
-
-		if (asn1_tag_remaining(data)) {
-			if (!asn1_start_tag(data,ASN1_CONTEXT(2))) goto err;
-			if (!asn1_read_OctetString(data, ctx, auth)) goto err;
-			if (!asn1_end_tag(data)) goto err;
+	if (data != NULL) {
+		if (asn1_has_error(data)) {
+			DEBUG(1, ("Failed to build krb5 wrapper at offset %d\n",
+				  (int)asn1_current_ofs(data)));
 		}
-	} else if (negResult == SPNEGO_ACCEPT_INCOMPLETE) {
-		data->has_error = 1;
-		goto err;
-	}
-
-	/* Binding against Win2K DC returns a duplicate of the responseToken in
-	 * the optional mechListMIC field. This is a bug in Win2K. We ignore
-	 * this field if it exists. Win2K8 may return a proper mechListMIC at
-	 * which point we need to implement the integrity checking. */
-	if (asn1_tag_remaining(data)) {
-		DATA_BLOB mechList = data_blob_null;
-		if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto err;
-		if (!asn1_read_OctetString(data, ctx, &mechList)) goto err;
-		data_blob_free(&mechList);
-		if (!asn1_end_tag(data)) goto err;
-		DEBUG(5,("spnego_parse_auth_response received mechListMIC, "
-		    "ignoring.\n"));
-	}
-
-	if (!asn1_end_tag(data)) goto err;
-	if (!asn1_end_tag(data)) goto err;
-
-	ret = !data->has_error;
 
-  err:
-
-	if (data->has_error) {
-		DEBUG(3,("spnego_parse_auth_response failed at %d\n", (int)data->ofs));
 		asn1_free(data);
-		data_blob_free(auth);
-		return false;
 	}
 
-	asn1_free(data);
 	return ret;
 }
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
deleted file mode 100644
index e661aeb..0000000
--- a/source3/libsmb/ntlmssp.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
-   Unix SMB/Netbios implementation.
-   Version 3.0
-   handle NLTMSSP, server side
-
-   Copyright (C) Andrew Tridgell      2001
-   Copyright (C) Andrew Bartlett 2001-2010
-   Copyright (C) Stefan Metzmacher 2005
-
-   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 "../auth/ntlmssp/ntlmssp.h"
-#include "../auth/ntlmssp/ntlmssp_private.h"
-#include "../libcli/auth/libcli_auth.h"
-#include "../librpc/gen_ndr/ndr_ntlmssp.h"
-#include "../auth/ntlmssp/ntlmssp_ndr.h"
-#include "../lib/crypto/md5.h"
-#include "../lib/crypto/arcfour.h"
-#include "../lib/crypto/hmacmd5.h"
-#include "../nsswitch/libwbclient/wbclient.h"
-
-static NTSTATUS ntlmssp3_client_initial(struct ntlmssp_state *ntlmssp_state,
-				       TALLOC_CTX *out_mem_ctx,
-				       DATA_BLOB reply, DATA_BLOB *next_request);
-static NTSTATUS ntlmssp3_client_challenge(struct ntlmssp_state *ntlmssp_state,
-				         TALLOC_CTX *out_mem_ctx, /* Unused at this time */
-					 const DATA_BLOB reply, DATA_BLOB *next_request);
-/**
- * Callbacks for NTLMSSP - for both client and server operating modes
- *
- */
-
-static const struct ntlmssp_callbacks {
-	enum ntlmssp_role role;
-	enum ntlmssp_message_type ntlmssp_command;
-	NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
-		       TALLOC_CTX *out_mem_ctx,
-		       DATA_BLOB in, DATA_BLOB *out);
-} ntlmssp_callbacks[] = {
-	{NTLMSSP_CLIENT, NTLMSSP_INITIAL, ntlmssp3_client_initial},
-	{NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp3_client_challenge},
-	{NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL},
-	{NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL}
-};
-
-/**
- * Set a username on an NTLMSSP context - ensures it is talloc()ed
- *
- */
-
-NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user)
-{
-	ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" );
-	if (!ntlmssp_state->user) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	return NT_STATUS_OK;
-}
-
-/**
- * Converts a password to the hashes on an NTLMSSP context.
- *
- */
-NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password)
-{
-	uint8_t lm_hash[16];
-	uint8_t nt_hash[16];
-
-	TALLOC_FREE(ntlmssp_state->lm_hash);
-	TALLOC_FREE(ntlmssp_state->nt_hash);
-
-	if (password == NULL) {
-		return NT_STATUS_OK;
-	}
-
-	if (E_deshash(password, lm_hash)) {
-		ntlmssp_state->lm_hash = (uint8_t *)
-			talloc_memdup(ntlmssp_state, lm_hash, 16);
-		if (!ntlmssp_state->lm_hash) {
-			return NT_STATUS_NO_MEMORY;
-		}
-	}
-
-	E_md4hash(password, nt_hash);
-
-	ntlmssp_state->nt_hash = (uint8_t *)
-		talloc_memdup(ntlmssp_state, nt_hash, 16);
-	if (!ntlmssp_state->nt_hash) {
-		TALLOC_FREE(ntlmssp_state->lm_hash);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	return NT_STATUS_OK;
-}
-
-NTSTATUS ntlmssp_set_password_hash(struct ntlmssp_state *state,
-				   const char *pwhash)
-{
-	char nt_hash[16];
-	size_t converted;
-
-	converted = strhex_to_str(
-		nt_hash, sizeof(nt_hash), pwhash, strlen(pwhash));
-	if (converted != sizeof(nt_hash)) {
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	TALLOC_FREE(state->lm_hash);
-	TALLOC_FREE(state->nt_hash);
-
-	state->nt_hash = (uint8_t *)talloc_memdup(state, nt_hash, 16);
-	if (!state->nt_hash) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	return NT_STATUS_OK;
-}
-
-/**
- * Set a domain on an NTLMSSP context - ensures it is talloc()ed
- *
- */
-NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain)
-{
-	ntlmssp_state->domain = talloc_strdup(ntlmssp_state,
-					      domain ? domain : "" );
-	if (!ntlmssp_state->domain) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	return NT_STATUS_OK;
-}
-
-/**
- * Request features for the NTLMSSP negotiation
- *
- * @param ntlmssp_state NTLMSSP state
- * @param feature_list List of space separated features requested from NTLMSSP.
- */
-void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list)
-{
-	/*
-	 * We need to set this to allow a later SetPassword
-	 * via the SAMR pipe to succeed. Strange.... We could
-	 * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
-	 */
-	if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
-	}
-	if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
-		ntlmssp_state->use_ccache = true;
-	}
-}
-
-/**
- * Request a feature for the NTLMSSP negotiation
- *
- * @param ntlmssp_state NTLMSSP state
- * @param feature Bit flag specifying the requested feature
- */
-void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature)
-{
-	/* As per JRA's comment above */
-	if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if (feature & NTLMSSP_FEATURE_SIGN) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if (feature & NTLMSSP_FEATURE_SEAL) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
-	}
-	if (feature & NTLMSSP_FEATURE_CCACHE) {
-		ntlmssp_state->use_ccache = true;
-	}
-}
-
-/**
- * Next state function for the NTLMSSP state machine
- *
- * @param ntlmssp_state NTLMSSP State
- * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB
- * @param out The reply, as an allocated DATA_BLOB, caller to free.
- * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
- */
-
-NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
-			const DATA_BLOB input, DATA_BLOB *out)
-{
-	uint32_t ntlmssp_command;
-	int i;
-
-	if (ntlmssp_state->expected_state == NTLMSSP_DONE) {
-		/* Called update after negotiations finished. */
-		DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n"));
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	*out = data_blob_null;
-
-	if (!input.length) {
-		switch (ntlmssp_state->role) {
-		case NTLMSSP_CLIENT:
-			ntlmssp_command = NTLMSSP_INITIAL;
-			break;
-		case NTLMSSP_SERVER:
-			/* 'datagram' mode - no neg packet */
-			ntlmssp_command = NTLMSSP_NEGOTIATE;
-			break;
-		default:
-			DEBUG(1, ("Invalid role: %d\n", ntlmssp_state->role));
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	} else {
-		if (!msrpc_parse(ntlmssp_state, &input, "Cd",
-				 "NTLMSSP",
-				 &ntlmssp_command)) {
-			DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n"));
-			dump_data(2, input.data, input.length);
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	}
-
-	if (ntlmssp_command != ntlmssp_state->expected_state) {
-		DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state));
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	for (i=0; ntlmssp_callbacks[i].fn; i++) {
-		if (ntlmssp_callbacks[i].role == ntlmssp_state->role
-		    && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) {
-			return ntlmssp_callbacks[i].fn(ntlmssp_state, ntlmssp_state, input, out);
-		}
-	}
-
-	DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n",
-		  ntlmssp_state->role, ntlmssp_command));
-
-	return NT_STATUS_INVALID_PARAMETER;
-}
-
-/*********************************************************************
- Client side NTLMSSP
-*********************************************************************/
-
-/**
- * Next state function for the Initial packet
- *
- * @param ntlmssp_state NTLMSSP State
- * @param request The request, as a DATA_BLOB.  reply.data must be NULL
- * @param request The reply, as an allocated DATA_BLOB, caller to free.
- * @return Errors or NT_STATUS_OK.
- */
-
-static NTSTATUS ntlmssp3_client_initial(struct ntlmssp_state *ntlmssp_state,
-				       TALLOC_CTX *out_mem_ctx,
-				       DATA_BLOB in, DATA_BLOB *out)
-{
-	const char *domain = ntlmssp_state->client.netbios_domain;
-	const char *workstation = ntlmssp_state->client.netbios_name;
-	NTSTATUS status;
-
-	/* These don't really matter in the initial packet, so don't panic if they are not set */
-	if (!domain) {
-		domain = "";
-	}
-
-	if (!workstation) {
-		workstation = "";
-	}
-
-	if (ntlmssp_state->unicode) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
-	} else {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
-	}
-
-	if (ntlmssp_state->use_ntlmv2) {
-		ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
-	}
-
-	/* generate the ntlmssp negotiate packet */
-	status = msrpc_gen(out_mem_ctx,
-		  out, "CddAA",
-		  "NTLMSSP",
-		  NTLMSSP_NEGOTIATE,
-		  ntlmssp_state->neg_flags,
-		  domain,
-		  workstation);
-
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0, ("ntlmssp_client_initial: failed to generate "
-			  "ntlmssp negotiate packet\n"));
-		return status;
-	}
-
-	if (DEBUGLEVEL >= 10) {
-		struct NEGOTIATE_MESSAGE *negotiate = talloc(
-			talloc_tos(), struct NEGOTIATE_MESSAGE);
-		if (negotiate != NULL) {
-			status = ntlmssp_pull_NEGOTIATE_MESSAGE(
-				out, negotiate, negotiate);
-			if (NT_STATUS_IS_OK(status)) {
-				NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
-						negotiate);
-			}
-			TALLOC_FREE(negotiate);
-		}
-	}
-
-	ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
-
-	return NT_STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-bool ntlmssp_is_anonymous(struct ntlmssp_state *ntlmssp_state)
-{
-	const char *user = ntlmssp_state->user;
-
-	if (user == NULL) {
-		return true;
-	}
-
-	if (strlen(user) == 0) {
-		return true;
-	}
-
-	return false;
-}
-
-/**
- * Next state function for the Challenge Packet.  Generate an auth packet.
- *
- * @param ntlmssp_state NTLMSSP State
- * @param request The request, as a DATA_BLOB.  reply.data must be NULL
- * @param request The reply, as an allocated DATA_BLOB, caller to free.
- * @return Errors or NT_STATUS_OK.
- */
-
-static NTSTATUS ntlmssp3_client_challenge(struct ntlmssp_state *ntlmssp_state,
-				         TALLOC_CTX *out_mem_ctx, /* Unused at this time */
-					 const DATA_BLOB reply, DATA_BLOB *next_request)
-{
-	uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
-	DATA_BLOB server_domain_blob;
-	DATA_BLOB challenge_blob;
-	DATA_BLOB struct_blob = data_blob_null;
-	char *server_domain;
-	const char *chal_parse_string;
-	const char *chal_parse_string_short = NULL;
-	const char *auth_gen_string;
-	DATA_BLOB lm_response = data_blob_null;
-	DATA_BLOB nt_response = data_blob_null;
-	DATA_BLOB session_key = data_blob_null;
-	DATA_BLOB encrypted_session_key = data_blob_null;
-	NTSTATUS nt_status = NT_STATUS_OK;
-	bool anon = ntlmssp_is_anonymous(ntlmssp_state);
-
-	if (!anon && ntlmssp_state->use_ccache) {
-		struct wbcCredentialCacheParams params;
-		struct wbcCredentialCacheInfo *info = NULL;
-		struct wbcAuthErrorInfo *error = NULL;
-		struct wbcNamedBlob auth_blob;
-		struct wbcBlob *wbc_next = NULL;
-		struct wbcBlob *wbc_session_key = NULL;
-		wbcErr wbc_status;
-		int i;
-
-		/*
-		 * We need to set the netbios name or we are not able to connect
-		 *  a Windows DC.
-		 */
-		if (ntlmssp_state->server.netbios_domain == NULL ||
-		    ntlmssp_state->server.netbios_domain[0] == '\0') {
-			ntlmssp_state->server.netbios_domain = ntlmssp_state->domain;
-		}
-
-		params.account_name = ntlmssp_state->user;
-		params.domain_name = ntlmssp_state->domain;
-		params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
-
-		auth_blob.name = "challenge_blob";
-		auth_blob.flags = 0;
-		auth_blob.blob.data = reply.data;
-		auth_blob.blob.length = reply.length;
-		params.num_blobs = 1;
-		params.blobs = &auth_blob;
-
-		wbc_status = wbcCredentialCache(&params, &info, &error);
-		wbcFreeMemory(error);
-		if (!WBC_ERROR_IS_OK(wbc_status)) {
-			goto noccache;
-		}
-
-		for (i=0; i<info->num_blobs; i++) {
-			if (strequal(info->blobs[i].name, "auth_blob")) {
-				wbc_next = &info->blobs[i].blob;
-			}
-			if (strequal(info->blobs[i].name, "session_key")) {
-				wbc_session_key = &info->blobs[i].blob;
-			}
-		}
-		if ((wbc_next == NULL) || (wbc_session_key == NULL)) {
-			wbcFreeMemory(info);
-			goto noccache;
-		}
-
-		*next_request = data_blob_talloc(ntlmssp_state,
-						 wbc_next->data,
-						 wbc_next->length);
-		ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state,
-							      wbc_session_key->data,
-							      wbc_session_key->length);
-
-		wbcFreeMemory(info);
-		goto done;
-	}
-
-noccache:
-
-	if (!msrpc_parse(ntlmssp_state, &reply, "CdBd",
-			 "NTLMSSP",
-			 &ntlmssp_command,
-			 &server_domain_blob,
-			 &chal_flags)) {
-		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
-		dump_data(2, reply.data, reply.length);
-
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	if (DEBUGLEVEL >= 10) {
-		struct CHALLENGE_MESSAGE *challenge = talloc(
-			talloc_tos(), struct CHALLENGE_MESSAGE);
-		if (challenge != NULL) {
-			NTSTATUS status;
-			challenge->NegotiateFlags = chal_flags;
-			status = ntlmssp_pull_CHALLENGE_MESSAGE(
-				&reply, challenge, challenge);
-			if (NT_STATUS_IS_OK(status)) {
-				NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
-						challenge);
-			}
-			TALLOC_FREE(challenge);
-		}
-	}
-
-	data_blob_free(&server_domain_blob);
-
-	DEBUG(3, ("Got challenge flags:\n"));
-	debug_ntlmssp_flags(chal_flags);
-
-	ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());
-
-	if (ntlmssp_state->unicode) {
-		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
-			chal_parse_string = "CdUdbddB";
-		} else {
-			chal_parse_string = "CdUdbdd";
-			chal_parse_string_short = "CdUdb";
-		}
-		auth_gen_string = "CdBBUUUBd";
-	} else {
-		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
-			chal_parse_string = "CdAdbddB";
-		} else {
-			chal_parse_string = "CdAdbdd";
-			chal_parse_string_short = "CdAdb";
-		}
-
-		auth_gen_string = "CdBBAAABd";
-	}
-
-	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
-	debug_ntlmssp_flags(ntlmssp_state->neg_flags);
-
-	if (!msrpc_parse(ntlmssp_state, &reply, chal_parse_string,
-			 "NTLMSSP",
-			 &ntlmssp_command,
-			 &server_domain,
-			 &chal_flags,
-			 &challenge_blob, 8,
-			 &unkn1, &unkn2,
-			 &struct_blob)) {
-
-		bool ok = false;
-
-		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
-
-		if (chal_parse_string_short != NULL) {
-			/*
-			 * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
-			 * is not used, some NTLMSSP servers don't return
-			 * the unused unkn1 and unkn2 fields.
-			 * See bug:
-			 * https://bugzilla.samba.org/show_bug.cgi?id=10016
-			 * for packet traces.
-			 * Try and parse again without them.
-			 */
-			ok = msrpc_parse(ntlmssp_state, &reply,
-				chal_parse_string_short,
-				"NTLMSSP",
-				&ntlmssp_command,
-				&server_domain,
-				&chal_flags,
-				&challenge_blob, 8);
-			if (!ok) {
-				DEBUG(1, ("Failed to short parse "
-					"the NTLMSSP Challenge: (#2)\n"));
-			}
-		}
-
-		if (!ok) {
-			dump_data(2, reply.data, reply.length);
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	}
-
-	if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
-		ntlmssp_state->server.is_standalone = true;
-	} else {
-		ntlmssp_state->server.is_standalone = false;
-	}
-	/* TODO: parse struct_blob and fill in the rest */
-	ntlmssp_state->server.netbios_name = "";
-	ntlmssp_state->server.netbios_domain = server_domain;
-	ntlmssp_state->server.dns_name = "";
-	ntlmssp_state->server.dns_domain = "";
-
-	if (challenge_blob.length != 8) {
-		data_blob_free(&struct_blob);
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
-	if (anon || !ntlmssp_state->nt_hash) {
-		static const uint8_t zeros[16] = {0, };
-		/* do nothing - blobs are zero length */
-
-		/* session key is all zeros */
-		session_key = data_blob_talloc(ntlmssp_state, zeros, 16);
-
-		/* not doing NLTM2 without a password */
-		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
-	} else if (ntlmssp_state->use_ntlmv2) {
-		if (!struct_blob.length) {
-			/* be lazy, match win2k - we can't do NTLMv2 without it */
-			DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-
-		/* TODO: if the remote server is standalone, then we should replace 'domain'
-		   with the server name as supplied above */
-
-		if (!SMBNTLMv2encrypt_hash(ntlmssp_state,
-					   ntlmssp_state->user,
-					   ntlmssp_state->domain,
-					   ntlmssp_state->nt_hash, &challenge_blob,
-					   &struct_blob,
-					   &lm_response, &nt_response, NULL,
-					   &session_key)) {
-			data_blob_free(&challenge_blob);
-			data_blob_free(&struct_blob);
-			return NT_STATUS_NO_MEMORY;
-		}
-	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-		MD5_CTX md5_session_nonce_ctx;
-		uint8_t session_nonce[16];
-		uint8_t session_nonce_hash[16];
-		uint8_t user_session_key[16];
-
-		lm_response = data_blob_talloc(ntlmssp_state, NULL, 24);
-		generate_random_buffer(lm_response.data, 8);
-		memset(lm_response.data+8, 0, 16);
-
-		memcpy(session_nonce, challenge_blob.data, 8);
-		memcpy(&session_nonce[8], lm_response.data, 8);
-
-		MD5Init(&md5_session_nonce_ctx);
-		MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
-		MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
-		MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
-
-		DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
-		DEBUG(5, ("challenge is: \n"));
-		dump_data(5, session_nonce_hash, 8);
-
-		nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
-		SMBNTencrypt_hash(ntlmssp_state->nt_hash,
-				  session_nonce_hash,
-				  nt_response.data);
-
-		session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
-
-		SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, user_session_key);
-		hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
-		dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
-	} else {
-		/* lanman auth is insecure, it may be disabled */
-		if (lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
-			lm_response = data_blob_talloc(ntlmssp_state,
-						       NULL, 24);
-			SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
-				   lm_response.data);
-		}
-
-		nt_response = data_blob_talloc(ntlmssp_state, NULL, 24);
-		SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
-			     nt_response.data);
-
-		session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
-		if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
-		    && lp_client_lanman_auth() && ntlmssp_state->lm_hash) {
-			SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
-					session_key.data);
-			dump_data_pw("LM session key\n", session_key.data, session_key.length);
-		} else {
-			SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, session_key.data);
-			dump_data_pw("NT session key:\n", session_key.data, session_key.length);
-		}
-	}
-	data_blob_free(&struct_blob);
-
-	/* Key exchange encryptes a new client-generated session key with
-	   the password-derived key */
-	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
-		/* Make up a new session key */
-		uint8_t client_session_key[16];
-		generate_random_buffer(client_session_key, sizeof(client_session_key));
-
-		/* Encrypt the new session key with the old one */
-		encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
-		dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
-		arcfour_crypt_blob(encrypted_session_key.data, encrypted_session_key.length, &session_key);
-		dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
-
-		/* Mark the new session key as the 'real' session key */
-		data_blob_free(&session_key);
-		session_key = data_blob_talloc(ntlmssp_state,
-					       client_session_key,
-					       sizeof(client_session_key));
-	}
-
-	/* this generates the actual auth packet */
-	nt_status = msrpc_gen(ntlmssp_state, next_request, auth_gen_string,
-		       "NTLMSSP",
-		       NTLMSSP_AUTH,
-		       lm_response.data, lm_response.length,
-		       nt_response.data, nt_response.length,
-		       ntlmssp_state->domain,
-		       ntlmssp_state->user,
-		       ntlmssp_state->client.netbios_name,
-		       encrypted_session_key.data, encrypted_session_key.length,
-		       ntlmssp_state->neg_flags);
-
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	if (DEBUGLEVEL >= 10) {
-		struct AUTHENTICATE_MESSAGE *authenticate = talloc(
-			talloc_tos(), struct AUTHENTICATE_MESSAGE);
-		if (authenticate != NULL) {
-			NTSTATUS status;
-			authenticate->NegotiateFlags =
-				ntlmssp_state->neg_flags;
-			status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
-				next_request, authenticate, authenticate);
-			if (NT_STATUS_IS_OK(status)) {
-				NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
-						authenticate);
-			}
-			TALLOC_FREE(authenticate);
-		}
-	}
-
-	data_blob_free(&encrypted_session_key);
-
-	data_blob_free(&ntlmssp_state->chal);
-
-	ntlmssp_state->session_key = session_key;
-
-	ntlmssp_state->chal = challenge_blob;
-	ntlmssp_state->lm_resp = lm_response;
-	ntlmssp_state->nt_resp = nt_response;
-
-done:
-
-	ntlmssp_state->expected_state = NTLMSSP_DONE;
-
-	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
-		DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
-	}
-
-	return nt_status;
-}
-
-NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
-			      const char *netbios_name,
-			      const char *netbios_domain,
-			      bool use_ntlmv2,
-			      struct ntlmssp_state **_ntlmssp_state)
-{
-	struct ntlmssp_state *ntlmssp_state;
-
-	if (!netbios_name) {
-		netbios_name = "";
-	}
-
-	if (!netbios_domain) {
-		netbios_domain = "";
-	}
-
-	ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
-	if (!ntlmssp_state) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	ntlmssp_state->role = NTLMSSP_CLIENT;
-
-	ntlmssp_state->unicode = True;
-
-	ntlmssp_state->use_ntlmv2 = use_ntlmv2;
-
-	ntlmssp_state->expected_state = NTLMSSP_INITIAL;
-
-	ntlmssp_state->neg_flags =
-		NTLMSSP_NEGOTIATE_128 |
-		NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
-		NTLMSSP_NEGOTIATE_NTLM |
-		NTLMSSP_NEGOTIATE_NTLM2 |
-		NTLMSSP_NEGOTIATE_KEY_EXCH |
-		NTLMSSP_REQUEST_TARGET;
-
-	ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
-	if (!ntlmssp_state->client.netbios_name) {
-		talloc_free(ntlmssp_state);
-		return NT_STATUS_NO_MEMORY;
-	}
-	ntlmssp_state->client.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
-	if (!ntlmssp_state->client.netbios_domain) {
-		talloc_free(ntlmssp_state);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	*_ntlmssp_state = ntlmssp_state;
-	return NT_STATUS_OK;
-}
diff --git a/source3/libsmb/ntlmssp_wrap.c b/source3/libsmb/ntlmssp_wrap.c
deleted file mode 100644
index 46f68ae..0000000
--- a/source3/libsmb/ntlmssp_wrap.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-   NLTMSSP wrappers
-
-   Copyright (C) Andrew Tridgell      2001
-   Copyright (C) Andrew Bartlett 2001-2003,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/>.
-*/
-
-#include "includes.h"
-#include "auth/ntlmssp/ntlmssp.h"
-#include "auth/ntlmssp/ntlmssp_private.h"
-#include "auth_generic.h"
-#include "auth/gensec/gensec.h"
-#include "auth/gensec/gensec_internal.h"
-#include "auth/credentials/credentials.h"
-#include "librpc/rpc/dcerpc.h"
-#include "lib/param/param.h"
-
-static NTSTATUS gensec_ntlmssp3_client_update(struct gensec_security *gensec_security,
-					      TALLOC_CTX *out_mem_ctx,
-					      struct tevent_context *ev,
-					      const DATA_BLOB request,
-					      DATA_BLOB *reply)
-{
-	NTSTATUS status;
-	struct gensec_ntlmssp_context *gensec_ntlmssp =
-		talloc_get_type_abort(gensec_security->private_data,
-				      struct gensec_ntlmssp_context);
-
-	status = ntlmssp_update(gensec_ntlmssp->ntlmssp_state, request, reply);
-	if (NT_STATUS_IS_OK(status) ||
-	    NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		talloc_steal(out_mem_ctx, reply->data);
-	}
-
-	return status;
-}
-
-static NTSTATUS gensec_ntlmssp3_client_start(struct gensec_security *gensec_security)
-{
-	NTSTATUS nt_status;
-	struct gensec_ntlmssp_context *gensec_ntlmssp;
-	const char *user, *domain;
-	const char *password;
-
-	nt_status = gensec_ntlmssp_start(gensec_security);
-	NT_STATUS_NOT_OK_RETURN(nt_status);
-
-	gensec_ntlmssp =
-		talloc_get_type_abort(gensec_security->private_data,
-				      struct gensec_ntlmssp_context);
-
-	nt_status = ntlmssp_client_start(gensec_ntlmssp,
-					 lp_netbios_name(), lp_workgroup(),
-					 lp_client_ntlmv2_auth(), &gensec_ntlmssp->ntlmssp_state);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
-	}
-
-	cli_credentials_get_ntlm_username_domain(gensec_security->credentials, gensec_ntlmssp, &user, &domain);
-	if (!user || !domain) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	nt_status = ntlmssp_set_username(gensec_ntlmssp->ntlmssp_state, user);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
-	}
-
-	nt_status = ntlmssp_set_domain(gensec_ntlmssp->ntlmssp_state, domain);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
-	}
-
-	password = cli_credentials_get_password(gensec_security->credentials);
-	if (!password) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	nt_status = ntlmssp_set_password(gensec_ntlmssp->ntlmssp_state, password);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
-	}
-
-	if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
-		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
-		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	}
-	if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
-		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
-	}
-
-	return NT_STATUS_OK;
-}
-
-static const char *gensec_ntlmssp3_client_oids[] = {
-	GENSEC_OID_NTLMSSP,
-	NULL
-};
-
-const struct gensec_security_ops gensec_ntlmssp3_client_ops = {
-	.name		= "ntlmssp3_client",
-	.sasl_name	= GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */
-	.auth_type	= DCERPC_AUTH_TYPE_NTLMSSP,
-	.oid            = gensec_ntlmssp3_client_oids,
-	.client_start   = gensec_ntlmssp3_client_start,
-	.magic 	        = gensec_ntlmssp_magic,
-	.update 	= gensec_ntlmssp3_client_update,
-	.sig_size	= gensec_ntlmssp_sig_size,
-	.sign_packet	= gensec_ntlmssp_sign_packet,
-	.check_packet	= gensec_ntlmssp_check_packet,
-	.seal_packet	= gensec_ntlmssp_seal_packet,
-	.unseal_packet	= gensec_ntlmssp_unseal_packet,
-	.wrap           = gensec_ntlmssp_wrap,
-	.unwrap         = gensec_ntlmssp_unwrap,
-	.session_key	= gensec_ntlmssp_session_key,
-	.have_feature   = gensec_ntlmssp_have_feature,
-	.enabled        = true,
-	.priority       = GENSEC_NTLMSSP
-};
diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c
index 4676b72..49b9ad6 100644
--- a/source3/libsmb/passchange.c
+++ b/source3/libsmb/passchange.c
@@ -57,7 +57,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
 	*err_str = NULL;
 
 	result = cli_connect_nb(remote_machine, NULL, 0, 0x20, NULL,
-				SMB_SIGNING_DEFAULT, 0, &cli);
+				SMB_SIGNING_IPC_DEFAULT, 0, &cli);
 	if (!NT_STATUS_IS_OK(result)) {
 		if (asprintf(err_str, "Unable to connect to SMB server on "
 			 "machine %s. Error was : %s.\n",
@@ -67,8 +67,9 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
 		return result;
 	}
 
-	result = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
-				 PROTOCOL_NT1);
+	result = smbXcli_negprot(cli->conn, cli->timeout,
+				 lp_client_ipc_min_protocol(),
+				 lp_client_ipc_max_protocol());
 
 	if (!NT_STATUS_IS_OK(result)) {
 		if (asprintf(err_str, "machine %s rejected the negotiate "
diff --git a/source3/pam_smbpass/wscript_build b/source3/pam_smbpass/wscript_build
index a4eaa6c..fb760b4 100644
--- a/source3/pam_smbpass/wscript_build
+++ b/source3/pam_smbpass/wscript_build
@@ -8,7 +8,7 @@ if bld.CONFIG_SET('WITH_PAM_MODULES'):
                   support.c''',
         allow_warnings=True,
         deps='''tdb talloc pam PAM_ERRORS wbclient cap asn1util param pdb
-                LIBNTLMSSP LIBTSOCKET''',
+                LIBTSOCKET''',
         cflags='-DLOCALEDIR=\"%s/locale\"' % bld.env.DATADIR,
         realname='pam_smbpass.so',
         install_path='${PAMMODULESDIR}',
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index c576b22..f357eb5 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -70,6 +70,7 @@
 #include "dbwrap/dbwrap_rbt.h"
 #include "../lib/util/bitmap.h"
 #include "librpc/gen_ndr/nbt.h"
+#include "source4/lib/tls/tls.h"
 
 #ifdef HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
@@ -639,6 +640,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.server_min_protocol = PROTOCOL_LANMAN1;
 	Globals._client_max_protocol = PROTOCOL_DEFAULT;
 	Globals.client_min_protocol = PROTOCOL_CORE;
+	Globals._client_ipc_max_protocol = PROTOCOL_DEFAULT;
+	Globals._client_ipc_min_protocol = PROTOCOL_DEFAULT;
 	Globals._security = SEC_AUTO;
 	Globals.encrypt_passwords = true;
 	Globals.client_schannel = Auto;
@@ -691,9 +694,12 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.client_plaintext_auth = false;	/* Do NOT use a plaintext password even if is requested by the server */
 	Globals.lanman_auth = false;	/* Do NOT use the LanMan hash, even if it is supplied */
 	Globals.ntlm_auth = true;	/* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
+	Globals.raw_ntlmv2_auth = false; /* Reject NTLMv2 without NTLMSSP */
 	Globals.client_ntlmv2_auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
 	/* Note, that we will also use NTLM2 session security (which is different), if it is available */
 
+	Globals.allow_dcerpc_auth_level_connect = false; /* we don't allow this by default */
+
 	Globals.map_to_guest = 0;	/* By Default, "Never" */
 	Globals.oplock_break_wait_time = 0;	/* By Default, 0 msecs. */
 	Globals.enhanced_browsing = true;
@@ -741,6 +747,9 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
 	Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SIGN;
 
+	Globals.ldap_server_require_strong_auth =
+		LDAP_SERVER_REQUIRE_STRONG_AUTH_YES;
+
 	/* This is what we tell the afs client. in reality we set the token 
 	 * to never expire, though, when this runs out the afs client will 
 	 * forget the token. Set to 0 to get NEVERDATE.*/
@@ -816,6 +825,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.client_use_spnego = true;
 
 	Globals.client_signing = SMB_SIGNING_DEFAULT;
+	Globals._client_ipc_signing = SMB_SIGNING_DEFAULT;
 	Globals.server_signing = SMB_SIGNING_DEFAULT;
 
 	Globals.defer_sharing_violations = true;
@@ -863,6 +873,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.dcerpc_endpoint_servers = str_list_make_v3_const(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
 
 	Globals.tls_enabled = true;
+	Globals.tls_verify_peer = TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
 
 	lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
 	lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
@@ -4427,13 +4438,37 @@ int lp_client_max_protocol(void)
 	return client_max_protocol;
 }
 
-int lp_winbindd_max_protocol(void)
+int lp_client_ipc_min_protocol(void)
 {
-	int client_max_protocol = lp__client_max_protocol();
-	if (client_max_protocol == PROTOCOL_DEFAULT) {
+	int client_ipc_min_protocol = lp__client_ipc_min_protocol();
+	if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
+		client_ipc_min_protocol = lp_client_min_protocol();
+	}
+	if (client_ipc_min_protocol < PROTOCOL_NT1) {
+		return PROTOCOL_NT1;
+	}
+	return client_ipc_min_protocol;
+}
+
+int lp_client_ipc_max_protocol(void)
+{
+	int client_ipc_max_protocol = lp__client_ipc_max_protocol();
+	if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
 		return PROTOCOL_LATEST;
 	}
-	return client_max_protocol;
+	if (client_ipc_max_protocol < PROTOCOL_NT1) {
+		return PROTOCOL_NT1;
+	}
+	return client_ipc_max_protocol;
+}
+
+int lp_client_ipc_signing(void)
+{
+	int client_ipc_signing = lp__client_ipc_signing();
+	if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
+		return SMB_SIGNING_REQUIRED;
+	}
+	return client_ipc_signing;
 }
 
 struct loadparm_global * get_globals(void)
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index f642d30..97f4944 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -391,9 +391,9 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
 						DATA_BLOB *rdata,
 						DATA_BLOB *reply_pdu)
 {
-	struct dcerpc_response *r;
+	const struct dcerpc_response *r = NULL;
+	DATA_BLOB tmp_stub = data_blob_null;
 	NTSTATUS ret = NT_STATUS_OK;
-	size_t pad_len = 0;
 
 	/*
 	 * Point the return values at the real data including the RPC
@@ -401,50 +401,128 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
 	 */
 	*rdata = *pdu;
 
+	if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
+	    !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+		/*
+		 * TODO: do we still need this hack which was introduced
+		 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
+		 *
+		 * I don't even know what AS/U might be...
+		 */
+		DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
+			  "fragment first/last ON.\n"));
+		pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+	}
+
 	/* Ensure we have the correct type. */
 	switch (pkt->ptype) {
-	case DCERPC_PKT_ALTER_RESP:
+	case DCERPC_PKT_BIND_NAK:
+		DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
+			  rpccli_pipe_txt(talloc_tos(), cli)));
+
+		ret = dcerpc_verify_ncacn_packet_header(pkt,
+						DCERPC_PKT_BIND_NAK,
+						0, /* max_auth_info */
+						DCERPC_PFC_FLAG_FIRST |
+						DCERPC_PFC_FLAG_LAST,
+						0); /* optional flags */
+		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
+			return ret;
+		}
+
+		/* Use this for now... */
+		return NT_STATUS_NETWORK_ACCESS_DENIED;
+
 	case DCERPC_PKT_BIND_ACK:
+		ret = dcerpc_verify_ncacn_packet_header(pkt,
+					expected_pkt_type,
+					pkt->u.bind_ack.auth_info.length,
+					DCERPC_PFC_FLAG_FIRST |
+					DCERPC_PFC_FLAG_LAST,
+					DCERPC_PFC_FLAG_CONC_MPX |
+					DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
+			return ret;
+		}
 
-		/* Client code never receives this kind of packets */
 		break;
 
+	case DCERPC_PKT_ALTER_RESP:
+		ret = dcerpc_verify_ncacn_packet_header(pkt,
+					expected_pkt_type,
+					pkt->u.alter_resp.auth_info.length,
+					DCERPC_PFC_FLAG_FIRST |
+					DCERPC_PFC_FLAG_LAST,
+					DCERPC_PFC_FLAG_CONC_MPX |
+					DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
+			return ret;
+		}
+
+		break;
 
 	case DCERPC_PKT_RESPONSE:
 
 		r = &pkt->u.response;
 
+		ret = dcerpc_verify_ncacn_packet_header(pkt,
+						expected_pkt_type,
+						r->stub_and_verifier.length,
+						0, /* required_flags */
+						DCERPC_PFC_FLAG_FIRST |
+						DCERPC_PFC_FLAG_LAST);
+		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
+			return ret;
+		}
+
+		tmp_stub.data = r->stub_and_verifier.data;
+		tmp_stub.length = r->stub_and_verifier.length;
+
 		/* Here's where we deal with incoming sign/seal. */
 		ret = dcerpc_check_auth(cli->auth, pkt,
-					&r->stub_and_verifier,
+					&tmp_stub,
 					DCERPC_RESPONSE_LENGTH,
-					pdu, &pad_len);
+					pdu);
 		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
 			return ret;
 		}
 
-		if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
-			return NT_STATUS_BUFFER_TOO_SMALL;
-		}
-
 		/* Point the return values at the NDR data. */
-		rdata->data = r->stub_and_verifier.data;
-
-		if (pkt->auth_length) {
-			/* We've already done integer wrap tests in
-			 * dcerpc_check_auth(). */
-			rdata->length = r->stub_and_verifier.length
-					 - pad_len
-					 - DCERPC_AUTH_TRAILER_LENGTH
-					 - pkt->auth_length;
-		} else {
-			rdata->length = r->stub_and_verifier.length;
-		}
+		*rdata = tmp_stub;
 
-		DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
+		DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
 			   (long unsigned int)pdu->length,
-			   (long unsigned int)rdata->length,
-			   (unsigned int)pad_len));
+			   (long unsigned int)rdata->length));
 
 		/*
 		 * If this is the first reply, and the allocation hint is
@@ -465,14 +543,24 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
 
 		break;
 
-	case DCERPC_PKT_BIND_NAK:
-		DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
-			  rpccli_pipe_txt(talloc_tos(), cli)));
-		/* Use this for now... */
-		return NT_STATUS_NETWORK_ACCESS_DENIED;
-
 	case DCERPC_PKT_FAULT:
 
+		ret = dcerpc_verify_ncacn_packet_header(pkt,
+						DCERPC_PKT_FAULT,
+						0, /* max_auth_info */
+						DCERPC_PFC_FLAG_FIRST |
+						DCERPC_PFC_FLAG_LAST,
+						DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+		if (!NT_STATUS_IS_OK(ret)) {
+			DEBUG(1, (__location__ ": Connection to %s got an unexpected "
+				  "RPC packet type - %u, expected %u: %s\n",
+				  rpccli_pipe_txt(talloc_tos(), cli),
+				  pkt->ptype, expected_pkt_type,
+				  nt_errstr(ret)));
+			NDR_PRINT_DEBUG(ncacn_packet, pkt);
+			return ret;
+		}
+
 		DEBUG(1, (__location__ ": RPC fault code %s received "
 			  "from %s!\n",
 			  dcerpc_errstr(talloc_tos(),
@@ -489,13 +577,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_RPC_PROTOCOL_ERROR;
 	}
 
-	if (pkt->ptype != expected_pkt_type) {
-		DEBUG(3, (__location__ ": Connection to %s got an unexpected "
-			  "RPC packet type - %u, not %u\n",
-			  rpccli_pipe_txt(talloc_tos(), cli),
-			  pkt->ptype, expected_pkt_type));
-		return NT_STATUS_RPC_PROTOCOL_ERROR;
-	}
 
 	if (pkt->call_id != call_id) {
 		DEBUG(3, (__location__ ": Connection to %s got an unexpected "
@@ -505,17 +586,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_RPC_PROTOCOL_ERROR;
 	}
 
-	/* Do this just before return - we don't want to modify any rpc header
-	   data before now as we may have needed to do cryptographic actions on
-	   it before. */
-
-	if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
-	    !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
-		DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
-			  "fragment first/last ON.\n"));
-		pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
-	}
-
 	return NT_STATUS_OK;
 }
 
@@ -866,6 +936,12 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 
 	state->pkt = talloc(state, struct ncacn_packet);
 	if (!state->pkt) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
 		tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
 		return;
 	}
@@ -875,18 +951,16 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 					  state->pkt,
 					  !state->endianess);
 	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
 		tevent_req_nterror(req, status);
 		return;
 	}
 
-	if (state->incoming_frag.length != state->pkt->frag_length) {
-		DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
-			  (unsigned int)state->incoming_frag.length,
-			  (unsigned int)state->pkt->frag_length));
-		tevent_req_nterror(req,  NT_STATUS_INVALID_PARAMETER);
-		return;
-	}
-
 	status = cli_pipe_validate_current_pdu(state,
 						state->cli, state->pkt,
 						&state->incoming_frag,
@@ -900,6 +974,28 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 		  (unsigned)state->reply_pdu_offset,
 		  nt_errstr(status)));
 
+	if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+	} else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+	} else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+	}
 	if (!NT_STATUS_IS_OK(status)) {
 		tevent_req_nterror(req, status);
 		return;
@@ -924,7 +1020,24 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 			 "%s\n",
 			 state->endianess?"little":"big",
 			 state->pkt->drep[0]?"little":"big"));
-		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+		tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+		tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
 		return;
 	}
 
@@ -932,6 +1045,12 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 	if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
 		if (!data_blob_realloc(NULL, &state->reply_pdu,
 				state->reply_pdu_offset + rdata.length)) {
+			/*
+			 * TODO: do a real async disconnect ...
+			 *
+			 * For now do it sync...
+			 */
+			TALLOC_FREE(state->cli->transport);
 			tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
 			return;
 		}
@@ -960,6 +1079,14 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 
 	subreq = get_complete_frag_send(state, state->ev, state->cli,
 					&state->incoming_frag);
+	if (subreq == NULL) {
+		/*
+		 * TODO: do a real async disconnect ...
+		 *
+		 * For now do it sync...
+		 */
+		TALLOC_FREE(state->cli->transport);
+	}
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
@@ -1123,7 +1250,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
 						auth->auth_type,
 						auth->auth_level,
 						0, /* auth_pad_length */
-						1, /* auth_context_id */
+						auth->auth_context_id,
 						&auth_token,
 						&auth_info);
 		if (!NT_STATUS_IS_OK(ret)) {
@@ -1628,9 +1755,8 @@ static bool check_bind_response(const struct dcerpc_bind_ack *r,
 
 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
 				struct rpc_pipe_client *cli,
+				struct pipe_auth_data *auth,
 				uint32_t rpc_call_id,
-				enum dcerpc_AuthType auth_type,
-				enum dcerpc_AuthLevel auth_level,
 				DATA_BLOB *pauth_blob,
 				DATA_BLOB *rpc_out)
 {
@@ -1640,10 +1766,10 @@ static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
 	u.auth3._pad = 0;
 
 	status = dcerpc_push_dcerpc_auth(mem_ctx,
-					 auth_type,
-					 auth_level,
+					 auth->auth_type,
+					 auth->auth_level,
 					 0, /* auth_pad_length */
-					 1, /* auth_context_id */
+					 auth->auth_context_id,
 					 pauth_blob,
 					 &u.auth3.auth_info);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1673,8 +1799,7 @@ static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
-					enum dcerpc_AuthType auth_type,
-					enum dcerpc_AuthLevel auth_level,
+					struct pipe_auth_data *auth,
 					uint32_t rpc_call_id,
 					const struct ndr_syntax_id *abstract,
 					const struct ndr_syntax_id *transfer,
@@ -1685,10 +1810,10 @@ static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
 	NTSTATUS status;
 
 	status = dcerpc_push_dcerpc_auth(mem_ctx,
-					 auth_type,
-					 auth_level,
+					 auth->auth_type,
+					 auth->auth_level,
 					 0, /* auth_pad_length */
-					 1, /* auth_context_id */
+					 auth->auth_context_id,
 					 pauth_blob,
 					 &auth_info);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1826,23 +1951,44 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
 		return;
 
 	default:
-		/* Paranoid lenght checks */
-		if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
-						+ pkt->auth_length) {
-			tevent_req_nterror(req,
-					NT_STATUS_INFO_LENGTH_MISMATCH);
+		if (pkt->auth_length == 0) {
+			tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
 			return;
 		}
+
 		/* get auth credentials */
-		status = dcerpc_pull_dcerpc_auth(talloc_tos(),
-						 &pkt->u.bind_ack.auth_info,
-						 &auth, false);
+		status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
+						  &pkt->u.bind_ack.auth_info,
+						  &auth, NULL, true);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
 				  nt_errstr(status)));
 			tevent_req_nterror(req, status);
 			return;
 		}
+
+		if (auth.auth_type != pauth->auth_type) {
+			DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
+				  auth.auth_type, pauth->auth_type));
+			tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+			return;
+		}
+
+		if (auth.auth_level != pauth->auth_level) {
+			DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
+				  auth.auth_level, pauth->auth_level));
+			tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+			return;
+		}
+
+		if (auth.auth_context_id != pauth->auth_context_id) {
+			DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
+				  (unsigned)auth.auth_context_id,
+				  (unsigned)pauth->auth_context_id));
+			tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+			return;
+		}
+
 		break;
 	}
 
@@ -1903,9 +2049,7 @@ static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
 	/* Now prepare the alter context pdu. */
 	data_blob_free(&state->rpc_out);
 
-	status = create_rpc_alter_context(state,
-					  auth->auth_type,
-					  auth->auth_level,
+	status = create_rpc_alter_context(state, auth,
 					  state->rpc_call_id,
 					  &state->cli->abstract_syntax,
 					  &state->cli->transfer_syntax,
@@ -1938,10 +2082,8 @@ static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
 	/* Now prepare the auth3 context pdu. */
 	data_blob_free(&state->rpc_out);
 
-	status = create_rpc_bind_auth3(state, state->cli,
+	status = create_rpc_bind_auth3(state, state->cli, auth,
 					state->rpc_call_id,
-					auth->auth_type,
-					auth->auth_level,
 					auth_token,
 					&state->rpc_out);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -2193,8 +2335,9 @@ static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
 	/*
 	 * TODO: do a real async disconnect ...
 	 *
-	 * For now the caller needs to free rpc_cli
+	 * For now we do it sync...
 	 */
+	TALLOC_FREE(hs->rpc_cli->transport);
 	hs->rpc_cli = NULL;
 
 	tevent_req_done(req);
@@ -2295,6 +2438,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
 
 	result->auth_type = DCERPC_AUTH_TYPE_NONE;
 	result->auth_level = DCERPC_AUTH_LEVEL_NONE;
+	result->auth_context_id = 0;
 
 	status = auth_generic_client_prepare(result,
 					     &auth_generic_ctx);
@@ -2355,6 +2499,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
 
 	result->auth_type = auth_type;
 	result->auth_level = auth_level;
+	result->auth_context_id = 1;
 
 	status = auth_generic_client_prepare(result,
 					     &auth_generic_ctx);
@@ -2425,6 +2570,7 @@ static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
 
 	result->auth_type = auth_type;
 	result->auth_level = auth_level;
+	result->auth_context_id = 1;
 
 	status = auth_generic_client_prepare(result,
 					     &auth_generic_ctx);
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index e0c1b85..176769f 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1585,6 +1585,7 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 	case NetlogonNetworkTransitiveInformation:
 	{
 		const char *wksname = nt_workstation;
+		const char *workgroup = lp_workgroup();
 
 		status = make_auth_context_fixed(talloc_tos(), &auth_context,
 						 logon->network->challenge);
@@ -1611,6 +1612,14 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 						     logon->network->nt.length)) {
 			status = NT_STATUS_NO_MEMORY;
 		}
+
+		if (NT_STATUS_IS_OK(status)) {
+			status = NTLMv2_RESPONSE_verify_netlogon_creds(
+						user_info->client.account_name,
+						user_info->client.domain_name,
+						user_info->password.response.nt,
+						creds, workgroup);
+		}
 		break;
 	}
 	case NetlogonInteractiveInformation:
@@ -1719,6 +1728,14 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 						r->out.validation->sam3);
 		break;
 	case 6:
+		/* Only allow this if the pipe is protected. */
+		if (p->auth.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
+			DEBUG(0,("netr_Validation6: client %s not using privacy for netlogon\n",
+				get_remote_machine_name()));
+			status = NT_STATUS_INVALID_PARAMETER;
+			break;
+		}
+
 		status = serverinfo_to_SamInfo6(server_info,
 						r->out.validation->sam6);
 		break;
@@ -2468,22 +2485,16 @@ NTSTATUS _netr_GetForestTrustInformation(struct pipes_struct *p,
 	NTSTATUS status;
 	struct netlogon_creds_CredentialState *creds;
 	struct lsa_ForestTrustInformation *info, **info_ptr;
-	struct loadparm_context *lp_ctx;
 
 	/* TODO: check server name */
 
-	lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers());
-	if (lp_ctx == NULL) {
-		DEBUG(0, ("loadparm_init_s3 failed\n"));
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	status = schannel_check_creds_state(p->mem_ctx, lp_ctx,
-					    r->in.computer_name,
-					    r->in.credential,
-					    r->out.return_authenticator,
-					    &creds);
-	talloc_unlink(p->mem_ctx, lp_ctx);
+	become_root();
+	status = netr_creds_server_step_check(p, p->mem_ctx,
+					      r->in.computer_name,
+					      r->in.credential,
+					      r->out.return_authenticator,
+					      &creds);
+	unbecome_root();
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -2570,22 +2581,16 @@ NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p,
 	bool trusted;
 	struct netr_TrustInfo *trust_info;
 	struct pdb_trusted_domain *td;
-	struct loadparm_context *lp_ctx;
-
-	lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers());
-	if (lp_ctx == NULL) {
-		DEBUG(0, ("loadparm_init_s3 failed\n"));
-		return NT_STATUS_INTERNAL_ERROR;
-	}
 
 	/* TODO: check server name */
 
-	status = schannel_check_creds_state(p->mem_ctx, lp_ctx,
-					    r->in.computer_name,
-					    r->in.credential,
-					    r->out.return_authenticator,
-					    &creds);
-	talloc_unlink(p->mem_ctx, lp_ctx);
+	become_root();
+	status = netr_creds_server_step_check(p, p->mem_ctx,
+					      r->in.computer_name,
+					      r->in.credential,
+					      r->out.return_authenticator,
+					      &creds);
+	unbecome_root();
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
diff --git a/source3/rpc_server/rpc_handles.c b/source3/rpc_server/rpc_handles.c
index 4e2edc6..62b545c 100644
--- a/source3/rpc_server/rpc_handles.c
+++ b/source3/rpc_server/rpc_handles.c
@@ -69,6 +69,7 @@ int make_base_pipes_struct(TALLOC_CTX *mem_ctx,
 	p->msg_ctx = msg_ctx;
 	p->transport = transport;
 	p->endian = endian;
+	p->allow_bind = true;
 
 	p->remote_address = tsocket_address_copy(remote_address, p);
 	if (p->remote_address == NULL) {
diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c
index d504847..5647596 100644
--- a/source3/rpc_server/rpc_ncacn_np.c
+++ b/source3/rpc_server/rpc_ncacn_np.c
@@ -224,7 +224,7 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	context_fns = talloc(p, struct pipe_rpc_fns);
+	context_fns = talloc_zero(p, struct pipe_rpc_fns);
 	if (context_fns == NULL) {
 		DEBUG(0,("talloc() failed!\n"));
 		TALLOC_FREE(p);
@@ -977,6 +977,7 @@ static NTSTATUS rpc_pipe_open_external(TALLOC_CTX *mem_ctx,
 	}
 	result->auth->auth_type = DCERPC_AUTH_TYPE_NONE;
 	result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+	result->auth->auth_context_id = 0;
 
 	status = rpccli_anon_bind_data(result, &auth);
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/rpc_server/rpc_pipes.h b/source3/rpc_server/rpc_pipes.h
index e65209a..d44ee92 100644
--- a/source3/rpc_server/rpc_pipes.h
+++ b/source3/rpc_server/rpc_pipes.h
@@ -94,6 +94,10 @@ struct pipe_rpc_fns {
 	uint32_t context_id;
 	struct ndr_syntax_id syntax;
 
+	/*
+	 * shall we allow "connect" auth level for this interface ?
+	 */
+	bool allow_connect;
 };
 
 /*
@@ -127,6 +131,13 @@ struct pipes_struct {
 	bool pipe_bound;
 
 	/*
+	 * States we can be in.
+	 */
+	bool allow_alter;
+	bool allow_bind;
+	bool allow_auth3;
+
+	/*
 	 * Set the DCERPC_FAULT to return.
 	 */
 	int fault_state;
diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c
index 01a854c..5effe66 100644
--- a/source3/rpc_server/rpc_server.c
+++ b/source3/rpc_server/rpc_server.c
@@ -558,6 +558,12 @@ static void named_pipe_packet_done(struct tevent_req *subreq)
 		return;
 	}
 
+	if (npc->p->fault_state != 0) {
+		DEBUG(2, ("Disconnect after fault\n"));
+		sys_errno = EINVAL;
+		goto fail;
+	}
+
 	/* clear out any data that may have been left around */
 	npc->count = 0;
 	TALLOC_FREE(npc->iov);
@@ -1292,6 +1298,12 @@ static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
 		goto fail;
 	}
 
+	if (ncacn_conn->p->fault_state != 0) {
+		DEBUG(2, ("Disconnect after fault\n"));
+		sys_errno = EINVAL;
+		goto fail;
+	}
+
 	/* clear out any data that may have been left around */
 	ncacn_conn->count = 0;
 	TALLOC_FREE(ncacn_conn->iov);
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
index 4b4b77a..2f6f020 100644
--- a/source3/rpc_server/samr/srv_samr_nt.c
+++ b/source3/rpc_server/samr/srv_samr_nt.c
@@ -5097,7 +5097,7 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 		case 18:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
 			if(!NT_STATUS_IS_OK(status)) {
-				return status;
+				break;
 			}
 			/* Used by AS/U JRA. */
 			status = set_user_info_18(&info->info18,
@@ -5114,7 +5114,7 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 		case 21:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
 			if(!NT_STATUS_IS_OK(status)) {
-				return status;
+				break;
 			}
 			status = set_user_info_21(&info->info21,
 						  p->mem_ctx,
@@ -5124,6 +5124,9 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 
 		case 23:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+			if(!NT_STATUS_IS_OK(status)) {
+				break;
+			}
 			arcfour_crypt_blob(info->info23.password.data, 516,
 					   &session_key);
 
@@ -5137,6 +5140,9 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 
 		case 24:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+			if(!NT_STATUS_IS_OK(status)) {
+				break;
+			}
 			arcfour_crypt_blob(info->info24.password.data,
 					   516,
 					   &session_key);
@@ -5150,6 +5156,9 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 
 		case 25:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+			if(!NT_STATUS_IS_OK(status)) {
+				break;
+			}
 			encode_or_decode_arc4_passwd_buffer(
 				info->info25.password.data,
 				&session_key);
@@ -5163,6 +5172,9 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p,
 
 		case 26:
 			status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
+			if(!NT_STATUS_IS_OK(status)) {
+				break;
+			}
 			encode_or_decode_arc4_passwd_buffer(
 				info->info26.password.data,
 				&session_key);
@@ -6734,6 +6746,11 @@ NTSTATUS _samr_ValidatePassword(struct pipes_struct *p,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
+	if (p->auth.auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+		p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (r->in.level < 1 || r->in.level > 3) {
 		return NT_STATUS_INVALID_INFO_CLASS;
 	}
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 4ffaa0d..bcd7e5d 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -30,7 +30,7 @@
 #include "includes.h"
 #include "system/filesys.h"
 #include "srv_pipe_internal.h"
-#include "../librpc/gen_ndr/dcerpc.h"
+#include "../librpc/gen_ndr/ndr_dcerpc.h"
 #include "../librpc/rpc/rpc_common.h"
 #include "dcesrv_auth_generic.h"
 #include "rpc_server.h"
@@ -44,6 +44,12 @@
 #include "librpc/ndr/ndr_table.h"
 #include "auth/gensec/gensec.h"
 #include "librpc/ndr/ndr_dcerpc.h"
+#include "lib/tsocket/tsocket.h"
+#include "../librpc/gen_ndr/ndr_samr.h"
+#include "../librpc/gen_ndr/ndr_lsa.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "../librpc/gen_ndr/ndr_epmapper.h"
+#include "../librpc/gen_ndr/ndr_echo.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -272,10 +278,14 @@ static bool setup_bind_nak(struct pipes_struct *p, struct ncacn_packet *pkt)
 	p->out_data.data_sent_length = 0;
 	p->out_data.current_pdu_sent = 0;
 
+	set_incoming_fault(p);
 	TALLOC_FREE(p->auth.auth_ctx);
 	p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
 	p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
 	p->pipe_bound = False;
+	p->allow_bind = false;
+	p->allow_alter = false;
+	p->allow_auth3 = false;
 
 	return True;
 }
@@ -338,39 +348,118 @@ static bool check_bind_req(struct pipes_struct *p,
 {
 	struct pipe_rpc_fns *context_fns;
 	bool ok;
+	const char *interface_name = NULL;
 
-	DEBUG(3,("check_bind_req for %s\n",
+	DEBUG(3,("check_bind_req for %s context_id=%u\n",
 		 ndr_interface_name(&abstract->uuid,
-				    abstract->if_version)));
+				    abstract->if_version),
+		 (unsigned)context_id));
+
+	ok = ndr_syntax_id_equal(transfer, &ndr_transfer_syntax_ndr);
+	if (!ok) {
+		DEBUG(1,("check_bind_req unknown transfer syntax for "
+			 "%s context_id=%u\n",
+			 ndr_interface_name(&abstract->uuid,
+				    abstract->if_version),
+			 (unsigned)context_id));
+		return false;
+	}
+
+	for (context_fns = p->contexts;
+	     context_fns != NULL;
+	     context_fns = context_fns->next)
+	{
+		if (context_fns->context_id != context_id) {
+			continue;
+		}
+
+		ok = ndr_syntax_id_equal(&context_fns->syntax,
+					 abstract);
+		if (ok) {
+			return true;
+		}
+
+		DEBUG(1,("check_bind_req: changing abstract syntax for "
+			 "%s context_id=%u into %s not supported\n",
+			 ndr_interface_name(&context_fns->syntax.uuid,
+					    context_fns->syntax.if_version),
+			 (unsigned)context_id,
+			 ndr_interface_name(&abstract->uuid,
+					    abstract->if_version)));
+		return false;
+	}
 
 	/* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
-	if (rpc_srv_pipe_exists_by_id(abstract) &&
-	   ndr_syntax_id_equal(transfer, &ndr_transfer_syntax_ndr)) {
-		DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
-			  rpc_srv_get_pipe_cli_name(abstract),
-			  rpc_srv_get_pipe_srv_name(abstract)));
-	} else {
+	if (!rpc_srv_pipe_exists_by_id(abstract)) {
 		return false;
 	}
 
+	DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
+		  rpc_srv_get_pipe_cli_name(abstract),
+		  rpc_srv_get_pipe_srv_name(abstract)));
+
 	ok = init_pipe_handles(p, abstract);
 	if (!ok) {
 		DEBUG(1, ("Failed to init pipe handles!\n"));
 		return false;
 	}
 
-	context_fns = talloc(p, struct pipe_rpc_fns);
+	context_fns = talloc_zero(p, struct pipe_rpc_fns);
 	if (context_fns == NULL) {
 		DEBUG(0,("check_bind_req: talloc() failed!\n"));
 		return false;
 	}
 
+	interface_name = ndr_interface_name(&abstract->uuid,
+					    abstract->if_version);
+	SMB_ASSERT(interface_name != NULL);
+
 	context_fns->next = context_fns->prev = NULL;
 	context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract);
 	context_fns->cmds = rpc_srv_get_pipe_cmds(abstract);
 	context_fns->context_id = context_id;
 	context_fns->syntax = *abstract;
 
+	context_fns->allow_connect = lp_allow_dcerpc_auth_level_connect();
+	/*
+	 * for the samr, lsarpc and netlogon interfaces we don't allow "connect"
+	 * auth_level by default.
+	 */
+	ok = ndr_syntax_id_equal(abstract, &ndr_table_samr.syntax_id);
+	if (ok) {
+		context_fns->allow_connect = false;
+	}
+	ok = ndr_syntax_id_equal(abstract, &ndr_table_lsarpc.syntax_id);
+	if (ok) {
+		context_fns->allow_connect = false;
+	}
+	ok = ndr_syntax_id_equal(abstract, &ndr_table_netlogon.syntax_id);
+	if (ok) {
+		context_fns->allow_connect = false;
+	}
+	/*
+	 * for the epmapper and echo interfaces we allow "connect"
+	 * auth_level by default.
+	 */
+	ok = ndr_syntax_id_equal(abstract, &ndr_table_epmapper.syntax_id);
+	if (ok) {
+		context_fns->allow_connect = true;
+	}
+	ok = ndr_syntax_id_equal(abstract, &ndr_table_rpcecho.syntax_id);
+	if (ok) {
+		context_fns->allow_connect = true;
+	}
+	/*
+	 * every interface can be modified to allow "connect" auth_level by
+	 * using a parametric option like:
+	 * allow dcerpc auth level connect:<interface>
+	 * e.g.
+	 * allow dcerpc auth level connect:samr = yes
+	 */
+	context_fns->allow_connect = lp_parm_bool(-1,
+		"allow dcerpc auth level connect",
+		interface_name, context_fns->allow_connect);
+
 	/* add to the list of open contexts */
 
 	DLIST_ADD( p->contexts, context_fns );
@@ -449,6 +538,8 @@ static bool pipe_auth_generic_bind(struct pipes_struct *p,
 
 	p->auth.auth_ctx = gensec_security;
 	p->auth.auth_type = auth_info->auth_type;
+	p->auth.auth_level = auth_info->auth_level;
+	p->auth.auth_context_id = auth_info->auth_context_id;
 
 	if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
 		p->auth.client_hdr_signing = true;
@@ -575,7 +666,6 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 {
 	struct dcerpc_auth auth_info = {0};
 	uint16_t assoc_gid;
-	unsigned int auth_type = DCERPC_AUTH_TYPE_NONE;
 	NTSTATUS status;
 	struct ndr_syntax_id id;
 	uint8_t pfc_flags = 0;
@@ -585,14 +675,38 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 	DATA_BLOB auth_blob = data_blob_null;
 	const struct ndr_interface_table *table;
 
-	/* No rebinds on a bound pipe - use alter context. */
-	if (p->pipe_bound) {
-		DEBUG(2,("Rejecting bind request on bound rpc connection\n"));
+	if (!p->allow_bind) {
+		DEBUG(2,("Pipe not in allow bind state\n"));
 		return setup_bind_nak(p, pkt);
 	}
+	p->allow_bind = false;
+
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+			DCERPC_PKT_BIND,
+			pkt->u.bind.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("api_pipe_bind_req: invalid pdu: %s\n",
+			  nt_errstr(status)));
+		NDR_PRINT_DEBUG(ncacn_packet, pkt);
+		goto err_exit;
+	}
 
 	if (pkt->u.bind.num_contexts == 0) {
-		DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
+		DEBUG(1, ("api_pipe_bind_req: no rpc contexts around\n"));
+		goto err_exit;
+	}
+
+	if (pkt->u.bind.ctx_list[0].num_transfer_syntaxes == 0) {
+		DEBUG(1, ("api_pipe_bind_req: no transfer syntaxes around\n"));
 		goto err_exit;
 	}
 
@@ -671,7 +785,6 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 		bind_ack_ctx.reason.value = 0;
 		bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
 	} else {
-		p->pipe_bound = False;
 		/* Rejection reason: abstract syntax not supported */
 		bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
 		bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
@@ -682,71 +795,25 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 	 * Check if this is an authenticated bind request.
 	 */
 	if (pkt->auth_length) {
-		/* Quick length check. Won't catch a bad auth footer,
-		 * prevents overrun. */
-
-		if (pkt->frag_length < RPC_HEADER_LEN +
-					DCERPC_AUTH_TRAILER_LENGTH +
-					pkt->auth_length) {
-			DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
-				"too long for fragment %u.\n",
-				(unsigned int)pkt->auth_length,
-				(unsigned int)pkt->frag_length));
-			goto err_exit;
-		}
-
 		/*
 		 * Decode the authentication verifier.
 		 */
-		status = dcerpc_pull_dcerpc_auth(pkt,
-						 &pkt->u.bind.auth_info,
-						 &auth_info, p->endian);
+		status = dcerpc_pull_auth_trailer(pkt, pkt,
+						  &pkt->u.bind.auth_info,
+						  &auth_info, NULL, true);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
 			goto err_exit;
 		}
 
-		auth_type = auth_info.auth_type;
-
-		/* Work out if we have to sign or seal etc. */
-		switch (auth_info.auth_level) {
-		case DCERPC_AUTH_LEVEL_INTEGRITY:
-			p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
-			break;
-		case DCERPC_AUTH_LEVEL_PRIVACY:
-			p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
-			break;
-		case DCERPC_AUTH_LEVEL_CONNECT:
-			p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT;
-			break;
-		default:
-			DEBUG(0, ("Unexpected auth level (%u).\n",
-				(unsigned int)auth_info.auth_level ));
+		if (!pipe_auth_generic_bind(p, pkt,
+					    &auth_info, &auth_resp)) {
 			goto err_exit;
 		}
-
-		switch (auth_type) {
-		case DCERPC_AUTH_TYPE_NONE:
-			break;
-
-		default:
-			if (!pipe_auth_generic_bind(p, pkt,
-						    &auth_info, &auth_resp)) {
-				goto err_exit;
-			}
-			break;
-		}
-	}
-
-	if (auth_type == DCERPC_AUTH_TYPE_NONE) {
-		/* Unauthenticated bind request. */
-		/* We're finished - no more packets. */
+	} else {
 		p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
-		/* We must set the pipe auth_level here also. */
 		p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
-		p->pipe_bound = True;
-		/* The session key was initialized from the SMB
-		 * session in make_internal_rpc_pipe_p */
+		p->auth.auth_context_id = 0;
 	}
 
 	ZERO_STRUCT(u.bind_ack);
@@ -793,15 +860,15 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
 			  nt_errstr(status)));
+		goto err_exit;
 	}
 
 	if (auth_resp.length) {
-
 		status = dcerpc_push_dcerpc_auth(pkt,
-						 auth_type,
-						 auth_info.auth_level,
-						 0,
-						 1, /* auth_context_id */
+						 p->auth.auth_type,
+						 p->auth.auth_level,
+						 0, /* pad_len */
+						 p->auth.auth_context_id,
 						 &auth_resp,
 						 &auth_blob);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -832,6 +899,22 @@ static bool api_pipe_bind_req(struct pipes_struct *p,
 	p->out_data.current_pdu_sent = 0;
 
 	TALLOC_FREE(auth_blob.data);
+
+	if (bind_ack_ctx.result == 0) {
+		p->allow_alter = true;
+		p->allow_auth3 = true;
+		if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) {
+			status = pipe_auth_verify_final(p);
+			if (!NT_STATUS_IS_OK(status)) {
+				DEBUG(0, ("pipe_auth_verify_final failed: %s\n",
+					  nt_errstr(status)));
+				goto err_exit;
+			}
+		}
+	} else {
+		goto err_exit;
+	}
+
 	return True;
 
   err_exit:
@@ -854,18 +937,39 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
 
 	DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
 
-	if (pkt->auth_length == 0) {
-		DEBUG(1, ("No auth field sent for bind request!\n"));
+	if (!p->allow_auth3) {
+		DEBUG(1, ("Pipe not in allow auth3 state.\n"));
+		goto err;
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+			DCERPC_PKT_AUTH3,
+			pkt->u.auth3.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("api_pipe_bind_auth3: invalid pdu: %s\n",
+			  nt_errstr(status)));
+		NDR_PRINT_DEBUG(ncacn_packet, pkt);
+		goto err;
+	}
+
+	/* We can only finish if the pipe is unbound for now */
+	if (p->pipe_bound) {
+		DEBUG(0, (__location__ ": Pipe already bound, "
+			  "AUTH3 not supported!\n"));
 		goto err;
 	}
 
-	/* Ensure there's enough data for an authenticated request. */
-	if (pkt->frag_length < RPC_HEADER_LEN
-				+ DCERPC_AUTH_TRAILER_LENGTH
-				+ pkt->auth_length) {
-			DEBUG(1,("api_pipe_ntlmssp_auth_process: auth_len "
-				"%u is too large.\n",
-                        (unsigned int)pkt->auth_length));
+	if (pkt->auth_length == 0) {
+		DEBUG(1, ("No auth field sent for auth3 request!\n"));
 		goto err;
 	}
 
@@ -873,9 +977,9 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
 	 * Decode the authentication verifier response.
 	 */
 
-	status = dcerpc_pull_dcerpc_auth(pkt,
-					 &pkt->u.auth3.auth_info,
-					 &auth_info, p->endian);
+	status = dcerpc_pull_auth_trailer(pkt, pkt,
+					  &pkt->u.auth3.auth_info,
+					  &auth_info, NULL, true);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, ("Failed to unmarshall dcerpc_auth.\n"));
 		goto err;
@@ -893,6 +997,21 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
 		goto err;
 	}
 
+	if (auth_info.auth_level != p->auth.auth_level) {
+		DEBUG(1, ("Auth level mismatch! Client sent %d, "
+			  "but auth was started as level %d!\n",
+			  auth_info.auth_level, p->auth.auth_level));
+		goto err;
+	}
+
+	if (auth_info.auth_context_id != p->auth.auth_context_id) {
+		DEBUG(0, ("Auth context id mismatch! Client sent %u, "
+			  "but auth was started as level %u!\n",
+			  (unsigned)auth_info.auth_context_id,
+			  (unsigned)p->auth.auth_context_id));
+		goto err;
+	}
+
 	gensec_security = p->auth.auth_ctx;
 
 	status = auth_generic_server_step(gensec_security,
@@ -923,6 +1042,10 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
 	return true;
 
 err:
+	p->pipe_bound = false;
+	p->allow_bind = false;
+	p->allow_alter = false;
+	p->allow_auth3 = false;
 
 	TALLOC_FREE(p->auth.auth_ctx);
 	return false;
@@ -940,15 +1063,49 @@ static bool api_pipe_alter_context(struct pipes_struct *p,
 	uint16_t assoc_gid;
 	NTSTATUS status;
 	union dcerpc_payload u;
-	struct dcerpc_ack_ctx bind_ack_ctx;
+	struct dcerpc_ack_ctx alter_ack_ctx;
 	DATA_BLOB auth_resp = data_blob_null;
 	DATA_BLOB auth_blob = data_blob_null;
 	struct gensec_security *gensec_security;
 
 	DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
 
-	if (pkt->u.bind.assoc_group_id != 0) {
-		assoc_gid = pkt->u.bind.assoc_group_id;
+	if (!p->allow_alter) {
+		DEBUG(1, ("Pipe not in allow alter state.\n"));
+		goto err_exit;
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+			DCERPC_PKT_ALTER,
+			pkt->u.alter.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("api_pipe_alter_context: invalid pdu: %s\n",
+			  nt_errstr(status)));
+		NDR_PRINT_DEBUG(ncacn_packet, pkt);
+		goto err_exit;
+	}
+
+	if (pkt->u.alter.num_contexts == 0) {
+		DEBUG(1, ("api_pipe_alter_context: no rpc contexts around\n"));
+		goto err_exit;
+	}
+
+	if (pkt->u.alter.ctx_list[0].num_transfer_syntaxes == 0) {
+		DEBUG(1, ("api_pipe_alter_context: no transfer syntaxes around\n"));
+		goto err_exit;
+	}
+
+	if (pkt->u.alter.assoc_group_id != 0) {
+		assoc_gid = pkt->u.alter.assoc_group_id;
 	} else {
 		assoc_gid = 0x53f0;
 	}
@@ -958,59 +1115,45 @@ static bool api_pipe_alter_context(struct pipes_struct *p,
 	 */
 
 	/* If the requested abstract synt uuid doesn't match our client pipe,
-		reject the bind_ack & set the transfer interface synt to all 0's,
+		reject the alter_ack & set the transfer interface synt to all 0's,
 		ver 0 (observed when NT5 attempts to bind to abstract interfaces
 		unknown to NT4)
 		Needed when adding entries to a DACL from NT5 - SK */
 
 	if (check_bind_req(p,
-			&pkt->u.bind.ctx_list[0].abstract_syntax,
-			&pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
-			pkt->u.bind.ctx_list[0].context_id)) {
+			&pkt->u.alter.ctx_list[0].abstract_syntax,
+			&pkt->u.alter.ctx_list[0].transfer_syntaxes[0],
+			pkt->u.alter.ctx_list[0].context_id)) {
 
-		bind_ack_ctx.result = 0;
-		bind_ack_ctx.reason.value = 0;
-		bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
+		alter_ack_ctx.result = 0;
+		alter_ack_ctx.reason.value = 0;
+		alter_ack_ctx.syntax = pkt->u.alter.ctx_list[0].transfer_syntaxes[0];
 	} else {
-		p->pipe_bound = False;
 		/* Rejection reason: abstract syntax not supported */
-		bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
-		bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
-		bind_ack_ctx.syntax = ndr_syntax_id_null;
+		alter_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
+		alter_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
+		alter_ack_ctx.syntax = ndr_syntax_id_null;
 	}
 
 	/*
 	 * Check if this is an authenticated alter context request.
 	 */
 	if (pkt->auth_length) {
-		/* Quick length check. Won't catch a bad auth footer,
-		 * prevents overrun. */
-
-		if (pkt->frag_length < RPC_HEADER_LEN +
-					DCERPC_AUTH_TRAILER_LENGTH +
-					pkt->auth_length) {
-			DEBUG(0,("api_pipe_alter_context: auth_len (%u) "
-				"too long for fragment %u.\n",
-				(unsigned int)pkt->auth_length,
-				(unsigned int)pkt->frag_length ));
+		/* We can only finish if the pipe is unbound for now */
+		if (p->pipe_bound) {
+			DEBUG(0, (__location__ ": Pipe already bound, "
+				  "Altering Context not yet supported!\n"));
 			goto err_exit;
 		}
 
-		status = dcerpc_pull_dcerpc_auth(pkt,
-						 &pkt->u.bind.auth_info,
-						 &auth_info, p->endian);
+		status = dcerpc_pull_auth_trailer(pkt, pkt,
+						  &pkt->u.alter.auth_info,
+						  &auth_info, NULL, true);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
 			goto err_exit;
 		}
 
-		/* We can only finish if the pipe is unbound for now */
-		if (p->pipe_bound) {
-			DEBUG(0, (__location__ ": Pipe already bound, "
-				  "Altering Context not yet supported!\n"));
-			goto err_exit;
-		}
-
 		if (auth_info.auth_type != p->auth.auth_type) {
 			DEBUG(0, ("Auth type mismatch! Client sent %d, "
 				  "but auth was started as type %d!\n",
@@ -1018,6 +1161,21 @@ static bool api_pipe_alter_context(struct pipes_struct *p,
 			goto err_exit;
 		}
 
+		if (auth_info.auth_level != p->auth.auth_level) {
+			DEBUG(0, ("Auth level mismatch! Client sent %d, "
+				  "but auth was started as level %d!\n",
+				  auth_info.auth_level, p->auth.auth_level));
+			goto err_exit;
+		}
+
+		if (auth_info.auth_context_id != p->auth.auth_context_id) {
+			DEBUG(0, ("Auth context id mismatch! Client sent %u, "
+				  "but auth was started as level %u!\n",
+				  (unsigned)auth_info.auth_context_id,
+				  (unsigned)p->auth.auth_context_id));
+			goto err_exit;
+		}
+
 		gensec_security = p->auth.auth_ctx;
 		status = auth_generic_server_step(gensec_security,
 						  pkt,
@@ -1054,7 +1212,7 @@ static bool api_pipe_alter_context(struct pipes_struct *p,
 	u.alter_resp.secondary_address_size = 1;
 
 	u.alter_resp.num_results = 1;
-	u.alter_resp.ctx_list = &bind_ack_ctx;
+	u.alter_resp.ctx_list = &alter_ack_ctx;
 
 	/* NOTE: We leave the auth_info empty so we can calculate the padding
 	 * later and then append the auth_info --simo */
@@ -1074,16 +1232,17 @@ static bool api_pipe_alter_context(struct pipes_struct *p,
 					  &u,
 					  &p->out_data.frag);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
+		DEBUG(0, ("Failed to marshall alter_resp packet. (%s)\n",
 			  nt_errstr(status)));
+		goto err_exit;
 	}
 
 	if (auth_resp.length) {
 		status = dcerpc_push_dcerpc_auth(pkt,
-						 auth_info.auth_type,
-						 auth_info.auth_level,
+						 p->auth.auth_type,
+						 p->auth.auth_level,
 						 0, /* pad_len */
-						 1, /* auth_context_id */
+						 p->auth.auth_context_id,
 						 &auth_resp,
 						 &auth_blob);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -1174,6 +1333,7 @@ static bool api_pipe_request(struct pipes_struct *p,
 	TALLOC_CTX *frame = talloc_stackframe();
 	bool ret = False;
 	struct pipe_rpc_fns *pipe_fns;
+	const char *interface_name = NULL;
 
 	if (!p->pipe_bound) {
 		DEBUG(1, ("Pipe not bound!\n"));
@@ -1194,8 +1354,40 @@ static bool api_pipe_request(struct pipes_struct *p,
 		return false;
 	}
 
+	interface_name = ndr_interface_name(&pipe_fns->syntax.uuid,
+					    pipe_fns->syntax.if_version);
+	SMB_ASSERT(interface_name != NULL);
+
+	switch (p->auth.auth_level) {
+	case DCERPC_AUTH_LEVEL_NONE:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		break;
+	default:
+		if (!pipe_fns->allow_connect) {
+			char *addr;
+
+			addr = tsocket_address_string(p->remote_address, frame);
+
+			DEBUG(1, ("%s: restrict auth_level_connect access "
+				  "to [%s] with auth[type=0x%x,level=0x%x] "
+				  "on [%s] from [%s]\n",
+				  __func__, interface_name,
+				  p->auth.auth_type,
+				  p->auth.auth_level,
+				  derpc_transport_string_by_transport(p->transport),
+				  addr));
+
+			setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
+			TALLOC_FREE(frame);
+			return true;
+		}
+		break;
+	}
+
 	if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) {
 		DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n"));
+		set_incoming_fault(p);
 		setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
 		data_blob_free(&p->out_data.rdata);
 		TALLOC_FREE(frame);
@@ -1209,9 +1401,7 @@ static bool api_pipe_request(struct pipes_struct *p,
 		return false;
 	}
 
-	DEBUG(5, ("Requested %s rpc service\n",
-		  ndr_interface_name(&pipe_fns->syntax.uuid,
-				     pipe_fns->syntax.if_version)));
+	DEBUG(5, ("Requested %s rpc service\n", interface_name));
 
 	ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
 			 &pipe_fns->syntax);
@@ -1345,7 +1535,11 @@ void set_incoming_fault(struct pipes_struct *p)
 	data_blob_free(&p->in_data.data);
 	p->in_data.pdu_needed_len = 0;
 	p->in_data.pdu.length = 0;
-	p->fault_state = DCERPC_FAULT_CANT_PERFORM;
+	p->fault_state = DCERPC_NCA_S_PROTO_ERROR;
+
+	p->allow_alter = false;
+	p->allow_auth3 = false;
+	p->pipe_bound = false;
 
 	DEBUG(10, ("Setting fault state\n"));
 }
@@ -1356,7 +1550,6 @@ static NTSTATUS dcesrv_auth_request(struct pipe_auth_data *auth,
 {
 	NTSTATUS status;
 	size_t hdr_size = DCERPC_REQUEST_LENGTH;
-	size_t pad_len;
 
 	DEBUG(10, ("Checking request auth.\n"));
 
@@ -1367,25 +1560,11 @@ static NTSTATUS dcesrv_auth_request(struct pipe_auth_data *auth,
 	/* in case of sealing this function will unseal the data in place */
 	status = dcerpc_check_auth(auth, pkt,
 				   &pkt->u.request.stub_and_verifier,
-				   hdr_size, raw_pkt,
-				   &pad_len);
+				   hdr_size, raw_pkt);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
-
-	/* remove padding and auth trailer,
-	 * this way the caller will get just the data */
-	if (pkt->auth_length) {
-		size_t trail_len = pad_len
-					+ DCERPC_AUTH_TRAILER_LENGTH
-					+ pkt->auth_length;
-		if (pkt->u.request.stub_and_verifier.length < trail_len) {
-			return NT_STATUS_INFO_LENGTH_MISMATCH;
-		}
-		pkt->u.request.stub_and_verifier.length -= trail_len;
-	}
-
 	return NT_STATUS_OK;
 }
 
@@ -1406,6 +1585,29 @@ static bool process_request_pdu(struct pipes_struct *p, struct ncacn_packet *pkt
 		return False;
 	}
 
+	/*
+	 * We don't ignore DCERPC_PFC_FLAG_PENDING_CANCEL.
+	 * TODO: we can reject it with DCERPC_FAULT_NO_CALL_ACTIVE later.
+	 */
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+			DCERPC_PKT_REQUEST,
+			pkt->u.request.stub_and_verifier.length,
+			0, /* required_flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("process_request_pdu: invalid pdu: %s\n",
+			  nt_errstr(status)));
+		NDR_PRINT_DEBUG(ncacn_packet, pkt);
+		set_incoming_fault(p);
+		return false;
+	}
+
 	hdr2 = dcerpc_sec_vt_header2_from_ncacn_packet(pkt);
 	if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
 		p->header2 = hdr2;
@@ -1597,7 +1799,7 @@ done:
 	if (!reply) {
 		DEBUG(3,("DCE/RPC fault sent!"));
 		set_incoming_fault(p);
-		setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
+		setup_fault_pdu(p, NT_STATUS(DCERPC_NCA_S_PROTO_ERROR));
 	}
 	/* pkt and p->in_data.pdu.data freed by caller */
 }
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index b4108d9..c32fbc7 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -1071,10 +1071,9 @@ out_free:
 		}
 	}
 	if (pipe_default_auth_type != DCERPC_AUTH_TYPE_NONE) {
-		/* If neither Integrity or Privacy are requested then
-		 * Use just Connect level */
+		/* If nothing is requested then default to integrity */
 		if (pipe_default_auth_level == DCERPC_AUTH_LEVEL_NONE) {
-			pipe_default_auth_level = DCERPC_AUTH_LEVEL_CONNECT;
+			pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
 		}
 	}
 
diff --git a/source3/script/tests/test_ntlm_auth_s3.sh b/source3/script/tests/test_ntlm_auth_s3.sh
index 655556b..bd4ffa1 100755
--- a/source3/script/tests/test_ntlm_auth_s3.sh
+++ b/source3/script/tests/test_ntlm_auth_s3.sh
@@ -94,6 +94,8 @@ testit "ntlm_auth with NTLMSSP client and gss-spnego server" $PYTHON $SRC3DIR/to
 testit "ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server" $PYTHON $SRC3DIR/torture/test_ntlm_auth.py $NTLM_AUTH $ADDARGS --client-domain=fOo --server-domain=fOo --client-helper=gss-spnego-client --server-helper=gss-spnego || failed=`expr $failed + 1`
 testit "ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server against winbind" $PYTHON $SRC3DIR/torture/test_ntlm_auth.py $NTLM_AUTH --client-username=$USERNAME --client-domain=$DOMAIN --client-password=$PASSWORD --server-use-winbindd --client-helper=gss-spnego-client --server-helper=gss-spnego $ADDARGS || failed=`expr $failed + 1`
 
+testit "wbinfo store cached credentials" $BINDIR/wbinfo --ccache-save=$DOMAIN/$USERNAME%$PASSWORD || failed=`expr $failed + 1`
+testit "ntlm_auth ccached credentials with NTLMSSP client and gss-spnego server" $PYTHON $SRC3DIR/torture/test_ntlm_auth.py $NTLM_AUTH $ADDARGS --client-username=$USERNAME --client-domain=$DOMAIN --client-use-cached-creds --client-helper=ntlmssp-client-1 --server-helper=gss-spnego --server-use-winbindd || failed=`expr $failed + 1`
 
 testit "ntlm_auth against winbindd with require-membership-of" $PYTHON $SRC3DIR/torture/test_ntlm_auth.py $NTLM_AUTH --client-username=$USERNAME --client-domain=$DOMAIN --client-password=$PASSWORD --server-use-winbindd $ADDARGS --require-membership-of=$SID || failed=`expr $failed + 1`
 testit "ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server against winbind with require-membership-of" $PYTHON $SRC3DIR/torture/test_ntlm_auth.py $NTLM_AUTH --client-username=$USERNAME --client-domain=$DOMAIN --client-password=$PASSWORD --server-use-winbindd --client-helper=gss-spnego-client --server-helper=gss-spnego $ADDARGS --require-membership-of=$SID || failed=`expr $failed + 1`
diff --git a/source3/script/tests/test_rpcclient_samlogon.sh b/source3/script/tests/test_rpcclient_samlogon.sh
index 01af7f8..a41ae44 100755
--- a/source3/script/tests/test_rpcclient_samlogon.sh
+++ b/source3/script/tests/test_rpcclient_samlogon.sh
@@ -12,16 +12,21 @@ PASSWORD="$2"
 shift 2
 ADDARGS="$*"
 
-rpcclient_samlogon()
+rpcclient_samlogon_schannel_seal()
 {
-	$VALGRIND $BINDIR/rpcclient -U% -c "samlogon $USERNAME $PASSWORD;samlogon $USERNAME $PASSWORD" $@
+	$VALGRIND $BINDIR/rpcclient -U% -c "schannel;samlogon $USERNAME $PASSWORD;samlogon $USERNAME $PASSWORD" $@
 }
 
+rpcclient_samlogon_schannel_sign()
+{
+	$VALGRIND $BINDIR/rpcclient -U% -c "schannelsign;samlogon $USERNAME $PASSWORD;samlogon $USERNAME $PASSWORD" $@
+}
 
 incdir=`dirname $0`/../../../testprogs/blackbox
 . $incdir/subunit.sh
 testit "rpcclient dsenumdomtrusts" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "dsenumdomtrusts" || failed=`expr $failed + 1`
 testit "rpcclient getdcsitecoverage" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "getdcsitecoverage" || failed=`expr $failed + 1`
-testit "rpcclient samlogon" rpcclient_samlogon $ADDARGS || failed=`expr $failed +1`
+testit "rpcclient samlogon schannel seal" rpcclient_samlogon_schannel_seal $ADDARGS || failed=`expr $failed +1`
+testit "rpcclient samlogon schannel sign" rpcclient_samlogon_schannel_sign $ADDARGS || failed=`expr $failed +1`
 
 testok $0 $failed
diff --git a/source3/script/tests/test_smbclient_auth.sh b/source3/script/tests/test_smbclient_auth.sh
index 057414c..cc075b9 100755
--- a/source3/script/tests/test_smbclient_auth.sh
+++ b/source3/script/tests/test_smbclient_auth.sh
@@ -21,6 +21,17 @@ ADDARGS="$*"
 incdir=`dirname $0`/../../../testprogs/blackbox
 . $incdir/subunit.sh
 
+echo "${SERVER_IP}" | grep -q ':.*:' && {
+	# If we have an ipv6 address e.g.
+	# fd00:0000:0000:0000:0000:0000:5357:5f03
+	# we also try
+	# fd00-0000-0000-0000-0000-0000-5357-5f03.ipv6-literal.net
+	IPV6LITERAL=$(echo "${SERVER_IP}.ipv6-literal.net" | sed -e 's!:!-!g' -e 's!%!s!')
+	testit "smbclient //${IPV6LITERAL}/tmpguest" $SMBCLIENT //${IPV6LITERAL}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS
+	testit "smbclient //${IPV6LITERAL}./tmpguest" $SMBCLIENT //${IPV6LITERAL}./tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS
+}
+testit "smbclient //${SERVER_IP}/tmpguest" $SMBCLIENT //${SERVER_IP}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -p 139 -c quit $ADDARGS
+
 testit "smbclient //$SERVER/guestonly" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS
 testit "smbclient //$SERVER/guestonly as anon" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS
 testit "smbclient //$SERVER/tmpguest" $SMBCLIENT //$SERVER/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 79db4b5..35e81fc 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -136,6 +136,9 @@ for env in ["nt4_dc", "nt4_member", "ad_member"]:
     plantestsuite("samba3.blackbox.smbclient_auth.plain (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_smbclient_auth.sh"), '$SERVER', '$SERVER_IP', '$DC_USERNAME', '$DC_PASSWORD', smbclient3, configuration])
     plantestsuite("samba3.blackbox.smbclient_auth.plain (%s) member creds" % env, env, [os.path.join(samba3srcdir, "script/tests/test_smbclient_auth.sh"), '$SERVER', '$SERVER_IP', '$SERVER/$USERNAME', '$PASSWORD', smbclient3, configuration])
 
+env="nt4_dc"
+plantestsuite("samba3.blackbox.smbclient_auth.plain (%s) ipv6" % env, env, [os.path.join(samba3srcdir, "script/tests/test_smbclient_auth.sh"), '$SERVER', '$SERVER_IPV6', '$SERVER/$USERNAME', '$PASSWORD', smbclient3, configuration])
+
 for env in ["nt4_member", "ad_member"]:
     plantestsuite("samba3.blackbox.net_cred_change.(%s:local)" % env, "%s:local" % env, [os.path.join(samba3srcdir, "script/tests/test_net_cred_change.sh"), configuration])
 
@@ -346,8 +349,8 @@ for t in tests:
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD', 'over ncacn_np ')
         plansmbtorture4testsuite(t, "ad_dc", 'ncacn_ip_tcp:$SERVER_IP -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ')
     elif t == "rpc.samr.passwords.validate":
-        plansmbtorture4testsuite(t, "nt4_dc", 'ncacn_ip_tcp:$SERVER_IP -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ')
-        plansmbtorture4testsuite(t, "ad_dc", 'ncacn_ip_tcp:$SERVER_IP -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ')
+        plansmbtorture4testsuite(t, "nt4_dc", 'ncacn_ip_tcp:$SERVER_IP[seal] -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ')
+        plansmbtorture4testsuite(t, "ad_dc", 'ncacn_ip_tcp:$SERVER_IP[seal] -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ')
     elif t == "smb2.durable-open" or t == "smb2.durable-v2-open" or t == "smb2.replay":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/durable -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/durable -U$USERNAME%$PASSWORD')
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index fe942c1..4e40758 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -518,6 +518,7 @@ void reply_negprot(struct smb_request *req)
 	size_t converted_size;
 	struct smbXsrv_connection *xconn = req->xconn;
 	struct smbd_server_connection *sconn = req->sconn;
+	bool signing_required = true;
 
 	START_PROFILE(SMBnegprot);
 
@@ -689,8 +690,9 @@ void reply_negprot(struct smb_request *req)
 
 	DEBUG( 5, ( "negprot index=%d\n", choice ) );
 
-	if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
-	    && (chosen_level < PROTOCOL_NT1)) {
+	/* We always have xconn->smb1.signing_state also for >= SMB2_02 */
+	signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
+	if (signing_required && (chosen_level < PROTOCOL_NT1)) {
 		exit_server_cleanly("SMB signing is required and "
 			"client negotiated a downlevel protocol");
 	}
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index d68bcb6..25b2ed6 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -37,6 +37,7 @@
 #include "../libcli/security/security.h"
 #include "auth/gensec/gensec.h"
 #include "lib/conn_tdb.h"
+#include "../libcli/smb/smb_signing.h"
 
 /****************************************************************************
  Add the standard 'Samba' signature to the end of the session setup.
@@ -599,7 +600,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
 	struct smbd_server_connection *sconn = req->sconn;
 	bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
 	bool signing_allowed = false;
-	bool signing_mandatory = false;
+	bool signing_mandatory = smb_signing_is_mandatory(
+		xconn->smb1.signing_state);
 
 	START_PROFILE(SMBsesssetupX);
 
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index 18382a9..41b55eb 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -25,6 +25,7 @@
 #include "../libcli/smb/smb2_negotiate_context.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../librpc/ndr/libndr.h"
+#include "../libcli/smb/smb_signing.h"
 
 extern fstring remote_proto;
 
@@ -160,6 +161,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	uint32_t max_read = lp_smb2_max_read();
 	uint32_t max_write = lp_smb2_max_write();
 	NTTIME now = timeval_to_nttime(&req->request_time);
+	bool signing_required = true;
 
 	status = smbd_smb2_request_verify_sizes(req, 0x24);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -287,7 +289,13 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	}
 
 	security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
-	if (lp_server_signing() == SMB_SIGNING_REQUIRED) {
+	/*
+	 * We use xconn->smb1.signing_state as that's already present
+	 * and used lpcfg_server_signing_allowed() to get the correct
+	 * defaults, e.g. signing_required for an ad_dc.
+	 */
+	signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
+	if (signing_required) {
 		security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
 	}
 
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 11d381f..fe64df0 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -258,7 +258,8 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 	}
 
 	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
-	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
+	    (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
+	{
 		x->global->signing_required = true;
 	}
 
diff --git a/source3/torture/test_ntlm_auth.py b/source3/torture/test_ntlm_auth.py
index d17af9b..fffeb26 100755
--- a/source3/torture/test_ntlm_auth.py
+++ b/source3/torture/test_ntlm_auth.py
@@ -27,300 +27,305 @@ import sys
 from optparse import OptionParser
 
 class ReadChildError(Exception):
-	pass
+    pass
 
 class WriteChildError(Exception):
-	pass
+    pass
 
 def readLine(pipe):
-	"""readLine(pipe) -> str
-	Read a line from the child's pipe, returns the string read.
-	Throws ReadChildError if the read fails.
-	"""
-	buf = os.read(pipe, 2047)
-	newline = buf.find('\n')
-	if newline == -1:
-		raise ReadChildError()
-	return buf[:newline]
+    """readLine(pipe) -> str
+    Read a line from the child's pipe, returns the string read.
+    Throws ReadChildError if the read fails.
+    """
+    buf = os.read(pipe, 2047)
+    newline = buf.find('\n')
+    if newline == -1:
+        raise ReadChildError()
+    return buf[:newline]
 
 def writeLine(pipe, buf):
-	"""writeLine(pipe, buf) -> nul
-	Write a line to the child's pipe.
-	Raises WriteChildError if the write fails.
-	"""
-	written = os.write(pipe, buf)
-	if written != len(buf):
-		raise WriteChildError()
-	os.write(pipe, "\n")
+    """writeLine(pipe, buf) -> nul
+    Write a line to the child's pipe.
+    Raises WriteChildError if the write fails.
+    """
+    written = os.write(pipe, buf)
+    if written != len(buf):
+        raise WriteChildError()
+    os.write(pipe, "\n")
 
 def parseCommandLine():
-	"""parseCommandLine() -> (opts, ntlm_auth_path)
-	Parse the command line.
-	Return a tuple consisting of the options and the path to ntlm_auth.
-	"""
-	usage = "usage: %prog [options] path/to/ntlm_auth"
-	parser = OptionParser(usage)
-
-	parser.set_defaults(client_username="foo")
-	parser.set_defaults(client_password="secret")
-	parser.set_defaults(client_domain="FOO")
-	parser.set_defaults(client_helper="ntlmssp-client-1")
-
-	parser.set_defaults(server_username="foo")
-	parser.set_defaults(server_password="secret")
-	parser.set_defaults(server_domain="FOO")
-	parser.set_defaults(server_helper="squid-2.5-ntlmssp")
-	parser.set_defaults(config_file="/etc/samba/smb.conf")
-
-	parser.add_option("--client-username", dest="client_username",\
-				help="User name for the client. [default: foo]")
-	parser.add_option("--client-password", dest="client_password",\
-				help="Password the client will send. [default: secret]")
-	parser.add_option("--client-domain", dest="client_domain",\
-				help="Domain the client authenticates for. [default: FOO]")
-	parser.add_option("--client-helper", dest="client_helper",\
-				help="Helper mode for the ntlm_auth client. [default: ntlmssp-client-1]")
-
-	parser.add_option("--target-hostname", dest="target_hostname",\
-				help="Target hostname for kerberos")
-	parser.add_option("--target-service", dest="target_service",\
-				help="Target service for kerberos")
-
-
-	parser.add_option("--server-username", dest="server_username",\
-				help="User name server uses for local auth. [default: foo]")
-	parser.add_option("--server-password", dest="server_password",\
-				help="Password server uses for local auth. [default: secret]")
-	parser.add_option("--server-domain", dest="server_domain",\
-				help="Domain server uses for local auth. [default: FOO]")
-	parser.add_option("--server-helper", dest="server_helper",\
-				help="Helper mode for the ntlm_auth server. [default: squid-2.5-server]")
-	parser.add_option("--server-use-winbindd", dest="server_use_winbindd",\
-				help="Use winbindd to check the password (rather than default username/pw)", action="store_true")
-	parser.add_option("--require-membership-of", dest="sid",\
-				help="Require that the user is a member of this group to authenticate.")
-
-
-	parser.add_option("-s", "--configfile", dest="config_file",\
-				help="Path to smb.conf file. [default:/etc/samba/smb.conf")
-
-	(opts, args) = parser.parse_args()
-	if len(args) != 1:
-		parser.error("Invalid number of arguments.")
-
-	if not os.access(args[0], os.X_OK):
-		parser.error("%s is not executable." % args[0])
-
-	return (opts, args[0])
+    """parseCommandLine() -> (opts, ntlm_auth_path)
+    Parse the command line.
+    Return a tuple consisting of the options and the path to ntlm_auth.
+    """
+    usage = "usage: %prog [options] path/to/ntlm_auth"
+    parser = OptionParser(usage)
+
+    parser.set_defaults(client_username="foo")
+    parser.set_defaults(client_password="secret")
+    parser.set_defaults(client_domain="FOO")
+    parser.set_defaults(client_helper="ntlmssp-client-1")
+
+    parser.set_defaults(server_username="foo")
+    parser.set_defaults(server_password="secret")
+    parser.set_defaults(server_domain="FOO")
+    parser.set_defaults(server_helper="squid-2.5-ntlmssp")
+    parser.set_defaults(config_file="/etc/samba/smb.conf")
+
+    parser.add_option("--client-username", dest="client_username",\
+                help="User name for the client. [default: foo]")
+    parser.add_option("--client-password", dest="client_password",\
+                help="Password the client will send. [default: secret]")
+    parser.add_option("--client-domain", dest="client_domain",\
+                help="Domain the client authenticates for. [default: FOO]")
+    parser.add_option("--client-helper", dest="client_helper",\
+                help="Helper mode for the ntlm_auth client. [default: ntlmssp-client-1]")
+    parser.add_option("--client-use-cached-creds", dest="client_use_cached_creds",\
+                help="Use winbindd credentials cache (rather than default username/pw)", action="store_true")
+
+    parser.add_option("--target-hostname", dest="target_hostname",\
+                help="Target hostname for kerberos")
+    parser.add_option("--target-service", dest="target_service",\
+                help="Target service for kerberos")
+
+
+    parser.add_option("--server-username", dest="server_username",\
+                help="User name server uses for local auth. [default: foo]")
+    parser.add_option("--server-password", dest="server_password",\
+                help="Password server uses for local auth. [default: secret]")
+    parser.add_option("--server-domain", dest="server_domain",\
+                help="Domain server uses for local auth. [default: FOO]")
+    parser.add_option("--server-helper", dest="server_helper",\
+                help="Helper mode for the ntlm_auth server. [default: squid-2.5-server]")
+    parser.add_option("--server-use-winbindd", dest="server_use_winbindd",\
+                help="Use winbindd to check the password (rather than default username/pw)", action="store_true")
+    parser.add_option("--require-membership-of", dest="sid",\
+                help="Require that the user is a member of this group to authenticate.")
+
+
+    parser.add_option("-s", "--configfile", dest="config_file",\
+                help="Path to smb.conf file. [default:/etc/samba/smb.conf")
+
+    (opts, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.error("Invalid number of arguments.")
+
+    if not os.access(args[0], os.X_OK):
+        parser.error("%s is not executable." % args[0])
+
+    return (opts, args[0])
 
 
 def main():
-	"""main() -> int
-	Run the test.
-	Returns 0 if test succeeded, <>0 otherwise.
-	"""
-	(opts, ntlm_auth_path) = parseCommandLine()
+    """main() -> int
+    Run the test.
+    Returns 0 if test succeeded, <>0 otherwise.
+    """
+    (opts, ntlm_auth_path) = parseCommandLine()
 
-	(client_in_r,  client_in_w)  = os.pipe()
-	(client_out_r, client_out_w) = os.pipe()
-
-	client_pid = os.fork()
-
-	if not client_pid:
-		# We're in the client child
-		os.close(0)
-		os.close(1)
-
-		os.dup2(client_out_r, 0)
-		os.close(client_out_r)
-		os.close(client_out_w)
-
-		os.dup2(client_in_w, 1)
-		os.close(client_in_r)
-		os.close(client_in_w)
-
-		client_args = []
-		client_args.append("--helper-protocol=%s" % opts.client_helper)
-		client_args.append("--username=%s" % opts.client_username)
-		client_args.append("--password=%s" % opts.client_password)
-		client_args.append("--domain=%s" % opts.client_domain)
-		client_args.append("--configfile=%s" % opts.config_file)
-		if opts.target_service:
-			client_args.append("--target-service=%s" % opts.target_service)
-		if opts.target_hostname:
-			client_args.append("--target-hostname=%s" % opts.target_hostname)
-
-		os.execv(ntlm_auth_path, client_args)
-
-	client_in = client_in_r
-	os.close(client_in_w)
-
-	client_out = client_out_w
-	os.close(client_out_r)
-
-	(server_in_r,  server_in_w)  = os.pipe()
-	(server_out_r, server_out_w) = os.pipe()
-
-	server_pid = os.fork()
-
-	if not server_pid:
-		# We're in the server child
-		os.close(0)
-		os.close(1)
-
-		os.dup2(server_out_r, 0)
-		os.close(server_out_r)
-		os.close(server_out_w)
-
-		os.dup2(server_in_w, 1)
-		os.close(server_in_r)
-		os.close(server_in_w)
-
-		server_args = []
-		server_args.append("--helper-protocol=%s" % opts.server_helper)
-		if not opts.server_use_winbindd:
-			server_args.append("--username=%s" % opts.server_username)
-			server_args.append("--password=%s" % opts.server_password)
-			server_args.append("--domain=%s" % opts.server_domain)
-			if opts.sid:
-				raise Exception("Server must be using winbindd for require-membership-of.")
-		else:
-			if opts.sid:
-				server_args.append("--require-membership-of=%s" % opts.sid)
-
-		server_args.append("--configfile=%s" % opts.config_file)
-
-		os.execv(ntlm_auth_path, server_args)
-
-	server_in = server_in_r
-	os.close(server_in_w)
-
-	server_out = server_out_w
-	os.close(server_out_r)
-
-	if opts.client_helper == "ntlmssp-client-1" and opts.server_helper == "squid-2.5-ntlmssp":
-
-		# We're in the parent
-		writeLine(client_out, "YR")
-		buf = readLine(client_in)
-		
-		if buf.count("YR ", 0, 3) != 1:
-			sys.exit(1)
-
-		writeLine(server_out, buf)
-		buf = readLine(server_in)
-
-		if buf.count("TT ", 0, 3) != 1:
-			sys.exit(2)
-
-		writeLine(client_out, buf)
-		buf = readLine(client_in)
-
-		if buf.count("AF ", 0, 3) != 1:
-			sys.exit(3)
-
-		# Client sends 'AF <base64 blob>' but server expects 'KK <abse64 blob>'
-		buf = buf.replace("AF", "KK", 1)
-		
-		writeLine(server_out, buf)
-		buf = readLine(server_in)
-		
-		if buf.count("AF ", 0, 3) != 1:
-			sys.exit(4)
-
-	
-	elif opts.client_helper == "ntlmssp-client-1" and opts.server_helper == "gss-spnego":
-		# We're in the parent
-		writeLine(client_out, "YR")
-		buf = readLine(client_in)
-		
-		if buf.count("YR ", 0, 3) != 1:
-			sys.exit(1)
-
-		writeLine(server_out, buf)
-		buf = readLine(server_in)
-
-		if buf.count("TT ", 0, 3) != 1:
-			sys.exit(2)
-
-		writeLine(client_out, buf)
-		buf = readLine(client_in)
+    (client_in_r,  client_in_w)  = os.pipe()
+    (client_out_r, client_out_w) = os.pipe()
 
-		if buf.count("AF ", 0, 3) != 1:
-			sys.exit(3)
+    client_pid = os.fork()
 
-		# Client sends 'AF <base64 blob>' but server expects 'KK <abse64 blob>'
-		buf = buf.replace("AF", "KK", 1)
-		
-		writeLine(server_out, buf)
-		buf = readLine(server_in)
-		
-		if buf.count("AF * ", 0, 5) != 1:
-			sys.exit(4)
+    if not client_pid:
+        # We're in the client child
+        os.close(0)
+        os.close(1)
 
+        os.dup2(client_out_r, 0)
+        os.close(client_out_r)
+        os.close(client_out_w)
 
-	elif opts.client_helper == "gss-spnego-client" and opts.server_helper == "gss-spnego":
-		# We're in the parent
-		writeLine(server_out, "YR")
-		buf = readLine(server_in)
-		
-		while True:
-			if buf.count("AF ", 0, 3) != 1 and buf.count("TT ", 0, 3) != 1:
-				sys.exit(1)
-
-			writeLine(client_out, buf)
-			buf = readLine(client_in)
-		
-			if buf.count("AF", 0, 2) == 1:
-				break
-
-			if buf.count("AF ", 0, 5) != 1 and buf.count("KK ", 0, 3) != 1 and buf.count("TT ", 0, 3) != 1:
-				sys.exit(2)
-
-			writeLine(server_out, buf)
-			buf = readLine(server_in)
-
-			if buf.count("AF * ", 0, 5) == 1:
-				break
-
-	else:
-		sys.exit(5)
+        os.dup2(client_in_w, 1)
+        os.close(client_in_r)
+        os.close(client_in_w)
 
-	if opts.client_helper == "ntlmssp-client-1":
-		writeLine(client_out, "GK")
-		buf = readLine(client_in)
+        client_args = []
+        client_args.append("--helper-protocol=%s" % opts.client_helper)
+        client_args.append("--username=%s" % opts.client_username)
+        if opts.client_use_cached_creds:
+            client_args.append("--use-cached-creds")
+        else:
+            client_args.append("--password=%s" % opts.client_password)
+        client_args.append("--domain=%s" % opts.client_domain)
+        client_args.append("--configfile=%s" % opts.config_file)
+        if opts.target_service:
+            client_args.append("--target-service=%s" % opts.target_service)
+        if opts.target_hostname:
+            client_args.append("--target-hostname=%s" % opts.target_hostname)
 
-		if buf.count("GK ", 0, 3) != 1:
-			sys.exit(4)
-
-		writeLine(client_out, "GF")
-		buf = readLine(client_in)
-
-		if buf.count("GF ", 0, 3) != 1:
-			sys.exit(4)
-
-	if opts.server_helper == "squid-2.5-ntlmssp":
-		writeLine(server_out, "GK")
-		buf = readLine(server_in)
-
-		if buf.count("GK ", 0, 3) != 1:
-			sys.exit(4)
+        os.execv(ntlm_auth_path, client_args)
 
-		writeLine(server_out, "GF")
-		buf = readLine(server_in)
-
-		if buf.count("GF ", 0, 3) != 1:
-			sys.exit(4)
-
-	os.close(server_in)
-	os.close(server_out)
-	os.close(client_in)
-	os.close(client_out)
-	os.waitpid(server_pid, 0)
-	os.waitpid(client_pid, 0)
-	sys.exit(0)
+    client_in = client_in_r
+    os.close(client_in_w)
+
+    client_out = client_out_w
+    os.close(client_out_r)
+
+    (server_in_r,  server_in_w)  = os.pipe()
+    (server_out_r, server_out_w) = os.pipe()
+
+    server_pid = os.fork()
+
+    if not server_pid:
+        # We're in the server child
+        os.close(0)
+        os.close(1)
+
+        os.dup2(server_out_r, 0)
+        os.close(server_out_r)
+        os.close(server_out_w)
+
+        os.dup2(server_in_w, 1)
+        os.close(server_in_r)
+        os.close(server_in_w)
+
+        server_args = []
+        server_args.append("--helper-protocol=%s" % opts.server_helper)
+        if not opts.server_use_winbindd:
+            server_args.append("--username=%s" % opts.server_username)
+            server_args.append("--password=%s" % opts.server_password)
+            server_args.append("--domain=%s" % opts.server_domain)
+            if opts.sid:
+                raise Exception("Server must be using winbindd for require-membership-of.")
+        else:
+            if opts.sid:
+                server_args.append("--require-membership-of=%s" % opts.sid)
+
+        server_args.append("--configfile=%s" % opts.config_file)
+
+        os.execv(ntlm_auth_path, server_args)
+
+    server_in = server_in_r
+    os.close(server_in_w)
+
+    server_out = server_out_w
+    os.close(server_out_r)
+
+    if opts.client_helper == "ntlmssp-client-1" and opts.server_helper == "squid-2.5-ntlmssp":
+
+        # We're in the parent
+        writeLine(client_out, "YR")
+        buf = readLine(client_in)
+
+        if buf.count("YR ", 0, 3) != 1:
+            sys.exit(1)
+
+        writeLine(server_out, buf)
+        buf = readLine(server_in)
+
+        if buf.count("TT ", 0, 3) != 1:
+            sys.exit(2)
+
+        writeLine(client_out, buf)
+        buf = readLine(client_in)
+
+        if buf.count("AF ", 0, 3) != 1:
+            sys.exit(3)
+
+        # Client sends 'AF <base64 blob>' but server expects 'KK <abse64 blob>'
+        buf = buf.replace("AF", "KK", 1)
+
+        writeLine(server_out, buf)
+        buf = readLine(server_in)
+
+        if buf.count("AF ", 0, 3) != 1:
+            sys.exit(4)
+
+
+    elif opts.client_helper == "ntlmssp-client-1" and opts.server_helper == "gss-spnego":
+        # We're in the parent
+        writeLine(client_out, "YR")
+        buf = readLine(client_in)
+
+        if buf.count("YR ", 0, 3) != 1:
+            sys.exit(1)
+
+        writeLine(server_out, buf)
+        buf = readLine(server_in)
+
+        if buf.count("TT ", 0, 3) != 1:
+            sys.exit(2)
+
+        writeLine(client_out, buf)
+        buf = readLine(client_in)
+
+        if buf.count("AF ", 0, 3) != 1:
+            sys.exit(3)
+
+        # Client sends 'AF <base64 blob>' but server expects 'KK <abse64 blob>'
+        buf = buf.replace("AF", "KK", 1)
+
+        writeLine(server_out, buf)
+        buf = readLine(server_in)
+
+        if buf.count("AF * ", 0, 5) != 1:
+            sys.exit(4)
+
+
+    elif opts.client_helper == "gss-spnego-client" and opts.server_helper == "gss-spnego":
+        # We're in the parent
+        writeLine(server_out, "YR")
+        buf = readLine(server_in)
+
+        while True:
+            if buf.count("AF ", 0, 3) != 1 and buf.count("TT ", 0, 3) != 1:
+                sys.exit(1)
+
+            writeLine(client_out, buf)
+            buf = readLine(client_in)
+
+            if buf.count("AF", 0, 2) == 1:
+                break
+
+            if buf.count("AF ", 0, 5) != 1 and buf.count("KK ", 0, 3) != 1 and buf.count("TT ", 0, 3) != 1:
+                sys.exit(2)
+
+            writeLine(server_out, buf)
+            buf = readLine(server_in)
+
+            if buf.count("AF * ", 0, 5) == 1:
+                break
+
+    else:
+        sys.exit(5)
+
+    if opts.client_helper == "ntlmssp-client-1":
+        writeLine(client_out, "GK")
+        buf = readLine(client_in)
+
+        if buf.count("GK ", 0, 3) != 1:
+            sys.exit(4)
+
+        writeLine(client_out, "GF")
+        buf = readLine(client_in)
+
+        if buf.count("GF ", 0, 3) != 1:
+            sys.exit(4)
+
+    if opts.server_helper == "squid-2.5-ntlmssp":
+        writeLine(server_out, "GK")
+        buf = readLine(server_in)
+
+        if buf.count("GK ", 0, 3) != 1:
+            sys.exit(4)
+
+        writeLine(server_out, "GF")
+        buf = readLine(server_in)
+
+        if buf.count("GF ", 0, 3) != 1:
+            sys.exit(4)
+
+    os.close(server_in)
+    os.close(server_out)
+    os.close(client_in)
+    os.close(client_out)
+    os.waitpid(server_pid, 0)
+    os.waitpid(client_pid, 0)
+    sys.exit(0)
 
 if __name__ == "__main__":
-	main()
+    main()
 
 
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 28553fc..5ed3129 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1933,7 +1933,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
 					c->opt_user_name, c->opt_workgroup,
 					c->opt_password ? c->opt_password : "",
 					CLI_FULL_CONNECTION_USE_KERBEROS,
-					SMB_SIGNING_DEFAULT);
+					SMB_SIGNING_IPC_DEFAULT);
 
 	if (NT_STATUS_IS_ERR(nt_status)) {
 		d_fprintf(stderr, _("Unable to open a connection to %s to "
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 1de08c4..93caf04 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -7396,7 +7396,7 @@ bool net_rpc_check(struct net_context *c, unsigned flags)
 		return false;
 
 	status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
-				lp_netbios_name(), SMB_SIGNING_DEFAULT,
+				lp_netbios_name(), SMB_SIGNING_IPC_DEFAULT,
 				0, &cli);
 	if (!NT_STATUS_IS_OK(status)) {
 		return false;
diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c
index 13a0ef1..de929ff 100644
--- a/source3/utils/net_util.c
+++ b/source3/utils/net_util.c
@@ -126,7 +126,7 @@ NTSTATUS connect_to_service(struct net_context *c,
 					service_name, service_type,
 					c->opt_user_name, c->opt_workgroup,
 					c->opt_password, flags,
-					SMB_SIGNING_DEFAULT);
+					SMB_SIGNING_IPC_DEFAULT);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		d_fprintf(stderr, _("Could not connect to server %s\n"),
 			  server_name);
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index a5fd249..1ac6881 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -29,7 +29,6 @@
 #include "popt_common.h"
 #include "utils/ntlm_auth.h"
 #include "../libcli/auth/libcli_auth.h"
-#include "../libcli/auth/spnego.h"
 #include "auth/ntlmssp/ntlmssp.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_internal.h"
@@ -38,7 +37,6 @@
 #include "smb_krb5.h"
 #include "lib/util/tiniparser.h"
 #include "../lib/crypto/arcfour.h"
-#include "libads/kerberos_proto.h"
 #include "nsswitch/winbind_client.h"
 #include "librpc/gen_ndr/krb5pac.h"
 #include "../lib/util/asn1.h"
@@ -100,6 +98,10 @@ typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode,
 				      struct ntlm_auth_state *state, char *buf,
 					int length, void **private2);
 
+static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
+				  struct loadparm_context *lp_ctx,
+				  char *buf, int length, void **private1);
+
 static void manage_squid_request(enum stdio_helper_mode stdio_helper_mode,
 				 struct loadparm_context *lp_ctx,
 				 struct ntlm_auth_state *state,
@@ -225,13 +227,25 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod
 
 static const char *get_password(struct cli_credentials *credentials)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
 	char *password = NULL;
+	struct ntlm_auth_state *state;
+
+	state = talloc_zero(frame, struct ntlm_auth_state);
+	if (state == NULL) {
+		DEBUG(0, ("squid_stream: Failed to talloc ntlm_auth_state\n"));
+		x_fprintf(x_stderr, "ERR\n");
+		exit(1);
+	}
+
+	state->mem_ctx = state;
 
 	/* Ask for a password */
 	x_fprintf(x_stdout, "PW\n");
 
-	manage_squid_request(NUM_HELPER_MODES /* bogus */, NULL, NULL, manage_gensec_get_pw_request, (void **)&password);
+	manage_squid_request(NUM_HELPER_MODES /* bogus */, NULL, state, manage_gensec_get_pw_request, (void **)&password);
 	talloc_steal(credentials, password);
+	TALLOC_FREE(frame);
 	return password;
 }
 
@@ -254,6 +268,10 @@ static void gensec_want_feature_list(struct gensec_security *state, char* featur
 		DEBUG(10, ("want GENSEC_FEATURE_SEAL\n"));
 		gensec_want_feature(state, GENSEC_FEATURE_SEAL);
 	}
+	if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
+		DEBUG(10, ("want GENSEC_FEATURE_NTLM_CCACHE\n"));
+		gensec_want_feature(state, GENSEC_FEATURE_NTLM_CCACHE);
+	}
 }
 
 static char winbind_separator(void)
@@ -953,57 +971,75 @@ static NTSTATUS local_pw_check(struct auth4_context *auth4_context,
 	return nt_status;
 }
 
-static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntlmssp_state)
+static NTSTATUS ntlm_auth_prepare_gensec_client(TALLOC_CTX *mem_ctx,
+						struct loadparm_context *lp_ctx,
+						struct gensec_security **gensec_security_out)
 {
-	NTSTATUS status;
-	if ( (opt_username == NULL) || (opt_domain == NULL) ) {
-		status = NT_STATUS_UNSUCCESSFUL;
-		DEBUG(1, ("Need username and domain for NTLMSSP\n"));
-		return NT_STATUS_INVALID_PARAMETER;
-	}
+	struct gensec_security *gensec_security = NULL;
+	NTSTATUS nt_status;
+	TALLOC_CTX *tmp_ctx;
+	const struct gensec_security_ops **backends = NULL;
+	struct gensec_settings *gensec_settings = NULL;
+	size_t idx = 0;
 
-	status = ntlmssp_client_start(NULL,
-				      lp_netbios_name(),
-				      lp_workgroup(),
-				      lp_client_ntlmv2_auth(),
-				      client_ntlmssp_state);
+	tmp_ctx = talloc_new(mem_ctx);
+	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
 
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Could not start NTLMSSP client: %s\n",
-			  nt_errstr(status)));
-		TALLOC_FREE(*client_ntlmssp_state);
-		return status;
+	gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
+	if (gensec_settings == NULL) {
+		DEBUG(10, ("lpcfg_gensec_settings failed\n"));
+		TALLOC_FREE(tmp_ctx);
+		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = ntlmssp_set_username(*client_ntlmssp_state, opt_username);
-
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Could not set username: %s\n",
-			  nt_errstr(status)));
-		TALLOC_FREE(*client_ntlmssp_state);
-		return status;
+	backends = talloc_zero_array(gensec_settings,
+				     const struct gensec_security_ops *, 4);
+	if (backends == NULL) {
+		TALLOC_FREE(tmp_ctx);
+		return NT_STATUS_NO_MEMORY;
 	}
+	gensec_settings->backends = backends;
+
+	gensec_init();
 
-	status = ntlmssp_set_domain(*client_ntlmssp_state, opt_domain);
+	/* These need to be in priority order, krb5 before NTLMSSP */
+#if defined(HAVE_KRB5)
+	backends[idx++] = &gensec_gse_krb5_security_ops;
+#endif
 
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Could not set domain: %s\n",
-			  nt_errstr(status)));
-		TALLOC_FREE(*client_ntlmssp_state);
-		return status;
+	backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
+
+	backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO);
+
+	nt_status = gensec_client_start(NULL, &gensec_security,
+					gensec_settings);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		TALLOC_FREE(tmp_ctx);
+		return nt_status;
 	}
 
-	if (opt_password) {
-		status = ntlmssp_set_password(*client_ntlmssp_state, opt_password);
+	talloc_unlink(tmp_ctx, gensec_settings);
 
-		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(1, ("Could not set password: %s\n",
-				  nt_errstr(status)));
-			TALLOC_FREE(*client_ntlmssp_state);
-			return status;
+	if (opt_target_service != NULL) {
+		nt_status = gensec_set_target_service(gensec_security,
+						      opt_target_service);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			TALLOC_FREE(tmp_ctx);
+			return nt_status;
 		}
 	}
 
+	if (opt_target_hostname != NULL) {
+		nt_status = gensec_set_target_hostname(gensec_security,
+						       opt_target_hostname);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			TALLOC_FREE(tmp_ctx);
+			return nt_status;
+		}
+	}
+
+	*gensec_security_out = talloc_steal(mem_ctx, gensec_security);
+	TALLOC_FREE(tmp_ctx);
 	return NT_STATUS_OK;
 }
 
@@ -1140,249 +1176,13 @@ static NTSTATUS ntlm_auth_prepare_gensec_server(TALLOC_CTX *mem_ctx,
 	return NT_STATUS_OK;
 }
 
-/*******************************************************************
- Used by firefox to drive NTLM auth to IIS servers.
-*******************************************************************/
-
-static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_msg,
-				DATA_BLOB *reply)
-{
-	struct winbindd_request wb_request;
-	struct winbindd_response wb_response;
-	int ctrl = 0;
-	NSS_STATUS result;
-
-	/* get winbindd to do the ntlmssp step on our behalf */
-	ZERO_STRUCT(wb_request);
-	ZERO_STRUCT(wb_response);
-
-	/*
-	 * This is tricky here. If we set krb5_auth in pam_winbind.conf
-	 * creds for users in trusted domain will be stored the winbindd
-	 * child of the trusted domain. If we ask the primary domain for
-	 * ntlm_ccache_auth, it will fail. So, we have to ask the trusted
-	 * domain's child for ccache_ntlm_auth. that is to say, we have to 
-	 * set WBFLAG_PAM_CONTACT_TRUSTDOM in request.flags.
-	 */
-	ctrl = get_pam_winbind_config();
-
-	if (ctrl & WINBIND_KRB5_AUTH) {
-		wb_request.flags |= WBFLAG_PAM_CONTACT_TRUSTDOM;
-	}
-
-	fstr_sprintf(wb_request.data.ccache_ntlm_auth.user,
-		"%s%c%s", opt_domain, winbind_separator(), opt_username);
-	wb_request.data.ccache_ntlm_auth.uid = geteuid();
-	wb_request.data.ccache_ntlm_auth.initial_blob_len = initial_msg.length;
-	wb_request.data.ccache_ntlm_auth.challenge_blob_len = challenge_msg.length;
-	wb_request.extra_len = initial_msg.length + challenge_msg.length;
-
-	if (wb_request.extra_len > 0) {
-		wb_request.extra_data.data = SMB_MALLOC_ARRAY(char, wb_request.extra_len);
-		if (wb_request.extra_data.data == NULL) {
-			return NT_STATUS_NO_MEMORY;
-		}
-
-		memcpy(wb_request.extra_data.data, initial_msg.data, initial_msg.length);
-		memcpy(wb_request.extra_data.data + initial_msg.length,
-			challenge_msg.data, challenge_msg.length);
-	}
-
-	result = winbindd_request_response(NULL, WINBINDD_CCACHE_NTLMAUTH, &wb_request, &wb_response);
-	SAFE_FREE(wb_request.extra_data.data);
-
-	if (result != NSS_STATUS_SUCCESS) {
-		winbindd_free_response(&wb_response);
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-
-	if (reply) {
-		*reply = data_blob(wb_response.extra_data.data,
-				wb_response.data.ccache_ntlm_auth.auth_blob_len);
-		if (wb_response.data.ccache_ntlm_auth.auth_blob_len > 0 &&
-				reply->data == NULL) {
-			winbindd_free_response(&wb_response);
-			return NT_STATUS_NO_MEMORY;
-		}
-	}
-
-	winbindd_free_response(&wb_response);
-	return NT_STATUS_MORE_PROCESSING_REQUIRED;
-}
-
 static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
 				   struct loadparm_context *lp_ctx,
 				   struct ntlm_auth_state *state,
 						char *buf, int length, void **private2)
 {
-	DATA_BLOB request, reply;
-	NTSTATUS nt_status;
-
-	if (!opt_username || !*opt_username) {
-		x_fprintf(x_stderr, "username must be specified!\n\n");
-		exit(1);
-	}
-
-	if (strlen(buf) < 2) {
-		DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf));
-		x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
-		return;
-	}
-
-	if (strlen(buf) > 3) {
-		if(strncmp(buf, "SF ", 3) == 0) {
-			DEBUG(10, ("Looking for flags to negotiate\n"));
-			talloc_free(state->want_feature_list);
-			state->want_feature_list = talloc_strdup(state->mem_ctx,
-					buf+3);
-			x_fprintf(x_stdout, "OK\n");
-			return;
-		}
-		request = base64_decode_data_blob(buf + 3);
-	} else {
-		request = data_blob_null;
-	}
-
-	if (strncmp(buf, "PW ", 3) == 0) {
-		/* We asked for a password and obviously got it :-) */
-
-		opt_password = SMB_STRNDUP((const char *)request.data,
-				request.length);
-
-		if (opt_password == NULL) {
-			DEBUG(1, ("Out of memory\n"));
-			x_fprintf(x_stdout, "BH Out of memory\n");
-			data_blob_free(&request);
-			return;
-		}
-
-		x_fprintf(x_stdout, "OK\n");
-		data_blob_free(&request);
-		return;
-	}
-
-	if (!state->ntlmssp_state && use_cached_creds) {
-		/* check whether cached credentials are usable. */
-		DATA_BLOB empty_blob = data_blob_null;
-
-		nt_status = do_ccache_ntlm_auth(empty_blob, empty_blob, NULL);
-		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-			/* failed to use cached creds */
-			use_cached_creds = False;
-		}
-	}
-
-	if (opt_password == NULL && !use_cached_creds) {
-		/* Request a password from the calling process.  After
-		   sending it, the calling process should retry asking for the
-		   negotiate. */
-
-		DEBUG(10, ("Requesting password\n"));
-		x_fprintf(x_stdout, "PW\n");
-		return;
-	}
-
-	if (strncmp(buf, "YR", 2) == 0) {
-		TALLOC_FREE(state->ntlmssp_state);
-		state->cli_state = CLIENT_INITIAL;
-	} else if (strncmp(buf, "TT", 2) == 0) {
-		/* No special preprocessing required */
-	} else if (strncmp(buf, "GF", 2) == 0) {
-		DEBUG(10, ("Requested negotiated NTLMSSP flags\n"));
-
-		if(state->cli_state == CLIENT_FINISHED) {
-			x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags);
-		}
-		else {
-			x_fprintf(x_stdout, "BH\n");
-		}
-
-		data_blob_free(&request);
-		return;
-	} else if (strncmp(buf, "GK", 2) == 0 ) {
-		DEBUG(10, ("Requested session key\n"));
-
-		if(state->cli_state == CLIENT_FINISHED) {
-			char *key64 = base64_encode_data_blob(state->mem_ctx,
-					state->session_key);
-			x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>");
-			TALLOC_FREE(key64);
-		}
-		else {
-			x_fprintf(x_stdout, "BH\n");
-		}
-
-		data_blob_free(&request);
-		return;
-	} else {
-		DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf));
-		x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
-		return;
-	}
-
-	if (!state->ntlmssp_state) {
-		nt_status = ntlm_auth_start_ntlmssp_client(
-				&state->ntlmssp_state);
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
-			return;
-		}
-		ntlmssp_want_feature_list(state->ntlmssp_state,
-				state->want_feature_list);
-		state->initial_message = data_blob_null;
-	}
-
-	DEBUG(10, ("got NTLMSSP packet:\n"));
-	dump_data(10, request.data, request.length);
-
-	if (use_cached_creds && !opt_password &&
-			(state->cli_state == CLIENT_RESPONSE)) {
-		nt_status = do_ccache_ntlm_auth(state->initial_message, request,
-				&reply);
-	} else {
-		nt_status = ntlmssp_update(state->ntlmssp_state, request,
-				&reply);
-	}
-
-	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		char *reply_base64 = base64_encode_data_blob(state->mem_ctx,
-				reply);
-		if (state->cli_state == CLIENT_INITIAL) {
-			x_fprintf(x_stdout, "YR %s\n", reply_base64);
-			state->initial_message = reply;
-			state->cli_state = CLIENT_RESPONSE;
-		} else {
-			x_fprintf(x_stdout, "KK %s\n", reply_base64);
-			data_blob_free(&reply);
-		}
-		TALLOC_FREE(reply_base64);
-		DEBUG(10, ("NTLMSSP challenge\n"));
-	} else if (NT_STATUS_IS_OK(nt_status)) {
-		char *reply_base64 = base64_encode_data_blob(talloc_tos(),
-				reply);
-		x_fprintf(x_stdout, "AF %s\n", reply_base64);
-		TALLOC_FREE(reply_base64);
-
-		if(state->have_session_key)
-			data_blob_free(&state->session_key);
-
-		state->session_key = data_blob(
-				state->ntlmssp_state->session_key.data,
-				state->ntlmssp_state->session_key.length);
-		state->neg_flags = state->ntlmssp_state->neg_flags;
-		state->have_session_key = true;
-
-		DEBUG(10, ("NTLMSSP OK!\n"));
-		state->cli_state = CLIENT_FINISHED;
-		TALLOC_FREE(state->ntlmssp_state);
-	} else {
-		x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
-		DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status)));
-		state->cli_state = CLIENT_ERROR;
-		TALLOC_FREE(state->ntlmssp_state);
-	}
-
-	data_blob_free(&request);
+	manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
+	return;
 }
 
 static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
@@ -1501,11 +1301,42 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
 	if (!(state->gensec_state)) {
 		switch (stdio_helper_mode) {
 		case GSS_SPNEGO_CLIENT:
+			/*
+			 * cached credentials are only supported by
+			 * NTLMSSP_CLIENT_1 for now.
+			 */
+			use_cached_creds = false;
+			/* fall through */
 		case NTLMSSP_CLIENT_1:
 			/* setup the client side */
 
-			nt_status = gensec_client_start(NULL, &state->gensec_state,
-							lpcfg_gensec_settings(NULL, lp_ctx));
+			if (state->set_password != NULL) {
+				use_cached_creds = false;
+			}
+
+			if (use_cached_creds) {
+				struct wbcCredentialCacheParams params;
+				struct wbcCredentialCacheInfo *info = NULL;
+				struct wbcAuthErrorInfo *error = NULL;
+				wbcErr wbc_status;
+
+				params.account_name = opt_username;
+				params.domain_name = opt_domain;
+				params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
+				params.num_blobs = 0;
+				params.blobs = NULL;
+
+				wbc_status = wbcCredentialCache(&params, &info,
+								&error);
+				wbcFreeMemory(error);
+				if (!WBC_ERROR_IS_OK(wbc_status)) {
+					use_cached_creds = false;
+				}
+				wbcFreeMemory(info);
+			}
+
+			nt_status = ntlm_auth_prepare_gensec_client(state, lp_ctx,
+								    &state->gensec_state);
 			if (!NT_STATUS_IS_OK(nt_status)) {
 				x_fprintf(x_stdout, "BH GENSEC mech failed to start: %s\n", nt_errstr(nt_status));
 				talloc_free(mem_ctx);
@@ -1520,7 +1351,10 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
 			if (opt_domain) {
 				cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED);
 			}
-			if (state->set_password) {
+			if (use_cached_creds) {
+				gensec_want_feature(state->gensec_state,
+						    GENSEC_FEATURE_NTLM_CCACHE);
+			} else if (state->set_password) {
 				cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED);
 			} else {
 				cli_credentials_set_password_callback(creds, get_password);
@@ -1615,12 +1449,17 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
 		return;
 	}
 
-	if (stdio_helper_mode == SQUID_2_5_NTLMSSP && strncmp(buf, "GF", 2) == 0) {
+	if (strncmp(buf, "GF", 2) == 0) {
 		uint32_t neg_flags;
 
+		DEBUG(10, ("Requested negotiated NTLMSSP feature flags\n"));
+
 		neg_flags = gensec_ntlmssp_neg_flags(state->gensec_state);
+		if (neg_flags == 0) {
+			x_fprintf(x_stdout, "BH\n");
+			return;
+		}
 
-		DEBUG(10, ("Requested negotiated feature flags\n"));
 		x_fprintf(x_stdout, "GF 0x%08x\n", neg_flags);
 		return;
 	}
@@ -1724,408 +1563,12 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
 	return;
 }
 
-static struct ntlmssp_state *client_ntlmssp_state = NULL;
-
-static bool manage_client_ntlmssp_init(struct spnego_data spnego)
-{
-	NTSTATUS status;
-	DATA_BLOB null_blob = data_blob_null;
-	DATA_BLOB to_server;
-	char *to_server_base64;
-	const char *my_mechs[] = {OID_NTLMSSP, NULL};
-	TALLOC_CTX *ctx = talloc_tos();
-
-	DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n"));
-
-	if (client_ntlmssp_state != NULL) {
-		DEBUG(1, ("Request for initial SPNEGO request where "
-			  "we already have a state\n"));
-		return False;
-	}
-
-	if (!client_ntlmssp_state) {
-		if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_client(&client_ntlmssp_state))) {
-			x_fprintf(x_stdout, "BH %s\n", nt_errstr(status));
-			return False;
-		}
-	}
-
-
-	if (opt_password == NULL) {
-
-		/* Request a password from the calling process.  After
-		   sending it, the calling process should retry with
-		   the negTokenInit. */
-
-		DEBUG(10, ("Requesting password\n"));
-		x_fprintf(x_stdout, "PW\n");
-		return True;
-	}
-
-	spnego.type = SPNEGO_NEG_TOKEN_INIT;
-	spnego.negTokenInit.mechTypes = my_mechs;
-	spnego.negTokenInit.reqFlags = data_blob_null;
-	spnego.negTokenInit.reqFlagsPadding = 0;
-	spnego.negTokenInit.mechListMIC = null_blob;
-
-	status = ntlmssp_update(client_ntlmssp_state, null_blob,
-				       &spnego.negTokenInit.mechToken);
-
-	if ( !(NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) ||
-			NT_STATUS_IS_OK(status)) ) {
-		DEBUG(1, ("Expected OK or MORE_PROCESSING_REQUIRED, got: %s\n",
-			  nt_errstr(status)));
-		TALLOC_FREE(client_ntlmssp_state);
-		return False;
-	}
-
-	spnego_write_data(ctx, &to_server, &spnego);
-	data_blob_free(&spnego.negTokenInit.mechToken);
-
-	to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
-	data_blob_free(&to_server);
-	x_fprintf(x_stdout, "KK %s\n", to_server_base64);
-	TALLOC_FREE(to_server_base64);
-	return True;
-}
-
-static void manage_client_ntlmssp_targ(struct spnego_data spnego)
-{
-	NTSTATUS status;
-	DATA_BLOB null_blob = data_blob_null;
-	DATA_BLOB request;
-	DATA_BLOB to_server;
-	char *to_server_base64;
-	TALLOC_CTX *ctx = talloc_tos();
-
-	DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n"));
-
-	if (client_ntlmssp_state == NULL) {
-		DEBUG(1, ("Got NTLMSSP tArg without a client state\n"));
-		x_fprintf(x_stdout, "BH Got NTLMSSP tArg without a client state\n");
-		return;
-	}
-
-	if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) {
-		x_fprintf(x_stdout, "NA\n");
-		TALLOC_FREE(client_ntlmssp_state);
-		return;
-	}
-
-	if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) {
-		x_fprintf(x_stdout, "AF\n");
-		TALLOC_FREE(client_ntlmssp_state);
-		return;
-	}
-
-	status = ntlmssp_update(client_ntlmssp_state,
-				       spnego.negTokenTarg.responseToken,
-				       &request);
-
-	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED or OK from "
-			  "ntlmssp_client_update, got: %s\n",
-			  nt_errstr(status)));
-		x_fprintf(x_stdout, "BH Expected MORE_PROCESSING_REQUIRED from "
-				    "ntlmssp_client_update\n");
-		data_blob_free(&request);
-		TALLOC_FREE(client_ntlmssp_state);
-		return;
-	}
-
-	spnego.type = SPNEGO_NEG_TOKEN_TARG;
-	spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
-	spnego.negTokenTarg.supportedMech = (const char *)OID_NTLMSSP;
-	spnego.negTokenTarg.responseToken = request;
-	spnego.negTokenTarg.mechListMIC = null_blob;
-
-	spnego_write_data(ctx, &to_server, &spnego);
-	data_blob_free(&request);
-
-	to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
-	data_blob_free(&to_server);
-	x_fprintf(x_stdout, "KK %s\n", to_server_base64);
-	TALLOC_FREE(to_server_base64);
-	return;
-}
-
-#ifdef HAVE_KRB5
-
-static bool manage_client_krb5_init(struct spnego_data spnego)
-{
-	char *principal;
-	DATA_BLOB tkt, tkt_wrapped, to_server;
-	DATA_BLOB session_key_krb5 = data_blob_null;
-	struct spnego_data reply;
-	char *reply_base64;
-	int retval;
-
-	const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
-	ssize_t len;
-	TALLOC_CTX *ctx = talloc_tos();
-
-	principal = spnego.negTokenInit.targetPrincipal;
-
-	/* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
-	 */
-	if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
-		principal = NULL;
-	}
-	
-	if (principal == NULL &&
-	    opt_target_service && opt_target_hostname && !is_ipaddress(opt_target_hostname)) {
-		DEBUG(3,("manage_client_krb5_init: using target "
-			 "hostname not SPNEGO principal\n"));
-
-		principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
-									 opt_target_service,
-									 opt_target_hostname,
-									 lp_realm());
-
-		if (!principal) {
-			return false;
-		}
-		
-		DEBUG(3,("manage_client_krb5_init: guessed "
-			 "server principal=%s\n",
-			 principal ? principal : "<null>"));
-	}
-	
-	if (principal == NULL) {
-		DEBUG(3,("manage_client_krb5_init: could not guess server principal\n"));
-		return false;
-	}
-
-	retval = cli_krb5_get_ticket(ctx, principal, 0,
-					  &tkt, &session_key_krb5,
-					  0, NULL, NULL, NULL);
-	if (retval) {
-		char *user = NULL;
-
-		/* Let's try to first get the TGT, for that we need a
-                   password. */
-
-		if (opt_password == NULL) {
-			DEBUG(10, ("Requesting password\n"));
-			x_fprintf(x_stdout, "PW\n");
-			return True;
-		}
-
-		user = talloc_asprintf(talloc_tos(), "%s@%s", opt_username, opt_domain);
-		if (!user) {
-			return false;
-		}
-
-		if ((retval = kerberos_kinit_password(user, opt_password, 0, NULL))) {
-			DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
-			return False;
-		}
-
-		retval = cli_krb5_get_ticket(ctx, principal, 0,
-						  &tkt, &session_key_krb5,
-						  0, NULL, NULL, NULL);
-		if (retval) {
-			DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
-			return False;
-		}
-
-	}
-
-	/* wrap that up in a nice GSS-API wrapping */
-	tkt_wrapped = spnego_gen_krb5_wrap(ctx, tkt, TOK_ID_KRB_AP_REQ);
-
-	data_blob_free(&session_key_krb5);
-
-	ZERO_STRUCT(reply);
-
-	reply.type = SPNEGO_NEG_TOKEN_INIT;
-	reply.negTokenInit.mechTypes = my_mechs;
-	reply.negTokenInit.reqFlags = data_blob_null;
-	reply.negTokenInit.reqFlagsPadding = 0;
-	reply.negTokenInit.mechToken = tkt_wrapped;
-	reply.negTokenInit.mechListMIC = data_blob_null;
-
-	len = spnego_write_data(ctx, &to_server, &reply);
-	data_blob_free(&tkt);
-
-	if (len == -1) {
-		DEBUG(1, ("Could not write SPNEGO data blob\n"));
-		return False;
-	}
-
-	reply_base64 = base64_encode_data_blob(talloc_tos(), to_server);
-	x_fprintf(x_stdout, "KK %s *\n", reply_base64);
-
-	TALLOC_FREE(reply_base64);
-	data_blob_free(&to_server);
-	DEBUG(10, ("sent GSS-SPNEGO KERBEROS5 negTokenInit\n"));
-	return True;
-}
-
-static void manage_client_krb5_targ(struct spnego_data spnego)
-{
-	switch (spnego.negTokenTarg.negResult) {
-	case SPNEGO_ACCEPT_INCOMPLETE:
-		DEBUG(1, ("Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE\n"));
-		x_fprintf(x_stdout, "BH Got a Kerberos negTokenTarg with "
-				    "ACCEPT_INCOMPLETE\n");
-		break;
-	case SPNEGO_ACCEPT_COMPLETED:
-		DEBUG(10, ("Accept completed\n"));
-		x_fprintf(x_stdout, "AF\n");
-		break;
-	case SPNEGO_REJECT:
-		DEBUG(10, ("Rejected\n"));
-		x_fprintf(x_stdout, "NA\n");
-		break;
-	default:
-		DEBUG(1, ("Got an invalid negTokenTarg\n"));
-		x_fprintf(x_stdout, "AF\n");
-	}
-}
-
-#endif
-
 static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode,
 				   struct loadparm_context *lp_ctx,
 				   struct ntlm_auth_state *state,
 					     char *buf, int length, void **private2)
 {
-	DATA_BLOB request;
-	struct spnego_data spnego;
-	ssize_t len;
-	TALLOC_CTX *ctx = talloc_tos();
-
-	if (!opt_username || !*opt_username) {
-		x_fprintf(x_stderr, "username must be specified!\n\n");
-		exit(1);
-	}
-
-	if (strlen(buf) <= 3) {
-		DEBUG(1, ("SPNEGO query [%s] too short\n", buf));
-		x_fprintf(x_stdout, "BH SPNEGO query too short\n");
-		return;
-	}
-
-	request = base64_decode_data_blob(buf+3);
-
-	if (strncmp(buf, "PW ", 3) == 0) {
-
-		/* We asked for a password and obviously got it :-) */
-
-		opt_password = SMB_STRNDUP((const char *)request.data, request.length);
-
-		if (opt_password == NULL) {
-			DEBUG(1, ("Out of memory\n"));
-			x_fprintf(x_stdout, "BH Out of memory\n");
-			data_blob_free(&request);
-			return;
-		}
-
-		x_fprintf(x_stdout, "OK\n");
-		data_blob_free(&request);
-		return;
-	}
-
-	if ( (strncmp(buf, "TT ", 3) != 0) &&
-	     (strncmp(buf, "AF ", 3) != 0) &&
-	     (strncmp(buf, "NA ", 3) != 0) ) {
-		DEBUG(1, ("SPNEGO request [%s] invalid\n", buf));
-		x_fprintf(x_stdout, "BH SPNEGO request invalid\n");
-		data_blob_free(&request);
-		return;
-	}
-
-	/* So we got a server challenge to generate a SPNEGO
-           client-to-server request... */
-
-	len = spnego_read_data(ctx, request, &spnego);
-	data_blob_free(&request);
-
-	if (len == -1) {
-		DEBUG(1, ("Could not read SPNEGO data for [%s]\n", buf));
-		x_fprintf(x_stdout, "BH Could not read SPNEGO data\n");
-		return;
-	}
-
-	if (spnego.type == SPNEGO_NEG_TOKEN_INIT) {
-
-		/* The server offers a list of mechanisms */
-
-		const char *const *mechType = spnego.negTokenInit.mechTypes;
-
-		while (*mechType != NULL) {
-
-#ifdef HAVE_KRB5
-			if ( (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) ||
-			     (strcmp(*mechType, OID_KERBEROS5) == 0) ) {
-				if (manage_client_krb5_init(spnego))
-					goto out;
-			}
-#endif
-
-			if (strcmp(*mechType, OID_NTLMSSP) == 0) {
-				if (manage_client_ntlmssp_init(spnego))
-					goto out;
-			}
-
-			mechType++;
-		}
-
-		DEBUG(1, ("Server offered no compatible mechanism\n"));
-		x_fprintf(x_stdout, "BH Server offered no compatible mechanism\n");
-		return;
-	}
-
-	if (spnego.type == SPNEGO_NEG_TOKEN_TARG) {
-
-		if (spnego.negTokenTarg.supportedMech == NULL) {
-			/* On accept/reject Windows does not send the
-                           mechanism anymore. Handle that here and
-                           shut down the mechanisms. */
-
-			switch (spnego.negTokenTarg.negResult) {
-			case SPNEGO_ACCEPT_COMPLETED:
-				x_fprintf(x_stdout, "AF\n");
-				break;
-			case SPNEGO_REJECT:
-				x_fprintf(x_stdout, "NA\n");
-				break;
-			default:
-				DEBUG(1, ("Got a negTokenTarg with no mech and an "
-					  "unknown negResult: %d\n",
-					  spnego.negTokenTarg.negResult));
-				x_fprintf(x_stdout, "BH Got a negTokenTarg with"
-						    " no mech and an unknown "
-						    "negResult\n");
-			}
-
-			TALLOC_FREE(client_ntlmssp_state);
-			goto out;
-		}
-
-		if (strcmp(spnego.negTokenTarg.supportedMech,
-			   OID_NTLMSSP) == 0) {
-			manage_client_ntlmssp_targ(spnego);
-			goto out;
-		}
-
-#if HAVE_KRB5
-		if (strcmp(spnego.negTokenTarg.supportedMech,
-			   OID_KERBEROS5_OLD) == 0) {
-			manage_client_krb5_targ(spnego);
-			goto out;
-		}
-#endif
-
-	}
-
-	DEBUG(1, ("Got an SPNEGO token I could not handle [%s]!\n", buf));
-	x_fprintf(x_stdout, "BH Got an SPNEGO token I could not handle\n");
-	return;
-
- out:
-	spnego_free_data(&spnego);
+	manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
 	return;
 }
 
diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c
index 939da9b..039e653 100644
--- a/source3/winbindd/winbindd_ccache_access.c
+++ b/source3/winbindd/winbindd_ccache_access.c
@@ -48,14 +48,16 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
 					    const char *password,
 					    const DATA_BLOB initial_msg,
 					    const DATA_BLOB challenge_msg,
+					    TALLOC_CTX *mem_ctx,
 					    DATA_BLOB *auth_msg,
-					    uint8_t session_key[16])
+					    uint8_t session_key[16],
+					    uint8_t *new_spnego)
 {
 	NTSTATUS status;
 	struct auth_generic_state *auth_generic_state = NULL;
-	DATA_BLOB dummy_msg, reply, session_key_blob;
+	DATA_BLOB reply, session_key_blob;
 
-	status = auth_generic_client_prepare(NULL, &auth_generic_state);
+	status = auth_generic_client_prepare(mem_ctx, &auth_generic_state);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, ("Could not start NTLMSSP client: %s\n",
@@ -87,29 +89,26 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
 		goto done;
 	}
 
-	gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SESSION_KEY);
+	if (initial_msg.length == 0) {
+		gensec_want_feature(auth_generic_state->gensec_security,
+				    GENSEC_FEATURE_SESSION_KEY);
+	}
 
-	status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
+	status = auth_generic_client_start_by_name(auth_generic_state,
+						   "ntlmssp_resume_ccache");
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Could not start NTLMSSP mech: %s\n",
+		DEBUG(1, ("Could not start NTLMSSP resume mech: %s\n",
 			nt_errstr(status)));
 		goto done;
 	}
 
-	/* We need to get our protocol handler into the right state. So first
-	   we ask it to generate the initial message. Actually the client has already
-	   sent its own initial message, so we're going to drop this one on the floor.
-	   The client might have sent a different message, for example with different
-	   negotiation options, but as far as I can tell this won't hurt us. (Unless
-	   the client sent a different username or domain, in which case that's their
-	   problem for telling us the wrong username or domain.)
-	   Since we have a copy of the initial message that the client sent, we could
-	   resolve any discrepancies if we had to.
-	*/
-	dummy_msg = data_blob_null;
+	/*
+	 * We inject the inital NEGOTIATE message our caller used
+	 * in order to get the state machine into the correct possition.
+	 */
 	reply = data_blob_null;
 	status = gensec_update(auth_generic_state->gensec_security,
-			       talloc_tos(), dummy_msg, &reply);
+			       talloc_tos(), initial_msg, &reply);
 	data_blob_free(&reply);
 
 	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
@@ -120,7 +119,7 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
 
 	/* Now we are ready to handle the server's actual response. */
 	status = gensec_update(auth_generic_state->gensec_security,
-			       NULL, challenge_msg, &reply);
+			       mem_ctx, challenge_msg, &reply);
 	if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
 		DEBUG(1, ("We didn't get a response to the challenge! [%s]\n",
 			nt_errstr(status)));
@@ -146,6 +145,8 @@ static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
 	memcpy(session_key, session_key_blob.data, 16);
 	data_blob_free(&session_key_blob);
 	*auth_msg = reply;
+	*new_spnego = gensec_have_feature(auth_generic_state->gensec_security,
+					  GENSEC_FEATURE_NEW_SPNEGO);
 	status = NT_STATUS_OK;
 
 done:
@@ -273,8 +274,9 @@ void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
 
 	result = do_ntlm_auth_with_stored_pw(
 		name_user, name_domain, entry->pass,
-		initial, challenge, &auth,
-		state->response->data.ccache_ntlm_auth.session_key);
+		initial, challenge, talloc_tos(), &auth,
+		state->response->data.ccache_ntlm_auth.session_key,
+		&state->response->data.ccache_ntlm_auth.new_spnego);
 
 	if (!NT_STATUS_IS_OK(result)) {
 		goto process_result;
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 1964fcff..075a818 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -996,7 +996,7 @@ static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
 
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-	enum smb_signing_setting smb_sign_client_connections = lp_client_signing();
+	enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
 
 	if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
 		/*
@@ -1049,8 +1049,8 @@ static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
 	cli_set_timeout(*cli, 10000); /* 10 seconds */
 
 	result = smbXcli_negprot((*cli)->conn, (*cli)->timeout,
-				 lp_client_min_protocol(),
-				 lp_winbindd_max_protocol());
+				 lp_client_ipc_min_protocol(),
+				 lp_client_ipc_max_protocol());
 
 	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result)));
diff --git a/source3/wscript_build b/source3/wscript_build
index ba670d3..be0b831 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -372,14 +372,9 @@ bld.SAMBA3_LIBRARY('smbd_shim',
 		   deps='talloc',
                    private_library=True)
 
-bld.SAMBA3_SUBSYSTEM('LIBNTLMSSP',
-                    source='''libsmb/ntlmssp.c
-                    libsmb/ntlmssp_wrap.c''',
-                    deps='NDR_NTLMSSP NTLMSSP_COMMON wbclient')
-
 bld.SAMBA3_SUBSYSTEM('auth_generic',
                     source='libsmb/auth_generic.c',
-                    deps='LIBNTLMSSP gse gensec')
+                    deps='gse gensec')
 
 bld.SAMBA3_LIBRARY('libsmb',
                    source='''libsmb/clientgen.c
@@ -407,7 +402,6 @@ bld.SAMBA3_LIBRARY('libsmb',
                    libsmb/smbsock_connect.c
                    libsmb/cli_smb2_fnum.c''',
                    deps='''
-                   LIBNTLMSSP
                    auth_generic
                    CLDAP
                    LIBNMB
@@ -1453,7 +1447,7 @@ bld.SAMBA3_BINARY('ntlm_auth',
                  tiniparser
                  libsmb
                  popt_samba3
-                 LIBNTLMSSP gse gensec''')
+                 gse gensec''')
 
 bld.SAMBA3_BINARY('timelimit',
                  source='script/tests/timelimit.c',
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index b1ecd18..057cddd 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -417,14 +417,17 @@ static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLO
 	if (!asn1_pop_tag(data)) goto err;
 
 
-	ret = data_blob_talloc(mem_ctx, data->data, data->length);
+	if (!asn1_extract_blob(data, mem_ctx, &ret)) {
+		goto err;
+	}
 	asn1_free(data);
 
 	return ret;
 
   err:
 
-	DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
+	DEBUG(1, ("Failed to build krb5 wrapper at offset %d\n",
+		  (int)asn1_current_ofs(data)));
 	asn1_free(data);
 	return ret;
 }
@@ -449,7 +452,7 @@ static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *
 	data_remaining = asn1_tag_remaining(data);
 
 	if (data_remaining < 3) {
-		data->has_error = true;
+		asn1_set_error(data);
 	} else {
 		if (!asn1_read(data, tok_id, 2)) goto err;
 		data_remaining -= 2;
@@ -459,7 +462,7 @@ static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *
 
 	if (!asn1_end_tag(data)) goto err;
 
-	ret = !data->has_error;
+	ret = !asn1_has_error(data);
 
   err:
 
diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c
index 2c98776..b92d0b8 100644
--- a/source4/auth/gensec/pygensec.c
+++ b/source4/auth/gensec/pygensec.c
@@ -540,6 +540,83 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args)
 	return ret;
 }
 
+static PyObject *py_gensec_sig_size(PyObject *self, PyObject *args)
+{
+	struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
+	Py_ssize_t data_size = 0;
+	size_t sig_size = 0;
+
+	if (!PyArg_ParseTuple(args, "n", &data_size)) {
+		return NULL;
+	}
+
+	sig_size = gensec_sig_size(security, data_size);
+
+	return PyLong_FromSize_t(sig_size);
+}
+
+static PyObject *py_gensec_sign_packet(PyObject *self, PyObject *args)
+{
+	NTSTATUS status;
+	TALLOC_CTX *mem_ctx = NULL;
+	Py_ssize_t data_length = 0;
+	Py_ssize_t pdu_length = 0;
+	DATA_BLOB data, pdu, sig;
+	PyObject *py_sig;
+	struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
+
+	if (!PyArg_ParseTuple(args, "z#z#", &data.data, &data_length, &pdu.data, &pdu_length)) {
+		return NULL;
+	}
+	data.length = data_length;
+	pdu.length = pdu_length;
+
+	mem_ctx = talloc_new(NULL);
+
+	status = gensec_sign_packet(security, mem_ctx,
+				    data.data, data.length,
+				    pdu.data, pdu.length, &sig);
+	if (!NT_STATUS_IS_OK(status)) {
+		PyErr_SetNTSTATUS(status);
+		talloc_free(mem_ctx);
+		return NULL;
+	}
+
+	py_sig = PyBytes_FromStringAndSize((const char *)sig.data, sig.length);
+	talloc_free(mem_ctx);
+	return py_sig;
+}
+
+static PyObject *py_gensec_check_packet(PyObject *self, PyObject *args)
+{
+	NTSTATUS status;
+	Py_ssize_t data_length = 0;
+	Py_ssize_t pdu_length = 0;
+	Py_ssize_t sig_length = 0;
+	DATA_BLOB data, pdu, sig;
+	struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
+
+	if (!PyArg_ParseTuple(args, "z#z#z#",
+			      &data.data, &data_length,
+			      &pdu.data, &pdu_length,
+			      &sig.data, &sig_length)) {
+		return NULL;
+	}
+	data.length = data_length;
+	pdu.length = pdu_length;
+	sig.length = sig_length;
+
+	status = gensec_check_packet(security,
+				     data.data, data.length,
+				     pdu.data, pdu.length, &sig);
+	if (!NT_STATUS_IS_OK(status)) {
+		PyErr_SetNTSTATUS(status);
+		return NULL;
+	}
+
+	Py_RETURN_NONE;
+}
+
 static PyMethodDef py_gensec_security_methods[] = {
 	{ "start_client", (PyCFunction)py_gensec_start_client, METH_VARARGS|METH_KEYWORDS|METH_CLASS, 
 		"S.start_client(settings) -> gensec" },
@@ -577,6 +654,12 @@ static PyMethodDef py_gensec_security_methods[] = {
 		"S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
 	{ "unwrap",  (PyCFunction)py_gensec_unwrap, METH_VARARGS,
 		"S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
+	{ "sig_size",  (PyCFunction)py_gensec_sig_size, METH_VARARGS,
+		"S.sig_size(data_size) -> sig_size\nSize of the DCERPC packet signature" },
+	{ "sign_packet",  (PyCFunction)py_gensec_sign_packet, METH_VARARGS,
+		"S.sign_packet(data, whole_pdu) -> sig\nSign a DCERPC packet." },
+	{ "check_packet",  (PyCFunction)py_gensec_check_packet, METH_VARARGS,
+		"S.check_packet(data, whole_pdu, sig)\nCheck a DCERPC packet." },
 	{ NULL }
 };
 
diff --git a/source4/auth/ntlm/auth_util.c b/source4/auth/ntlm/auth_util.c
index 16977fa..3e5a0da 100644
--- a/source4/auth/ntlm/auth_util.c
+++ b/source4/auth/ntlm/auth_util.c
@@ -350,7 +350,9 @@ NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth4_context *auth_conte
 				if (!SMBNTLMv2encrypt_hash(user_info_temp,
 							   user_info_in->client.account_name, 
 							   user_info_in->client.domain_name, 
-							   user_info_in->password.hash.nt->hash, &chall_blob,
+							   user_info_in->password.hash.nt->hash,
+							   &chall_blob,
+							   NULL, /* server_timestamp */
 							   &names_blob,
 							   &lmv2_response, &ntlmv2_response, 
 							   &lmv2_session_key, &ntlmv2_session_key)) {
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 69a6b61..99ca148 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -45,6 +45,23 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 
 	DEBUG(10, ("BindSimple dn: %s\n",req->dn));
 
+	reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
+	if (!reply) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (req->dn != NULL &&
+	    strlen(req->dn) != 0 &&
+	    call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
+	    call->conn->sockets.active != call->conn->sockets.tls)
+	{
+		status = NT_STATUS_NETWORK_ACCESS_DENIED;
+		result = LDAP_STRONG_AUTH_REQUIRED;
+		errstr = talloc_asprintf(reply,
+					 "BindSimple: Transport encryption required.");
+		goto do_reply;
+	}
+
 	status = crack_auto_name_to_nt4_name(call, call->conn->connection->event.ctx, call->conn->lp_ctx, req->dn, &nt4_domain, &nt4_account);
 	if (NT_STATUS_IS_OK(status)) {
 		status = authenticate_username_pw(call,
@@ -58,11 +75,6 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 						  &session_info);
 	}
 
-	reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
-	if (!reply) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
 	if (NT_STATUS_IS_OK(status)) {
 		result = LDAP_SUCCESS;
 		errstr = NULL;
@@ -86,6 +98,7 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 		errstr = talloc_asprintf(reply, "Simple Bind Failed: %s", nt_errstr(status));
 	}
 
+do_reply:
 	resp = &reply->msg->r.BindResponse;
 	resp->response.resultcode = result;
 	resp->response.errormessage = errstr;
@@ -181,6 +194,7 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 			gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
 			gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
 			gensec_want_feature(conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
+			gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);
 			
 			status = gensec_start_mech_by_sasl_name(conn->gensec, req->creds.SASL.mechanism);
 			
@@ -217,7 +231,6 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 		result = LDAP_SASL_BIND_IN_PROGRESS;
 		errstr = NULL;
 	} else if (NT_STATUS_IS_OK(status)) {
-		struct auth_session_info *old_session_info=NULL;
 		struct ldapsrv_sasl_postprocess_context *context = NULL;
 
 		result = LDAP_SUCCESS;
@@ -262,17 +275,38 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
 					status = NT_STATUS_NO_MEMORY;
 				}
 			}
+		} else {
+			switch (call->conn->require_strong_auth) {
+			case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
+				break;
+			case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
+				if (call->conn->sockets.active == call->conn->sockets.tls) {
+					break;
+				}
+				status = NT_STATUS_NETWORK_ACCESS_DENIED;
+				result = LDAP_STRONG_AUTH_REQUIRED;
+				errstr = talloc_asprintf(reply,
+						"SASL:[%s]: not allowed if TLS is used.",
+						 req->creds.SASL.mechanism);
+				break;
+			case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
+				status = NT_STATUS_NETWORK_ACCESS_DENIED;
+				result = LDAP_STRONG_AUTH_REQUIRED;
+				errstr = talloc_asprintf(reply,
+						 "SASL:[%s]: Sign or Seal are required.",
+						 req->creds.SASL.mechanism);
+				break;
+			}
 		}
 
 		if (result != LDAP_SUCCESS) {
-			conn->session_info = old_session_info;
 		} else if (!NT_STATUS_IS_OK(status)) {
-			conn->session_info = old_session_info;
 			result = LDAP_OPERATIONS_ERROR;
 			errstr = talloc_asprintf(reply, 
 						 "SASL:[%s]: Failed to setup SASL socket: %s", 
 						 req->creds.SASL.mechanism, nt_errstr(status));
 		} else {
+			struct auth_session_info *old_session_info=NULL;
 
 			old_session_info = conn->session_info;
 			conn->session_info = NULL;
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index d849ed3..f4134d7 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -334,6 +334,12 @@ static void ldapsrv_accept(struct stream_connection *c,
 
 	conn->sockets.active = conn->sockets.raw;
 
+	if (conn->is_privileged) {
+		conn->require_strong_auth = LDAP_SERVER_REQUIRE_STRONG_AUTH_NO;
+	} else {
+		conn->require_strong_auth = lpcfg_ldap_server_require_strong_auth(conn->lp_ctx);
+	}
+
 	if (!NT_STATUS_IS_OK(ldapsrv_backend_Init(conn))) {
 		ldapsrv_terminate_connection(conn, "backend Init failed");
 		return;
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 6f8b433..87a7163 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -22,6 +22,7 @@
 #include "lib/socket/socket.h"
 #include "lib/stream/packet.h"
 #include "system/network.h"
+#include "lib/param/loadparm.h"
 
 struct ldapsrv_connection {
 	struct loadparm_context *lp_ctx;
@@ -42,6 +43,7 @@ struct ldapsrv_connection {
 
 	bool global_catalog;
 	bool is_privileged;
+	enum ldap_server_require_strong_auth require_strong_auth;
 
 	struct {
 		int initial_timeout;
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index 2fe4ff7..f2197e6 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -31,7 +31,7 @@
 #if ENABLE_GNUTLS
 #include <gnutls/gnutls.h>
 
-#define DH_BITS 1024
+#define DH_BITS 2048
 
 #if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
 typedef gnutls_datum gnutls_datum_t;
diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h
index e6c27f3..e600c89 100644
--- a/source4/lib/tls/tls.h
+++ b/source4/lib/tls/tls.h
@@ -68,10 +68,33 @@ const struct socket_ops *socket_tls_ops(enum socket_type type);
 struct tstream_context;
 struct tstream_tls_params;
 
+enum tls_verify_peer_state {
+	TLS_VERIFY_PEER_NO_CHECK = 0,
+#define TLS_VERIFY_PEER_NO_CHECK_STRING "no_check"
+
+	TLS_VERIFY_PEER_CA_ONLY = 10,
+#define TLS_VERIFY_PEER_CA_ONLY_STRING "ca_only"
+
+	TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE = 20,
+#define TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING \
+		"ca_and_name_if_available"
+
+	TLS_VERIFY_PEER_CA_AND_NAME = 30,
+#define TLS_VERIFY_PEER_CA_AND_NAME_STRING "ca_and_name"
+
+	TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE = 9999,
+#define TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING \
+		"as_strict_as_possible"
+};
+
+const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer);
+
 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 				   const char *ca_file,
 				   const char *crl_file,
 				   const char *tls_priority,
+				   enum tls_verify_peer_state verify_peer,
+				   const char *peer_name,
 				   struct tstream_tls_params **_tlsp);
 
 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
diff --git a/source4/lib/tls/tls_tstream.c b/source4/lib/tls/tls_tstream.c
index 188a3b8..5045e88 100644
--- a/source4/lib/tls/tls_tstream.c
+++ b/source4/lib/tls/tls_tstream.c
@@ -20,22 +20,64 @@
 #include "includes.h"
 #include "system/network.h"
 #include "system/filesys.h"
+#include "system/time.h"
 #include "../util/tevent_unix.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../lib/tsocket/tsocket_internal.h"
+#include "../lib/util/util_net.h"
 #include "lib/tls/tls.h"
 
 #if ENABLE_GNUTLS
 #include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
 
-#define DH_BITS 1024
+#define DH_BITS 2048
 
 #if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
 typedef gnutls_datum gnutls_datum_t;
 #endif
 
+/*
+ * define our own values in a high range
+ */
+#ifndef HAVE_DECL_GNUTLS_CERT_EXPIRED
+#define GNUTLS_CERT_EXPIRED                    0x10000000
+#define REQUIRE_CERT_TIME_CHECKS 1
+#endif
+#ifndef HAVE_DECL_GNUTLS_CERT_NOT_ACTIVATED
+#define GNUTLS_CERT_NOT_ACTIVATED              0x20000000
+#ifndef REQUIRE_CERT_TIME_CHECKS
+#define REQUIRE_CERT_TIME_CHECKS 1
+#endif
+#endif
+#ifndef HAVE_DECL_GNUTLS_CERT_UNEXPECTED_OWNER
+#define GNUTLS_CERT_UNEXPECTED_OWNER           0x40000000
+#endif
+
 #endif /* ENABLE_GNUTLS */
 
+const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
+{
+	switch (verify_peer) {
+	case TLS_VERIFY_PEER_NO_CHECK:
+		return TLS_VERIFY_PEER_NO_CHECK_STRING;
+
+	case TLS_VERIFY_PEER_CA_ONLY:
+		return TLS_VERIFY_PEER_CA_ONLY_STRING;
+
+	case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
+		return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
+
+	case TLS_VERIFY_PEER_CA_AND_NAME:
+		return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
+
+	case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
+		return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
+	}
+
+	return "unknown tls_verify_peer_state";
+}
+
 static const struct tstream_context_ops tstream_tls_ops;
 
 struct tstream_tls {
@@ -46,6 +88,9 @@ struct tstream_tls {
 	gnutls_session tls_session;
 #endif /* ENABLE_GNUTLS */
 
+	enum tls_verify_peer_state verify_peer;
+	const char *peer_name;
+
 	struct tevent_context *current_ev;
 
 	struct tevent_immediate *retry_im;
@@ -871,6 +916,8 @@ struct tstream_tls_params {
 	const char *tls_priority;
 #endif /* ENABLE_GNUTLS */
 	bool tls_enabled;
+	enum tls_verify_peer_state verify_peer;
+	const char *peer_name;
 };
 
 static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
@@ -897,6 +944,8 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 				   const char *ca_file,
 				   const char *crl_file,
 				   const char *tls_priority,
+				   enum tls_verify_peer_state verify_peer,
+				   const char *peer_name,
 				   struct tstream_tls_params **_tlsp)
 {
 #if ENABLE_GNUTLS
@@ -914,6 +963,21 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 
 	talloc_set_destructor(tlsp, tstream_tls_params_destructor);
 
+	tlsp->verify_peer = verify_peer;
+	if (peer_name != NULL) {
+		tlsp->peer_name = talloc_strdup(tlsp, peer_name);
+		if (tlsp->peer_name == NULL) {
+			talloc_free(tlsp);
+			return NT_STATUS_NO_MEMORY;
+		}
+	} else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
+		DEBUG(0,("TLS failed to missing peer_name - "
+			 "with 'tls verify peer = %s'\n",
+			 tls_verify_peer_string(tlsp->verify_peer)));
+		talloc_free(tlsp);
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
+
 	ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
 	if (ret != GNUTLS_E_SUCCESS) {
 		DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
@@ -931,6 +995,13 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 			talloc_free(tlsp);
 			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 		}
+	} else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
+		DEBUG(0,("TLS failed to missing cafile %s - "
+			 "with 'tls verify peer = %s'\n",
+			 ca_file,
+			 tls_verify_peer_string(tlsp->verify_peer)));
+		talloc_free(tlsp);
+		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
 
 	if (crl_file && *crl_file && file_exist(crl_file)) {
@@ -943,6 +1014,13 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
 			talloc_free(tlsp);
 			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 		}
+	} else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
+		DEBUG(0,("TLS failed to missing crlfile %s - "
+			 "with 'tls verify peer = %s'\n",
+			 crl_file,
+			 tls_verify_peer_string(tlsp->verify_peer)));
+		talloc_free(tlsp);
+		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
 
 	tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
@@ -997,6 +1075,13 @@ struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
 	talloc_set_destructor(tlss, tstream_tls_destructor);
 
 	tlss->plain_stream = plain_stream;
+	tlss->verify_peer = tls_params->verify_peer;
+	if (tls_params->peer_name != NULL) {
+		tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
+		if (tevent_req_nomem(tlss->peer_name, req)) {
+			return tevent_req_post(req, ev);
+		}
+	}
 
 	tlss->current_ev = ev;
 	tlss->retry_im = tevent_create_immediate(tlss);
@@ -1362,6 +1447,170 @@ static void tstream_tls_retry_handshake(struct tstream_context *stream)
 		return;
 	}
 
+	if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
+		unsigned int status = UINT32_MAX;
+		bool ip = true;
+		const char *hostname = NULL;
+#ifndef HAVE_GNUTLS_CERTIFICATE_VERIFY_PEERS3
+		bool need_crt_checks = false;
+#endif
+
+		if (tlss->peer_name != NULL) {
+			ip = is_ipaddress(tlss->peer_name);
+		}
+
+		if (!ip) {
+			hostname = tlss->peer_name;
+		}
+
+		if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
+			hostname = NULL;
+		}
+
+		if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
+			if (hostname == NULL) {
+				DEBUG(1,("TLS %s - no hostname available for "
+					 "verify_peer[%s] and peer_name[%s]\n",
+					 __location__,
+					 tls_verify_peer_string(tlss->verify_peer),
+					 tlss->peer_name));
+				tlss->error = EINVAL;
+				tevent_req_error(req, tlss->error);
+				return;
+			}
+		}
+
+#ifdef HAVE_GNUTLS_CERTIFICATE_VERIFY_PEERS3
+		ret = gnutls_certificate_verify_peers3(tlss->tls_session,
+						       hostname,
+						       &status);
+		if (ret != GNUTLS_E_SUCCESS) {
+			DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
+			tlss->error = EIO;
+			tevent_req_error(req, tlss->error);
+			return;
+		}
+#else /* not HAVE_GNUTLS_CERTIFICATE_VERIFY_PEERS3 */
+		ret = gnutls_certificate_verify_peers2(tlss->tls_session, &status);
+		if (ret != GNUTLS_E_SUCCESS) {
+			DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
+			tlss->error = EIO;
+			tevent_req_error(req, tlss->error);
+			return;
+		}
+
+		if (status == 0) {
+			if (hostname != NULL) {
+				need_crt_checks = true;
+			}
+#ifdef REQUIRE_CERT_TIME_CHECKS
+			need_crt_checks = true;
+#endif
+		}
+
+		if (need_crt_checks) {
+			gnutls_x509_crt crt;
+			const gnutls_datum *cert_list;
+			unsigned int cert_list_size = 0;
+#ifdef REQUIRE_CERT_TIME_CHECKS
+			time_t now = time(NULL);
+			time_t tret = -1;
+#endif
+
+			cert_list = gnutls_certificate_get_peers(tlss->tls_session,
+								 &cert_list_size);
+			if (cert_list == NULL) {
+				cert_list_size = 0;
+			}
+			if (cert_list_size == 0) {
+				DEBUG(1,("TLS %s - cert_list_size == 0\n",
+					 __location__));
+				tlss->error = EIO;
+				tevent_req_error(req, tlss->error);
+				return;
+			}
+
+			ret = gnutls_x509_crt_init(&crt);
+			if (ret != GNUTLS_E_SUCCESS) {
+				DEBUG(1,("TLS %s - %s\n", __location__,
+					 gnutls_strerror(ret)));
+				tlss->error = EIO;
+				tevent_req_error(req, tlss->error);
+				return;
+			}
+			ret = gnutls_x509_crt_import(crt,
+						     &cert_list[0],
+						     GNUTLS_X509_FMT_DER);
+			if (ret != GNUTLS_E_SUCCESS) {
+				DEBUG(1,("TLS %s - %s\n", __location__,
+					 gnutls_strerror(ret)));
+				gnutls_x509_crt_deinit(crt);
+				tlss->error = EIO;
+				tevent_req_error(req, tlss->error);
+				return;
+			}
+
+			if (hostname != NULL) {
+				ret = gnutls_x509_crt_check_hostname(crt,
+								     hostname);
+				if (ret == 0) {
+					status |= GNUTLS_CERT_INVALID;
+					status |= GNUTLS_CERT_UNEXPECTED_OWNER;
+				}
+			}
+
+#ifndef HAVE_DECL_GNUTLS_CERT_NOT_ACTIVATED
+			/*
+			 * GNUTLS_CERT_NOT_ACTIVATED is defined by ourself
+			 */
+			tret = gnutls_x509_crt_get_activation_time(crt);
+			if ((tret == -1) || (now > tret)) {
+				status |= GNUTLS_CERT_INVALID;
+				status |= GNUTLS_CERT_NOT_ACTIVATED;
+			}
+#endif
+#ifndef HAVE_DECL_GNUTLS_CERT_EXPIRED
+			/*
+			 * GNUTLS_CERT_EXPIRED is defined by ourself
+			 */
+			tret = gnutls_certificate_expiration_time_peers(tlss->tls_session);
+			if ((tret == -1) || (now > tret)) {
+				status |= GNUTLS_CERT_INVALID;
+				status |= GNUTLS_CERT_EXPIRED;
+			}
+#endif
+			gnutls_x509_crt_deinit(crt);
+		}
+#endif
+
+		if (status != 0) {
+			DEBUG(1,("TLS %s - check failed for "
+				 "verify_peer[%s] and peer_name[%s] "
+				 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
+				 __location__,
+				 tls_verify_peer_string(tlss->verify_peer),
+				 tlss->peer_name,
+				 status,
+				 status & GNUTLS_CERT_INVALID ? "invalid " : "",
+				 status & GNUTLS_CERT_REVOKED ? "revoked " : "",
+				 status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
+					"signer_not_found " : "",
+				 status & GNUTLS_CERT_SIGNER_NOT_CA ?
+					"signer_not_ca " : "",
+				 status & GNUTLS_CERT_INSECURE_ALGORITHM ?
+					"insecure_algorithm " : "",
+				 status & GNUTLS_CERT_NOT_ACTIVATED ?
+					"not_activated " : "",
+				 status & GNUTLS_CERT_EXPIRED ?
+					"expired " : "",
+				 status & GNUTLS_CERT_UNEXPECTED_OWNER ?
+					"unexptected_owner " : ""));
+			tlss->error = EINVAL;
+			tevent_req_error(req, tlss->error);
+			return;
+		}
+	}
+
 	tevent_req_done(req);
 #else /* ENABLE_GNUTLS */
 	tevent_req_error(req, ENOSYS);
diff --git a/source4/lib/tls/tlscert.c b/source4/lib/tls/tlscert.c
index 8eab04a..f1808d7 100644
--- a/source4/lib/tls/tlscert.c
+++ b/source4/lib/tls/tlscert.c
@@ -30,9 +30,10 @@
 #endif
 
 #define ORGANISATION_NAME "Samba Administration"
-#define UNIT_NAME         "Samba - temporary autogenerated certificate"
+#define CA_NAME           "Samba - temporary autogenerated CA certificate"
+#define UNIT_NAME         "Samba - temporary autogenerated HOST certificate"
 #define LIFETIME          700*24*60*60
-#define DH_BITS 		  1024
+#define RSA_BITS          4096
 
 /* 
    auto-generate a set of self signed certificates
@@ -77,11 +78,11 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
 
 	DEBUG(3,("Generating private key\n"));
 	TLSCHECK(gnutls_x509_privkey_init(&key));
-	TLSCHECK(gnutls_x509_privkey_generate(key,   GNUTLS_PK_RSA, DH_BITS, 0));
+	TLSCHECK(gnutls_x509_privkey_generate(key,   GNUTLS_PK_RSA, RSA_BITS, 0));
 
 	DEBUG(3,("Generating CA private key\n"));
 	TLSCHECK(gnutls_x509_privkey_init(&cakey));
-	TLSCHECK(gnutls_x509_privkey_generate(cakey, GNUTLS_PK_RSA, DH_BITS, 0));
+	TLSCHECK(gnutls_x509_privkey_generate(cakey, GNUTLS_PK_RSA, RSA_BITS, 0));
 
 	DEBUG(3,("Generating CA certificate\n"));
 	TLSCHECK(gnutls_x509_crt_init(&cacrt));
@@ -90,7 +91,7 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
 				      ORGANISATION_NAME, strlen(ORGANISATION_NAME)));
 	TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, 
 				      GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0,
-				      UNIT_NAME, strlen(UNIT_NAME)));
+				      CA_NAME, strlen(CA_NAME)));
 	TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt,
 				      GNUTLS_OID_X520_COMMON_NAME, 0,
 				      hostname, strlen(hostname)));
@@ -98,10 +99,8 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
 	TLSCHECK(gnutls_x509_crt_set_serial(cacrt, &serial, sizeof(serial)));
 	TLSCHECK(gnutls_x509_crt_set_activation_time(cacrt, activation));
 	TLSCHECK(gnutls_x509_crt_set_expiration_time(cacrt, expiry));
-	TLSCHECK(gnutls_x509_crt_set_ca_status(cacrt, 0));
-#ifdef GNUTLS_KP_TLS_WWW_SERVER
-	TLSCHECK(gnutls_x509_crt_set_key_purpose_oid(cacrt, GNUTLS_KP_TLS_WWW_SERVER, 0));
-#endif
+	TLSCHECK(gnutls_x509_crt_set_ca_status(cacrt, 1));
+	TLSCHECK(gnutls_x509_crt_set_key_usage(cacrt, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN));
 	TLSCHECK(gnutls_x509_crt_set_version(cacrt, 3));
 	TLSCHECK(gnutls_x509_crt_get_key_id(cacrt, 0, keyid, &keyidsize));
 #if HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID
@@ -134,6 +133,7 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
 	TLSCHECK(gnutls_x509_crt_set_subject_key_id(crt, keyid, keyidsize));
 #endif
 	TLSCHECK(gnutls_x509_crt_sign(crt, crt, key));
+	TLSCHECK(gnutls_x509_crt_sign(crt, cacrt, cakey));
 
 	DEBUG(3,("Exporting TLS keys\n"));
 
diff --git a/source4/lib/tls/wscript b/source4/lib/tls/wscript
index 83520a7..6584e36 100644
--- a/source4/lib/tls/wscript
+++ b/source4/lib/tls/wscript
@@ -39,6 +39,11 @@ def configure(conf):
     conf.CHECK_FUNCS_IN('gnutls_global_init', 'gnutls',
                         headers='gnutls/gnutls.h')
 
+    conf.CHECK_FUNCS_IN('gnutls_certificate_verify_peers3', 'gnutls',
+                        headers='gnutls/gnutls.h')
+    conf.CHECK_DECLS('GNUTLS_CERT_EXPIRED GNUTLS_CERT_NOT_ACTIVATED GNUTLS_CERT_UNEXPECTED_OWNER',
+                     headers='gnutls/gnutls.h gnutls/x509.h')
+
     conf.CHECK_VARIABLE('gnutls_x509_crt_set_version',
                         headers='gnutls/gnutls.h gnutls/x509.h',
                         define='HAVE_GNUTLS_X509_CRT_SET_VERSION',
diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c
index 1715192..35d963e 100644
--- a/source4/libcli/cliconnect.c
+++ b/source4/libcli/cliconnect.c
@@ -77,7 +77,7 @@ NTSTATUS smbcli_negprot(struct smbcli_state *cli, bool unicode, int maxprotocol)
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	return smb_raw_negotiate(cli->transport, unicode, maxprotocol);
+	return smb_raw_negotiate(cli->transport, unicode, PROTOCOL_CORE, maxprotocol);
 }
 
 /* wrapper around smb_raw_sesssetup() */
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c
index 0da49f3..c5d8219 100644
--- a/source4/libcli/ldap/ldap_bind.c
+++ b/source4/libcli/ldap/ldap_bind.c
@@ -32,6 +32,7 @@
 #include "auth/credentials/credentials.h"
 #include "lib/stream/packet.h"
 #include "param/param.h"
+#include "param/loadparm.h"
 
 struct ldap_simple_creds {
 	const char *dn;
@@ -216,7 +217,7 @@ _PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
 	struct ldap_SearchResEntry *search;
 	int count, i;
 	bool first = true;
-
+	int wrap_flags = 0;
 	const char **sasl_names;
 	uint32_t old_gensec_features;
 	static const char *supported_sasl_mech_attrs[] = {
@@ -285,12 +286,29 @@ _PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
 
 	gensec_init();
 
+	if (conn->sockets.active == conn->sockets.tls) {
+		/*
+		 * require Kerberos SIGN/SEAL only if we don't use SSL
+		 * Windows seem not to like double encryption
+		 */
+		wrap_flags = 0;
+	} else if (cli_credentials_is_anonymous(creds)) {
+		/*
+		 * anonymous isn't protected
+		 */
+		wrap_flags = 0;
+	} else {
+		wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
+	}
+
 try_logon_again:
 	/*
 	  we loop back here on a logon failure, and re-create the
 	  gensec session. The logon_retries counter ensures we don't
 	  loop forever.
 	 */
+	data_blob_free(&input);
+	TALLOC_FREE(conn->gensec);
 
 	status = gensec_client_start(conn, &conn->gensec,
 				     lpcfg_gensec_settings(conn, lp_ctx));
@@ -299,10 +317,8 @@ try_logon_again:
 		goto failed;
 	}
 
-	/* require Kerberos SIGN/SEAL only if we don't use SSL
-	 * Windows seem not to like double encryption */
 	old_gensec_features = cli_credentials_get_gensec_features(creds);
-	if (conn->sockets.active == conn->sockets.tls) {
+	if (wrap_flags == 0) {
 		cli_credentials_set_gensec_features(creds, old_gensec_features & ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL));
 	}
 
@@ -318,6 +334,21 @@ try_logon_again:
 	 * context, so we don't tatoo it ) */
 	cli_credentials_set_gensec_features(creds, old_gensec_features);
 
+	if (wrap_flags & ADS_AUTH_SASL_SEAL) {
+		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
+		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
+	}
+	if (wrap_flags & ADS_AUTH_SASL_SIGN) {
+		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
+	}
+
+	/*
+	 * This is an indication for the NTLMSSP backend to
+	 * also encrypt when only GENSEC_FEATURE_SIGN is requested
+	 * in gensec_[un]wrap().
+	 */
+	gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);
+
 	if (conn->host) {
 		status = gensec_set_target_hostname(conn->gensec, conn->host);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -406,6 +437,13 @@ try_logon_again:
 
 		result = response->r.BindResponse.response.resultcode;
 
+		if (result == LDAP_STRONG_AUTH_REQUIRED) {
+			if (wrap_flags == 0) {
+				wrap_flags = ADS_AUTH_SASL_SIGN;
+				goto try_logon_again;
+			}
+		}
+
 		if (result == LDAP_INVALID_CREDENTIALS) {
 			/*
 			  try a second time on invalid credentials, to
@@ -434,8 +472,6 @@ try_logon_again:
 				  new credentials, or get a new ticket
 				  if using kerberos
 				 */
-				talloc_free(conn->gensec);
-				conn->gensec = NULL;
 				goto try_logon_again;
 			}
 		}
@@ -466,6 +502,20 @@ try_logon_again:
 	conn->bind.type = LDAP_BIND_SASL;
 	conn->bind.creds = creds;
 
+	if (wrap_flags & ADS_AUTH_SASL_SEAL) {
+		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+
+		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+	} else if (wrap_flags & ADS_AUTH_SASL_SIGN) {
+		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+	}
+
 	if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
 	    !gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
 		return NT_STATUS_OK;
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
index 94367a1..bcd6979 100644
--- a/source4/libcli/ldap/ldap_client.c
+++ b/source4/libcli/ldap/ldap_client.c
@@ -465,16 +465,15 @@ _PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *con
 			char *ca_file = lpcfg_tls_cafile(state, conn->lp_ctx);
 			char *crl_file = lpcfg_tls_crlfile(state, conn->lp_ctx);
 			const char *tls_priority = lpcfg_tls_priority(conn->lp_ctx);
-			if (!ca_file || !*ca_file) {
-				composite_error(result,
-						NT_STATUS_INVALID_PARAMETER_MIX);
-				return result;
-			}
+			enum tls_verify_peer_state verify_peer =
+				lpcfg_tls_verify_peer(conn->lp_ctx);
 
 			status = tstream_tls_params_client(state,
 							   ca_file,
 							   crl_file,
 							   tls_priority,
+							   verify_peer,
+							   conn->host,
 							   &state->tls_params);
 			if (!NT_STATUS_IS_OK(status)) {
 				composite_error(result, status);
diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c
index f910acb..448a263 100644
--- a/source4/libcli/ldap/ldap_controls.c
+++ b/source4/libcli/ldap/ldap_controls.c
@@ -512,10 +512,10 @@ static bool encode_verify_name_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -716,10 +716,10 @@ static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -774,10 +774,10 @@ static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -809,10 +809,10 @@ static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -837,10 +837,10 @@ static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -865,10 +865,10 @@ static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *ou
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -897,10 +897,10 @@ static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -935,10 +935,10 @@ static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -971,10 +971,10 @@ static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -1047,10 +1047,10 @@ static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -1089,10 +1089,10 @@ static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 
 	return true;
@@ -1140,10 +1140,10 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
 		return false;
 	}
 
-	*out = data_blob_talloc(mem_ctx, data->data, data->length);
-	if (out->data == NULL) {
+	if (!asn1_extract_blob(data, mem_ctx, out)) {
 		return false;
 	}
+
 	talloc_free(data);
 	return true;
 }
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index 95e6943..8220cd7 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -95,6 +95,7 @@ struct smbcli_options {
 	unsigned int use_spnego:1;
 	unsigned int unicode:1;
 	unsigned int ntstatus_support:1;
+	int min_protocol;
 	int max_protocol;
 	uint32_t max_xmit;
 	uint16_t max_mux;
diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c
index 9b0ed38..4b42c26 100644
--- a/source4/libcli/raw/rawnegotiate.c
+++ b/source4/libcli/raw/rawnegotiate.c
@@ -37,6 +37,7 @@ static void smb_raw_negotiate_done(struct tevent_req *subreq);
 struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx,
 					  struct tevent_context *ev,
 					  struct smbcli_transport *transport,
+					  int minprotocol,
 					  int maxprotocol)
 {
 	struct tevent_req *req;
@@ -51,10 +52,14 @@ struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx,
 	}
 	state->transport = transport;
 
+	if (maxprotocol > PROTOCOL_NT1) {
+		maxprotocol = PROTOCOL_NT1;
+	}
+
 	subreq = smbXcli_negprot_send(state, ev,
 				      transport->conn,
 				      timeout_msec,
-				      PROTOCOL_CORE,
+				      minprotocol,
 				      maxprotocol);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
@@ -127,7 +132,8 @@ NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req)
 /*
  Send a negprot command (sync interface)
 */
-NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int maxprotocol)
+NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode,
+			   int minprotocol, int maxprotocol)
 {
 	NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
 	struct tevent_req *subreq = NULL;
@@ -136,6 +142,7 @@ NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int
 	subreq = smb_raw_negotiate_send(transport,
 					transport->ev,
 					transport,
+					minprotocol,
 					maxprotocol);
 	if (subreq == NULL) {
 		return NT_STATUS_NO_MEMORY;
diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index 9535380..1a6ae34 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -134,6 +134,7 @@ static void smb2_connect_socket_done(struct composite_context *creq)
 	struct tevent_req *subreq;
 	NTSTATUS status;
 	uint32_t timeout_msec;
+	enum protocol_types min_protocol;
 
 	status = smbcli_sock_connect_recv(creq, state, &sock);
 	if (tevent_req_nterror(req, status)) {
@@ -146,10 +147,14 @@ static void smb2_connect_socket_done(struct composite_context *creq)
 	}
 
 	timeout_msec = state->transport->options.request_timeout * 1000;
+	min_protocol = state->transport->options.min_protocol;
+	if (min_protocol < PROTOCOL_SMB2_02) {
+		min_protocol = PROTOCOL_SMB2_02;
+	}
 
 	subreq = smbXcli_negprot_send(state, state->ev,
 				      state->transport->conn, timeout_msec,
-				      PROTOCOL_SMB2_02,
+				      min_protocol,
 				      state->transport->options.max_protocol);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c
index d87d5ec..fffa768 100644
--- a/source4/libcli/smb_composite/connect.c
+++ b/source4/libcli/smb_composite/connect.c
@@ -297,6 +297,7 @@ static NTSTATUS connect_send_negprot(struct composite_context *c,
 	state->subreq = smb_raw_negotiate_send(state,
 					       state->transport->ev,
 					       state->transport,
+					       state->transport->options.min_protocol,
 					       state->transport->options.max_protocol);
 	NT_STATUS_HAVE_NO_MEMORY(state->subreq);
 	tevent_req_set_callback(state->subreq, subreq_handler, c);
diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c
index e4964c1..9f989f2 100644
--- a/source4/libcli/smb_composite/sesssetup.c
+++ b/source4/libcli/smb_composite/sesssetup.c
@@ -329,9 +329,21 @@ static NTSTATUS session_setup_nt1(struct composite_context *c,
 	
 
 	if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
+		if (!cli_credentials_is_anonymous(io->in.credentials) &&
+		    session->options.ntlmv2_auth &&
+		    session->transport->options.use_spnego)
+		{
+			/*
+			 * Don't send an NTLMv2_RESPONSE without NTLMSSP
+			 * if we want to use spnego
+			 */
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
 		nt_status = cli_credentials_get_ntlm_response(io->in.credentials, state, 
 							      &flags, 
 							      session->transport->negotiate.secblob, 
+							      NULL, /* server_timestamp */
 							      names_blob,
 							      &state->setup.nt1.in.password1,
 							      &state->setup.nt1.in.password2,
@@ -392,24 +404,13 @@ static NTSTATUS session_setup_old(struct composite_context *c,
 	struct sesssetup_state *state = talloc_get_type(c->private_data,
 							struct sesssetup_state);
 	const char *password = cli_credentials_get_password(io->in.credentials);
-	const char *domain = cli_credentials_get_domain(io->in.credentials);
 
 	/*
 	 * domain controllers tend to reject the NTLM v2 blob
 	 * if the netbiosname is not valid (e.g. IP address or FQDN)
 	 * so just leave it away (as Windows client do)
 	 */
-	DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, NULL, domain);
-
 	DATA_BLOB session_key;
-	int flags = 0;
-	if (session->options.lanman_auth) {
-		flags |= CLI_CRED_LANMAN_AUTH;
-	}
-
-	if (session->options.ntlmv2_auth) {
-		flags |= CLI_CRED_NTLMv2_AUTH;
-	}
 
 	state->setup.old.level      = RAW_SESSSETUP_OLD;
 	state->setup.old.in.bufsize = session->transport->options.max_xmit;
@@ -423,9 +424,21 @@ static NTSTATUS session_setup_old(struct composite_context *c,
 						 &state->setup.old.in.domain);
 	
 	if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
+		DATA_BLOB names_blob = data_blob_null;
+		int flags = 0;
+
+		if (!cli_credentials_is_anonymous(io->in.credentials) &&
+		    !session->options.lanman_auth)
+		{
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		flags |= CLI_CRED_LANMAN_AUTH;
+
 		nt_status = cli_credentials_get_ntlm_response(io->in.credentials, state, 
 							      &flags, 
 							      session->transport->negotiate.secblob, 
+							      NULL, /* server_timestamp */
 							      names_blob,
 							      &state->setup.old.in.password,
 							      NULL,
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 6ce0d35..ade742c 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -65,6 +65,8 @@ struct rpc_request {
 	DATA_BLOB request_data;
 	bool ignore_timeout;
 	bool wait_for_sync;
+	bool verify_bitmask1;
+	bool verify_pcontext;
 
 	struct {
 		void (*callback)(struct rpc_request *);
@@ -139,7 +141,9 @@ static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
 	}
 
 	c->call_id = 1;
-	c->security_state.auth_info = NULL;
+	c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
+	c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
+	c->security_state.auth_context_id = 0;
 	c->security_state.session_key = dcerpc_generic_session_key;
 	c->security_state.generic_state = NULL;
 	c->flags = 0;
@@ -220,12 +224,8 @@ static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
 		return;
 	}
 
-	if (hs->p->conn->security_state.auth_info == NULL) {
-		return;
-	}
-
-	*auth_type = hs->p->conn->security_state.auth_info->auth_type;
-	*auth_level = hs->p->conn->security_state.auth_info->auth_level;
+	*auth_type = hs->p->conn->security_state.auth_type;
+	*auth_level = hs->p->conn->security_state.auth_level;
 }
 
 struct dcerpc_bh_raw_call_state {
@@ -743,12 +743,16 @@ static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX
 	struct dcerpc_auth auth;
 	uint32_t auth_length;
 
-	if (!c->security_state.auth_info ||
-	    !c->security_state.generic_state) {
-		return NT_STATUS_OK;
+	status = dcerpc_verify_ncacn_packet_header(pkt, DCERPC_PKT_RESPONSE,
+					pkt->u.response.stub_and_verifier.length,
+					0, /* required_flags */
+					DCERPC_PFC_FLAG_FIRST |
+					DCERPC_PFC_FLAG_LAST);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
-	switch (c->security_state.auth_info->auth_level) {
+	switch (c->security_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
 		break;
@@ -768,6 +772,14 @@ static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX
 		return NT_STATUS_INVALID_LEVEL;
 	}
 
+	if (pkt->auth_length == 0) {
+		return NT_STATUS_INVALID_NETWORK_RESPONSE;
+	}
+
+	if (c->security_state.generic_state == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
 	status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
 					  &pkt->u.response.stub_and_verifier,
 					  &auth, &auth_length, false);
@@ -775,8 +787,20 @@ static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX
 
 	pkt->u.response.stub_and_verifier.length -= auth_length;
 
+	if (auth.auth_type != c->security_state.auth_type) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (auth.auth_level != c->security_state.auth_level) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
+	if (auth.auth_context_id != c->security_state.auth_context_id) {
+		return NT_STATUS_RPC_PROTOCOL_ERROR;
+	}
+
 	/* check signature or unseal the packet */
-	switch (c->security_state.auth_info->auth_level) {
+	switch (c->security_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		status = gensec_unseal_packet(c->security_state.generic_state, 
 					      raw_packet->data + DCERPC_REQUEST_LENGTH,
@@ -832,13 +856,13 @@ static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
 	size_t payload_length;
 	enum ndr_err_code ndr_err;
 	size_t hdr_size = DCERPC_REQUEST_LENGTH;
+	struct dcerpc_auth auth_info = {
+		.auth_type = c->security_state.auth_type,
+		.auth_level = c->security_state.auth_level,
+		.auth_context_id = c->security_state.auth_context_id,
+	};
 
-	/* non-signed packets are simpler */
-	if (c->security_state.auth_info == NULL) {
-		return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
-	}
-
-	switch (c->security_state.auth_info->auth_level) {
+	switch (c->security_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
 		if (sig_size == 0) {
@@ -885,21 +909,18 @@ static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
 	   ndr_push_align() as that is relative to the start of the
 	   whole packet, whereas w2k8 wants it relative to the start
 	   of the stub */
-	c->security_state.auth_info->auth_pad_length =
+	auth_info.auth_pad_length =
 		DCERPC_AUTH_PAD_LENGTH(pkt->u.request.stub_and_verifier.length);
-	ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
+	ndr_err = ndr_push_zero(ndr, auth_info.auth_pad_length);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		return ndr_map_error2ntstatus(ndr_err);
 	}
 
 	payload_length = pkt->u.request.stub_and_verifier.length + 
-		c->security_state.auth_info->auth_pad_length;
-
-	/* we start without signature, it will appended later */
-	c->security_state.auth_info->credentials = data_blob(NULL,0);
+		auth_info.auth_pad_length;
 
 	/* add the auth verifier */
-	ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info);
+	ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth_info);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		return ndr_map_error2ntstatus(ndr_err);
 	}
@@ -917,7 +938,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
 	dcerpc_set_auth_length(blob, sig_size);
 
 	/* sign or seal the packet */
-	switch (c->security_state.auth_info->auth_level) {
+	switch (c->security_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		status = gensec_seal_packet(c->security_state.generic_state, 
 					    mem_ctx, 
@@ -957,7 +978,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
 		DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
 			(unsigned) creds2.length,
 			(unsigned) sig_size,
-			(unsigned) c->security_state.auth_info->auth_pad_length,
+			(unsigned) auth_info.auth_pad_length,
 			(unsigned) pkt->u.request.stub_and_verifier.length));
 		dcerpc_set_frag_length(blob, blob->length + creds2.length);
 		dcerpc_set_auth_length(blob, creds2.length);
@@ -1225,7 +1246,7 @@ struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
 
 	/* construct the NDR form of the packet */
 	status = ncacn_push_auth(&blob, state, &pkt,
-				 p->conn->security_state.auth_info);
+				 p->conn->security_state.tmp_auth_info.out);
 	if (tevent_req_nterror(req, status)) {
 		return tevent_req_post(req, ev);
 	}
@@ -1298,6 +1319,7 @@ static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
 		tevent_req_data(req,
 		struct dcerpc_bind_state);
 	struct dcecli_connection *conn = state->p->conn;
+	struct dcecli_security *sec = &conn->security_state;
 	struct dcerpc_binding *b = NULL;
 	NTSTATUS status;
 	uint32_t flags;
@@ -1331,14 +1353,34 @@ static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
 		return;
 	}
 
-	if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
-	    (pkt->u.bind_ack.num_results == 0) ||
-	    (pkt->u.bind_ack.ctx_list[0].result != 0)) {
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+					DCERPC_PKT_BIND_ACK,
+					pkt->u.bind_ack.auth_info.length,
+					DCERPC_PFC_FLAG_FIRST |
+					DCERPC_PFC_FLAG_LAST,
+					DCERPC_PFC_FLAG_CONC_MPX |
+					DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+	if (!NT_STATUS_IS_OK(status)) {
 		state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
 		tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
 		return;
 	}
 
+	if (pkt->u.bind_ack.num_results != 1) {
+		state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
+		tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+		return;
+	}
+
+	if (pkt->u.bind_ack.ctx_list[0].result != 0) {
+		status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
+		DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
+			 pkt->u.bind_ack.ctx_list[0].reason.value,
+			 nt_errstr(status)));
+		tevent_req_nterror(req, status);
+		return;
+	}
+
 	/*
 	 * DCE-RPC 1.1 (c706) specifies
 	 * CONST_MUST_RCV_FRAG_SIZE as 1432
@@ -1371,11 +1413,13 @@ static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
 	}
 
 	/* the bind_ack might contain a reply set of credentials */
-	if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
+	if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
 		uint32_t auth_length;
 
-		status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
-						  conn->security_state.auth_info, &auth_length, true);
+		status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
+						  &pkt->u.bind_ack.auth_info,
+						  sec->tmp_auth_info.in,
+						  &auth_length, true);
 		if (tevent_req_nterror(req, status)) {
 			return;
 		}
@@ -1425,9 +1469,8 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
 	}
 
 	/* construct the NDR form of the packet */
-	status = ncacn_push_auth(&blob, mem_ctx,
-				 &pkt,
-				 p->conn->security_state.auth_info);
+	status = ncacn_push_auth(&blob, mem_ctx, &pkt,
+				 p->conn->security_state.tmp_auth_info.out);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -1463,8 +1506,7 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c,
 	  to run the auth routines so that we don't get the sign/seal
 	  info out of step with the server
 	*/
-	if (c->security_state.auth_info && c->security_state.generic_state &&
-	    pkt->ptype == DCERPC_PKT_RESPONSE) {
+	if (pkt->ptype == DCERPC_PKT_RESPONSE) {
 		status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
 	}
 
@@ -1504,7 +1546,16 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c,
 	}
 
 	if (pkt->ptype == DCERPC_PKT_FAULT) {
+		status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
 		DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
+		if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+			dcerpc_connection_dead(c, status);
+			return;
+		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+			dcerpc_connection_dead(c, status);
+			return;
+		}
 		req->fault_code = pkt->u.fault.status;
 		req->status = NT_STATUS_NET_WRITE_FAULT;
 		goto req_done;
@@ -1513,20 +1564,27 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c,
 	if (pkt->ptype != DCERPC_PKT_RESPONSE) {
 		DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
 			 (int)pkt->ptype)); 
-		req->fault_code = DCERPC_FAULT_OTHER;
-		req->status = NT_STATUS_NET_WRITE_FAULT;
-		goto req_done;
+		dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
 	}
 
 	/* now check the status from the auth routines, and if it failed then fail
 	   this request accordingly */
 	if (!NT_STATUS_IS_OK(status)) {
-		req->status = status;
-		goto req_done;
+		dcerpc_connection_dead(c, status);
+		return;
 	}
 
 	length = pkt->u.response.stub_and_verifier.length;
 
+	if (req->payload.length + length > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
+		DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
+			 (unsigned)req->payload.length + length,
+			 DCERPC_NCACN_PAYLOAD_MAX_SIZE));
+		dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
 	if (length > 0) {
 		req->payload.data = talloc_realloc(req, 
 						   req->payload.data, 
@@ -1547,6 +1605,13 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c,
 		return;
 	}
 
+	if (req->verify_bitmask1) {
+		req->p->conn->security_state.verified_bitmask1 = true;
+	}
+	if (req->verify_pcontext) {
+		req->p->verified_pcontext = true;
+	}
+
 	if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
 		req->flags |= DCERPC_PULL_BIGENDIAN;
 	} else {
@@ -1571,6 +1636,8 @@ req_done:
 	}
 }
 
+static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
+
 /*
   perform the send side of a async dcerpc request
 */
@@ -1581,6 +1648,7 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
 					       DATA_BLOB *stub_data)
 {
 	struct rpc_request *req;
+	NTSTATUS status;
 
 	req = talloc_zero(mem_ctx, struct rpc_request);
 	if (req == NULL) {
@@ -1603,6 +1671,12 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
 	req->request_data.length = stub_data->length;
 	req->request_data.data = stub_data->data;
 
+	status = dcerpc_request_prepare_vt(req);
+	if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(req);
+		return NULL;
+	}
+
 	DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
 	talloc_set_destructor(req, dcerpc_req_dequeue);
 
@@ -1617,6 +1691,120 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
 	return req;
 }
 
+static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
+{
+	struct dcecli_security *sec = &req->p->conn->security_state;
+	struct dcerpc_sec_verification_trailer *t;
+	struct dcerpc_sec_vt *c = NULL;
+	struct ndr_push *ndr = NULL;
+	enum ndr_err_code ndr_err;
+
+	if (sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+		return NT_STATUS_OK;
+	}
+
+	t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
+	if (t == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (!sec->verified_bitmask1) {
+		t->commands = talloc_realloc(t, t->commands,
+					     struct dcerpc_sec_vt,
+					     t->count.count + 1);
+		if (t->commands == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		c = &t->commands[t->count.count++];
+		ZERO_STRUCTP(c);
+
+		c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
+		if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
+			c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
+		}
+		req->verify_bitmask1 = true;
+	}
+
+	if (!req->p->verified_pcontext) {
+		t->commands = talloc_realloc(t, t->commands,
+					     struct dcerpc_sec_vt,
+					     t->count.count + 1);
+		if (t->commands == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		c = &t->commands[t->count.count++];
+		ZERO_STRUCTP(c);
+
+		c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
+		c->u.pcontext.abstract_syntax = req->p->syntax;
+		c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
+
+		req->verify_pcontext = true;
+	}
+
+	if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
+		t->commands = talloc_realloc(t, t->commands,
+					     struct dcerpc_sec_vt,
+					     t->count.count + 1);
+		if (t->commands == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		c = &t->commands[t->count.count++];
+		ZERO_STRUCTP(c);
+
+		c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
+		c->u.header2.ptype = DCERPC_PKT_REQUEST;
+		if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
+			c->u.header2.drep[0] = 0;
+		} else {
+			c->u.header2.drep[0] = DCERPC_DREP_LE;
+		}
+		c->u.header2.drep[1] = 0;
+		c->u.header2.drep[2] = 0;
+		c->u.header2.drep[3] = 0;
+		c->u.header2.call_id = req->call_id;
+		c->u.header2.context_id = req->p->context_id;
+		c->u.header2.opnum = req->opnum;
+	}
+
+	if (t->count.count == 0) {
+		TALLOC_FREE(t);
+		return NT_STATUS_OK;
+	}
+
+	c = &t->commands[t->count.count - 1];
+	c->command |= DCERPC_SEC_VT_COMMAND_END;
+
+	if (DEBUGLEVEL >= 10) {
+		NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
+	}
+
+	ndr = ndr_push_init_ctx(req);
+	if (ndr == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/*
+	 * for now we just copy and append
+	 */
+
+	ndr_err = ndr_push_bytes(ndr, req->request_data.data,
+				 req->request_data.length);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return ndr_map_error2ntstatus(ndr_err);
+	}
+
+	ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
+						NDR_SCALARS | NDR_BUFFERS,
+						t);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return ndr_map_error2ntstatus(ndr_err);
+	}
+	req->request_data = ndr_push_blob(ndr);
+
+	return NT_STATUS_OK;
+}
+
 /*
   Send a request using the transport
 */
@@ -1646,25 +1834,9 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c)
 		need_async = true;
 	}
 
-	if (c->security_state.auth_info &&
-	    c->security_state.generic_state)
-	{
-		struct gensec_security *gensec = c->security_state.generic_state;
-
-		switch (c->security_state.auth_info->auth_level) {
-		case DCERPC_AUTH_LEVEL_PRIVACY:
-		case DCERPC_AUTH_LEVEL_INTEGRITY:
-			can_async = gensec_have_feature(gensec,
+	if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
+		can_async = gensec_have_feature(c->security_state.generic_state,
 						GENSEC_FEATURE_ASYNC_REPLIES);
-			break;
-		case DCERPC_AUTH_LEVEL_CONNECT:
-		case DCERPC_AUTH_LEVEL_NONE:
-			can_async = true;
-			break;
-		default:
-			can_async = false;
-			break;
-		}
 	}
 
 	if (need_async && !can_async) {
@@ -1684,8 +1856,7 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c)
 	   request header size */
 	chunk_size = p->conn->srv_max_recv_frag;
 	chunk_size -= DCERPC_REQUEST_LENGTH;
-	if (c->security_state.auth_info &&
-	    c->security_state.generic_state) {
+	if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
 		size_t max_payload = chunk_size;
 
 		max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
@@ -2121,7 +2292,7 @@ struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
 
 	/* construct the NDR form of the packet */
 	status = ncacn_push_auth(&blob, state, &pkt,
-				 p->conn->security_state.auth_info);
+				 p->conn->security_state.tmp_auth_info.out);
 	if (tevent_req_nterror(req, status)) {
 		return tevent_req_post(req, ev);
 	}
@@ -2194,6 +2365,7 @@ static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
 		tevent_req_data(req,
 		struct dcerpc_alter_context_state);
 	struct dcecli_connection *conn = state->p->conn;
+	struct dcecli_security *sec = &conn->security_state;
 	NTSTATUS status;
 
 	/*
@@ -2215,23 +2387,15 @@ static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
 	 */
 	tevent_req_defer_callback(req, state->ev);
 
-	if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
-	    pkt->u.alter_resp.num_results == 1 &&
-	    pkt->u.alter_resp.ctx_list[0].result != 0) {
-		status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
-		DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
-			 pkt->u.alter_resp.ctx_list[0].reason.value,
-			 nt_errstr(status)));
-		tevent_req_nterror(req, status);
-		return;
-	}
-
 	if (pkt->ptype == DCERPC_PKT_FAULT) {
 		DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
 			 dcerpc_errstr(state, pkt->u.fault.status)));
 		if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
 			state->p->last_fault_code = pkt->u.fault.status;
 			tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
+		} else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
+			state->p->last_fault_code = pkt->u.fault.status;
+			tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
 		} else {
 			state->p->last_fault_code = pkt->u.fault.status;
 			status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
@@ -2240,21 +2404,42 @@ static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
 		return;
 	}
 
-	if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
-	    pkt->u.alter_resp.num_results == 0 ||
-	    pkt->u.alter_resp.ctx_list[0].result != 0) {
+	status = dcerpc_verify_ncacn_packet_header(pkt,
+					DCERPC_PKT_ALTER_RESP,
+					pkt->u.alter_resp.auth_info.length,
+					DCERPC_PFC_FLAG_FIRST |
+					DCERPC_PFC_FLAG_LAST,
+					DCERPC_PFC_FLAG_CONC_MPX |
+					DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
+	if (!NT_STATUS_IS_OK(status)) {
+		state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
+		tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+		return;
+	}
+
+	if (pkt->u.alter_resp.num_results != 1) {
 		state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
 		tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
 		return;
 	}
 
+	if (pkt->u.alter_resp.ctx_list[0].result != 0) {
+		status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
+		DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
+			 pkt->u.alter_resp.ctx_list[0].reason.value,
+			 nt_errstr(status)));
+		tevent_req_nterror(req, status);
+		return;
+	}
+
 	/* the alter_resp might contain a reply set of credentials */
-	if (conn->security_state.auth_info &&
-	    pkt->u.alter_resp.auth_info.length) {
+	if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
 		uint32_t auth_length;
 
-		status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
-						  conn->security_state.auth_info, &auth_length, true);
+		status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
+						  &pkt->u.alter_resp.auth_info,
+						  sec->tmp_auth_info.in,
+						  &auth_length, true);
 		if (tevent_req_nterror(req, status)) {
 			return;
 		}
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 6385dd0..39d28a6 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -46,11 +46,21 @@ struct dcecli_connection;
 struct gensec_settings;
 struct cli_credentials;
 struct dcecli_security {
-	struct dcerpc_auth *auth_info;
+	enum dcerpc_AuthType auth_type;
+	enum dcerpc_AuthLevel auth_level;
+	uint32_t auth_context_id;
+	struct {
+		struct dcerpc_auth *out;
+		struct dcerpc_auth *in;
+		TALLOC_CTX *mem;
+	} tmp_auth_info;
 	struct gensec_security *generic_state;
 
 	/* get the session key */
 	NTSTATUS (*session_key)(struct dcecli_connection *, DATA_BLOB *);
+
+	bool verified_bitmask1;
+
 };
 
 /*
@@ -126,6 +136,8 @@ struct dcerpc_pipe {
 	 */
 	bool inhibit_timeout_processing;
 	bool timed_out;
+
+	bool verified_pcontext;
 };
 
 /* default timeout for all rpc requests, in seconds */
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index 2d60d38..d617b07 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -124,7 +124,8 @@ _PUBLIC_ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
 
 struct bind_auth_state {
 	struct dcerpc_pipe *pipe;
-	DATA_BLOB credentials;
+	struct dcerpc_auth out_auth_info;
+	struct dcerpc_auth in_auth_info;
 	bool more_processing;	/* Is there anything more to do after the
 				 * first bind itself received? */
 };
@@ -141,6 +142,27 @@ static void bind_auth_next_step(struct composite_context *c)
 	state = talloc_get_type(c->private_data, struct bind_auth_state);
 	sec = &state->pipe->conn->security_state;
 
+	if (state->in_auth_info.auth_type != sec->auth_type) {
+		composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (state->in_auth_info.auth_level != sec->auth_level) {
+		composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (state->in_auth_info.auth_context_id != sec->auth_context_id) {
+		composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
+		return;
+	}
+
+	state->out_auth_info = (struct dcerpc_auth) {
+		.auth_type = sec->auth_type,
+		.auth_level = sec->auth_level,
+		.auth_context_id = sec->auth_context_id,
+	};
+
 	/* The status value here, from GENSEC is vital to the security
 	 * of the system.  Even if the other end accepts, if GENSEC
 	 * claims 'MORE_PROCESSING_REQUIRED' then you must keep
@@ -156,16 +178,14 @@ static void bind_auth_next_step(struct composite_context *c)
 
 	c->status = gensec_update_ev(sec->generic_state, state,
 				  state->pipe->conn->event_ctx,
-				  sec->auth_info->credentials,
-				  &state->credentials);
+				  state->in_auth_info.credentials,
+				  &state->out_auth_info.credentials);
 	if (state->pipe->timed_out) {
 		composite_error(c, NT_STATUS_IO_TIMEOUT);
 		return;
 	}
 	state->pipe->inhibit_timeout_processing = false;
 
-	data_blob_free(&sec->auth_info->credentials);
-
 	if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 		more_processing = true;
 		c->status = NT_STATUS_OK;
@@ -173,18 +193,21 @@ static void bind_auth_next_step(struct composite_context *c)
 
 	if (!composite_is_ok(c)) return;
 
-	if (state->credentials.length == 0) {
+	if (state->out_auth_info.credentials.length == 0) {
 		composite_done(c);
 		return;
 	}
 
-	sec->auth_info->credentials = state->credentials;
+	state->in_auth_info = (struct dcerpc_auth) {
+		.auth_type = DCERPC_AUTH_TYPE_NONE,
+	};
+	sec->tmp_auth_info.in = &state->in_auth_info;
+	sec->tmp_auth_info.mem = state;
+	sec->tmp_auth_info.out = &state->out_auth_info;
 
 	if (!more_processing) {
 		/* NO reply expected, so just send it */
 		c->status = dcerpc_auth3(state->pipe, state);
-		data_blob_free(&state->credentials);
-		sec->auth_info->credentials = data_blob(NULL, 0);
 		if (!composite_is_ok(c)) return;
 
 		composite_done(c);
@@ -197,8 +220,6 @@ static void bind_auth_next_step(struct composite_context *c)
 					   state->pipe,
 					   &state->pipe->syntax,
 					   &state->pipe->transfer_syntax);
-	data_blob_free(&state->credentials);
-	sec->auth_info->credentials = data_blob(NULL, 0);
 	if (composite_nomem(subreq, c)) return;
 	tevent_req_set_callback(subreq, bind_auth_recv_alter, c);
 }
@@ -209,6 +230,11 @@ static void bind_auth_recv_alter(struct tevent_req *subreq)
 	struct composite_context *c =
 		tevent_req_callback_data(subreq,
 		struct composite_context);
+	struct bind_auth_state *state =	talloc_get_type(c->private_data,
+							struct bind_auth_state);
+	struct dcecli_security *sec = &state->pipe->conn->security_state;
+
+	ZERO_STRUCT(sec->tmp_auth_info);
 
 	c->status = dcerpc_alter_context_recv(subreq);
 	TALLOC_FREE(subreq);
@@ -225,14 +251,15 @@ static void bind_auth_recv_bindreply(struct tevent_req *subreq)
 		struct composite_context);
 	struct bind_auth_state *state =	talloc_get_type(c->private_data,
 							struct bind_auth_state);
+	struct dcecli_security *sec = &state->pipe->conn->security_state;
+
+	ZERO_STRUCT(sec->tmp_auth_info);
 
 	c->status = dcerpc_bind_recv(subreq);
 	TALLOC_FREE(subreq);
 	if (!composite_is_ok(c)) return;
 
 	if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) {
-		struct dcecli_security *sec = &state->pipe->conn->security_state;
-
 		gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER);
 	}
 
@@ -353,15 +380,20 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
 		return c;
 	}
 
-	sec->auth_info = talloc(p, struct dcerpc_auth);
-	if (composite_nomem(sec->auth_info, c)) return c;
+	sec->auth_type = auth_type;
+	sec->auth_level = auth_level,
+	/*
+	 * We use auth_context_id = 1 as some older
+	 * Samba versions (<= 4.2.3) use that value hardcoded
+	 * in a response.
+	 */
+	sec->auth_context_id = 1;
 
-	sec->auth_info->auth_type = auth_type;
-	sec->auth_info->auth_level = auth_level,
-	sec->auth_info->auth_pad_length = 0;
-	sec->auth_info->auth_reserved = 0;
-	sec->auth_info->auth_context_id = random();
-	sec->auth_info->credentials = data_blob(NULL, 0);
+	state->out_auth_info = (struct dcerpc_auth) {
+		.auth_type = sec->auth_type,
+		.auth_level = sec->auth_level,
+		.auth_context_id = sec->auth_context_id,
+	};
 
 	/* The status value here, from GENSEC is vital to the security
 	 * of the system.  Even if the other end accepts, if GENSEC
@@ -377,8 +409,8 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
 	state->pipe->timed_out = false;
 	c->status = gensec_update_ev(sec->generic_state, state,
 				  p->conn->event_ctx,
-				  sec->auth_info->credentials,
-				  &state->credentials);
+				  data_blob_null,
+				  &state->out_auth_info.credentials);
 	if (state->pipe->timed_out) {
 		composite_error(c, NT_STATUS_IO_TIMEOUT);
 		return c;
@@ -394,25 +426,28 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
 	state->more_processing = NT_STATUS_EQUAL(c->status,
 						 NT_STATUS_MORE_PROCESSING_REQUIRED);
 
-	if (state->credentials.length == 0) {
+	if (state->out_auth_info.credentials.length == 0) {
 		composite_done(c);
 		return c;
 	}
 
-	sec->auth_info->credentials = state->credentials;
-
 	if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) {
-		if (auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
+		if (sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
 			state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING;
 		}
 	}
 
+	state->in_auth_info = (struct dcerpc_auth) {
+		.auth_type = DCERPC_AUTH_TYPE_NONE,
+	};
+	sec->tmp_auth_info.in = &state->in_auth_info;
+	sec->tmp_auth_info.mem = state;
+	sec->tmp_auth_info.out = &state->out_auth_info;
+
 	/* The first request always is a dcerpc_bind. The subsequent ones
 	 * depend on gensec results */
 	subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
 				  &syntax, &transfer_syntax);
-	data_blob_free(&state->credentials);
-	sec->auth_info->credentials = data_blob(NULL, 0);
 	if (composite_nomem(subreq, c)) return c;
 	tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
 
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 9c5dbeb..8ed1257 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -183,6 +183,11 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CT
 		conn->in.fallback_to_anonymous  = false;
 	}
 
+	conn->in.options.min_protocol = PROTOCOL_NT1;
+	conn->in.options.max_protocol = PROTOCOL_NT1;
+
+	conn->in.options.signing = lpcfg_client_ipc_signing(lp_ctx);
+
 	/* send smb connect request */
 	conn_req = smb_composite_connect_send(conn, s->io.conn,
 					      s->io.resolve_ctx,
@@ -277,6 +282,17 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
 
 	lpcfg_smbcli_options(lp_ctx, &options);
 
+	options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
+	if (options.min_protocol < PROTOCOL_SMB2_02) {
+		options.min_protocol = PROTOCOL_SMB2_02;
+	}
+	options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
+	if (options.max_protocol < PROTOCOL_SMB2_02) {
+		options.max_protocol = PROTOCOL_SMB2_02;
+	}
+
+	options.signing = lpcfg_client_ipc_signing(lp_ctx);
+
 	/* send smb2 connect request */
 	subreq = smb2_connect_send(s, c->event_ctx,
 			host,
@@ -773,6 +789,7 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
 	struct composite_context *ncacn_unix_req;
 	struct composite_context *ncalrpc_req;
 	enum dcerpc_transport_t transport;
+	enum protocol_types min_ipc_protocol;
 	uint32_t flags;
 
 	/* dcerpc pipe connect input parameters */
@@ -786,6 +803,11 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
 	transport = dcerpc_binding_get_transport(s->binding);
 	flags = dcerpc_binding_get_flags(s->binding);
 
+	min_ipc_protocol = lpcfg_client_ipc_min_protocol(s->lp_ctx);
+	if (min_ipc_protocol >= PROTOCOL_SMB2_02) {
+		flags |= DCERPC_SMB2;
+	}
+
 	/* connect dcerpc pipe depending on required transport */
 	switch (transport) {
 	case NCACN_NP:
diff --git a/source4/librpc/rpc/dcerpc_roh.c b/source4/librpc/rpc/dcerpc_roh.c
index 61a22a7..6da2978 100644
--- a/source4/librpc/rpc/dcerpc_roh.c
+++ b/source4/librpc/rpc/dcerpc_roh.c
@@ -185,8 +185,17 @@ struct tevent_req *dcerpc_pipe_open_roh_send(struct dcecli_connection *conn,
 
 	/* Initialize TLS */
 	if (use_tls) {
-		status = tstream_tls_params_client(state->roh, NULL, NULL,
-						   lpcfg_tls_priority(lp_ctx),
+		char *ca_file = lpcfg_tls_cafile(state, lp_ctx);
+		char *crl_file = lpcfg_tls_crlfile(state, lp_ctx);
+		const char *tls_priority = lpcfg_tls_priority(lp_ctx);
+		enum tls_verify_peer_state verify_peer =
+			lpcfg_tls_verify_peer(lp_ctx);
+
+		status = tstream_tls_params_client(state->roh,
+						   ca_file, crl_file,
+						   tls_priority,
+						   verify_peer,
+						   state->rpc_proxy,
 						   &state->tls_params);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0,("%s: Failed tstream_tls_params_client - %s\n",
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index ff3e60e..e2e4a64 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -678,15 +678,15 @@ struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
 
 	/* Perform an authenticated DCE-RPC bind
 	 */
-	if (!(conn->flags & (DCERPC_SIGN|DCERPC_SEAL))) {
+	if (!(conn->flags & (DCERPC_CONNECT|DCERPC_SEAL))) {
 		/*
 		  we are doing an authenticated connection,
-		  but not using sign or seal. We must force
-		  the CONNECT dcerpc auth type as a NONE auth
-		  type doesn't allow authentication
-		  information to be passed.
+		  which needs to use [connect], [sign] or [seal].
+		  If nothing is specified, we default to [sign] now.
+		  This give roughly the same protection as
+		  ncacn_np with smb signing.
 		*/
-		conn->flags |= DCERPC_CONNECT;
+		conn->flags |= DCERPC_SIGN;
 	}
 
 	if (conn->flags & DCERPC_AUTH_SPNEGO) {
@@ -776,6 +776,16 @@ _PUBLIC_ NTSTATUS dcerpc_pipe_auth(TALLOC_CTX *mem_ctx,
 NTSTATUS dcerpc_generic_session_key(struct dcecli_connection *c,
 				    DATA_BLOB *session_key)
 {
+	*session_key = data_blob_null;
+
+	if (c != NULL) {
+		if (c->transport.transport != NCALRPC &&
+		    c->transport.transport != NCACN_UNIX_STREAM)
+		{
+			return NT_STATUS_LOCAL_USER_SESSION_KEY;
+		}
+	}
+
 	/* this took quite a few CPU cycles to find ... */
 	session_key->data = discard_const_p(unsigned char, "SystemLibraryDTC");
 	session_key->length = 16;
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index af3313f..f53b2dd 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -36,10 +36,11 @@ void lpcfg_smbcli_options(struct loadparm_context *lp_ctx,
 {
 	options->max_xmit = lpcfg_max_xmit(lp_ctx);
 	options->max_mux = lpcfg_max_mux(lp_ctx);
-	options->use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_use_spnego(lp_ctx);
+	options->use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_client_use_spnego(lp_ctx);
 	options->signing = lpcfg_client_signing(lp_ctx);
 	options->request_timeout = SMB_REQUEST_TIMEOUT;
 	options->ntstatus_support = lpcfg_nt_status_support(lp_ctx);
+	options->min_protocol = lpcfg_client_min_protocol(lp_ctx);
 	options->max_protocol = lpcfg__client_max_protocol(lp_ctx);
 	options->unicode = lpcfg_unicode(lp_ctx);
 	options->use_oplocks = true;
diff --git a/source4/rpc_server/backupkey/dcesrv_backupkey.c b/source4/rpc_server/backupkey/dcesrv_backupkey.c
index 3edd1b6..5e29ac7 100644
--- a/source4/rpc_server/backupkey/dcesrv_backupkey.c
+++ b/source4/rpc_server/backupkey/dcesrv_backupkey.c
@@ -54,6 +54,14 @@ static const AlgorithmIdentifier _hx509_signature_rsa_with_var_num = {
 	{ 7, discard_const_p(unsigned, rsa_with_var_num) }, NULL
 };
 
+#define DCESRV_INTERFACE_BACKUPKEY_BIND(call, iface) \
+	dcesrv_interface_backupkey_bind(call, iface)
+static NTSTATUS dcesrv_interface_backupkey_bind(struct dcesrv_call_state *dce_call,
+						const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_require_privacy(dce_call, iface);
+}
+
 static NTSTATUS set_lsa_secret(TALLOC_CTX *mem_ctx,
 			       struct ldb_context *ldb,
 			       const char *name,
@@ -1805,11 +1813,6 @@ static WERROR dcesrv_bkrp_BackupKey(struct dcesrv_call_state *dce_call,
 		return WERR_NOT_SUPPORTED;
 	}
 
-	if (!dce_call->conn->auth_state.auth_info ||
-		dce_call->conn->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
-		DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
-	}
-
 	ldb_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
 				dce_call->conn->dce_ctx->lp_ctx,
 				system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
diff --git a/source4/rpc_server/common/reply.c b/source4/rpc_server/common/reply.c
index 007b680..8f0e304 100644
--- a/source4/rpc_server/common/reply.c
+++ b/source4/rpc_server/common/reply.c
@@ -97,28 +97,41 @@ void dcesrv_init_hdr(struct ncacn_packet *pkt, bool bigendian)
 /*
   return a dcerpc fault
 */
-NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
+NTSTATUS dcesrv_fault_with_flags(struct dcesrv_call_state *call,
+				 uint32_t fault_code,
+				 uint8_t extra_flags)
 {
 	struct ncacn_packet pkt;
 	struct data_blob_list_item *rep;
-	uint8_t zeros[4];
+	static const uint8_t zeros[4] = { 0, };
 	NTSTATUS status;
 
-	/* setup a bind_ack */
+	/* setup a fault */
 	dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
 	pkt.auth_length = 0;
 	pkt.call_id = call->pkt.call_id;
 	pkt.ptype = DCERPC_PKT_FAULT;
-	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
-	pkt.u.fault.alloc_hint = 0;
-	pkt.u.fault.context_id = 0;
+	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+	pkt.u.fault.alloc_hint = 24;
+	switch (call->pkt.ptype) {
+	case DCERPC_PKT_REQUEST:
+		pkt.u.fault.context_id = call->pkt.u.request.context_id;
+		break;
+	default:
+		pkt.u.fault.context_id = 0;
+		break;
+	}
+	if (fault_code == DCERPC_NCA_S_PROTO_ERROR) {
+		/*
+		 * context_id = 0 is forced on protocol errors.
+		 */
+		pkt.u.fault.context_id = 0;
+	}
 	pkt.u.fault.cancel_count = 0;
 	pkt.u.fault.status = fault_code;
-
-	ZERO_STRUCT(zeros);
 	pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros));
 
-	rep = talloc(call, struct data_blob_list_item);
+	rep = talloc_zero(call, struct data_blob_list_item);
 	if (!rep) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -142,7 +155,10 @@ NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
 	return NT_STATUS_OK;
 }
 
-
+NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
+{
+	return dcesrv_fault_with_flags(call, fault_code, 0);
+}
 
 _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 {
@@ -183,9 +199,9 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 
 	/* we can write a full max_recv_frag size, minus the dcerpc
 	   request header size */
-	chunk_size = call->conn->cli_max_recv_frag;
+	chunk_size = call->conn->max_xmit_frag;
 	chunk_size -= DCERPC_REQUEST_LENGTH;
-	if (call->conn->auth_state.auth_info &&
+	if (call->conn->auth_state.auth_finished &&
 	    call->conn->auth_state.gensec_security) {
 		size_t max_payload = chunk_size;
 
@@ -206,7 +222,7 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 		struct data_blob_list_item *rep;
 		struct ncacn_packet pkt;
 
-		rep = talloc(call, struct data_blob_list_item);
+		rep = talloc_zero(call, struct data_blob_list_item);
 		NT_STATUS_HAVE_NO_MEMORY(rep);
 
 		length = MIN(chunk_size, stub.length);
@@ -259,5 +275,12 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *c,
 				    DATA_BLOB *session_key)
 {
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(c->endpoint->ep_description);
+
+	if (transport != NCALRPC && transport != NCACN_UNIX_STREAM) {
+		return NT_STATUS_NO_USER_SESSION_KEY;
+	}
+
 	return dcerpc_generic_session_key(NULL, session_key);
 }
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 7c1e2d3..a303d3c 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -42,9 +42,6 @@
 #include "lib/util/samba_modules.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 
-/* this is only used when the client asks for an unknown interface */
-#define DUMMY_ASSOC_GROUP 0x0FFFFFFF
-
 extern const struct dcesrv_interface dcesrv_mgmt_interface;
 
 
@@ -74,7 +71,7 @@ static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_c
 
 	assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
 	if (assoc_group == NULL) {
-		DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
+		DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
 		return NULL;
 	}
 	return talloc_reference(mem_ctx, assoc_group);
@@ -269,7 +266,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 	/* check if this endpoint exists
 	 */
 	if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
-		ep = talloc(dce_ctx, struct dcesrv_endpoint);
+		ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
 		if (!ep) {
 			return NT_STATUS_NO_MEMORY;
 		}
@@ -278,7 +275,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 		add_ep = true;
 
 		/* add mgmt interface */
-		ifl = talloc(ep, struct dcesrv_if_list);
+		ifl = talloc_zero(ep, struct dcesrv_if_list);
 		if (!ifl) {
 			return NT_STATUS_NO_MEMORY;
 		}
@@ -297,7 +294,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 	}
 
 	/* talloc a new interface list element */
-	ifl = talloc(ep, struct dcesrv_if_list);
+	ifl = talloc_zero(ep, struct dcesrv_if_list);
 	if (!ifl) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -408,6 +405,9 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
 	p->msg_ctx = msg_ctx;
 	p->server_id = server_id;
 	p->state_flags = state_flags;
+	p->allow_bind = true;
+	p->max_recv_frag = 5840;
+	p->max_xmit_frag = 5840;
 
 	*_p = p;
 	return NT_STATUS_OK;
@@ -450,6 +450,23 @@ static void dcesrv_call_set_list(struct dcesrv_call_state *call,
 	}
 }
 
+static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
+					 const char *reason)
+{
+	if (call->conn->terminate != NULL) {
+		return;
+	}
+
+	call->conn->allow_bind = false;
+	call->conn->allow_alter = false;
+	call->conn->allow_auth3 = false;
+	call->conn->allow_request = false;
+
+	call->terminate_reason = talloc_strdup(call, reason);
+	if (call->terminate_reason == NULL) {
+		call->terminate_reason = __location__;
+	}
+}
 
 /*
   return a dcerpc bind_nak
@@ -460,6 +477,13 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
 	struct dcerpc_bind_nak_version version;
 	struct data_blob_list_item *rep;
 	NTSTATUS status;
+	static const uint8_t _pad[3] = { 0, };
+
+	/*
+	 * We add the call to the pending_call_list
+	 * in order to defer the termination.
+	 */
+	dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
 
 	/* setup a bind_nak */
 	dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
@@ -472,9 +496,9 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
 	version.rpc_vers_minor = 0;
 	pkt.u.bind_nak.num_versions = 1;
 	pkt.u.bind_nak.versions = &version;
-	pkt.u.bind_nak._pad = data_blob_null;
+	pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
 
-	rep = talloc(call, struct data_blob_list_item);
+	rep = talloc_zero(call, struct data_blob_list_item);
 	if (!rep) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -498,6 +522,19 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
 	return NT_STATUS_OK;	
 }
 
+static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
+				 uint32_t fault_code)
+{
+	/*
+	 * We add the call to the pending_call_list
+	 * in order to defer the termination.
+	 */
+	dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
+
+	return dcesrv_fault_with_flags(call, fault_code,
+				       DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
+}
+
 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
 {
 	DLIST_REMOVE(c->conn->contexts, c);
@@ -510,6 +547,115 @@ static int dcesrv_connection_context_destructor(struct dcesrv_connection_context
 	return 0;
 }
 
+static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+	struct dcesrv_connection_context *context = dce_call->context;
+	const struct dcesrv_interface *iface = context->iface;
+
+	context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+}
+
+NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
+						 const struct dcesrv_interface *iface)
+{
+	if (dce_call->context == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
+	return NT_STATUS_OK;
+}
+
+NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
+					       const struct dcesrv_interface *iface)
+{
+	if (dce_call->context == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
+						       const struct dcesrv_interface *iface)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+	struct dcesrv_connection_context *context = dce_call->context;
+
+	if (context == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = false;
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+	return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
+						      const struct dcesrv_interface *iface)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
+	struct dcesrv_connection_context *context = dce_call->context;
+
+	if (context == NULL) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (transport == NCALRPC) {
+		context->allow_connect = true;
+		return NT_STATUS_OK;
+	}
+
+	/*
+	 * allow overwrite per interface
+	 * allow dcerpc auth level connect:<interface>
+	 */
+	context->allow_connect = true;
+	context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
+					"allow dcerpc auth level connect",
+					iface->name,
+					context->allow_connect);
+	return NT_STATUS_OK;
+}
+
 /*
   handle a bind request
 */
@@ -524,14 +670,57 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 	uint32_t context_id;
 	const struct dcesrv_interface *iface;
 	uint32_t extra_flags = 0;
+	uint16_t max_req = 0;
+	uint16_t max_rep = 0;
+	const char *ep_prefix = "";
+	const char *endpoint = NULL;
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_BIND,
+			call->pkt.u.bind.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_bind_nak(call,
+			DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
+	}
+
+	/* max_recv_frag and max_xmit_frag result always in the same value! */
+	max_req = MIN(call->pkt.u.bind.max_xmit_frag,
+		      call->pkt.u.bind.max_recv_frag);
+	/*
+	 * The values are between 2048 and 5840 tested against Windows 2012R2
+	 * via ncacn_ip_tcp on port 135.
+	 */
+	max_req = MAX(2048, max_req);
+	max_rep = MIN(max_req, call->conn->max_recv_frag);
+	/* They are truncated to an 8 byte boundary. */
+	max_rep &= 0xFFF8;
+
+	/* max_recv_frag and max_xmit_frag result always in the same value! */
+	call->conn->max_recv_frag = max_rep;
+	call->conn->max_xmit_frag = max_rep;
 
 	/*
 	  if provided, check the assoc_group is valid
 	 */
-	if (call->pkt.u.bind.assoc_group_id != 0 &&
-	    lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
-	    dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
-		return dcesrv_bind_nak(call, 0);	
+	if (call->pkt.u.bind.assoc_group_id != 0) {
+		call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
+								       call->conn->dce_ctx,
+								       call->pkt.u.bind.assoc_group_id);
+	} else {
+		call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
+								 call->conn->dce_ctx);
+	}
+	if (call->conn->assoc_group == NULL) {
+		return dcesrv_bind_nak(call, 0);
 	}
 
 	if (call->pkt.u.bind.num_contexts < 1 ||
@@ -540,12 +729,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 	}
 
 	context_id = call->pkt.u.bind.ctx_list[0].context_id;
-
-	/* you can't bind twice on one context */
-	if (dcesrv_find_context(call->conn, context_id) != NULL) {
-		return dcesrv_bind_nak(call, 0);
-	}
-
 	if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
 	uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
 
@@ -573,7 +756,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
 	if (iface) {
 		/* add this context to the list of available context_ids */
-		struct dcesrv_connection_context *context = talloc(call->conn, 
+		struct dcesrv_connection_context *context = talloc_zero(call->conn,
 								   struct dcesrv_connection_context);
 		if (context == NULL) {
 			return dcesrv_bind_nak(call, 0);
@@ -581,22 +764,15 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 		context->conn = call->conn;
 		context->iface = iface;
 		context->context_id = context_id;
-		if (call->pkt.u.bind.assoc_group_id != 0) {
-			context->assoc_group = dcesrv_assoc_group_reference(context,
-									    call->conn->dce_ctx, 
-									    call->pkt.u.bind.assoc_group_id);
-		} else {
-			context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
-		}
-		if (context->assoc_group == NULL) {
-			talloc_free(context);
-			return dcesrv_bind_nak(call, 0);
-		}
+		/* legacy for openchange dcesrv_mapiproxy.c */
+		context->assoc_group = call->conn->assoc_group;
 		context->private_data = NULL;
 		DLIST_ADD(call->conn->contexts, context);
 		call->context = context;
 		talloc_set_destructor(context, dcesrv_connection_context_destructor);
 
+		dcesrv_prepare_context_auth(call);
+
 		status = iface->bind(call, iface, if_version);
 		if (!NT_STATUS_IS_OK(status)) {
 			char *uuid_str = GUID_string(call, &uuid);
@@ -611,10 +787,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 		}
 	}
 
-	if (call->conn->cli_max_recv_frag == 0) {
-		call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
-	}
-
 	if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
 	    (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
 		call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
@@ -627,9 +799,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
 	/* handle any authentication that is being requested */
 	if (!dcesrv_auth_bind(call)) {
-		talloc_free(call->context);
-		call->context = NULL;
-		return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
+		struct dcesrv_auth *auth = &call->conn->auth_state;
+
+		TALLOC_FREE(call->context);
+
+		if (auth->auth_level != DCERPC_AUTH_LEVEL_NONE) {
+			/*
+			 * We only give INVALID_AUTH_TYPE if the auth_level was
+			 * valid.
+			 */
+			return dcesrv_bind_nak(call,
+					DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE);
+		}
+		return dcesrv_bind_nak(call,
+					DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
 	}
 
 	/* setup a bind_ack */
@@ -638,29 +821,39 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 	pkt.call_id = call->pkt.call_id;
 	pkt.ptype = DCERPC_PKT_BIND_ACK;
 	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
-	pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
-	pkt.u.bind_ack.max_recv_frag = 0x2000;
+	pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
+	pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
+	pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
 
-	/*
-	  make it possible for iface->bind() to specify the assoc_group_id
-	  This helps the openchange mapiproxy plugin to work correctly.
-	  
-	  metze
-	*/
-	if (call->context) {
-		pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
-	} else {
-		pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
+	if (iface) {
+		endpoint = dcerpc_binding_get_string_option(
+				call->conn->endpoint->ep_description,
+				"endpoint");
 	}
 
-	if (iface) {
-		/* FIXME: Use pipe name as specified by endpoint instead of interface name */
-		pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
-	} else {
-		pkt.u.bind_ack.secondary_address = "";
+	if (endpoint == NULL) {
+		endpoint = "";
+	}
+
+	if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
+		/*
+		 * TODO: check if this is really needed
+		 *
+		 * Or if we should fix this in our idl files.
+		 */
+		ep_prefix = "\\PIPE\\";
+		endpoint += 6;
+	}
+
+	pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
+							   ep_prefix,
+							   endpoint);
+	if (pkt.u.bind_ack.secondary_address == NULL) {
+		TALLOC_FREE(call->context);
+		return NT_STATUS_NO_MEMORY;
 	}
 	pkt.u.bind_ack.num_results = 1;
-	pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
+	pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
 	if (!pkt.u.bind_ack.ctx_list) {
 		talloc_free(call->context);
 		call->context = NULL;
@@ -678,7 +871,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 		return dcesrv_bind_nak(call, 0);
 	}
 
-	rep = talloc(call, struct data_blob_list_item);
+	rep = talloc_zero(call, struct data_blob_list_item);
 	if (!rep) {
 		talloc_free(call->context);
 		call->context = NULL;
@@ -686,7 +879,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 	}
 
 	status = ncacn_push_auth(&rep->blob, call, &pkt,
-							 call->conn->auth_state.auth_info);
+				 call->out_auth_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		talloc_free(call->context);
 		call->context = NULL;
@@ -713,9 +906,35 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 */
 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
 {
+	NTSTATUS status;
+
+	if (!call->conn->allow_auth3) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	if (call->conn->auth_state.auth_finished) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_AUTH3,
+			call->pkt.u.auth3.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
 	/* handle the auth3 in the auth code */
 	if (!dcesrv_auth_auth3(call)) {
-		return dcesrv_fault(call, DCERPC_FAULT_OTHER);
+		call->conn->auth_state.auth_invalid = true;
 	}
 
 	talloc_free(call);
@@ -757,30 +976,22 @@ static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_
 	}
 
 	/* add this context to the list of available context_ids */
-	context = talloc(call->conn, struct dcesrv_connection_context);
+	context = talloc_zero(call->conn, struct dcesrv_connection_context);
 	if (context == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 	context->conn = call->conn;
 	context->iface = iface;
 	context->context_id = context_id;
-	if (call->pkt.u.alter.assoc_group_id != 0) {
-		context->assoc_group = dcesrv_assoc_group_reference(context,
-								    call->conn->dce_ctx, 
-								    call->pkt.u.alter.assoc_group_id);
-	} else {
-		context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
-	}
-	if (context->assoc_group == NULL) {
-		talloc_free(context);
-		call->context = NULL;
-		return NT_STATUS_NO_MEMORY;
-	}
+	/* legacy for openchange dcesrv_mapiproxy.c */
+	context->assoc_group = call->conn->assoc_group;
 	context->private_data = NULL;
 	DLIST_ADD(call->conn->contexts, context);
 	call->context = context;
 	talloc_set_destructor(context, dcesrv_connection_context_destructor);
 
+	dcesrv_prepare_context_auth(call);
+
 	status = iface->bind(call, iface, if_version);
 	if (!NT_STATUS_IS_OK(status)) {
 		/* we don't want to trigger the iface->unbind() hook */
@@ -819,15 +1030,11 @@ static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
 		}
 	}
 	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
-	pkt.u.alter_resp.max_xmit_frag = 0x2000;
-	pkt.u.alter_resp.max_recv_frag = 0x2000;
-	if (result == 0) {
-		pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
-	} else {
-		pkt.u.alter_resp.assoc_group_id = 0;
-	}
+	pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
+	pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
+	pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
 	pkt.u.alter_resp.num_results = 1;
-	pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
+	pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
 	if (!pkt.u.alter_resp.ctx_list) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -839,21 +1046,15 @@ static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
 
 	status = dcesrv_auth_alter_ack(call, &pkt);
 	if (!NT_STATUS_IS_OK(status)) {
-		if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
-		    || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
-		    || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
-		    || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-			return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
-		}
-		return dcesrv_fault(call, 0);
+		return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
 	}
 
-	rep = talloc(call, struct data_blob_list_item);
+	rep = talloc_zero(call, struct data_blob_list_item);
 	if (!rep) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
+	status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -878,38 +1079,86 @@ static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
 {
 	NTSTATUS status;
-	uint32_t context_id;
+	const struct dcerpc_ctx_list *ctx = NULL;
+	bool auth_ok = false;
+
+	if (!call->conn->allow_alter) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+			DCERPC_PKT_ALTER,
+			call->pkt.u.alter.auth_info.length,
+			0, /* required flags */
+			DCERPC_PFC_FLAG_FIRST |
+			DCERPC_PFC_FLAG_LAST |
+			DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
+			0x08 | /* this is not defined, but should be ignored */
+			DCERPC_PFC_FLAG_CONC_MPX |
+			DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+			DCERPC_PFC_FLAG_MAYBE |
+			DCERPC_PFC_FLAG_OBJECT_UUID);
+	if (!NT_STATUS_IS_OK(status)) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
 
-	/* handle any authentication that is being requested */
-	if (!dcesrv_auth_alter(call)) {
-		/* TODO: work out the right reject code */
-		return dcesrv_alter_resp(call,
-				DCERPC_BIND_PROVIDER_REJECT,
-				DCERPC_BIND_REASON_ASYNTAX);
+	auth_ok = dcesrv_auth_alter(call);
+	if (!auth_ok) {
+		if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_FAULT_ACCESS_DENIED);
+		}
 	}
 
-	context_id = call->pkt.u.alter.ctx_list[0].context_id;
+	if (call->pkt.u.alter.num_contexts < 1) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+	ctx = &call->pkt.u.alter.ctx_list[0];
+	if (ctx->num_transfer_syntaxes < 1) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
 
 	/* see if they are asking for a new interface */
-	call->context = dcesrv_find_context(call->conn, context_id);
+	call->context = dcesrv_find_context(call->conn, ctx->context_id);
 	if (!call->context) {
-		status = dcesrv_alter_new_context(call, context_id);
+		status = dcesrv_alter_new_context(call, ctx->context_id);
 		if (!NT_STATUS_IS_OK(status)) {
 			return dcesrv_alter_resp(call,
 				DCERPC_BIND_PROVIDER_REJECT,
 				DCERPC_BIND_REASON_ASYNTAX);
 		}
+	} else {
+		bool ok;
+
+		ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
+					 &call->context->iface->syntax_id);
+		if (!ok) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		if (ctx->num_transfer_syntaxes != 1) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
+
+		ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
+					 &ndr_transfer_syntax_ndr);
+		if (!ok) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
+		}
 	}
 
-	if (call->pkt.u.alter.assoc_group_id != 0 &&
-	    lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
-	    call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
-		DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
-			 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
-		/* TODO: can they ask for a new association group? */
-		return dcesrv_alter_resp(call,
-				DCERPC_BIND_PROVIDER_REJECT,
-				DCERPC_BIND_REASON_ASYNTAX);
+	/* handle any authentication that is being requested */
+	if (!auth_ok) {
+		if (call->in_auth_info.auth_type !=
+		    call->conn->auth_state.auth_type)
+		{
+			return dcesrv_fault_disconnect(call,
+					DCERPC_FAULT_SEC_PKG_ERROR);
+		}
+		return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
 	}
 
 	return dcesrv_alter_resp(call,
@@ -982,10 +1231,17 @@ done:
 */
 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
 {
+	const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
+	enum dcerpc_transport_t transport =
+		dcerpc_binding_get_transport(endpoint->ep_description);
 	struct ndr_pull *pull;
 	NTSTATUS status;
 	struct dcesrv_connection_context *context;
 
+	if (!call->conn->allow_request) {
+		return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
 	/* if authenticated, and the mech we use can't do async replies, don't use them... */
 	if (call->conn->auth_state.gensec_security && 
 	    !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
@@ -997,6 +1253,49 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
 		return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
 	}
 
+	switch (call->conn->auth_state.auth_level) {
+	case DCERPC_AUTH_LEVEL_NONE:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		break;
+	default:
+		if (!context->allow_connect) {
+			char *addr;
+
+			addr = tsocket_address_string(call->conn->remote_address,
+						      call);
+
+			DEBUG(2, ("%s: restrict auth_level_connect access "
+				  "to [%s] with auth[type=0x%x,level=0x%x] "
+				  "on [%s] from [%s]\n",
+				  __func__, context->iface->name,
+				  call->conn->auth_state.auth_type,
+				  call->conn->auth_state.auth_level,
+				  derpc_transport_string_by_transport(transport),
+				  addr));
+			return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+		}
+		break;
+	}
+
+	if (call->conn->auth_state.auth_level < context->min_auth_level) {
+		char *addr;
+
+		addr = tsocket_address_string(call->conn->remote_address, call);
+
+		DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
+			  "to [%s] with auth[type=0x%x,level=0x%x] "
+			  "on [%s] from [%s]\n",
+			  __func__,
+			  context->min_auth_level,
+			  context->iface->name,
+			  call->conn->auth_state.auth_type,
+			  call->conn->auth_state.auth_level,
+			  derpc_transport_string_by_transport(transport),
+			  addr));
+		return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+	}
+
 	pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
 	NT_STATUS_HAVE_NO_MEMORY(pull);
 
@@ -1083,12 +1382,13 @@ _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(stru
 /*
   process some input to a dcerpc endpoint server.
 */
-NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
-				     struct ncacn_packet *pkt,
-				     DATA_BLOB blob)
+static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
+					    struct ncacn_packet *pkt,
+					    DATA_BLOB blob)
 {
 	NTSTATUS status;
 	struct dcesrv_call_state *call;
+	struct dcesrv_call_state *existing = NULL;
 
 	call = talloc_zero(dce_conn, struct dcesrv_call_state);
 	if (!call) {
@@ -1109,77 +1409,187 @@ NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
 
 	talloc_set_destructor(call, dcesrv_call_dequeue);
 
-	/* we have to check the signing here, before combining the
-	   pdus */
-	if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
-	    !dcesrv_auth_request(call, &blob)) {
-		return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);		
+	if (call->conn->allow_bind) {
+		/*
+		 * Only one bind is possible per connection
+		 */
+		call->conn->allow_bind = false;
+		return dcesrv_bind(call);
 	}
 
-	/* see if this is a continued packet */
-	if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
-	    !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
-		struct dcesrv_call_state *call2 = call;
-		uint32_t alloc_size;
-
-		/* we only allow fragmented requests, no other packet types */
-		if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
-			return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
+	/* we have to check the signing here, before combining the
+	   pdus */
+	if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+		if (!call->conn->allow_request) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
 		}
 
-		/* this is a continuation of an existing call - find the call
-		   then tack it on the end */
-		call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
-		if (!call) {
-			return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
+		status = dcerpc_verify_ncacn_packet_header(&call->pkt,
+				DCERPC_PKT_REQUEST,
+				call->pkt.u.request.stub_and_verifier.length,
+				0, /* required_flags */
+				DCERPC_PFC_FLAG_FIRST |
+				DCERPC_PFC_FLAG_LAST |
+				DCERPC_PFC_FLAG_PENDING_CANCEL |
+				0x08 | /* this is not defined, but should be ignored */
+				DCERPC_PFC_FLAG_CONC_MPX |
+				DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
+				DCERPC_PFC_FLAG_MAYBE |
+				DCERPC_PFC_FLAG_OBJECT_UUID);
+		if (!NT_STATUS_IS_OK(status)) {
+			return dcesrv_fault_disconnect(call,
+					DCERPC_NCA_S_PROTO_ERROR);
 		}
 
-		if (call->pkt.ptype != call2->pkt.ptype) {
-			/* trying to play silly buggers are we? */
-			return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
+		if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
+			/*
+			 * We don't use dcesrv_fault_disconnect()
+			 * here, because we don't want to set
+			 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
+			 *
+			 * Note that we don't check against the negotiated
+			 * max_recv_frag, but a hard coded value.
+			 */
+			dcesrv_call_disconnect_after(call,
+				"dcesrv_auth_request - frag_length too large");
+			return dcesrv_fault(call,
+					DCERPC_NCA_S_PROTO_ERROR);
 		}
-		if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
-			return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
+
+		if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+			/* only one request is possible in the fragmented list */
+			if (dce_conn->incoming_fragmented_call_list != NULL) {
+				TALLOC_FREE(call);
+				call = dce_conn->incoming_fragmented_call_list;
+				dcesrv_call_disconnect_after(call,
+					"dcesrv_auth_request - "
+					"existing fragmented call");
+				return dcesrv_fault(call,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
+				return dcesrv_fault_disconnect(call,
+						DCERPC_FAULT_NO_CALL_ACTIVE);
+			}
+		} else {
+			const struct dcerpc_request *nr = &call->pkt.u.request;
+			const struct dcerpc_request *er = NULL;
+			int cmp;
+
+			existing = dcesrv_find_fragmented_call(dce_conn,
+							call->pkt.call_id);
+			if (existing == NULL) {
+				dcesrv_call_disconnect_after(call,
+					"dcesrv_auth_request - "
+					"no existing fragmented call");
+				return dcesrv_fault(call,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			er = &existing->pkt.u.request;
+
+			if (call->pkt.ptype != existing->pkt.ptype) {
+				/* trying to play silly buggers are we? */
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			cmp = memcmp(call->pkt.drep, existing->pkt.drep,
+				     sizeof(pkt->drep));
+			if (cmp != 0) {
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			if (nr->context_id != er->context_id)  {
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
+			if (nr->opnum != er->opnum)  {
+				return dcesrv_fault_disconnect(existing,
+						DCERPC_NCA_S_PROTO_ERROR);
+			}
 		}
-		if (call->pkt.call_id != call2->pkt.call_id) {
-			return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
+
+		if (!dcesrv_auth_request(call, &blob)) {
+			/*
+			 * We don't use dcesrv_fault_disconnect()
+			 * here, because we don't want to set
+			 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
+			 */
+			dcesrv_call_disconnect_after(call,
+						"dcesrv_auth_request - failed");
+			return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
 		}
-		if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
-			return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
+	}
+
+	/* see if this is a continued packet */
+	if (existing != NULL) {
+		struct dcerpc_request *er = &existing->pkt.u.request;
+		const struct dcerpc_request *nr = &call->pkt.u.request;
+		size_t available;
+		size_t alloc_size;
+		size_t alloc_hint;
+
+		/*
+		 * Up to 4 MByte are allowed by all fragments
+		 */
+		available = DCERPC_NCACN_PAYLOAD_MAX_SIZE;
+		if (er->stub_and_verifier.length > available) {
+			dcesrv_call_disconnect_after(existing,
+				"dcesrv_auth_request - existing payload too large");
+			return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
 		}
-		if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
-			return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
+		available -= er->stub_and_verifier.length;
+		if (nr->alloc_hint > available) {
+			dcesrv_call_disconnect_after(existing,
+				"dcesrv_auth_request - alloc hint too large");
+			return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
 		}
-
-		alloc_size = call->pkt.u.request.stub_and_verifier.length +
-			call2->pkt.u.request.stub_and_verifier.length;
-		if (call->pkt.u.request.alloc_hint > alloc_size) {
-			alloc_size = call->pkt.u.request.alloc_hint;
+		if (nr->stub_and_verifier.length > available) {
+			dcesrv_call_disconnect_after(existing,
+				"dcesrv_auth_request - new payload too large");
+			return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
 		}
-
-		call->pkt.u.request.stub_and_verifier.data = 
-			talloc_realloc(call, 
-				       call->pkt.u.request.stub_and_verifier.data, 
+		alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
+		/* allocate at least 1 byte */
+		alloc_hint = MAX(alloc_hint, 1);
+		alloc_size = er->stub_and_verifier.length +
+			     nr->stub_and_verifier.length;
+		alloc_size = MAX(alloc_size, alloc_hint);
+
+		er->stub_and_verifier.data =
+			talloc_realloc(existing,
+				       er->stub_and_verifier.data,
 				       uint8_t, alloc_size);
-		if (!call->pkt.u.request.stub_and_verifier.data) {
-			return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
+		if (er->stub_and_verifier.data == NULL) {
+			TALLOC_FREE(call);
+			return dcesrv_fault_with_flags(existing,
+						       DCERPC_FAULT_OUT_OF_RESOURCES,
+						       DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
 		}
-		memcpy(call->pkt.u.request.stub_and_verifier.data +
-		       call->pkt.u.request.stub_and_verifier.length,
-		       call2->pkt.u.request.stub_and_verifier.data,
-		       call2->pkt.u.request.stub_and_verifier.length);
-		call->pkt.u.request.stub_and_verifier.length += 
-			call2->pkt.u.request.stub_and_verifier.length;
+		memcpy(er->stub_and_verifier.data +
+		       er->stub_and_verifier.length,
+		       nr->stub_and_verifier.data,
+		       nr->stub_and_verifier.length);
+		er->stub_and_verifier.length += nr->stub_and_verifier.length;
 
-		call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
+		existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
 
-		talloc_free(call2);
+		TALLOC_FREE(call);
+		call = existing;
 	}
 
 	/* this may not be the last pdu in the chain - if its isn't then
 	   just put it on the incoming_fragmented_call_list and wait for the rest */
 	if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
 	    !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+		/*
+		 * Up to 4 MByte are allowed by all fragments
+		 */
+		if (call->pkt.u.request.alloc_hint > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
+			dcesrv_call_disconnect_after(call,
+				"dcesrv_auth_request - initial alloc hint too large");
+			return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+		}
 		dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
 		return NT_STATUS_OK;
 	} 
@@ -1189,7 +1599,8 @@ NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
 
 	switch (call->pkt.ptype) {
 	case DCERPC_PKT_BIND:
-		status = dcesrv_bind(call);
+		status = dcesrv_bind_nak(call,
+			DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
 		break;
 	case DCERPC_PKT_AUTH3:
 		status = dcesrv_auth3(call);
@@ -1201,7 +1612,7 @@ NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
 		status = dcesrv_request(call);
 		break;
 	default:
-		status = NT_STATUS_INVALID_PARAMETER;
+		status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
 		break;
 	}
 
@@ -1228,7 +1639,7 @@ _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_INTERNAL_ERROR;
 	}
 
-	dce_ctx = talloc(mem_ctx, struct dcesrv_context);
+	dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
 	NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
 	dce_ctx->initial_euid = geteuid();
 	dce_ctx->endpoint_list	= NULL;
@@ -1367,6 +1778,11 @@ static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, cons
 	srv_conn = talloc_get_type(dce_conn->transport.private_data,
 				   struct stream_connection);
 
+	dce_conn->allow_bind = false;
+	dce_conn->allow_auth3 = false;
+	dce_conn->allow_alter = false;
+	dce_conn->allow_request = false;
+
 	if (dce_conn->pending_call_list == NULL) {
 		char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
 
@@ -1430,6 +1846,7 @@ struct dcesrv_sock_reply_state {
 };
 
 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
+static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
 
 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
 {
@@ -1445,7 +1862,7 @@ static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
 		struct dcesrv_sock_reply_state *substate;
 		struct tevent_req *subreq;
 
-		substate = talloc(call, struct dcesrv_sock_reply_state);
+		substate = talloc_zero(call, struct dcesrv_sock_reply_state);
 		if (!substate) {
 			dcesrv_terminate_connection(dce_conn, "no memory");
 			return;
@@ -1456,7 +1873,7 @@ static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
 
 		DLIST_REMOVE(call->replies, rep);
 
-		if (call->replies == NULL) {
+		if (call->replies == NULL && call->terminate_reason == NULL) {
 			substate->call = call;
 		}
 
@@ -1476,6 +1893,20 @@ static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
 					substate);
 	}
 
+	if (call->terminate_reason != NULL) {
+		struct tevent_req *subreq;
+
+		subreq = tevent_queue_wait_send(call,
+						dce_conn->event_ctx,
+						dce_conn->send_queue);
+		if (!subreq) {
+			dcesrv_terminate_connection(dce_conn, __location__);
+			return;
+		}
+		tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
+					call);
+	}
+
 	DLIST_REMOVE(call->conn->call_list, call);
 	call->list = DCESRV_LIST_NONE;
 }
@@ -1503,8 +1934,51 @@ static void dcesrv_sock_reply_done(struct tevent_req *subreq)
 	}
 }
 
+static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
 
+static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
+						struct dcesrv_call_state);
+	bool ok;
+	struct timeval tv;
 
+	/* make sure we stop send queue before removing subreq */
+	tevent_queue_stop(call->conn->send_queue);
+
+	ok = tevent_queue_wait_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ok) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+
+	/* disconnect after 200 usecs */
+	tv = timeval_current_ofs_usec(200);
+	subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
+	if (subreq == NULL) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+	tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
+				call);
+}
+
+static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
+{
+	struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
+						struct dcesrv_call_state);
+	bool ok;
+
+	ok = tevent_wakeup_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ok) {
+		dcesrv_terminate_connection(call->conn, __location__);
+		return;
+	}
+
+	dcesrv_terminate_connection(call->conn, call->terminate_reason);
+}
 
 struct dcesrv_socket_context {
 	const struct dcesrv_endpoint *endpoint;
@@ -1720,7 +2194,7 @@ static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
 	NTSTATUS status;
 	const char *endpoint;
 
-	dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
+	dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
 	NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 
 	/* remember the endpoint of this socket */
@@ -1776,7 +2250,7 @@ static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
 	full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
 				    endpoint);
 
-	dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
+	dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
 	NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 
 	/* remember the endpoint of this socket */
@@ -1810,7 +2284,7 @@ static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
+	dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
 	NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 
 	/* remember the endpoint of this socket */
@@ -1848,7 +2322,7 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct
 		port = atoi(endpoint);
 	}
 
-	dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
+	dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
 	NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 
 	/* remember the endpoint of this socket */
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 9a697ce..7e8b18a 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -130,6 +130,14 @@ struct dcesrv_call_state {
 
 	/* this is used by the boilerplate code to generate DCERPC faults */
 	uint32_t fault_code;
+
+	/* the reason why we terminate the connection after sending a response */
+	const char *terminate_reason;
+
+	/* temporary auth_info fields */
+	struct dcerpc_auth in_auth_info;
+	struct dcerpc_auth _out_auth_info;
+	struct dcerpc_auth *out_auth_info;
 };
 
 #define DCESRV_HANDLE_ANY 255
@@ -146,18 +154,23 @@ struct dcesrv_handle {
 
 /* hold the authentication state information */
 struct dcesrv_auth {
-	struct dcerpc_auth *auth_info;
+	enum dcerpc_AuthType auth_type;
+	enum dcerpc_AuthLevel auth_level;
+	uint32_t auth_context_id;
 	struct gensec_security *gensec_security;
 	struct auth_session_info *session_info;
 	NTSTATUS (*session_key)(struct dcesrv_connection *, DATA_BLOB *session_key);
 	bool client_hdr_signing;
 	bool hdr_signing;
+	bool auth_finished;
+	bool auth_invalid;
 };
 
 struct dcesrv_connection_context {
 	struct dcesrv_connection_context *next, *prev;
 	uint32_t context_id;
 
+	/* TODO: remove this legacy (for openchange) in master */
 	struct dcesrv_assoc_group *assoc_group;
 
 	/* the connection this is on */
@@ -168,6 +181,12 @@ struct dcesrv_connection_context {
 
 	/* private data for the interface implementation */
 	void *private_data;
+
+	/*
+	 * the minimum required auth level for this interface
+	 */
+	enum dcerpc_AuthLevel min_auth_level;
+	bool allow_connect;
 };
 
 
@@ -195,12 +214,20 @@ struct dcesrv_connection {
 	struct dcesrv_call_state *call_list;
 
 	/* the maximum size the client wants to receive */
-	uint32_t cli_max_recv_frag;
+	uint16_t max_recv_frag;
+	uint16_t max_xmit_frag;
 
 	DATA_BLOB partial_input;
 
-	/* the current authentication state */
-	struct dcesrv_auth auth_state;
+	/* This can be removed in master... */
+	struct  {
+		struct dcerpc_auth *auth_info;
+		struct gensec_security *gensec_security;
+		struct auth_session_info *session_info;
+		NTSTATUS (*session_key)(struct dcesrv_connection *, DATA_BLOB *session_key);
+		bool client_hdr_signing;
+		bool hdr_signing;
+	} _unused_auth_state;
 
 	/* the event_context that will be used for this connection */
 	struct tevent_context *event_ctx;
@@ -232,6 +259,20 @@ struct dcesrv_connection {
 
 	const struct tsocket_address *local_address;
 	const struct tsocket_address *remote_address;
+
+	/* the current authentication state */
+	struct dcesrv_auth auth_state;
+
+	/*
+	 * remember which pdu types are allowed
+	 */
+	bool allow_bind;
+	bool allow_auth3;
+	bool allow_alter;
+	bool allow_request;
+
+	/* the association group the connection belongs to */
+	struct dcesrv_assoc_group *assoc_group;
 };
 
 
@@ -414,5 +455,13 @@ _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call);
  */
 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call);
 
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
+							  const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
+						        const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
+						       const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
+						      const struct dcesrv_interface *iface);
 
 #endif /* SAMBA_DCERPC_SERVER_H */
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 374c2e0..2b3f8b0 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -39,26 +39,55 @@
 */
 bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 {
-	struct cli_credentials *server_credentials;
+	struct cli_credentials *server_credentials = NULL;
 	struct ncacn_packet *pkt = &call->pkt;
 	struct dcesrv_connection *dce_conn = call->conn;
 	struct dcesrv_auth *auth = &dce_conn->auth_state;
 	NTSTATUS status;
 	uint32_t auth_length;
 
-	if (pkt->u.bind.auth_info.length == 0) {
-		dce_conn->auth_state.auth_info = NULL;
+	if (pkt->auth_length == 0) {
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		auth->auth_context_id = 0;
 		return true;
 	}
 
-	dce_conn->auth_state.auth_info = talloc(dce_conn, struct dcerpc_auth);
-	if (!dce_conn->auth_state.auth_info) {
+	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
+					  &call->in_auth_info,
+					  &auth_length, false);
+	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
-	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
-					  dce_conn->auth_state.auth_info,
-					  &auth_length, false);
+	switch (call->in_auth_info.auth_level) {
+	case DCERPC_AUTH_LEVEL_CONNECT:
+	case DCERPC_AUTH_LEVEL_CALL:
+	case DCERPC_AUTH_LEVEL_PACKET:
+	case DCERPC_AUTH_LEVEL_INTEGRITY:
+	case DCERPC_AUTH_LEVEL_PRIVACY:
+		/*
+		 * We evaluate auth_type only if auth_level was valid
+		 */
+		break;
+	default:
+		/*
+		 * Setting DCERPC_AUTH_LEVEL_NONE,
+		 * gives the caller a chance to decide what
+		 * reject_reason to use
+		 *
+		 * Note: DCERPC_AUTH_LEVEL_NONE == 1
+		 */
+		auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+		auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+		auth->auth_context_id = 0;
+		return false;
+	}
+
+	auth->auth_type = call->in_auth_info.auth_type;
+	auth->auth_level = call->in_auth_info.auth_level;
+	auth->auth_context_id = call->in_auth_info.auth_context_id;
+
 	server_credentials 
 		= cli_credentials_init(call);
 	if (!server_credentials) {
@@ -69,9 +98,9 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 	cli_credentials_set_conf(server_credentials, call->conn->dce_ctx->lp_ctx);
 	status = cli_credentials_set_machine_account(server_credentials, call->conn->dce_ctx->lp_ctx);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
-		talloc_free(server_credentials);
-		server_credentials = NULL;
+		DEBUG(1, ("Failed to obtain server credentials: %s\n",
+			  nt_errstr(status)));
+		return false;
 	}
 
 	status = samba_server_gensec_start(dce_conn, call->event_ctx, 
@@ -96,12 +125,12 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 		}
 	}
 
-	status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type, 
-					       auth->auth_info->auth_level);
+	status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
+					       auth->auth_level);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n",
-			  (int)auth->auth_info->auth_type,
-			  (int)auth->auth_info->auth_level,
+			  (int)auth->auth_type,
+			  (int)auth->auth_level,
 			  nt_errstr(status)));
 		return false;
 	}
@@ -119,10 +148,20 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
 	NTSTATUS status;
 	bool want_header_signing = false;
 
-	if (!call->conn->auth_state.gensec_security) {
+	dce_conn->allow_alter = true;
+	dce_conn->allow_auth3 = true;
+
+	if (call->pkt.auth_length == 0) {
+		dce_conn->auth_state.auth_finished = true;
+		dce_conn->allow_request = true;
 		return NT_STATUS_OK;
 	}
 
+	/* We can't work without an existing gensec state */
+	if (!call->conn->auth_state.gensec_security) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
 	if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
 		dce_conn->auth_state.client_hdr_signing = true;
 		want_header_signing = true;
@@ -132,10 +171,17 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
 		want_header_signing = false;
 	}
 
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = dce_conn->auth_state.auth_type,
+		.auth_level = dce_conn->auth_state.auth_level,
+		.auth_context_id = dce_conn->auth_state.auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
 	status = gensec_update_ev(dce_conn->auth_state.gensec_security,
 			       call, call->event_ctx,
-			       dce_conn->auth_state.auth_info->credentials, 
-			       &dce_conn->auth_state.auth_info->credentials);
+			       call->in_auth_info.credentials,
+			       &call->out_auth_info->credentials);
 	
 	if (NT_STATUS_IS_OK(status)) {
 		status = gensec_session_info(dce_conn->auth_state.gensec_security,
@@ -145,6 +191,8 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
 			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
 			return status;
 		}
+		dce_conn->auth_state.auth_finished = true;
+		dce_conn->allow_request = true;
 
 		if (!gensec_have_feature(dce_conn->auth_state.gensec_security,
 					 GENSEC_FEATURE_SIGN_PKT_HEADER))
@@ -163,9 +211,6 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
 		dce_conn->auth_state.session_key = dcesrv_generic_session_key;
 		return NT_STATUS_OK;
 	} else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		dce_conn->auth_state.auth_info->auth_pad_length = 0;
-		dce_conn->auth_state.auth_info->auth_reserved = 0;
-
 		if (!gensec_have_feature(dce_conn->auth_state.gensec_security,
 					 GENSEC_FEATURE_SIGN_PKT_HEADER))
 		{
@@ -198,24 +243,49 @@ bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
 	NTSTATUS status;
 	uint32_t auth_length;
 
-	/* We can't work without an existing gensec state, and an new blob to feed it */
-	if (!dce_conn->auth_state.auth_info ||
-	    !dce_conn->auth_state.gensec_security ||
-	    pkt->u.auth3.auth_info.length == 0) {
+	if (pkt->auth_length == 0) {
+		return false;
+	}
+
+	if (dce_conn->auth_state.auth_finished) {
+		return false;
+	}
+
+	/* We can't work without an existing gensec state */
+	if (!dce_conn->auth_state.gensec_security) {
 		return false;
 	}
 
 	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
-					  dce_conn->auth_state.auth_info, &auth_length, true);
+					  &call->in_auth_info, &auth_length, true);
 	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
+	if (call->in_auth_info.auth_type != dce_conn->auth_state.auth_type) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_level != dce_conn->auth_state.auth_level) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_context_id != dce_conn->auth_state.auth_context_id) {
+		return false;
+	}
+
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = dce_conn->auth_state.auth_type,
+		.auth_level = dce_conn->auth_state.auth_level,
+		.auth_context_id = dce_conn->auth_state.auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
 	/* Pass the extra data we got from the client down to gensec for processing */
 	status = gensec_update_ev(dce_conn->auth_state.gensec_security,
 			       call, call->event_ctx,
-			       dce_conn->auth_state.auth_info->credentials, 
-			       &dce_conn->auth_state.auth_info->credentials);
+			       call->in_auth_info.credentials,
+			       &call->out_auth_info->credentials);
 	if (NT_STATUS_IS_OK(status)) {
 		status = gensec_session_info(dce_conn->auth_state.gensec_security,
 					     dce_conn,
@@ -224,8 +294,18 @@ bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
 			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
 			return false;
 		}
+		dce_conn->auth_state.auth_finished = true;
+		dce_conn->allow_request = true;
+
 		/* Now that we are authenticated, go back to the generic session key... */
 		dce_conn->auth_state.session_key = dcesrv_generic_session_key;
+
+		if (call->out_auth_info->credentials.length != 0) {
+
+			DEBUG(4, ("GENSEC produced output token (len=%u) at bind_auth3\n",
+				  (unsigned)call->out_auth_info->credentials.length));
+			return false;
+		}
 		return true;
 	} else {
 		DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_auth3: %s\n",
@@ -247,27 +327,40 @@ bool dcesrv_auth_alter(struct dcesrv_call_state *call)
 	uint32_t auth_length;
 
 	/* on a pure interface change there is no auth blob */
-	if (pkt->u.alter.auth_info.length == 0) {
+	if (pkt->auth_length == 0) {
+		if (!dce_conn->auth_state.auth_finished) {
+			return false;
+		}
 		return true;
 	}
 
-	/* We can't work without an existing gensec state */
-	if (!dce_conn->auth_state.gensec_security) {
+	if (dce_conn->auth_state.auth_finished) {
 		return false;
 	}
 
-	dce_conn->auth_state.auth_info = talloc(dce_conn, struct dcerpc_auth);
-	if (!dce_conn->auth_state.auth_info) {
+	/* We can't work without an existing gensec state */
+	if (!dce_conn->auth_state.gensec_security) {
 		return false;
 	}
 
 	status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
-					  dce_conn->auth_state.auth_info,
-					  &auth_length, true);
+					  &call->in_auth_info, &auth_length, true);
 	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
+	if (call->in_auth_info.auth_type != dce_conn->auth_state.auth_type) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_level != dce_conn->auth_state.auth_level) {
+		return false;
+	}
+
+	if (call->in_auth_info.auth_context_id != dce_conn->auth_state.auth_context_id) {
+		return false;
+	}
+
 	return true;
 }
 
@@ -282,19 +375,25 @@ NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_pack
 
 	/* on a pure interface change there is no auth_info structure
 	   setup */
-	if (!call->conn->auth_state.auth_info ||
-	    dce_conn->auth_state.auth_info->credentials.length == 0) {
+	if (call->pkt.auth_length == 0) {
 		return NT_STATUS_OK;
 	}
 
 	if (!call->conn->auth_state.gensec_security) {
-		return NT_STATUS_INVALID_PARAMETER;
+		return NT_STATUS_INTERNAL_ERROR;
 	}
 
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = dce_conn->auth_state.auth_type,
+		.auth_level = dce_conn->auth_state.auth_level,
+		.auth_context_id = dce_conn->auth_state.auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
 	status = gensec_update_ev(dce_conn->auth_state.gensec_security,
 			       call, call->event_ctx,
-			       dce_conn->auth_state.auth_info->credentials, 
-			       &dce_conn->auth_state.auth_info->credentials);
+			       call->in_auth_info.credentials,
+			       &call->out_auth_info->credentials);
 
 	if (NT_STATUS_IS_OK(status)) {
 		status = gensec_session_info(dce_conn->auth_state.gensec_security,
@@ -304,13 +403,13 @@ NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_pack
 			DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
 			return status;
 		}
+		dce_conn->auth_state.auth_finished = true;
+		dce_conn->allow_request = true;
 
 		/* Now that we are authenticated, got back to the generic session key... */
 		dce_conn->auth_state.session_key = dcesrv_generic_session_key;
 		return NT_STATUS_OK;
 	} else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		dce_conn->auth_state.auth_info->auth_pad_length = 0;
-		dce_conn->auth_state.auth_info->auth_reserved = 0;
 		return NT_STATUS_OK;
 	}
 
@@ -326,24 +425,23 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
 {
 	struct ncacn_packet *pkt = &call->pkt;
 	struct dcesrv_connection *dce_conn = call->conn;
-	struct dcerpc_auth auth;
 	NTSTATUS status;
 	uint32_t auth_length;
 	size_t hdr_size = DCERPC_REQUEST_LENGTH;
 
-	if (!dce_conn->auth_state.auth_info ||
-	    !dce_conn->auth_state.gensec_security) {
-		if (pkt->auth_length != 0) {
-			return false;
-		}
-		return true;
+	if (!dce_conn->allow_request) {
+		return false;
+	}
+
+	if (dce_conn->auth_state.auth_invalid) {
+		return false;
 	}
 
 	if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
 		hdr_size += 16;
 	}
 
-	switch (dce_conn->auth_state.auth_info->auth_level) {
+	switch (dce_conn->auth_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
 		break;
@@ -363,36 +461,41 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
 		return false;
 	}
 
+	if (!dce_conn->auth_state.gensec_security) {
+		return false;
+	}
+
 	status = dcerpc_pull_auth_trailer(pkt, call,
 					  &pkt->u.request.stub_and_verifier,
-					  &auth, &auth_length, false);
+					  &call->in_auth_info, &auth_length, false);
 	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
-	if (auth.auth_type != dce_conn->auth_state.auth_info->auth_type) {
+	if (call->in_auth_info.auth_type != dce_conn->auth_state.auth_type) {
 		return false;
 	}
 
-	if (auth.auth_level != dce_conn->auth_state.auth_info->auth_level) {
+	if (call->in_auth_info.auth_level != dce_conn->auth_state.auth_level) {
 		return false;
 	}
 
-	if (auth.auth_context_id != dce_conn->auth_state.auth_info->auth_context_id) {
+	if (call->in_auth_info.auth_context_id != dce_conn->auth_state.auth_context_id) {
 		return false;
 	}
 
 	pkt->u.request.stub_and_verifier.length -= auth_length;
 
 	/* check signature or unseal the packet */
-	switch (dce_conn->auth_state.auth_info->auth_level) {
+	switch (dce_conn->auth_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		status = gensec_unseal_packet(dce_conn->auth_state.gensec_security,
 					      full_packet->data + hdr_size,
 					      pkt->u.request.stub_and_verifier.length, 
 					      full_packet->data,
-					      full_packet->length-auth.credentials.length,
-					      &auth.credentials);
+					      full_packet->length-
+					      call->in_auth_info.credentials.length,
+					      &call->in_auth_info.credentials);
 		memcpy(pkt->u.request.stub_and_verifier.data, 
 		       full_packet->data + hdr_size,
 		       pkt->u.request.stub_and_verifier.length);
@@ -403,8 +506,9 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
 					     pkt->u.request.stub_and_verifier.data, 
 					     pkt->u.request.stub_and_verifier.length,
 					     full_packet->data,
-					     full_packet->length-auth.credentials.length,
-					     &auth.credentials);
+					     full_packet->length-
+					     call->in_auth_info.credentials.length,
+					     &call->in_auth_info.credentials);
 		break;
 
 	case DCERPC_AUTH_LEVEL_CONNECT:
@@ -418,10 +522,10 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
 	}
 
 	/* remove the indicated amount of padding */
-	if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) {
+	if (pkt->u.request.stub_and_verifier.length < call->in_auth_info.auth_pad_length) {
 		return false;
 	}
-	pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length;
+	pkt->u.request.stub_and_verifier.length -= call->in_auth_info.auth_pad_length;
 
 	return NT_STATUS_IS_OK(status);
 }
@@ -441,13 +545,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 	uint32_t payload_length;
 	DATA_BLOB creds2;
 
-	/* non-signed packets are simple */
-	if (dce_conn->auth_state.auth_info == NULL) {
-		status = ncacn_push_auth(blob, call, pkt, NULL);
-		return NT_STATUS_IS_OK(status);
-	}
-
-	switch (dce_conn->auth_state.auth_info->auth_level) {
+	switch (dce_conn->auth_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
 		if (sig_size == 0) {
@@ -472,6 +570,10 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 		return false;
 	}
 
+	if (!dce_conn->auth_state.gensec_security) {
+		return false;
+	}
+
 	ndr = ndr_push_init_ctx(call);
 	if (!ndr) {
 		return false;
@@ -486,28 +588,31 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 		return false;
 	}
 
+	call->_out_auth_info = (struct dcerpc_auth) {
+		.auth_type = dce_conn->auth_state.auth_type,
+		.auth_level = dce_conn->auth_state.auth_level,
+		.auth_context_id = dce_conn->auth_state.auth_context_id,
+	};
+	call->out_auth_info = &call->_out_auth_info;
+
 	/* pad to 16 byte multiple in the payload portion of the
 	   packet. This matches what w2k3 does. Note that we can't use
 	   ndr_push_align() as that is relative to the start of the
 	   whole packet, whereas w2k8 wants it relative to the start
 	   of the stub */
-	dce_conn->auth_state.auth_info->auth_pad_length =
+	call->out_auth_info->auth_pad_length =
 		DCERPC_AUTH_PAD_LENGTH(pkt->u.response.stub_and_verifier.length);
-	ndr_err = ndr_push_zero(ndr,
-				dce_conn->auth_state.auth_info->auth_pad_length);
+	ndr_err = ndr_push_zero(ndr, call->out_auth_info->auth_pad_length);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		return false;
 	}
 
 	payload_length = pkt->u.response.stub_and_verifier.length +
-		dce_conn->auth_state.auth_info->auth_pad_length;
-
-	/* we start without signature, it will appended later */
-	dce_conn->auth_state.auth_info->credentials = data_blob(NULL, 0);
+		call->out_auth_info->auth_pad_length;
 
 	/* add the auth verifier */
 	ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,
-				       dce_conn->auth_state.auth_info);
+				       call->out_auth_info);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		return false;
 	}
@@ -525,7 +630,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 	dcerpc_set_auth_length(blob, sig_size);
 
 	/* sign or seal the packet */
-	switch (dce_conn->auth_state.auth_info->auth_level) {
+	switch (dce_conn->auth_state.auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		status = gensec_seal_packet(dce_conn->auth_state.gensec_security, 
 					    call,
@@ -558,7 +663,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 	if (creds2.length != sig_size) {
 		DEBUG(3,("dcesrv_auth_response: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
 			 (unsigned)creds2.length, (uint32_t)sig_size,
-			 (unsigned)dce_conn->auth_state.auth_info->auth_pad_length,
+			 (unsigned)call->out_auth_info->auth_pad_length,
 			 (unsigned)pkt->u.response.stub_and_verifier.length));
 		dcerpc_set_frag_length(blob, blob->length + creds2.length);
 		dcerpc_set_auth_length(blob, creds2.length);
diff --git a/source4/rpc_server/dcesrv_mgmt.c b/source4/rpc_server/dcesrv_mgmt.c
index 8c4eb63..4d3428d 100644
--- a/source4/rpc_server/dcesrv_mgmt.c
+++ b/source4/rpc_server/dcesrv_mgmt.c
@@ -23,6 +23,14 @@
 #include "rpc_server/dcerpc_server.h"
 #include "librpc/gen_ndr/ndr_mgmt.h"
 
+#define DCESRV_INTERFACE_MGMT_BIND(call, iface) \
+       dcesrv_interface_mgmt_bind(call, iface)
+static NTSTATUS dcesrv_interface_mgmt_bind(struct dcesrv_call_state *dce_call,
+					     const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_allow_connect(dce_call, iface);
+}
+
 /* 
   mgmt_inq_if_ids 
 */
diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
index be31500..7571756 100644
--- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
+++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
@@ -28,6 +28,14 @@
 #include "dnsserver.h"
 #include "lib/ldb/include/ldb_private.h"
 
+#define DCESRV_INTERFACE_DNSSERVER_BIND(call, iface) \
+	dcesrv_interface_dnsserver_bind(call, iface)
+static NTSTATUS dcesrv_interface_dnsserver_bind(struct dcesrv_call_state *dce_call,
+					        const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_require_integrity(dce_call, iface);
+}
+
 struct dnsserver_state {
 	struct loadparm_context *lp_ctx;
 	struct ldb_context *samdb;
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index d331313..3fe6c13 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -39,6 +39,14 @@
 	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \
 } while (0)
 
+#define DCESRV_INTERFACE_DRSUAPI_BIND(call, iface) \
+	dcesrv_interface_drsuapi_bind(call, iface)
+static NTSTATUS dcesrv_interface_drsuapi_bind(struct dcesrv_call_state *dce_call,
+					      const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_require_privacy(dce_call, iface);
+}
+
 /* 
   drsuapi_DsBind 
 */
diff --git a/source4/rpc_server/echo/rpc_echo.c b/source4/rpc_server/echo/rpc_echo.c
index 4863c77..49c9e23 100644
--- a/source4/rpc_server/echo/rpc_echo.c
+++ b/source4/rpc_server/echo/rpc_echo.c
@@ -26,6 +26,13 @@
 #include "librpc/gen_ndr/ndr_echo.h"
 #include "lib/events/events.h"
 
+#define DCESRV_INTERFACE_RPCECHO_BIND(call, iface) \
+       dcesrv_interface_rpcecho_bind(call, iface)
+static NTSTATUS dcesrv_interface_rpcecho_bind(struct dcesrv_call_state *dce_call,
+					      const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_allow_connect(dce_call, iface);
+}
 
 static NTSTATUS dcesrv_echo_AddOne(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_AddOne *r)
 {
diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c
index 62627ce..6b934d7 100644
--- a/source4/rpc_server/epmapper/rpc_epmapper.c
+++ b/source4/rpc_server/epmapper/rpc_epmapper.c
@@ -24,6 +24,14 @@
 #include "librpc/gen_ndr/ndr_epmapper.h"
 #include "rpc_server/dcerpc_server.h"
 
+#define DCESRV_INTERFACE_EPMAPPER_BIND(call, iface) \
+       dcesrv_interface_epmapper_bind(call, iface)
+static NTSTATUS dcesrv_interface_epmapper_bind(struct dcesrv_call_state *dce_call,
+					     const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_allow_connect(dce_call, iface);
+}
+
 typedef uint32_t error_status_t;
 
 /* handle types for this module */
diff --git a/source4/rpc_server/handles.c b/source4/rpc_server/handles.c
index be9f16c..820da49 100644
--- a/source4/rpc_server/handles.c
+++ b/source4/rpc_server/handles.c
@@ -46,7 +46,7 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_contex
 
 	sid = &context->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
 
-	h = talloc(context->assoc_group, struct dcesrv_handle);
+	h = talloc_zero(context->conn->assoc_group, struct dcesrv_handle);
 	if (!h) {
 		return NULL;
 	}
@@ -56,12 +56,12 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_contex
 		talloc_free(h);
 		return NULL;
 	}
-	h->assoc_group = context->assoc_group;
+	h->assoc_group = context->conn->assoc_group;
 	h->iface = context->iface;
 	h->wire_handle.handle_type = handle_type;
 	h->wire_handle.uuid = GUID_random();
 	
-	DLIST_ADD(context->assoc_group->handles, h);
+	DLIST_ADD(context->conn->assoc_group->handles, h);
 
 	talloc_set_destructor(h, dcesrv_handle_destructor);
 
@@ -87,7 +87,7 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(
 		return dcesrv_handle_new(context, handle_type);
 	}
 
-	for (h=context->assoc_group->handles; h; h=h->next) {
+	for (h=context->conn->assoc_group->handles; h; h=h->next) {
 		if (h->wire_handle.handle_type == p->handle_type &&
 		    GUID_equal(&p->uuid, &h->wire_handle.uuid)) {
 			if (handle_type != DCESRV_HANDLE_ANY &&
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index c40322f..8a0f66b 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -34,6 +34,14 @@
 #include "libcli/lsarpc/util_lsarpc.h"
 #include "lib/messaging/irpc.h"
 
+#define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
+       dcesrv_interface_lsarpc_bind(call, iface)
+static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
+					     const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_reject_connect(dce_call, iface);
+}
+
 /*
   this type allows us to distinguish handle types
 */
diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c
index 9a8fdfb..f4da0b4 100644
--- a/source4/rpc_server/lsa/lsa_lookup.c
+++ b/source4/rpc_server/lsa/lsa_lookup.c
@@ -718,7 +718,7 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
 {
 	enum dcerpc_transport_t transport =
 		dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
-	struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
+	const struct dcesrv_auth *auth = &dce_call->conn->auth_state;
 	struct lsa_policy_state *policy_state;
 	struct lsa_LookupSids2 q;
 	NTSTATUS status;
@@ -731,8 +731,8 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
 	 * We don't have policy handles on this call. So this must be restricted
 	 * to crypto connections only.
 	 */
-	if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
-	    auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+	if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
+	    auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
 		DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
 	}
 
@@ -946,7 +946,7 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX
 {
 	enum dcerpc_transport_t transport =
 		dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
-	struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
+	const struct dcesrv_auth *auth = &dce_call->conn->auth_state;
 	struct lsa_policy_state *policy_state;
 	struct lsa_LookupNames3 q;
 	NTSTATUS status;
@@ -959,8 +959,8 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX
 	 * We don't have policy handles on this call. So this must be restricted
 	 * to crypto connections only.
 	 */
-	if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
-	    auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
+	if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
+	    auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
 		DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
 	}
 
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 49b5b2f..7a92a6d 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -44,6 +44,14 @@
 #include "librpc/gen_ndr/ndr_winbind_c.h"
 #include "lib/socket/netif.h"
 
+#define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
+       dcesrv_interface_netlogon_bind(call, iface)
+static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
+					       const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_reject_connect(dce_call, iface);
+}
+
 static struct memcache *global_challenge_table;
 
 struct netlogon_server_pipe_state {
@@ -128,6 +136,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 	bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
 	bool reject_des_client = !allow_nt4_crypto;
 	bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
+	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
+	bool reject_none_rpc = (schannel == true);
 
 	ZERO_STRUCTP(r->out.return_credentials);
 	*r->out.rid = 0;
@@ -200,6 +210,10 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 
 	negotiate_flags = *r->in.negotiate_flags & server_flags;
 
+	if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
+		reject_none_rpc = false;
+	}
+
 	if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
 		reject_des_client = false;
 	}
@@ -236,6 +250,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 	 */
 	*r->out.negotiate_flags = negotiate_flags;
 
+	if (reject_none_rpc) {
+		/* schannel must be used, but client did not offer it. */
+		DEBUG(0,("%s: schannel required but client failed "
+			"to offer it. Client was %s\n",
+			__func__, r->in.account_name));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	switch (r->in.secure_channel_type) {
 	case SEC_CHAN_WKSTA:
 	case SEC_CHAN_DNS_DOMAIN:
@@ -514,7 +536,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca
 /*
  * If schannel is required for this call test that it actually is available.
  */
-static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
+static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
 					const char *computer_name,
 					bool integrity, bool privacy)
 {
@@ -550,11 +572,11 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 						    struct netlogon_creds_CredentialState **creds_out)
 {
 	NTSTATUS nt_status;
-	struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
-	bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
+	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
+	bool schannel_global_required = (schannel == true);
 
 	if (schannel_global_required) {
-		nt_status = schannel_check_required(auth_info,
+		nt_status = schannel_check_required(&dce_call->conn->auth_state,
 						    computer_name,
 						    true, false);
 		if (!NT_STATUS_IS_OK(nt_status)) {
@@ -813,6 +835,8 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonE
 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 					struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
 {
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	const char *workgroup = lpcfg_workgroup(lp_ctx);
 	struct auth4_context *auth_context;
 	struct auth_usersupplied_info *user_info;
 	struct auth_user_info_dc *user_info_dc;
@@ -883,6 +907,13 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 		user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
 		user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
 
+		nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
+					user_info->client.account_name,
+					user_info->client.domain_name,
+					user_info->password.response.nt,
+					creds, workgroup);
+		NT_STATUS_NOT_OK_RETURN(nt_status);
+
 		break;
 
 
@@ -978,6 +1009,10 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal
 		break;
 
 	case 6:
+		if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
 		nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
 							   user_info_dc,
 							   &sam3);
@@ -1034,8 +1069,7 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call,
 		return nt_status;
 	}
 
-	if (!dce_call->conn->auth_state.auth_info ||
-	    dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+	if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
 		return NT_STATUS_ACCESS_DENIED;
 	}
 	return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
diff --git a/source4/rpc_server/remote/dcesrv_remote.c b/source4/rpc_server/remote/dcesrv_remote.c
index be4bd12..3eb0ad4 100644
--- a/source4/rpc_server/remote/dcesrv_remote.c
+++ b/source4/rpc_server/remote/dcesrv_remote.c
@@ -117,9 +117,9 @@ static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct
 	}
 
 	/* If we already have a remote association group ID, then use that */
-	if (dce_call->context->assoc_group->proxied_id != 0) {
+	if (dce_call->conn->assoc_group->proxied_id != 0) {
 		status = dcerpc_binding_set_assoc_group_id(b,
-			dce_call->context->assoc_group->proxied_id);
+			dce_call->conn->assoc_group->proxied_id);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0, ("dcerpc_binding_set_assoc_group_id() - %s'\n",
 				  nt_errstr(status)));
@@ -148,8 +148,8 @@ static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct
 		return status;
 	}
 
-	if (dce_call->context->assoc_group->proxied_id == 0) {
-		dce_call->context->assoc_group->proxied_id =
+	if (dce_call->conn->assoc_group->proxied_id == 0) {
+		dce_call->conn->assoc_group->proxied_id =
 			dcerpc_binding_get_assoc_group_id(priv->c_pipe->binding);
 	}
 
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 9f3bd10..423fcf0 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -41,6 +41,14 @@
 #include "lib/util/tsort.h"
 #include "libds/common/flag_mapping.h"
 
+#define DCESRV_INTERFACE_SAMR_BIND(call, iface) \
+       dcesrv_interface_samr_bind(call, iface)
+static NTSTATUS dcesrv_interface_samr_bind(struct dcesrv_call_state *dce_call,
+					     const struct dcesrv_interface *iface)
+{
+	return dcesrv_interface_bind_reject_connect(dce_call, iface);
+}
+
 /* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */
 
 #define QUERY_STRING(msg, field, attr) \
@@ -4318,6 +4326,10 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
 		DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
 	}
 
+	if (dce_call->conn->auth_state.auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+		DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
+	}
+
 	(*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep);
 
 	r2.in.domain_name = NULL;
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
index 1466dec..f053dad 100644
--- a/source4/rpc_server/samr/samr_password.c
+++ b/source4/rpc_server/samr/samr_password.c
@@ -419,7 +419,10 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
 
 	nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
+		DEBUG(3,("samr: failed to get session key: %s "
+			 "=> NT_STATUS_WRONG_PASSWORD\n",
+			nt_errstr(nt_status)));
+		return NT_STATUS_WRONG_PASSWORD;
 	}
 
 	arcfour_crypt_blob(pwbuf->data, 516, &session_key);
@@ -458,7 +461,10 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
 
 	nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
+		DEBUG(3,("samr: failed to get session key: %s "
+			 "=> NT_STATUS_WRONG_PASSWORD\n",
+			nt_errstr(nt_status)));
+		return NT_STATUS_WRONG_PASSWORD;
 	}
 
 	co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
@@ -500,11 +506,26 @@ NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call,
 				   const uint8_t *nt_pwd_hash)
 {
 	struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL;
+	uint8_t random_session_key[16] = { 0, };
 	DATA_BLOB session_key = data_blob(NULL, 0);
 	DATA_BLOB in, out;
 	NTSTATUS nt_status = NT_STATUS_OK;
 
 	nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
+	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_USER_SESSION_KEY)) {
+		DEBUG(3,("samr: failed to get session key: %s "
+			 "=> use a random session key\n",
+			 nt_errstr(nt_status)));
+
+		/*
+		 * Windows just uses a random key
+		 */
+		generate_random_buffer(random_session_key,
+				       sizeof(random_session_key));
+		session_key = data_blob_const(random_session_key,
+					      sizeof(random_session_key));
+		nt_status = NT_STATUS_OK;
+	}
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		return nt_status;
 	}
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 69330f2..6de8527 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -43,8 +43,11 @@ smbclient4 = binpath('smbclient4')
 bbdir = os.path.join(srcdir(), "testprogs/blackbox")
 
 # Simple tests for LDAP and CLDAP
-for options in ['-U"$USERNAME%$PASSWORD" --option=socket:testnonblock=true', '-U"$USERNAME%$PASSWORD"', '-U"$USERNAME%$PASSWORD" -k yes', '-U"$USERNAME%$PASSWORD" -k no', '-U"$USERNAME%$PASSWORD" -k no --sign', '-U"$USERNAME%$PASSWORD" -k no --encrypt', '-U"$USERNAME%$PASSWORD" -k yes --encrypt', '-U"$USERNAME%$PASSWORD" -k yes --sign']:
-    plantestsuite("samba4.ldb.ldap with options %s(ad_dc_ntvfs)" % options, "ad_dc_ntvfs", "%s/test_ldb.sh ldap $SERVER %s" % (bbdir, options))
+for auth_type in ['', '-k no', '-k yes']:
+    for auth_level in ['--option=clientldapsaslwrapping=plain', '--sign', '--encrypt']:
+        creds = '-U"$USERNAME%$PASSWORD"'
+        options = creds + ' ' + auth_type + ' ' + auth_level
+        plantestsuite("samba4.ldb.ldap with options %r(ad_dc_ntvfs)" % options, "ad_dc_ntvfs", "%s/test_ldb.sh ldap $SERVER %s" % (bbdir, options))
 
 # see if we support ADS on the Samba3 side
 try:
@@ -64,6 +67,58 @@ if have_tls_support:
         plantestsuite("samba4.ldb.ldaps with options %s(ad_dc_ntvfs)" % options, "ad_dc_ntvfs",
                 "%s/test_ldb.sh ldaps $SERVER_IP %s" % (bbdir, options))
 
+    creds_options = [
+        '--simple-bind-dn=$USERNAME@$REALM --password=$PASSWORD',
+    ]
+    peer_options = {
+        'SERVER_IP': '$SERVER_IP',
+        'SERVER_NAME': '$SERVER',
+        'SERVER.REALM': '$SERVER.$REALM',
+    }
+    tls_verify_options = [
+        '--option="tlsverifypeer=no_check"',
+        '--option="tlsverifypeer=ca_only"',
+        '--option="tlsverifypeer=ca_and_name_if_available"',
+        '--option="tlsverifypeer=ca_and_name"',
+        '--option="tlsverifypeer=as_strict_as_possible"',
+    ]
+
+    # we use :local for fl2008r2dc because of the self-signed certificate
+    for env in ["ad_dc_ntvfs", "fl2008r2dc:local"]:
+        for peer_key in peer_options.keys():
+            peer_val = peer_options[peer_key]
+            for creds in creds_options:
+                for tls_verify in tls_verify_options:
+                    options = creds + ' ' + tls_verify
+                    plantestsuite("samba4.ldb.simple.ldaps with options %s %s(%s)" % (
+                                  peer_key, options, env), env,
+                                  "%s/test_ldb_simple.sh ldaps %s %s" % (bbdir, peer_val, options))
+
+# test all "ldap server require strong auth" combinations
+for env in ["ad_dc_ntvfs", "fl2008r2dc", "fl2003dc"]:
+    options = '--simple-bind-dn="$USERNAME@$REALM" --password="$PASSWORD"'
+    plantestsuite("samba4.ldb.simple.ldap with SIMPLE-BIND %s(%s)" % (options, env),
+                  env, "%s/test_ldb_simple.sh ldap $SERVER %s" % (bbdir, options))
+    if have_tls_support:
+        options += ' --option="tlsverifypeer=no_check"'
+        plantestsuite("samba4.ldb.simple.ldaps with SIMPLE-BIND %s(%s)" % (options, env),
+                      env, "%s/test_ldb_simple.sh ldaps $SERVER %s" % (bbdir, options))
+
+    auth_options = [
+        '--option=clientldapsaslwrapping=plain',
+        '--sign',
+        '--encrypt',
+    ]
+
+    for auth_option in auth_options:
+        options = '-U"$USERNAME%$PASSWORD"' + ' ' + auth_option
+        plantestsuite("samba4.ldb.simple.ldap with SASL-BIND %s(%s)" % (options, env),
+                      env, "%s/test_ldb_simple.sh ldap $SERVER %s" % (bbdir, options))
+    if have_tls_support:
+        options = '-U"$USERNAME%$PASSWORD" --option="tlsverifypeer=no_check"'
+        plantestsuite("samba4.ldb.simple.ldaps with SASL-BIND %s(%s)" % (options, env),
+                      env, "%s/test_ldb_simple.sh ldaps $SERVER %s" % (bbdir, options))
+
 for options in ['-U"$USERNAME%$PASSWORD"']:
     plantestsuite("samba4.ldb.ldapi with options %s(ad_dc_ntvfs:local)" % options, "ad_dc_ntvfs:local",
             "%s/test_ldb.sh ldapi $PREFIX_ABS/ad_dc_ntvfs/private/ldapi %s" % (bbdir, options))
@@ -83,11 +138,11 @@ else:
 # add tests to this list as they start passing, so we test
 # that they stay passing
 ncacn_np_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", "rpc.altercontext", "rpc.netlogon", "rpc.netlogon.admin", "rpc.handles", "rpc.samsync", "rpc.samba3-sessionkey", "rpc.samba3-getusername", "rpc.samba3-lsa", "rpc.samba3-bind", "rpc.samba3-netlogon", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext"]
-ncalrpc_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", "rpc.altercontext", "rpc.netlogon", "rpc.drsuapi", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext"]
+ncalrpc_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", "rpc.altercontext", "rpc.netlogon", "rpc.netlogon.admin", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext"]
 drs_rpc_tests = smbtorture4_testsuites("drs.rpc")
-ncacn_ip_tcp_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", "rpc.netlogon", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext", "rpc.samr.passwords.validate"] + drs_rpc_tests
-slow_ncacn_np_tests = ["rpc.samlogon", "rpc.samr.users", "rpc.samr.large-dc", "rpc.samr.users.privileges", "rpc.samr.passwords", "rpc.samr.passwords.pwdlastset", "rpc.samr.passwords.lockout", "rpc.samr.passwords.badpwdcount"]
-slow_ncacn_ip_tcp_tests = ["rpc.samr", "rpc.cracknames"]
+ncacn_ip_tcp_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", "rpc.drsuapi", "rpc.netlogon", "rpc.netlogon.admin", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext", "rpc.samr.passwords.validate"] + drs_rpc_tests
+slow_ncacn_np_tests = ["rpc.samlogon", "rpc.samr", "rpc.samr.users", "rpc.samr.large-dc", "rpc.samr.users.privileges", "rpc.samr.passwords", "rpc.samr.passwords.pwdlastset", "rpc.samr.passwords.lockout", "rpc.samr.passwords.badpwdcount"]
+slow_ncacn_ip_tcp_tests = ["rpc.cracknames"]
 
 all_rpc_tests = ncalrpc_tests + ncacn_np_tests + ncacn_ip_tcp_tests + slow_ncacn_np_tests + slow_ncacn_ip_tcp_tests + ["rpc.lsa.secrets", "rpc.pac", "rpc.samba3-sharesec", "rpc.countcalls"]
 
@@ -135,7 +190,10 @@ for transport in ["ncacn_np", "ncacn_ip_tcp"]:
     else:
         raise AssertionError("Invalid transport %r" % transport)
     for t in tests:
-        plansmbtorture4testsuite(t, env, ["%s:$SERVER" % transport, '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], "samba4.%s on %s" % (t, transport))
+        bindoptions = ''
+        if t == 'rpc.cracknames':
+            bindoptions = 'seal'
+        plansmbtorture4testsuite(t, env, ["%s:$SERVER[%s]" % (transport,bindoptions), '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], "samba4.%s on %s with %s" % (t, transport, bindoptions))
 
 # Tests for the DFS referral calls implementation
 for t in smbtorture4_testsuites("dfs."):
@@ -482,6 +540,7 @@ planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.rpcecho")
 planoldpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.registry", extra_args=['-U"$USERNAME%$PASSWORD"'])
 planoldpythontestsuite("ad_dc_ntvfs", "samba.tests.dcerpc.dnsserver", extra_args=['-U"$USERNAME%$PASSWORD"'])
 planoldpythontestsuite("ad_dc", "samba.tests.dcerpc.dnsserver", extra_args=['-U"$USERNAME%$PASSWORD"'])
+planoldpythontestsuite("ad_dc", "samba.tests.dcerpc.raw_protocol", extra_args=['-U"$USERNAME%$PASSWORD"'])
 plantestsuite_loadlist("samba4.ldap.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
 plantestsuite_loadlist("samba4.tokengroups.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
 plantestsuite("samba4.sam.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN'])
@@ -519,7 +578,7 @@ plantestsuite("samba4.blackbox.setpassword.py", "none", ["PYTHON=%s" % python, o
 plantestsuite("samba4.blackbox.newuser.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_newuser.sh"), '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.group.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_group.sh"), '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.spn.py(ad_dc_ntvfs:local)", "ad_dc_ntvfs:local", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_spn.sh"), '$PREFIX/ad_dc_ntvfs'])
-plantestsuite_loadlist("samba4.ldap.bind(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(srcdir(), "auth/credentials/tests/bind.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '$LOADLIST', '$LISTOPT'])
+plantestsuite_loadlist("samba4.ldap.bind(fl2008r2dc)", "fl2008r2dc", [python, os.path.join(srcdir(), "auth/credentials/tests/bind.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '$LOADLIST', '$LISTOPT'])
 
 # This makes sure we test the rid allocation code
 t = "rpc.samr.large-dc"
diff --git a/source4/smb_server/smb/negprot.c b/source4/smb_server/smb/negprot.c
index cdfa2b4..dfcc1a2 100644
--- a/source4/smb_server/smb/negprot.c
+++ b/source4/smb_server/smb/negprot.c
@@ -387,8 +387,10 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
 		nt_status = cli_credentials_set_machine_account(server_credentials, req->smb_conn->lp_ctx);
 		if (!NT_STATUS_IS_OK(nt_status)) {
 			DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(nt_status)));
-			talloc_free(server_credentials);
-			server_credentials = NULL;
+			/*
+			 * We keep the server_credentials as anonymous
+			 * this is required for the spoolss.notify test
+			 */
 		}
 
 		nt_status = samba_server_gensec_start(req,
diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index 4ebc0c4..e06853a 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -263,6 +263,7 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 	const char *remote_machine = NULL;
 	struct tevent_req *subreq;
 	struct sesssetup_context *state;
+	bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
 
 	sess->nt1.out.vuid = 0;
 	sess->nt1.out.action = 0;
@@ -338,6 +339,15 @@ static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
 	user_info->password.response.nt = sess->nt1.in.password2;
 	user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
 
+	if (!allow_raw && user_info->password.response.nt.length >= 48) {
+		/*
+		 * NTLMv2_RESPONSE has at least 48 bytes
+		 * and should only be supported via NTLMSSP.
+		 */
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto failed;
+	}
+
 	subreq = auth_check_password_send(state,
 					  req->smb_conn->connection->event.ctx,
 					  state->auth_context,
diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c
index b48b170..addd278 100644
--- a/source4/smb_server/smb2/negprot.c
+++ b/source4/smb_server/smb2/negprot.c
@@ -49,8 +49,10 @@ static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB *
 	nt_status = cli_credentials_set_machine_account(server_credentials, req->smb_conn->lp_ctx);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(nt_status)));
-		talloc_free(server_credentials);
-		server_credentials = NULL;
+		/*
+		 * We keep the server_credentials as anonymous
+		 * this is required for the spoolss.notify test
+		 */
 	}
 
 	req->smb_conn->negotiate.server_credentials = talloc_steal(req->smb_conn, server_credentials);
@@ -145,6 +147,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
 
 	switch (signing_setting) {
 	case SMB_SIGNING_DEFAULT:
+	case SMB_SIGNING_IPC_DEFAULT:
 		smb_panic(__location__);
 		break;
 	case SMB_SIGNING_OFF:
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index d4b8de6..5e261a2 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -201,14 +201,6 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
 	   set SMB2_NEGOTIATE_SIGNING_REQUIRED */
 	if (io->smb2.in.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
 		smb_sess->smb2_signing.required = true;
-	} else if (req->smb_conn->smb2_signing_required) {
-		/*
-		 * if required signing was negotiates in SMB2 Negotiate
-		 * then the client made an error not using it here
-		 */
-		DEBUG(1, ("SMB2 signing required on the connection but not used on session\n"));
-		req->status = NT_STATUS_FOOBAR;
-		goto failed;
 	}
 
 	/* disable receipt of more packets on this socket until we've
diff --git a/source4/torture/basic/base.c b/source4/torture/basic/base.c
index 6a792b2..01ac170 100644
--- a/source4/torture/basic/base.c
+++ b/source4/torture/basic/base.c
@@ -371,6 +371,7 @@ static bool run_negprot_nowait(struct torture_context *tctx)
 		struct tevent_req *req;
 		req = smb_raw_negotiate_send(cli, tctx->ev,
 					     cli->transport,
+					     PROTOCOL_CORE,
 					     PROTOCOL_NT1);
 		tevent_loop_once(tctx->ev);
 		if (!tevent_req_is_in_progress(req)) {
@@ -1527,6 +1528,7 @@ static bool torture_chkpath_test(struct torture_context *tctx,
 static bool torture_samba3_errorpaths(struct torture_context *tctx)
 {
 	bool nt_status_support;
+	bool client_ntlmv2_auth;
 	struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
 	bool result = false;
 	int fnum;
@@ -1536,18 +1538,27 @@ static bool torture_samba3_errorpaths(struct torture_context *tctx)
 	NTSTATUS status;
 
 	nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
+	client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(tctx->lp_ctx);
 
 	if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
 		torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
 		goto fail;
 	}
+	if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "yes")) {
+		torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = yes'\n");
+		goto fail;
+	}
 
 	if (!torture_open_connection(&cli_nt, tctx, 0)) {
 		goto fail;
 	}
 
 	if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
-		torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
+		torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = no'\n");
+		goto fail;
+	}
+	if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "no")) {
+		torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = no'\n");
 		goto fail;
 	}
 
@@ -1557,7 +1568,12 @@ static bool torture_samba3_errorpaths(struct torture_context *tctx)
 
 	if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
 			    nt_status_support ? "yes":"no")) {
-		torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support = yes'");
+		torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support'");
+		goto fail;
+	}
+	if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth",
+			       client_ntlmv2_auth ? "yes":"no")) {
+		torture_result(tctx, TORTURE_FAIL, "Could not reset 'client ntlmv2 auth'");
 		goto fail;
 	}
 
diff --git a/source4/torture/ndr/ntlmssp.c b/source4/torture/ndr/ntlmssp.c
index 36127ce..aeac26f 100644
--- a/source4/torture/ndr/ntlmssp.c
+++ b/source4/torture/ndr/ntlmssp.c
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    test suite for ntlmssp ndr operations
 
-   Copyright (C) Guenther Deschner 2010
+   Copyright (C) Guenther Deschner 2010,2015
 
    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
@@ -33,10 +33,26 @@ static const uint8_t ntlmssp_NEGOTIATE_MESSAGE_data[] = {
 static bool ntlmssp_NEGOTIATE_MESSAGE_check(struct torture_context *tctx,
 					    struct NEGOTIATE_MESSAGE *r)
 {
+	torture_assert_str_equal(tctx, r->Signature, "NTLMSSP", "Signature");
+	torture_assert_int_equal(tctx, r->MessageType, NtLmNegotiate, "MessageType");
+	torture_assert_int_equal(tctx, r->NegotiateFlags, 0xe2088297, "NegotiateFlags");
+	torture_assert_int_equal(tctx, r->DomainNameLen, 0, "DomainNameLen");
+	torture_assert_int_equal(tctx, r->DomainNameMaxLen, 0, "DomainNameMaxLen");
+	torture_assert(tctx, r->DomainName == NULL, "DomainName");
+	torture_assert_int_equal(tctx, r->WorkstationLen, 0, "WorkstationLen");
+	torture_assert_int_equal(tctx, r->WorkstationMaxLen, 0, "WorkstationMaxLen");
+	torture_assert(tctx, r->Workstation == NULL, "Workstation");
+	torture_assert_int_equal(tctx, r->Version.version.ProductMajorVersion, NTLMSSP_WINDOWS_MAJOR_VERSION_6, "ProductMajorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductMinorVersion, NTLMSSP_WINDOWS_MINOR_VERSION_1, "ProductMinorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductBuild, 0x1db0, "ProductBuild");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[0], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[1], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[2], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.NTLMRevisionCurrent, NTLMSSP_REVISION_W2K3, "NTLMRevisionCurrent");
+
 	return true;
 }
 
-#if 0
 static const uint8_t ntlmssp_CHALLENGE_MESSAGE_data[] = {
 	0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
 	0x0a, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x00, 0x00, 0x95, 0x82, 0x89, 0xe2,
@@ -59,6 +75,48 @@ static const uint8_t ntlmssp_CHALLENGE_MESSAGE_data[] = {
 static bool ntlmssp_CHALLENGE_MESSAGE_check(struct torture_context *tctx,
 					    struct CHALLENGE_MESSAGE *r)
 {
+	uint8_t chal[8] = { 0xed, 0xc8, 0x2b, 0x7d, 0x2e, 0xd7, 0xd0, 0xd9 };
+	uint8_t data[8] = { 0 };
+
+	torture_assert_str_equal(tctx, r->Signature, "NTLMSSP", "Signature");
+	torture_assert_int_equal(tctx, r->MessageType, NtLmChallenge, "MessageType");
+	torture_assert_int_equal(tctx, r->TargetNameLen, 10, "TargetNameLen");
+	torture_assert_int_equal(tctx, r->TargetNameMaxLen, 10, "TargetNameMaxLen");
+	torture_assert_str_equal(tctx, r->TargetName, "SAMBA", "TargetName");
+	torture_assert_int_equal(tctx, r->NegotiateFlags, 0xe2898295, "NegotiateFlags");
+	torture_assert_mem_equal(tctx, r->ServerChallenge, chal, 8, "ServerChallenge");
+	torture_assert_mem_equal(tctx, r->Reserved, data, 8, "Reserved");
+	torture_assert_int_equal(tctx, r->TargetInfoLen, 120, "TargetInfoLen");
+	torture_assert_int_equal(tctx, r->TargetInfoMaxLen, 120, "TargetInfoMaxLen");
+	torture_assert_int_equal(tctx, r->TargetInfo->count, 5, "TargetInfo->count");
+
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[0].AvId, MsvAvNbDomainName, "AvId");
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[0].AvLen, 10, "AvLen");
+	torture_assert_str_equal(tctx, r->TargetInfo->pair[0].Value.AvNbDomainName, "SAMBA", "AvNbDomainName");
+
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[1].AvId, MsvAvNbComputerName, "AvId");
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[1].AvLen, 16, "AvLen");
+	torture_assert_str_equal(tctx, r->TargetInfo->pair[1].Value.AvNbComputerName, "MTHELENA", "AvNbComputerName");
+
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[2].AvId, MsvAvDnsDomainName, "AvId");
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[2].AvLen, 28, "AvLen");
+	torture_assert_str_equal(tctx, r->TargetInfo->pair[2].Value.AvDnsDomainName, "ber.redhat.com", "AvDnsDomainName");
+
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[3].AvId, MsvAvDnsComputerName, "AvId");
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[3].AvLen, 46, "AvLen");
+	torture_assert_str_equal(tctx, r->TargetInfo->pair[3].Value.AvDnsComputerName, "mthelena.ber.redhat.com", "AvDnsComputerName");
+
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[4].AvId, MsvAvEOL, "AvId");
+	torture_assert_int_equal(tctx, r->TargetInfo->pair[4].AvLen, 0, "AvLen");
+
+	torture_assert_int_equal(tctx, r->Version.version.ProductMajorVersion, NTLMSSP_WINDOWS_MAJOR_VERSION_6, "ProductMajorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductMinorVersion, NTLMSSP_WINDOWS_MINOR_VERSION_1, "ProductMinorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductBuild, 0, "ProductBuild");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[0], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[1], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[2], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.NTLMRevisionCurrent, NTLMSSP_REVISION_W2K3, "NTLMRevisionCurrent");
+
 	return true;
 }
 
@@ -106,18 +164,133 @@ static const uint8_t ntlmssp_AUTHENTICATE_MESSAGE_data[] = {
 static bool ntlmssp_AUTHENTICATE_MESSAGE_check(struct torture_context *tctx,
 					       struct AUTHENTICATE_MESSAGE *r)
 {
+	uint8_t lm_challenge_response[24] = { 0 };
+	struct NTLMv2_RESPONSE v2;
+	struct AV_PAIR_LIST AvPairs;
+	uint8_t Response[16] = {
+		0x38, 0xcf, 0xfb, 0x39, 0x5a, 0xb3, 0x4c, 0x58,
+		0x86, 0x35, 0xa3, 0xe7, 0x1e, 0x00, 0x98, 0x43
+	};
+	uint8_t ChallengeFromClient[8] = {
+		0x3c, 0x21, 0x0a, 0xe9, 0xde, 0x61, 0xc0, 0x7e
+	};
+	uint8_t MachineId[32] = {
+		0x0a, 0xfd, 0x3b, 0x2c, 0xad, 0x43, 0x46, 0x8b,
+		0x49, 0x01, 0x6c, 0xa5, 0xf3, 0xbc, 0xd2, 0x13,
+		0xbb, 0x70, 0xe2, 0x65, 0x96, 0xba, 0x0d, 0x8d,
+		0x5d, 0x31, 0xe6, 0x47, 0x94, 0x61, 0xed, 0x28
+	};
+	uint8_t EncryptedRandomSessionKey[16] = {
+		0xA4, 0x23, 0xD4, 0x5C, 0x16, 0x52, 0x8D, 0x56,
+		0x34, 0x2D, 0x1C, 0xFF, 0x86, 0x17, 0xC9, 0x4F
+	};
+
+	torture_assert_str_equal(tctx, r->Signature, "NTLMSSP", "Signature");
+	torture_assert_int_equal(tctx, r->MessageType, NtLmAuthenticate, "MessageType");
+	torture_assert_int_equal(tctx, r->LmChallengeResponseLen, 24, "LmChallengeResponseLen");
+	torture_assert_int_equal(tctx, r->LmChallengeResponseMaxLen, 24, "LmChallengeResponseMaxLen");
+	torture_assert_mem_equal(tctx, r->LmChallengeResponse->v1.Response, lm_challenge_response, 24, "LmChallengeResponse");
+
+	torture_assert_int_equal(tctx, r->NtChallengeResponseLen, 270, "NtChallengeResponseLen");
+	torture_assert_int_equal(tctx, r->NtChallengeResponseMaxLen, 270, "NtChallengeResponseMaxLen");
+
+	v2 = r->NtChallengeResponse->v2;
+
+	torture_assert_mem_equal(tctx, v2.Response, Response, 16, "v2.Response");
+	torture_assert_int_equal(tctx, v2.Challenge.RespType, 1, "RespType");
+	torture_assert_int_equal(tctx, v2.Challenge.HiRespType, 1, "HiRespType");
+	torture_assert_int_equal(tctx, v2.Challenge.Reserved1, 0, "Reserved1");
+	torture_assert_int_equal(tctx, v2.Challenge.Reserved2, 0, "Reserved2");
+	/* 	TimeStamp                : Tue Sep 14 17:06:53 2010 CEST */
+	torture_assert_mem_equal(tctx, v2.Challenge.ChallengeFromClient, ChallengeFromClient, 8, "v2.Challenge.ChallengeFromClient");
+	torture_assert_int_equal(tctx, v2.Challenge.Reserved3, 0, "Reserved3");
+
+	AvPairs = v2.Challenge.AvPairs;
+
+	torture_assert_int_equal(tctx, AvPairs.count, 8, "AvPairs.count");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[0].AvId, MsvAvNbDomainName, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[0].AvLen, 10, "AvLen");
+	torture_assert_str_equal(tctx, AvPairs.pair[0].Value.AvNbDomainName, "SAMBA", "Value.AvNbDomainName");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[1].AvId, MsvAvNbComputerName, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[1].AvLen, 16, "AvLen");
+	torture_assert_str_equal(tctx, AvPairs.pair[1].Value.AvNbComputerName, "MTHELENA", "Value.AvNbComputerName");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[2].AvId, MsvAvDnsDomainName, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[2].AvLen, 28, "AvLen");
+	torture_assert_str_equal(tctx, AvPairs.pair[2].Value.AvDnsDomainName, "ber.redhat.com", "Value.AvDnsDomainName");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[3].AvId, MsvAvDnsComputerName, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[3].AvLen, 46, "AvLen");
+	torture_assert_str_equal(tctx, AvPairs.pair[3].Value.AvDnsComputerName, "mthelena.ber.redhat.com", "Value.AvDnsComputerName");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[4].AvId, MsvAvSingleHost, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].AvLen, 48, "AvLen");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.Size, 48, "Value.AvSingleHost.Size");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.Z4, 0, "Value.AvSingleHost.Z4");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.token_info.Flags, 0, "Value.AvSingleHost.token_info.Flags");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.token_info.TokenIL, 0x00003000, "Value.AvSingleHost.token_info.TokenIL");
+	torture_assert_mem_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.token_info.MachineId, MachineId, 32, "Value.AvSingleHost.token_info.MachineId");
+	torture_assert_int_equal(tctx, AvPairs.pair[4].Value.AvSingleHost.remaining.length, 0, "Value.AvSingleHost.remaining.length");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[5].AvId, MsvChannelBindings, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[5].AvLen, 16, "AvLen");
+	torture_assert_mem_equal(tctx, AvPairs.pair[5].Value.ChannelBindings, lm_challenge_response, 16, "Value.ChannelBindings");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[6].AvId, MsvAvTargetName, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[6].AvLen, 26, "AvLen");
+	torture_assert_str_equal(tctx, AvPairs.pair[6].Value.AvTargetName, "cifs/mthelena", "Value.AvTargetName");
+
+	torture_assert_int_equal(tctx, AvPairs.pair[7].AvId, MsvAvEOL, "AvId");
+	torture_assert_int_equal(tctx, AvPairs.pair[7].AvLen, 0, "AvLen");
+
+	torture_assert_int_equal(tctx, r->DomainNameLen, 14, "DomainNameLen");
+	torture_assert_int_equal(tctx, r->DomainNameMaxLen, 14, "DomainNameMaxLen");
+	torture_assert_str_equal(tctx, r->DomainName, "W2K8DOM", "DomainName");
+
+	torture_assert_int_equal(tctx, r->UserNameLen, 26, "UserNameLen");
+	torture_assert_int_equal(tctx, r->UserNameMaxLen, 26, "UserNameMaxLen");
+	torture_assert_str_equal(tctx, r->UserName, "Administrator", "UserName");
+
+	torture_assert_int_equal(tctx, r->WorkstationLen, 12, "WorkstationLen");
+	torture_assert_int_equal(tctx, r->WorkstationMaxLen, 12, "WorkstationMaxLen");
+	torture_assert_str_equal(tctx, r->Workstation, "W2K8R2", "Workstation");
+
+	torture_assert_int_equal(tctx, r->EncryptedRandomSessionKeyLen, 16, "EncryptedRandomSessionKeyLen");
+	torture_assert_int_equal(tctx, r->EncryptedRandomSessionKeyMaxLen, 16, "EncryptedRandomSessionKeyMaxLen");
+	torture_assert_mem_equal(tctx, r->EncryptedRandomSessionKey->data, EncryptedRandomSessionKey, 16, "EncryptedRandomSessionKeyMaxLen");
+
+	torture_assert_int_equal(tctx, r->NegotiateFlags, 0xe2888215, "NegotiateFlags");
+
+	torture_assert_int_equal(tctx, r->Version.version.ProductMajorVersion, NTLMSSP_WINDOWS_MAJOR_VERSION_6, "ProductMajorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductMinorVersion, NTLMSSP_WINDOWS_MINOR_VERSION_1, "ProductMinorVersion");
+	torture_assert_int_equal(tctx, r->Version.version.ProductBuild, 0x1db0, "ProductBuild");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[0], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[1], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.Reserved[2], 0x00, "Reserved");
+	torture_assert_int_equal(tctx, r->Version.version.NTLMRevisionCurrent, NTLMSSP_REVISION_W2K3, "NTLMRevisionCurrent");
+
 	return true;
 }
-#endif
 
 struct torture_suite *ndr_ntlmssp_suite(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite = torture_suite_create(ctx, "ntlmssp");
 
 	torture_suite_add_ndr_pull_test(suite, NEGOTIATE_MESSAGE, ntlmssp_NEGOTIATE_MESSAGE_data, ntlmssp_NEGOTIATE_MESSAGE_check);
-#if 0
 	torture_suite_add_ndr_pull_test(suite, CHALLENGE_MESSAGE, ntlmssp_CHALLENGE_MESSAGE_data, ntlmssp_CHALLENGE_MESSAGE_check);
 	torture_suite_add_ndr_pull_test(suite, AUTHENTICATE_MESSAGE, ntlmssp_AUTHENTICATE_MESSAGE_data, ntlmssp_AUTHENTICATE_MESSAGE_check);
-#endif
+
+	torture_suite_add_ndr_pullpush_test(suite,
+					    NEGOTIATE_MESSAGE,
+					    data_blob_const(ntlmssp_NEGOTIATE_MESSAGE_data, sizeof(ntlmssp_NEGOTIATE_MESSAGE_data)),
+					    ntlmssp_NEGOTIATE_MESSAGE_check);
+
+	torture_suite_add_ndr_pullpush_test(suite,
+					    CHALLENGE_MESSAGE,
+					    data_blob_const(ntlmssp_CHALLENGE_MESSAGE_data, sizeof(ntlmssp_CHALLENGE_MESSAGE_data)),
+					    ntlmssp_CHALLENGE_MESSAGE_check);
+
 	return suite;
 }
diff --git a/source4/torture/raw/samba3misc.c b/source4/torture/raw/samba3misc.c
index f40a4f1..dc460b9 100644
--- a/source4/torture/raw/samba3misc.c
+++ b/source4/torture/raw/samba3misc.c
@@ -440,22 +440,29 @@ bool torture_samba3_badpath(struct torture_context *torture)
 	bool ret = true;
 	TALLOC_CTX *mem_ctx;
 	bool nt_status_support;
+	bool client_ntlmv2_auth;
 
 	torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed");
 
 	nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);
+	client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(torture->lp_ctx);
 
 	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");
+	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "yes"), ret, fail, "Could not set 'client ntlmv2 auth = yes'\n");
 
 	torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n");
 
 	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");
+	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "no"), ret, fail, "Could not set 'client ntlmv2 auth = no'\n");
 
 	torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n");
 
 	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
 						       nt_status_support ? "yes":"no"), 
 			    ret, fail, "Could not set 'nt status support' back to where it was\n");
+	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth",
+						       client_ntlmv2_auth ? "yes":"no"),
+			    ret, fail, "Could not set 'client ntlmv2 auth' back to where it was\n");
 
 	torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory");
 
diff --git a/source4/torture/rpc/backupkey.c b/source4/torture/rpc/backupkey.c
index a3b8aaa..a4d36aa 100644
--- a/source4/torture/rpc/backupkey.c
+++ b/source4/torture/rpc/backupkey.c
@@ -1545,8 +1545,10 @@ static bool test_ServerWrap_encrypt_decrypt_manual(struct torture_context *tctx,
 						   struct bkrp_server_side_wrapped *server_side_wrapped,
 						   enum test_wrong wrong)
 {
-        struct dcerpc_pipe *lsa_p;
-	struct dcerpc_binding_handle *lsa_b;
+	char *lsa_binding_string = NULL;
+	struct dcerpc_binding *lsa_binding = NULL;
+	struct dcerpc_pipe *lsa_p = NULL;
+	struct dcerpc_binding_handle *lsa_b = NULL;
 	struct lsa_OpenSecret r_secret;
 	struct lsa_QuerySecret r_query_secret;
 	struct policy_handle *handle, sec_handle;
@@ -1571,9 +1573,20 @@ static bool test_ServerWrap_encrypt_decrypt_manual(struct torture_context *tctx,
 	ZERO_STRUCT(r_query_secret);
 
 	/* Now read BCKUPKEY_P and prove we can do a matching decrypt and encrypt */
-	
+
+	/* lsa_OpenSecret only works with ncacn_np and AUTH_LEVEL_NONE */
+	lsa_binding_string = talloc_asprintf(tctx, "ncacn_np:%s",
+				torture_setting_string(tctx, "host", NULL));
+	torture_assert(tctx, lsa_binding_string != NULL, "lsa_binding_string");
+
+	torture_assert_ntstatus_ok(tctx,
+		dcerpc_parse_binding(tctx, lsa_binding_string, &lsa_binding),
+		"Failed to parse dcerpc binding");
+
 	torture_assert_ntstatus_ok(tctx,
-				   torture_rpc_connection(tctx, &lsa_p, &ndr_table_lsarpc),
+				   dcerpc_pipe_connect_b(tctx, &lsa_p,
+					lsa_binding, &ndr_table_lsarpc,
+					cmdline_credentials, tctx->ev, tctx->lp_ctx),
 				   "Opening LSA pipe");
 	lsa_b = lsa_p->binding_handle;
 
diff --git a/source4/torture/rpc/forest_trust.c b/source4/torture/rpc/forest_trust.c
index ccb19ed..aae745f 100644
--- a/source4/torture/rpc/forest_trust.c
+++ b/source4/torture/rpc/forest_trust.c
@@ -516,7 +516,8 @@ static bool test_validate_trust(struct torture_context *tctx,
 	NTSTATUS status;
 	struct cli_credentials *credentials;
 	struct dcerpc_binding *b;
-	struct dcerpc_pipe *p;
+	struct dcerpc_pipe *p1 = NULL;
+	struct dcerpc_pipe *p = NULL;
 
 	struct netr_GetForestTrustInformation fr;
 	struct lsa_ForestTrustInformation *forest_trust_info;
@@ -547,7 +548,7 @@ static bool test_validate_trust(struct torture_context *tctx,
 					trusted_dom_name, CRED_SPECIFIED);
 	cli_credentials_set_secure_channel_type(credentials, SEC_CHAN_DOMAIN);
 
-	status = dcerpc_pipe_connect_b(tctx, &p, b,
+	status = dcerpc_pipe_connect_b(tctx, &p1, b,
 				       &ndr_table_netlogon, credentials,
 				       tctx->ev, tctx->lp_ctx);
 
@@ -559,11 +560,16 @@ static bool test_validate_trust(struct torture_context *tctx,
 		return false;
 	}
 
-	if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
+	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 				    credentials, &creds)) {
 		torture_comment(tctx, "test_SetupCredentials3 failed.\n");
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		torture_comment(tctx, "test_SetupCredentialsPipe failed.\n");
+		return false;
+	}
 
 	netlogon_creds_client_authenticator(creds, &a);
 
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 44cdbdc..bff0926 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -4134,7 +4134,8 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p,
 	struct netr_Authenticator req_auth;
 	struct netr_Authenticator rep_auth;
 	struct netr_ServerPasswordSet2 s;
-	struct dcerpc_pipe *p2;
+	struct dcerpc_pipe *p1 = NULL;
+	struct dcerpc_pipe *p2 = NULL;
 	NTSTATUS status;
 	bool ok;
 	int rc;
@@ -4223,18 +4224,25 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p,
 	status = dcerpc_parse_binding(tctx, binding, &b2);
 	torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
 
-	status = dcerpc_pipe_connect_b(tctx, &p2, b2,
+	status = dcerpc_pipe_connect_b(tctx, &p1, b2,
 				       &ndr_table_netlogon,
 				       cli_credentials_init_anon(tctx),
 				       tctx->ev, tctx->lp_ctx);
 	torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b");
 
-	ok = check_pw_with_ServerAuthenticate3(p2, tctx,
+	ok = check_pw_with_ServerAuthenticate3(p1, tctx,
 					       NETLOGON_NEG_AUTH2_ADS_FLAGS,
 					       server_name,
 					       incoming_creds, &creds);
 	torture_assert_int_equal(tctx, ok, expected_result,
 				 "check_pw_with_ServerAuthenticate3");
+	if (expected_result == true) {
+		ok = test_SetupCredentialsPipe(p1, tctx, incoming_creds, creds,
+					       DCERPC_SIGN | DCERPC_SEAL, &p2);
+		torture_assert_int_equal(tctx, ok, true,
+					 "test_SetupCredentialsPipe");
+	}
+	TALLOC_FREE(p1);
 
 	if (trusted->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
 #ifdef SAMBA4_USES_HEIMDAL
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 9f8e8f1..c8e864d 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -359,6 +359,35 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
 	return true;
 }
 
+bool test_SetupCredentialsPipe(const struct dcerpc_pipe *p1,
+			       struct torture_context *tctx,
+			       struct cli_credentials *machine_credentials,
+			       struct netlogon_creds_CredentialState *creds,
+			       uint32_t additional_flags,
+			       struct dcerpc_pipe **_p2)
+{
+	NTSTATUS status;
+	struct dcerpc_binding *b2 = NULL;
+	struct dcerpc_pipe *p2 = NULL;
+
+	b2 = dcerpc_binding_dup(tctx, p1->binding);
+	torture_assert(tctx, b2 != NULL, "dcerpc_binding_dup");
+	dcerpc_binding_set_flags(b2,
+				 DCERPC_SCHANNEL | additional_flags,
+				 DCERPC_AUTH_OPTIONS);
+
+	cli_credentials_set_netlogon_creds(machine_credentials, creds);
+	status = dcerpc_pipe_connect_b(tctx, &p2, b2,
+				       &ndr_table_netlogon,
+				       machine_credentials,
+				       tctx->ev, tctx->lp_ctx);
+	cli_credentials_set_netlogon_creds(machine_credentials, NULL);
+	torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b schannel");
+
+	*_p2 = p2;
+	return true;
+}
+
 /*
   try a change password for our machine account
 */
@@ -436,7 +465,7 @@ static bool test_SetPassword(struct torture_context *tctx,
   try a change password for our machine account
 */
 static bool test_SetPassword_flags(struct torture_context *tctx,
-				   struct dcerpc_pipe *p,
+				   struct dcerpc_pipe *p1,
 				   struct cli_credentials *machine_credentials,
 				   uint32_t negotiate_flags)
 {
@@ -445,14 +474,20 @@ static bool test_SetPassword_flags(struct torture_context *tctx,
 	struct netlogon_creds_CredentialState *creds;
 	struct netr_Authenticator credential, return_authenticator;
 	struct samr_Password new_password;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
-	if (!test_SetupCredentials2(p, tctx, negotiate_flags,
+	if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
 				    machine_credentials,
 				    cli_credentials_get_secure_channel_type(machine_credentials),
 				    &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
 
 	r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 	r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
@@ -532,7 +567,7 @@ static DATA_BLOB netlogon_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
   try a change password for our machine account
 */
 static bool test_SetPassword2_with_flags(struct torture_context *tctx,
-					 struct dcerpc_pipe *p,
+					 struct dcerpc_pipe *p1,
 					 struct cli_credentials *machine_credentials,
 					 uint32_t flags)
 {
@@ -544,11 +579,19 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx,
 	struct samr_Password nt_hash;
 	struct netr_Authenticator credential, return_authenticator;
 	struct netr_CryptPassword new_password;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
-	if (!test_SetupCredentials2(p, tctx, flags, machine_credentials, cli_credentials_get_secure_channel_type(machine_credentials), &creds)) {
+	if (!test_SetupCredentials2(p1, tctx, flags, machine_credentials,
+				    cli_credentials_get_secure_channel_type(machine_credentials),
+				    &creds)) {
+		return false;
+	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
 		return false;
 	}
+	b = p->binding_handle;
 
 	r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 	r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
@@ -839,6 +882,7 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
 	status = cli_credentials_get_ntlm_response(cmdline_credentials, tctx,
 						   &flags,
 						   chal,
+						   NULL, /* server_timestamp */
 						   names_blob,
 						   &lm_resp, &nt_resp,
 						   NULL, NULL);
@@ -2507,7 +2551,7 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
 }
 
 static bool test_netr_GetForestTrustInformation(struct torture_context *tctx,
-						struct dcerpc_pipe *p,
+						struct dcerpc_pipe *p1,
 						struct cli_credentials *machine_credentials)
 {
 	struct netr_GetForestTrustInformation r;
@@ -2515,12 +2559,18 @@ static bool test_netr_GetForestTrustInformation(struct torture_context *tctx,
 	struct netr_Authenticator a;
 	struct netr_Authenticator return_authenticator;
 	struct lsa_ForestTrustInformation *forest_trust_info;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
-	if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
 				    machine_credentials, &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
 
 	netlogon_creds_client_authenticator(creds, &a);
 
@@ -3343,7 +3393,7 @@ static bool test_netr_DsRAddressToSitenamesExW(struct torture_context *tctx,
 }
 
 static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx,
-					       struct dcerpc_pipe *p,
+					       struct dcerpc_pipe *p1,
 					       struct cli_credentials *machine_credentials,
 					       uint32_t negotiate_flags)
 {
@@ -3356,14 +3406,20 @@ static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx,
 	struct netr_TrustInfo *trust_info;
 
 	struct netlogon_creds_CredentialState *creds;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
 	struct samr_Password nt_hash;
 
-	if (!test_SetupCredentials3(p, tctx, negotiate_flags,
+	if (!test_SetupCredentials3(p1, tctx, negotiate_flags,
 				    machine_credentials, &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
 
 	netlogon_creds_client_authenticator(creds, &a);
 
@@ -3413,7 +3469,7 @@ static bool test_netr_ServerGetTrustInfo_AES(struct torture_context *tctx,
 }
 
 static bool test_GetDomainInfo(struct torture_context *tctx,
-			       struct dcerpc_pipe *p,
+			       struct dcerpc_pipe *p1,
 			       struct cli_credentials *machine_credentials)
 {
 	struct netr_LogonGetDomainInfo r;
@@ -3436,14 +3492,20 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
 	char **spns = NULL;
 	int num_spns = 0;
 	char *temp_str;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
 	torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n");
 
-	if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
 				    machine_credentials, &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
 
 	/* We won't double-check this when we are over 'local' transports */
 	if (dcerpc_server_name(p)) {
@@ -3868,7 +3930,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
 }
 
 static bool test_GetDomainInfo_async(struct torture_context *tctx,
-				     struct dcerpc_pipe *p,
+				     struct dcerpc_pipe *p1,
 				     struct cli_credentials *machine_credentials)
 {
 	NTSTATUS status;
@@ -3882,6 +3944,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx,
 	int i;
 	union netr_WorkstationInfo query;
 	union netr_DomainInfo info;
+	struct dcerpc_pipe *p = NULL;
 
 	torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
 
@@ -3889,6 +3952,10 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx,
 				    machine_credentials, &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
 
 	ZERO_STRUCT(r);
 	r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
@@ -3962,7 +4029,7 @@ static bool test_ManyGetDCName(struct torture_context *tctx,
 	int i;
 
 	if (p->conn->transport.transport != NCACN_NP) {
-		return true;
+		torture_skip(tctx, "test_ManyGetDCName works only with NCACN_NP");
 	}
 
 	torture_comment(tctx, "Torturing GetDCName\n");
diff --git a/source4/torture/rpc/netlogon.h b/source4/torture/rpc/netlogon.h
index f2f2a6f..a4ab8f0 100644
--- a/source4/torture/rpc/netlogon.h
+++ b/source4/torture/rpc/netlogon.h
@@ -28,3 +28,10 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
 			    uint32_t negotiate_flags,
 			    struct cli_credentials *machine_credentials,
 			    struct netlogon_creds_CredentialState **creds_out);
+
+bool test_SetupCredentialsPipe(const struct dcerpc_pipe *p1,
+			       struct torture_context *tctx,
+			       struct cli_credentials *machine_credentials,
+			       struct netlogon_creds_CredentialState *creds,
+			       uint32_t additional_flags,
+			       struct dcerpc_pipe **_p2);
diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c
index 196d9f8..e880f80 100644
--- a/source4/torture/rpc/remote_pac.c
+++ b/source4/torture/rpc/remote_pac.c
@@ -118,7 +118,7 @@ static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx,
 /* Also happens to be a really good one-step verfication of our Kerberos stack */
 
 static bool test_PACVerify(struct torture_context *tctx,
-			   struct dcerpc_pipe *p,
+			   struct dcerpc_pipe *p1,
 			   struct cli_credentials *credentials,
 			   enum netr_SchannelType secure_channel_type,
 			   const char *test_machine_name,
@@ -151,7 +151,8 @@ static bool test_PACVerify(struct torture_context *tctx,
 	struct auth_session_info *session_info;
 	struct pac_data *pac_data;
 
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 	TALLOC_CTX *tmp_ctx = talloc_new(tctx);
 	torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
 
@@ -175,11 +176,16 @@ static bool test_PACVerify(struct torture_context *tctx,
 						    credentials);
 	torture_assert(tctx, server_creds, "Failed to copy of credentials");
 
-	if (!test_SetupCredentials2(p, tctx, negotiate_flags,
+	if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
 				    server_creds, secure_channel_type,
 				    &creds)) {
 		return false;
 	}
+	if (!test_SetupCredentialsPipe(p1, tctx, server_creds, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
 
 	auth_context = talloc_zero(tmp_ctx, struct auth4_context);
 	torture_assert(tctx, auth_context != NULL, "talloc_new() failed");
@@ -525,14 +531,15 @@ 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 */
 static bool test_S2U4Self(struct torture_context *tctx,
-			  struct dcerpc_pipe *p,
+			  struct dcerpc_pipe *p1,
 			  struct cli_credentials *credentials,
 			  enum netr_SchannelType secure_channel_type,
 			  const char *test_machine_name,
 			  uint32_t negotiate_flags)
 {
 	NTSTATUS status;
-	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct dcerpc_pipe *p = NULL;
+	struct dcerpc_binding_handle *b = NULL;
 
 	struct netr_LogonSamLogon r;
 
@@ -584,6 +591,17 @@ static bool test_S2U4Self(struct torture_context *tctx,
 						    credentials);
 	torture_assert(tctx, server_creds, "Failed to copy of credentials");
 
+	if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
+				    server_creds, secure_channel_type,
+				    &creds)) {
+		return false;
+	}
+	if (!test_SetupCredentialsPipe(p1, tctx, server_creds, creds,
+				       DCERPC_SIGN | DCERPC_SEAL, &p)) {
+		return false;
+	}
+	b = p->binding_handle;
+
 	auth_context = talloc_zero(tmp_ctx, struct auth4_context);
 	torture_assert(tctx, auth_context != NULL, "talloc_new() failed");
 
@@ -711,12 +729,13 @@ static bool test_S2U4Self(struct torture_context *tctx,
 	chal = data_blob_const(ninfo.challenge,
 			       sizeof(ninfo.challenge));
 
-	names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(client_creds),
-						cli_credentials_get_domain(client_creds));
+	names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(server_creds),
+						cli_credentials_get_domain(server_creds));
 
 	status = cli_credentials_get_ntlm_response(client_creds, tctx,
 						   &flags,
 						   chal,
+						   NULL, /* server_timestamp */
 						   names_blob,
 						   &lm_resp, &nt_resp,
 						   NULL, NULL);
@@ -744,12 +763,6 @@ static bool test_S2U4Self(struct torture_context *tctx,
 	r.out.validation = &validation;
 	r.out.authoritative = &authoritative;
 
-	if (!test_SetupCredentials2(p, tctx, negotiate_flags,
-				    server_creds, secure_channel_type,
-				    &creds)) {
-		return false;
-	}
-
 	ZERO_STRUCT(auth2);
 	netlogon_creds_client_authenticator(creds, &auth);
 
diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c
index ade4a40..9e521cd 100644
--- a/source4/torture/rpc/samba3rpc.c
+++ b/source4/torture/rpc/samba3rpc.c
@@ -1189,10 +1189,10 @@ static bool schan(struct torture_context *tctx,
 		generate_random_buffer(chal.data, chal.length);
 		names_blob = NTLMv2_generate_names_blob(
 			mem_ctx,
-			cli_credentials_get_workstation(user_creds),
-			cli_credentials_get_domain(user_creds));
+			cli_credentials_get_workstation(wks_creds),
+			cli_credentials_get_domain(wks_creds));
 		status = cli_credentials_get_ntlm_response(
-			user_creds, mem_ctx, &flags, chal, names_blob,
+			user_creds, mem_ctx, &flags, chal, NULL, names_blob,
 			&lm_resp, &nt_resp, NULL, NULL);
 		if (!NT_STATUS_IS_OK(status)) {
 			torture_comment(tctx, "cli_credentials_get_ntlm_response failed:"
@@ -1362,7 +1362,6 @@ static bool torture_netlogon_samba3(struct torture_context *torture)
 {
 	NTSTATUS status;
 	struct smbcli_state *cli;
-	struct cli_credentials *anon_creds;
 	struct cli_credentials *wks_creds;
 	const char *wks_name;
 	int i;
@@ -1374,10 +1373,6 @@ static bool torture_netlogon_samba3(struct torture_context *torture)
 		wks_name = get_myname(torture);
 	}
 
-	if (!(anon_creds = cli_credentials_init_anon(torture))) {
-		torture_fail(torture, "create_anon_creds failed\n");
-	}
-
 	lpcfg_smbcli_options(torture->lp_ctx, &options);
 	lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
 
@@ -1386,7 +1381,7 @@ static bool torture_netlogon_samba3(struct torture_context *torture)
 					lpcfg_smb_ports(torture->lp_ctx),
 					"IPC$", NULL,
 					lpcfg_socket_options(torture->lp_ctx),
-					anon_creds,
+					cmdline_credentials,
 					lpcfg_resolve_context(torture->lp_ctx),
 					torture->ev, &options, &session_options,
 					lpcfg_gensec_settings(torture, torture->lp_ctx));
@@ -1406,7 +1401,7 @@ static bool torture_netlogon_samba3(struct torture_context *torture)
 				     CRED_SPECIFIED);
 
 	torture_assert(torture,
-		join3(torture, cli, false, cmdline_credentials, wks_creds),
+		join3(torture, cli, false, NULL, wks_creds),
 		"join failed");
 
 	cli_credentials_set_domain(
@@ -1433,7 +1428,7 @@ static bool torture_netlogon_samba3(struct torture_context *torture)
 	}
 
 	torture_assert(torture,
-		leave(torture, cli, cmdline_credentials, wks_creds),
+		leave(torture, cli, NULL, wks_creds),
 		"leave failed");
 
 	return true;
@@ -1532,26 +1527,14 @@ static bool torture_samba3_sessionkey(struct torture_context *torture)
 	}
 
 	torture_assert(torture,
-		test_join3(torture, false, anon_creds, cmdline_credentials, wks_name),
-		"join using ntlmssp bind on an anonymous smb connection failed");
-
-	torture_assert(torture,
 		test_join3(torture, false, cmdline_credentials, NULL, wks_name),
 		"join using anonymous bind on an authenticated smb connection failed");
 
-	torture_assert(torture,
-		test_join3(torture, false, cmdline_credentials, cmdline_credentials, wks_name),
-		"join using ntlmssp bind on an authenticated smb connection failed");
-
 	/*
 	 * The following two are tests for setuserinfolevel 25
 	 */
 
 	torture_assert(torture,
-		test_join3(torture, true, anon_creds, cmdline_credentials, wks_name),
-		"join using ntlmssp bind on an anonymous smb connection failed");
-
-	torture_assert(torture,
 		test_join3(torture, true, cmdline_credentials, NULL, wks_name),
 		"join using anonymous bind on an authenticated smb connection failed");
 
@@ -1799,20 +1782,6 @@ static bool torture_samba3_rpc_getusername(struct torture_context *torture)
 	lpcfg_smbcli_options(torture->lp_ctx, &options);
 	lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
 
-	status = smbcli_full_connection(
-		torture, &cli, torture_setting_string(torture, "host", NULL),
-		lpcfg_smb_ports(torture->lp_ctx),
-		"IPC$", NULL, lpcfg_socket_options(torture->lp_ctx), cmdline_credentials,
-		lpcfg_resolve_context(torture->lp_ctx), torture->ev, &options,
-		&session_options, lpcfg_gensec_settings(torture, torture->lp_ctx));
-	torture_assert_ntstatus_ok(torture, status, "smbcli_full_connection failed\n");
-
-	if (!(user_sid = whoami(torture, torture, cli->tree))) {
-		torture_fail(torture, "whoami on auth'ed connection failed\n");
-	}
-
-	talloc_free(cli);
-
 	if (!(anon_creds = cli_credentials_init_anon(torture))) {
 		torture_fail(torture, "create_anon_creds failed\n");
 	}
@@ -1833,6 +1802,20 @@ static bool torture_samba3_rpc_getusername(struct torture_context *torture)
 	torture_assert_sid_equal(torture, user_sid, dom_sid_parse_talloc(torture, "s-1-5-7"),
 		"Anon lsa_GetUserName returned unexpected SID");
 
+	talloc_free(cli);
+
+	status = smbcli_full_connection(
+		torture, &cli, torture_setting_string(torture, "host", NULL),
+		lpcfg_smb_ports(torture->lp_ctx),
+		"IPC$", NULL, lpcfg_socket_options(torture->lp_ctx), cmdline_credentials,
+		lpcfg_resolve_context(torture->lp_ctx), torture->ev, &options,
+		&session_options, lpcfg_gensec_settings(torture, torture->lp_ctx));
+	torture_assert_ntstatus_ok(torture, status, "smbcli_full_connection failed\n");
+
+	if (!(user_sid = whoami(torture, torture, cli->tree))) {
+		torture_fail(torture, "whoami on auth'ed connection failed\n");
+	}
+
 	if (!(user_creds = cli_credentials_init(torture))) {
 		torture_fail(torture, "cli_credentials_init failed\n");
 	}
@@ -1844,7 +1827,7 @@ static bool torture_samba3_rpc_getusername(struct torture_context *torture)
 				     generate_random_password(user_creds, 8, 255),
 				     CRED_SPECIFIED);
 
-	if (!create_user(torture, torture, cli, cmdline_credentials,
+	if (!create_user(torture, torture, cli, NULL,
 			 cli_credentials_get_username(user_creds),
 			 cli_credentials_get_password(user_creds),
 			 &domain_name, &created_sid)) {
@@ -1899,7 +1882,7 @@ static bool torture_samba3_rpc_getusername(struct torture_context *torture)
 
  del:
 	if (!delete_user(torture, cli,
-			 cmdline_credentials,
+			 NULL,
 			 cli_credentials_get_username(user_creds))) {
 		torture_fail(torture, "delete_user failed\n");
 	}
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 9000fe9..4465698 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -1755,7 +1755,8 @@ bool torture_rpc_samlogon(struct torture_context *torture)
 	 * with INTERNAL_ERROR */
 
 	status = dcerpc_binding_set_flags(b,
-					  DCERPC_SCHANNEL | DCERPC_SIGN |
+					  DCERPC_SCHANNEL |
+					  DCERPC_SIGN | DCERPC_SEAL |
 					  DCERPC_SCHANNEL_128,
 					  DCERPC_AUTH_OPTIONS);
 	torture_assert_ntstatus_ok(torture, status, "set flags");
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 293b672..dcdbb8a 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -3096,6 +3096,7 @@ static bool test_SamLogon(struct torture_context *tctx,
 		status = cli_credentials_get_ntlm_response(test_credentials, tctx,
 							   &flags,
 							   chal,
+							   NULL, /* server_timestamp */
 							   names_blob,
 							   &lm_resp, &nt_resp,
 							   NULL, NULL);
@@ -3257,7 +3258,8 @@ static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
 	 * with INTERNAL_ERROR */
 
 	status = dcerpc_binding_set_flags(b,
-					  DCERPC_SCHANNEL | DCERPC_SIGN |
+					  DCERPC_SCHANNEL |
+					  DCERPC_SIGN | DCERPC_SEAL |
 					  DCERPC_SCHANNEL_AUTO,
 					  DCERPC_AUTH_OPTIONS);
 	torture_assert_ntstatus_ok(tctx, status, "set flags");
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
index a72dd31..829c969 100644
--- a/source4/torture/rpc/schannel.c
+++ b/source4/torture/rpc/schannel.c
@@ -62,6 +62,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
 	struct netr_SamBaseInfo *base = NULL;
 	const char *crypto_alg = "";
 	bool can_do_validation_6 = true;
+	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
 
 	if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
 		flags |= CLI_CRED_LANMAN_AUTH;
@@ -86,6 +87,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
 	status = cli_credentials_get_ntlm_response(cmdline_credentials, tctx,
 						   &flags,
 						   chal,
+						   NULL, /* server_timestamp */
 						   names_blob,
 						   &lm_resp, &nt_resp,
 						   NULL, NULL);
@@ -131,16 +133,26 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
 		}
 	}
 
-	r.in.validation_level = 6;
+	dcerpc_binding_handle_auth_info(b, NULL, &auth_level);
+	if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+		r.in.validation_level = 6;
 
-	torture_comment(tctx,
-			"Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
-			ninfo.identity_info.account_name.string, crypto_alg,
-			r.in.validation_level);
+		torture_comment(tctx,
+				"Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
+				ninfo.identity_info.account_name.string, crypto_alg,
+				r.in.validation_level);
+
+		torture_assert_ntstatus_ok(tctx,
+			dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
+			"LogonSamLogonEx failed");
+	} else {
+		torture_comment(tctx,
+				"Skip auth_level[%u] Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
+				auth_level, ninfo.identity_info.account_name.string, crypto_alg,
+				r.in.validation_level);
+		r.out.result = NT_STATUS_INVALID_INFO_CLASS;
+	}
 
-	torture_assert_ntstatus_ok(tctx,
-		dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
-		"LogonSamLogonEx failed");
 	if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
 		can_do_validation_6 = false;
 	} else {
@@ -842,6 +854,7 @@ static bool torture_schannel_bench_start(struct torture_schannel_bench_conn *con
 	status = cli_credentials_get_ntlm_response(user_creds, conn->tmp,
 						   &flags,
 						   chal,
+						   NULL, /* server_timestamp */
 						   names_blob,
 						   &lm_resp, &nt_resp,
 						   NULL, NULL);
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
index 5ee2c2a..7fbf301 100644
--- a/source4/torture/rpc/testjoin.c
+++ b/source4/torture/rpc/testjoin.c
@@ -503,10 +503,36 @@ _PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx,
 	struct test_join *tj;
 	struct samr_SetUserInfo s;
 	union samr_UserInfo u;
-	
+	const char *binding_str = NULL;
+	struct dcerpc_binding *binding = NULL;
+	enum dcerpc_transport_t transport;
+
 	tj = talloc_zero(tctx, struct test_join);
 	if (!tj) return NULL;
 
+	binding_str = torture_setting_string(tctx, "binding", NULL);
+	if (binding_str == NULL) {
+		const char *host = torture_setting_string(tctx, "host", NULL);
+		binding_str = talloc_asprintf(tj, "ncacn_np:%s", host);
+	}
+	status = dcerpc_parse_binding(tj, binding_str, &binding);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0, ("dcerpc_parse_binding(%s) failed - %s\n",
+			  binding_str, nt_errstr(status)));
+		talloc_free(tj);
+		return NULL;
+	}
+	transport = dcerpc_binding_get_transport(binding);
+	switch (transport) {
+	case NCALRPC:
+	case NCACN_UNIX_STREAM:
+		break;
+	default:
+		dcerpc_binding_set_transport(binding, NCACN_NP);
+		dcerpc_binding_set_flags(binding, 0, DCERPC_AUTH_OPTIONS);
+		break;
+	}
+
 	libnet_r = talloc_zero(tj, struct libnet_JoinDomain);
 	if (!libnet_r) {
 		talloc_free(tj);
@@ -522,9 +548,10 @@ _PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx,
 	tj->libnet_r = libnet_r;
 		
 	libnet_ctx->cred = cmdline_credentials;
-	libnet_r->in.binding = torture_setting_string(tctx, "binding", NULL);
-	if (!libnet_r->in.binding) {
-		libnet_r->in.binding = talloc_asprintf(libnet_r, "ncacn_np:%s", torture_setting_string(tctx, "host", NULL));
+	libnet_r->in.binding = dcerpc_binding_string(libnet_r, binding);
+	if (libnet_r->in.binding == NULL) {
+		talloc_free(tj);
+		return NULL;
 	}
 	libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED;
 	libnet_r->in.netbios_name = machine_name;
diff --git a/testprogs/blackbox/test_ldb_simple.sh b/testprogs/blackbox/test_ldb_simple.sh
new file mode 100755
index 0000000..7375cbf
--- /dev/null
+++ b/testprogs/blackbox/test_ldb_simple.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+if [ $# -lt 2 ]; then
+cat <<EOF
+Usage: test_ldb_simple.sh PROTOCOL SERVER [OPTIONS]
+EOF
+exit 1;
+fi
+
+
+p=$1
+SERVER=$2
+PREFIX=$3
+shift 2
+options="$*"
+
+. `dirname $0`/subunit.sh
+
+check() {
+	name="$1"
+	shift
+	cmdline="$*"
+	echo "test: $name"
+	$cmdline
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "success: $name"
+	else
+		echo "failure: $name"
+		failed=`expr $failed + 1`
+	fi
+	return $status
+}
+
+export PATH="$BINDIR:$PATH"
+
+ldbsearch="$VALGRIND ldbsearch"
+
+check "currentTime" $ldbsearch $CONFIGURATION $options --basedn='' -H $p://$SERVER -s base currentTime || failed=`expr $failed + 1`
+
+exit $failed
diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5
index 4b3a69f..34f81b6 100644
--- a/wscript_configure_system_mitkrb5
+++ b/wscript_configure_system_mitkrb5
@@ -59,7 +59,8 @@ conf.CHECK_FUNCS_IN('_et_list', 'com_err')
 conf.CHECK_HEADERS('com_err.h', lib='com_err')
 
 conf.CHECK_HEADERS('krb5.h krb5/locate_plugin.h', lib='krb5')
-conf.CHECK_HEADERS('gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h gssapi/gssapi_ext.h gssapi/gssapi_krb5.h', lib='gssapi')
+possible_gssapi_headers="gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h gssapi/gssapi_ext.h gssapi/gssapi_krb5.h gssapi/gssapi_oid.h"
+conf.CHECK_HEADERS(possible_gssapi_headers, lib='gssapi')
 
 conf.CHECK_FUNCS_IN('krb5_encrypt_data', 'k5crypto')
 conf.CHECK_FUNCS_IN('des_set_key','crypto')
@@ -87,6 +88,7 @@ conf.CHECK_FUNCS_IN('''
        gss_krb5_export_lucid_sec_context
        gss_import_cred gss_export_cred
        ''', 'gssapi gssapi_krb5')
+conf.CHECK_VARIABLE('GSS_KRB5_CRED_NO_CI_FLAGS_X', headers=possible_gssapi_headers)
 conf.CHECK_FUNCS_IN('krb5_mk_req_extended krb5_kt_compare', 'krb5')
 conf.CHECK_FUNCS('''
        krb5_set_default_in_tkt_etypes krb5_set_default_tgs_enctypes

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-samba/samba.git




More information about the Pkg-samba-maint mailing list