diff --git a/net/samba413/Makefile b/net/samba413/Makefile index f1dea1c15f3d..ccbb438ecb6a 100644 --- a/net/samba413/Makefile +++ b/net/samba413/Makefile @@ -1,697 +1,697 @@ PORTNAME= ${SAMBA4_BASENAME}413 PORTVERSION= ${SAMBA4_VERSION} -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES?= net MASTER_SITES= SAMBA/samba/stable SAMBA/samba/rc DISTNAME= ${SAMBA4_DISTNAME} MAINTAINER= timur@FreeBSD.org COMMENT= Free SMB/CIFS and AD/DC server and client for Unix WWW= https://www.samba.org/ LICENSE= GPLv3+ LICENSE_FILE= ${WRKSRC}/COPYING IGNORE_NONTHREAD_PYTHON= needs port lang/python${PYTHON_SUFFIX} to be build with THREADS support CONFLICTS_INSTALL?= samba4* # bin/cifsdd bin/dbwrap_tool bin/dumpmscat bin/findsmb bin/gentest USES= cpe EXTRA_PATCHES+= ${PATCHDIR}/0001-Zfs-provision-1.patch:-p1 SAMBA4_BASENAME= samba SAMBA4_PORTNAME= ${SAMBA4_BASENAME}4 SAMBA4_VERSION= 4.13.17 SAMBA4_DISTNAME= ${SAMBA4_BASENAME}-${SAMBA4_VERSION:S|.p|pre|:S|.r|rc|:S|.t|tp|:S|.a|alpha|} WRKSRC?= ${WRKDIR}/${DISTNAME} PLIST?= ${PKGDIR}/pkg-plist CPE_VENDOR= samba CPE_PRODUCT= samba # Directories VARDIR= ${DESTDIR}/var SAMBA4_RUNDIR= ${VARDIR}/run/${SAMBA4_PORTNAME} SAMBA4_LOGDIR= ${VARDIR}/log/${SAMBA4_PORTNAME} SAMBA4_LOCKDIR= ${VARDIR}/db/${SAMBA4_PORTNAME} SAMBA4_BINDDNSDIR= ${SAMBA4_LOCKDIR}/bind-dns SAMBA4_PRIVATEDIR= ${SAMBA4_LOCKDIR}/private SAMBA4_PAMDIR= ${PREFIX}/lib SAMBA4_LIBDIR= ${PREFIX}/lib/${SAMBA4_PORTNAME} SAMBA4_INCLUDEDIR= ${PREFIX}/include/${SAMBA4_PORTNAME} SAMBA4_CONFDIR= ${PREFIX}/etc SAMBA4_CONFIG= smb4.conf SAMBA4_MODULES_CLASS= auth bind9 gensec gpext idmap ldb nss_info \ pdb perfcount process_model service vfs CONFIGURE_ARGS+= --mandir="${MANPREFIX}/man" \ --sysconfdir="${SAMBA4_CONFDIR}" \ --includedir="${SAMBA4_INCLUDEDIR}" \ --datadir="${DATADIR}" \ --libdir="${SAMBA4_LIBDIR}" \ --with-privatelibdir="${SAMBA4_LIBDIR}/private" \ --with-pammodulesdir="${SAMBA4_PAMDIR}" \ --with-modulesdir="${SAMBA4_MODULEDIR}" \ --with-pkgconfigdir="${PKGCONFIGDIR}" \ --localstatedir="${VARDIR}" \ --with-piddir="${SAMBA4_RUNDIR}" \ --with-sockets-dir="${SAMBA4_RUNDIR}" \ --with-privileged-socket-dir="${SAMBA4_RUNDIR}" \ --with-lockdir="${SAMBA4_LOCKDIR}" \ --with-statedir="${SAMBA4_LOCKDIR}" \ --with-cachedir="${SAMBA4_LOCKDIR}" \ --with-bind-dns-dir=${SAMBA4_BINDDNSDIR} \ --with-privatedir="${SAMBA4_PRIVATEDIR}" \ --with-logfilebase="${SAMBA4_LOGDIR}" # XXX: Flags CONFIGURE_ENV+= PTHREAD_LDFLAGS="-lpthread" MAKE_ENV+= PYTHONHASHSEED=1 USES+= compiler:c++11-lang iconv localbase:ldflags \ perl5 pkgconfig shebangfix waf gettext-runtime USE_PERL5= build USE_LDCONFIG= ${SAMBA4_LIBDIR} WAF_CMD= buildtools/bin/waf CONFIGURE_LOG= bin/config.log PKGCONFIGDIR?= ${PREFIX}/libdata/pkgconfig PKGCONFIGDIR_REL?= ${PKGCONFIGDIR:S,^${PREFIX}/,,} PLIST_SUB+= PKGCONFIGDIR=${PKGCONFIGDIR_REL} SUB_LIST+= PKGCONFIGDIR=${PKGCONFIGDIR_REL} ############################################################################## OPTIONS_SUB= yes OPTIONS_DEFINE= AD_DC ADS CLUSTER CUPS DOCS FAM GPGME \ LDAP MANDOC NTVFS PROFILE PYTHON3 QUOTAS \ SPOTLIGHT SYSLOG UTMP #OPTIONS_DEFINE+= DEVELOPER MEMORY_DEBUG OPTIONS_GROUP= VFS OPTIONS_GROUP_VFS= FRUIT GLUSTERFS OPTIONS_SINGLE= GSSAPI ZEROCONF OPTIONS_SINGLE_GSSAPI= GSSAPI_BUILTIN GSSAPI_MIT #GSSAPI_HEIMDAL OPTIONS_SINGLE_ZEROCONF= ZEROCONF_NONE AVAHI MDNSRESPONDER OPTIONS_RADIO= DNS -OPTIONS_RADIO_DNS= NSUPDATE BIND911 BIND916 +OPTIONS_RADIO_DNS= NSUPDATE BIND916 BIND918 # Make those default options OPTIONS_DEFAULT= AD_DC ADS DOCS FAM LDAP \ PROFILE PYTHON3 QUOTAS SYSLOG UTMP \ FRUIT GSSAPI_BUILTIN AVAHI ############################################################################## ADS_DESC= Active Directory client(implies LDAP) AD_DC_DESC= Active Directory Domain Controller(implies PYTHON3) CLUSTER_DESC= Clustering support DEVELOPER_DESC= With developer framework(implies NTVFS) FAM_DESC= File Alteration Monitor GPGME_DESC= GpgME support LDAP_DESC= LDAP client LIBZFS_DESC= LibZFS SPOTLIGHT_DESC= Spotlight server-side search support MANDOC_DESC= Build manpages from DOCBOOK templates MEMORY_DEBUG_DESC= Debug memory allocator NTVFS_DESC= Build *DEPRECATED* NTVFS file server PICKY_DEVELOPER_DESC= Treat compiler warnings as errors(implies DEVELOPER) PROFILE_DESC= Profiling data QUOTAS_DESC= Disk quota support UTMP_DESC= UTMP accounting VFS_DESC= VFS modules GLUSTERFS_DESC= GlusterFS support FRUIT_DESC= MacOSX and TimeMachine support GSSAPI_BUILTIN_DESC= GSSAPI support via bundled Heimdal ZEROCONF_DESC= Zero configuration networking ZEROCONF_NONE_DESC= Zeroconf support is absent DNS_DESC= DNS frontend -BIND911_DESC= Use Bind 9.11 as AD DC DNS server frontend BIND916_DESC= Use Bind 9.16 as AD DC DNS server frontend +BIND918_DESC= Use Bind 9.18 as AD DC DNS server frontend NSUPDATE_DESC= Use samba NSUPDATE utility for AD DC ############################################################################## # XXX: Unconditional dependencies which can't be switched off(if present in # the system) # Iconv(picked up unconditionaly) LIB_DEPENDS+= libiconv.so:converters/libiconv # unwind LIB_DEPENDS+= libunwind.so:devel/libunwind # Readline(sponsored by Python) # XXX: USES=readline pollutes CPPFLAGS, so we explicitly put dependency LIB_DEPENDS+= libreadline.so:devel/readline # popt LIB_DEPENDS+= libpopt.so:devel/popt # inotify LIB_DEPENDS+= libinotify.so:devel/libinotify # GNUTLS LIB_DEPENDS+= libgnutls.so:security/gnutls LIB_DEPENDS+= libgcrypt.so:security/libgcrypt # NFSv4 ACL glue LIB_DEPENDS+= libsunacl.so:sysutils/libsunacl # Jansson BUILD_DEPENDS+= jansson>=2.10:devel/jansson RUN_DEPENDS+= jansson>=2.10:devel/jansson # tasn1 BUILD_DEPENDS+= libtasn1>=3.8:security/libtasn1 RUN_DEPENDS+= libtasn1>=3.8:security/libtasn1 # External Samba dependencies # Needed for IDL compiler BUILD_DEPENDS+= p5-Parse-Yapp>=0:devel/p5-Parse-Yapp # Libarchive SAMBA4_BUNDLED_LIBS+= !libarchive BUILD_DEPENDS+= libarchive>=3.1.2:archivers/libarchive RUN_DEPENDS+= libarchive>=3.1.2:archivers/libarchive ### Bundled libraries SAMBA4_BUNDLED_CMOCKA?= no SAMBA4_BUNDLED_TALLOC?= no SAMBA4_BUNDLED_TEVENT?= no SAMBA4_BUNDLED_TDB?= no SAMBA4_BUNDLED_LDB?= yes # cmocka .if defined(SAMBA4_BUNDLED_CMOCKA) && ${SAMBA4_BUNDLED_CMOCKA} == yes SAMBA4_BUNDLED_LIBS+= cmocka CONFLICTS_INSTALL+= cmocka-1.* PLIST_SUB+= SAMBA4_BUNDLED_CMOCKA="" SUB_LIST+= SAMBA4_BUNDLED_CMOCKA="" .else SAMBA4_BUNDLED_LIBS+= !cmocka BUILD_DEPENDS+= cmocka>=1.1.3:sysutils/cmocka TEST_DEPENDS+= cmocka>=1.1.3:sysutils/cmocka PLIST_SUB+= SAMBA4_BUNDLED_CMOCKA="@comment " SUB_LIST+= SAMBA4_BUNDLED_CMOCKA="@comment " .endif # talloc .if defined(SAMBA4_BUNDLED_TALLOC) && ${SAMBA4_BUNDLED_TALLOC} == yes SAMBA4_BUNDLED_LIBS+= talloc CONFLICTS_INSTALL+= talloc-* talloc1-* PLIST_SUB+= SAMBA4_BUNDLED_TALLOC="" SUB_LIST+= SAMBA4_BUNDLED_TALLOC="" .else SAMBA4_BUNDLED_LIBS+= !talloc BUILD_DEPENDS+= talloc>=2.3.1:devel/talloc RUN_DEPENDS+= talloc>=2.3.1:devel/talloc PLIST_SUB+= SAMBA4_BUNDLED_TALLOC="@comment " SUB_LIST+= SAMBA4_BUNDLED_TALLOC="@comment " .endif # tevent .if defined(SAMBA4_BUNDLED_TEVENT) && ${SAMBA4_BUNDLED_TEVENT} == yes SAMBA4_BUNDLED_LIBS+= tevent CONFLICTS_INSTALL+= tevent-* tevent1-* PLIST_SUB+= SAMBA4_BUNDLED_TEVENT="" SUB_LIST+= SAMBA4_BUNDLED_TEVENT="" .else SAMBA4_BUNDLED_LIBS+= !tevent BUILD_DEPENDS+= tevent>=0.10.2:devel/tevent RUN_DEPENDS+= tevent>=0.10.2:devel/tevent PLIST_SUB+= SAMBA4_BUNDLED_TEVENT="@comment " SUB_LIST+= SAMBA4_BUNDLED_TEVENT="@comment " .endif # tdb .if defined(SAMBA4_BUNDLED_TDB) && ${SAMBA4_BUNDLED_TDB} == yes SAMBA4_BUNDLED_LIBS+= tdb CONFLICTS_INSTALL+= tdb-* tdb1-* PLIST_SUB+= SAMBA4_BUNDLED_TDB="" SUB_LIST+= SAMBA4_BUNDLED_TDB="" .else SAMBA4_BUNDLED_LIBS+= !tdb BUILD_DEPENDS+= tdb>=1.4.3:databases/tdb RUN_DEPENDS+= tdb>=1.4.3:databases/tdb PLIST_SUB+= SAMBA4_BUNDLED_TDB="@comment " SUB_LIST+= SAMBA4_BUNDLED_TDB="@comment " .endif # ldb .if defined(SAMBA4_BUNDLED_LDB) && ${SAMBA4_BUNDLED_LDB} == yes SAMBA4_BUNDLED_LDB= yes SAMBA4_BUNDLED_LIBS+= ldb PLIST_SUB+= SAMBA4_BUNDLED_LDB="" SUB_LIST+= SAMBA4_BUNDLED_LDB="" SAMBA4_MODULEDIR= ${SAMBA4_LIBDIR}/modules .else SAMBA4_BUNDLED_LIBS+= !ldb BUILD_DEPENDS+= ldb22>=2.2.0:databases/ldb22 RUN_DEPENDS+= ldb22>=2.2.0:databases/ldb22 PLIST_SUB+= SAMBA4_BUNDLED_LDB="@comment " SUB_LIST+= SAMBA4_BUNDLED_LDB="@comment " SAMBA4_MODULEDIR= ${PREFIX}/lib/shared-modules .endif .if (defined(SAMBA4_BUNDLED_TALLOC) && ${SAMBA4_BUNDLED_TALLOC} == yes) \ || (defined(SAMBA4_BUNDLED_TDB) && ${SAMBA4_BUNDLED_TDB} == yes) \ || (defined(SAMBA4_BUNDLED_LDB) && ${SAMBA4_BUNDLED_LDB} == yes) \ || (defined(SAMBA4_BUNDLED_TEVENT) && ${SAMBA4_BUNDLED_TEVENT} == yes) SAMBA4_BUNDLED_LIBS+= replace .endif # Don't use external libcom_err SAMBA4_BUNDLED_LIBS+= com_err # Set the test environment variables TEST_USES= python TEST_ENV+= PYTHON="${PYTHON_CMD}" \ SHA1SUM=/sbin/sha1 \ SHA256SUM=/sbin/sha256 \ MD5SUM=/sbin/md5 \ PYTHONDONTWRITEBYTECODE=1 TEST_DEPENDS+= bash:shells/bash \ tshark:net/tshark # External Python modules TEST_BUILD_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}iso8601>=0.1.11:devel/py-iso8601@${PY_FLAVOR} TEST_RUN_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}iso8601>=0.1.11:devel/py-iso8601@${PY_FLAVOR} ############################################################################## CONFIGURE_ARGS+= \ --with-pam \ --with-iconv \ --with-winbind \ --with-regedit \ --disable-rpath \ --without-lttng \ --without-gettext \ --enable-pthreadpool \ --without-fake-kaserver \ --without-systemd \ --with-libarchive \ --with-acl-support \ --with-sendfile-support \ --disable-ctdb-tests # ${ICONV_CONFIGURE_BASE} ############################################################################## FRUIT_PREVENTS= ZEROCONF_NONE FRUIT_PREVENTS_MSG= MacOSX support requires Zeroconf(AVAHI or MDNSRESPONDER) FRUIT_VARS= SAMBA4_MODULES+=vfs_fruit FRUIT_PLIST_FILES= man/man8/vfs_fruit.8.gz GLUSTERFS_CONFIGURE_ENABLE= glusterfs GLUSTERFS_LIB_DEPENDS= libglusterfs.so:net/glusterfs GLUSTERFS_VARS= SAMBA4_MODULES+=vfs_glusterfs GLUSTERFS_PLIST_FILES= man/man8/vfs_glusterfs.8.gz ZEROCONF_NONE_MAKE_ENV= ZEROCONF=none ############################################################################## AVAHI_CONFIGURE_ENABLE= avahi AVAHI_LIB_DEPENDS= libavahi-client.so:net/avahi-app AVAHI_VARS= SAMBA4_SERVICES+=avahi_daemon MDNSRESPONDER_CONFIGURE_ENABLE= dnssd MDNSRESPONDER_LIB_DEPENDS= libdns_sd.so:net/mDNSResponder MDNSRESPONDER_VARS= SAMBA4_SERVICES+=mdnsd ############################################################################## -BIND911_RUN_DEPENDS= bind911>=9.11.0.0:dns/bind911 BIND916_RUN_DEPENDS= bind916>=9.16.0.0:dns/bind916 +BIND918_RUN_DEPENDS= bind918>=9.18.0.0:dns/bind918 NSUPDATE_RUN_DEPENDS= samba-nsupdate:dns/samba-nsupdate ############################################################################## MEMORY_DEBUG_IMPLIES= DEBUG MEMORY_DEBUG_CONFIGURE_ENV= ADDITIONAL_CFLAGS="-DENABLE_JEMALLOC `pkg-config --cflags jemalloc`" ADDITIONAL_LDFLAGS="`pkg-config --libs jemalloc`" MEMORY_DEBUG_LIB_DEPENDS= libjemalloc.so.2:devel/jemalloc # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194046 GDB_CMD?= ${LOCALBASE}/bin/gdb # https://bugzilla.samba.org/show_bug.cgi?id=8969 PICKY_DEVELOPER_IMPLIES= DEVELOPER PICKY_DEVELOPER_CONFIGURE_ON= --picky-developer DEVELOPER_IMPLIES= NTVFS DEVELOPER_CONFIGURE_ON= --enable-developer --enable-selftest --abi-check-disable DEVELOPER_CONFIGURE_ENV= WAF_CMD_FORMAT=string DEVELOPER_RUN_DEPENDS= ${SAMBA4_LMDB_DEPENDS} DEVELOPER_BUILD_DEPENDS= ${GDB_CMD}:devel/gdb \ ${SAMBA4_LMDB_DEPENDS} DEVELOPER_TEST_DEPENDS= ${GDB_CMD}:devel/gdb DEVELOPER_VARS_OFF= GDB_CMD=true # XXX: Mostly used in conjuction with the DEVELOPER option, don't enable it # if you don't know what you are doing NTVFS_IMPLIES= AD_DC NTVFS_CONFIGURE_WITH= ntvfs-fileserver NTVFS_VARS= SAMBA4_MODULES+=service_smb NTVFS_PLIST_FILES= lib/samba4/private/libntvfs-samba4.so ############################################################################## AD_DC_IMPLIES= PYTHON3 AD_DC_CONFIGURE_OFF= --without-ad-dc AD_DC_BUILD_DEPENDS= ${SAMBA4_LMDB_DEPENDS} AD_DC_RUN_DEPENDS= ${SAMBA4_LMDB_DEPENDS} AD_DC_VARS= PLIST+=${PKGDIR}/pkg-plist.ad_dc ADS_IMPLIES= LDAP ADS_CONFIGURE_WITH= ads dnsupdate CLUSTER_CONFIGURE_WITH= cluster-support CLUSTER_VARS= PLIST+=${PKGDIR}/pkg-plist.cluster CUPS_CONFIGURE_ENABLE= cups iprint CUPS_LIB_DEPENDS= libcups.so:print/cups # https://bugzilla.samba.org/show_bug.cgi?id=9545 FAM_USES= fam FAM_CONFIGURE_WITH= fam GPGME_CONFIGURE_WITH= gpgme GPGME_LIB_DEPENDS= libgpgme.so:security/gpgme GSSAPI_MIT_CONFIGURE_ON= --with-system-mitkrb5 ${GSSAPIBASEDIR} \ --with-system-mitkdc=${GSSAPIBASEDIR}/sbin/krb5kdc \ --with-experimental-mit-ad-dc GSSAPI_MIT_USES= gssapi:mit GSSAPI_HEIMDAL_CONFIGURE_ON= --with-system-heimdalkrb5 ${GSSAPIBASEDIR} GSSAPI_HEIMDAL_USES= gssapi:heimdal GSSAPI_HEIMDAL_PREVENTS= AD_DC GSSAPI_HEIMDAL_PREVENTS_MSG= GSSAPI_HEIMDAL and AD_DC enable conflicting options LDAP_CONFIGURE_WITH= ldap LDAP_CONFIGURE_ON= --with-openldap=${LOCALBASE} LDAP_USE= OPENLDAP=yes LDAP_VARS= SAMBA4_MODULES+=idmap_ldap LIBZFS_CONFIGURE_WITH= libzfs LIBZFS_VARS= SAMBA4_MODULES+=vfs_zfs_space MANDOC_BUILD_DEPENDS= ${LOCALBASE}/share/xsl/docbook/manpages/docbook.xsl:textproc/docbook-xsl \ xsltproc:textproc/libxslt MANDOC_CONFIGURE_ENV_OFF= XSLTPROC="true" PROFILE_CONFIGURE_WITH= profiling-data QUOTAS_CONFIGURE_WITH= quotas SPOTLIGHT_CONFIGURE_ENABLE= spotlight SPOTLIGHT_BUILD_DEPENDS= tracker>=1.4.1:sysutils/tracker SPOTLIGHT_RUN_DEPENDS= tracker>=1.4.1:sysutils/tracker # ICU SPOTLIGHT_LIB_DEPENDS= libicuuc.so:devel/icu SPOTLIGHT_USES= bison gnome SPOTLIGHT_USE= gnome=glib20 SYSLOG_CONFIGURE_WITH= syslog UTMP_CONFIGURE_WITH= utmp ############################################################################## .include ############################################################################## .if !defined(WANT_EXP_MODULES) || empty(WANT_EXP_MODULES) WANT_EXP_MODULES= vfs_cacheprime .endif .if ${WANT_EXP_MODULES:Mvfs_snapper} # snapper needs dbus LIB_DEPENDS+= libdbus-1.so:devel/dbus LIB_DEPENDS+= libdbus-glib-1.so:devel/dbus-glib .endif SAMBA4_MODULES+= krb5_winbind_krb5_locator idmap_nss idmap_autorid \ idmap_rid idmap_hash idmap_tdb idmap_tdb2 idmap_script \ nss-info_hash # List of extra modules taken from RHEL build # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197320 .if ${PORT_OPTIONS:MADS} SAMBA4_MODULES+= idmap_ad idmap_rfc2307 nss-info_template \ nss-info_rfc2307 nss-info_sfu nss-info_sfu20 .endif # This kind of special for this distribution SAMBA4_MODULES+= vfs_freebsd SAMBA4_MODULES+= vfs_acl_tdb vfs_acl_xattr vfs_aio_fork vfs_aio_pthread \ vfs_audit vfs_cap vfs_catia vfs_commit vfs_crossrename \ vfs_default_quota vfs_dirsort vfs_expand_msdfs \ vfs_extd_audit vfs_fake_perms vfs_full_audit \ vfs_linux_xfs_sgid vfs_media_harmony vfs_offline \ vfs_preopen vfs_readahead vfs_readonly vfs_recycle \ vfs_shadow_copy vfs_shadow_copy2 vfs_shell_snap \ vfs_streams_depot vfs_streams_xattr vfs_syncops \ vfs_time_audit vfs_unityed_media vfs_virusfilter \ vfs_widelinks vfs_worm vfs_xattr_tdb vfs_zfsacl .if ${PORT_OPTIONS:MDEVELOPER} SAMBA4_MODULES+= auth_skel pdb_test gpext_security gpext_registry \ gpext_scripts perfcount_test vfs_fake_dfq \ vfs_skel_opaque vfs_skel_transparent \ vfs_shadow_copy_test vfs_fake_acls \ vfs_nfs4acl_xattr vfs_error_inject vfs_delay_inject .endif # Python bindings .if ! ${PORT_OPTIONS:MPYTHON3} || defined(NO_PYTHON) USES+= python:build,test CONFIGURE_ARGS+= --disable-python .else USES+= python:3.6+ PLIST+= ${PKGDIR}/pkg-plist.python # Don't cache Python modules CONFIGURE_ARGS+= --nopycache MAKE_ENV+= PYTHONDONTWRITEBYTECODE=1 . if defined(SAMBA4_BUNDLED_TALLOC) && ${SAMBA4_BUNDLED_TALLOC} == yes SAMBA4_BUNDLED_LIBS+= pytalloc-util . else SAMBA4_BUNDLED_LIBS+= !pytalloc-util . endif . if defined(SAMBA4_BUNDLED_TEVENT) && ${SAMBA4_BUNDLED_TEVENT} == yes SAMBA4_BUNDLED_LIBS+= pytevent . else SAMBA4_BUNDLED_LIBS+= !pytevent . endif . if defined(SAMBA4_BUNDLED_TDB) && ${SAMBA4_BUNDLED_TDB} == yes SAMBA4_BUNDLED_LIBS+= pytdb . else SAMBA4_BUNDLED_LIBS+= !pytdb . endif . if defined(SAMBA4_BUNDLED_LDB) && ${SAMBA4_BUNDLED_LDB} == yes SAMBA4_BUNDLED_LIBS+= pyldb pyldb-util . else SAMBA4_BUNDLED_LIBS+= !pyldb !pyldb-util . endif # samba-tool requires those for *upgrade . if ${PORT_OPTIONS:MAD_DC} RUN_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}dnspython>=1.15.0:dns/py-dnspython@${PY_FLAVOR} RUN_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}markdown>=2.6.11:textproc/py-markdown@${PY_FLAVOR} . if ${PORT_OPTIONS:MGPGME} RUN_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}gpgme>=1.14.0:security/py-gpgme@${PY_FLAVOR} . endif . endif .endif .if defined(WANT_EXP_MODULES) && !empty(WANT_EXP_MODULES) SAMBA4_MODULES+= ${WANT_EXP_MODULES} .endif .if defined(SAMBA4_BUNDLED_LIBS) && !empty(SAMBA4_BUNDLED_LIBS) CONFIGURE_ARGS+= --bundled-libraries="${SAMBA4_BUNDLED_LIBS:Q:C|(\\\\ )+|,|g:S|\\||g}" .endif .if defined(SAMBA4_MODULES) && !empty(SAMBA4_MODULES) CONFIGURE_ARGS+= --with-shared-modules="${SAMBA4_MODULES:C|-|_|:Q:C|(\\\\ )+|,|g:S|\\||g}" .endif # XXX: Hack for nss-info_* -> nss_info/* modules # Add selected modules to the plist .for module in ${SAMBA4_MODULES} PLIST_FILES+= ${SAMBA4_MODULEDIR}/${module:C|_|/|:C|-|_|}.so .endfor .for module_class in ${SAMBA4_MODULES_CLASS} PLIST_DIRS+= ${SAMBA4_MODULEDIR}/${module_class} .endfor PLIST_DIRS+= ${SAMBA4_MODULEDIR} .if defined(WITH_DEBUG) CONFIGURE_ARGS+= --verbose --enable-debug MAKE_ARGS+= --verbose DEBUG_FLAGS?= -g -ggdb3 -O0 .endif ############################################################################## .include ############################################################################## # Implemented in the gcrypt on AMD64 .if ${ARCH} == "amd64" CONFIGURE_ARGS+= --accel-aes=intelaesni .else CONFIGURE_ARGS+= --accel-aes=none .endif # Only for 64-bit architectures .if ${ARCH} != armv6 && ${ARCH} != armv7 && ${ARCH} != i386 && ${ARCH} != mips && ${ARCH} != powerpc && ${ARCH} != powerpcspe . if defined(SAMBA4_BUNDLED_LDB) && ${SAMBA4_BUNDLED_LDB} == yes && (${PORT_OPTIONS:MAD_DC} || ${PORT_OPTIONS:MDEVELOPER}) # LMDB SAMBA4_LMDB_DEPENDS= lmdb>=0.9.16:databases/lmdb PLIST_FILES+= ${SAMBA4_LIBDIR}/private/libldb-mdb-int-samba4.so \ ${SAMBA4_MODULEDIR}/ldb/mdb.so . endif .endif .if ${PORT_OPTIONS:MGSSAPI_MIT} PLIST_FILES+= ${SAMBA4_MODULEDIR}/krb5/winbind_krb5_localauth.so \ man/man8/winbind_krb5_localauth.8.gz . if ${PORT_OPTIONS:MAD_DC} PLIST_FILES+= ${SAMBA4_LIBDIR}/krb5/plugins/kdb/samba.so . endif .endif # for libexecinfo: (so that __builtin_frame_address() finds the top of the stack) CFLAGS_amd64+= -fno-omit-frame-pointer # No fancy color error messages CONFIGURE_ENV+= NOCOLOR=yes WAF_LOG_FORMAT='%(c1)s%(zone)s%(c2)s %(message)s' MAKE_ENV+= NOCOLOR=yes WAF_LOG_FORMAT='%(c1)s%(zone)s%(c2)s %(message)s' .if ${CHOSEN_COMPILER_TYPE} == clang CFLAGS+= -fno-color-diagnostics .endif # Allow rpcgen to find proper CPP MAKE_ENV+= RPCGEN_CPP="${CPP}" #.if ${readline_ARGS} == port #CFLAGS+= -D_FUNCTION_DEF #.endif # Make sure that the right version of Python is used by the tools # https://bugzilla.samba.org/show_bug.cgi?id=7305 SHEBANG_FILES= ${PATCH_WRKSRC}/source4/scripting/bin/* ${PATCH_WRKSRC}/selftest/* SAMBA4_SUB= SAMBA4_LOGDIR="${SAMBA4_LOGDIR}" \ SAMBA4_RUNDIR="${SAMBA4_RUNDIR}" \ SAMBA4_LOCKDIR="${SAMBA4_LOCKDIR}" \ SAMBA4_LIBDIR="${SAMBA4_LIBDIR}" \ SAMBA4_MODULEDIR="${SAMBA4_MODULEDIR}" \ SAMBA4_BINDDNSDIR="${SAMBA4_BINDDNSDIR}" \ SAMBA4_PRIVATEDIR="${SAMBA4_PRIVATEDIR}" \ SAMBA4_CONFDIR="${SAMBA4_CONFDIR}" \ SAMBA4_CONFIG="${SAMBA4_CONFIG}" \ SAMBA4_SERVICES="${SAMBA4_SERVICES}" PLIST_SUB+= ${SAMBA4_SUB} SUB_LIST+= ${SAMBA4_SUB} USE_RC_SUBR= samba_server SUB_FILES= pkg-message README.FreeBSD PORTDOCS= README.FreeBSD post-extract: @${RM} -r ${WRKSRC}/pidl/lib/Parse/Yapp post-patch: @${REINPLACE_CMD} -e 's|$${PKGCONFIGDIR}|${PKGCONFIGDIR}|g' \ ${PATCH_WRKSRC}/buildtools/wafsamba/pkgconfig.py @${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|g' \ ${PATCH_WRKSRC}/buildtools/wafsamba/wafsamba.py @${REINPLACE_CMD} -e 's|%%GDB_CMD%%|${GDB_CMD}|g' \ ${PATCH_WRKSRC}/buildtools/scripts/abi_gen.sh @${REINPLACE_CMD} -e 's|%%SAMBA4_CONFIG%%|${SAMBA4_CONFIG}|g' \ ${PATCH_WRKSRC}/dynconfig/wscript # Use threading (or multiprocessing) but not thread (renamed in python 3+). pre-configure: .if !${PORT_OPTIONS:MAD_DC} && ${PORT_OPTIONS:MNTVFS} @${ECHO_CMD}; \ ${ECHO_MSG} "===> NTVFS option requires AD_DC to be set"; \ ${ECHO_CMD}; \ ${FALSE} .endif .if (!${PORT_OPTIONS:MPYTHON3} || defined(NO_PYTHON)) && ${PORT_OPTIONS:MAD_DC} @${ECHO_CMD}; \ ${ECHO_MSG} "===> AD_DC option requires PYTHON3 to be set"; \ ${ECHO_CMD}; \ ${FALSE} .endif @if ! ${PYTHON_CMD} -c "import multiprocessing;" 2>/dev/null; then \ ${ECHO_CMD}; \ ${ECHO_MSG} "===> ${PKGNAME} "${IGNORE_NONTHREAD_PYTHON:Q}.; \ ${ECHO_CMD}; \ ${FALSE}; \ fi pre-build-MANDOC-off: ${MKDIR} ${BUILD_WRKSRC}/bin/default/docs-xml/ ${CP} -rp ${BUILD_WRKSRC}/docs/manpages ${BUILD_WRKSRC}/bin/default/docs-xml/ .for man in libcli/nbt/man/nmblookup4.1 \ librpc/tools/ndrdump.1 \ source4/lib/registry/man/regdiff.1 \ source4/lib/registry/man/regpatch.1 \ source4/lib/registry/man/regshell.1 \ source4/lib/registry/man/regtree.1 \ source4/scripting/man/samba-gpupdate.8 \ source4/torture/man/gentest.1 \ source4/torture/man/locktest.1 \ source4/torture/man/masktest.1 \ source4/torture/man/smbtorture.1 \ source4/utils/man/ntlm_auth4.1 \ source4/utils/oLschema2ldif/oLschema2ldif.1 \ lib/tdb/man/tdbdump.8 \ lib/tdb/man/tdbbackup.8 \ lib/tdb/man/tdbtool.8 \ lib/talloc/man/talloc.3 \ lib/tdb/man/tdbrestore.8 \ lib/ldb/man/ldbadd.1 \ lib/ldb/man/ldbsearch.1 \ lib/ldb/man/ldbmodify.1 \ lib/ldb/man/ldbrename.1 \ lib/ldb/man/ldbdel.1 \ lib/ldb/man/ldbedit.1 \ docs-xml/manpages/vfs_freebsd.8 ${MKDIR} `dirname ${BUILD_WRKSRC}/bin/default/${man}` ${INSTALL_MAN} ${FILESDIR}/man/`basename ${man}` ${BUILD_WRKSRC}/bin/default/${man} .endfor .if ${PORT_OPTIONS:MCLUSTER} ${MKDIR} ${BUILD_WRKSRC}/bin/default/ctdb/ . for man in ctdb_diagnostics.1 ctdb.1 ctdbd_wrapper.1 ctdbd.1 ltdbtool.1 onnode.1 ping_pong.1 \ ctdb.conf.5 ctdb.sysconfig.5 ctdb-script.options.5 \ ctdb.7 ctdb-statistics.7 ctdb-tunables.7 ${INSTALL_MAN} ${FILESDIR}/man/${man} ${BUILD_WRKSRC}/bin/default/ctdb/ . endfor .endif post-install-rm-junk: ${RM} -r ${STAGEDIR}${PYTHON_SITELIBDIR}/samba/third_party ${FIND} ${STAGEDIR}${PYTHON_SITELIBDIR} -name __pycache__ \ -type d -print0 | ${XARGS} -0 -n 1 -t ${RM} -r post-install-fix-manpages: .for f in vfs_aio_linux.8 vfs_btrfs.8 vfs_ceph.8 vfs_gpfs.8 ${RM} ${STAGEDIR}${PREFIX}/man/man8/${f} .endfor .if defined(SAMBA4_BUNDLED_LDB) && ${SAMBA4_BUNDLED_LDB} == yes . for f in ldbadd.1 ldbdel.1 ldbedit.1 ldbmodify.1 ldbrename.1 ldbsearch.1 ${MV} ${STAGEDIR}${PREFIX}/man/man1/${f} ${STAGEDIR}${PREFIX}/man/man1/samba-${f} . endfor .endif .if defined(SAMBA4_BUNDLED_TDB) && ${SAMBA4_BUNDLED_TDB} == yes . for f in tdbbackup.8 tdbdump.8 tdbrestore.8 tdbtool.8 ${MV} ${STAGEDIR}${PREFIX}/man/man8/${f} ${STAGEDIR}${PREFIX}/man/man8/samba-${f} . endfor .endif post-install: post-install-rm-junk post-install-fix-manpages ${LN} -sf smb.conf.5.gz ${STAGEDIR}${PREFIX}/man/man5/smb4.conf.5.gz # Run post-install script .for dir in ${SAMBA4_LOGDIR} ${SAMBA4_RUNDIR} ${SAMBA4_LOCKDIR} ${SAMBA4_MODULEDIR} ${INSTALL} -d -m 0755 "${STAGEDIR}${dir}" .endfor ${INSTALL} -d -m 0750 "${STAGEDIR}${SAMBA4_BINDDNSDIR}" ${INSTALL} -d -m 0750 "${STAGEDIR}${SAMBA4_PRIVATEDIR}" .for module_class in ${SAMBA4_MODULES_CLASS} ${INSTALL} -d -m 0755 "${STAGEDIR}${SAMBA4_MODULEDIR}/${module_class}" .endfor .if !defined(WITH_DEBUG) -${FIND} ${STAGEDIR}${PREFIX}/bin ${STAGEDIR}${PREFIX}/sbin ${STAGEDIR}${PREFIX}/libexec \ -type f -print0 | ${XARGS} -0 -n 1 -t ${STRIP_CMD} -${FIND} ${STAGEDIR}${PREFIX}/lib -name '*.so*' \ -type f -print0 | ${XARGS} -0 -n 1 -t ${STRIP_CMD} .endif post-install-FRUIT-off: ${RM} ${STAGEDIR}${SAMBA4_MODULEDIR}/vfs/fruit.so ${RM} ${STAGEDIR}${PREFIX}/man/man8/vfs_fruit.8 post-install-DOCS-on: ${MKDIR} ${STAGEDIR}${DOCSDIR} .for doc in ${PORTDOCS} ${INSTALL_DATA} ${WRKDIR}/${doc} ${STAGEDIR}${DOCSDIR} .endfor post-install-CLUSTER-on: ${LN} -nfs ../../../../share/ctdb/events/legacy/00.ctdb.script ${STAGEDIR}${PREFIX}/etc/ctdb/events/legacy/00.ctdb.script ${LN} -nfs ../../../../share/ctdb/events/legacy/10.interface.script ${STAGEDIR}${PREFIX}/etc/ctdb/events/legacy/10.interface.script ${LN} -nfs ../../../../share/ctdb/events/legacy/05.system.script ${STAGEDIR}${PREFIX}/etc/ctdb/events/legacy/05.system.script ${LN} -nfs ../../../../share/ctdb/events/legacy/01.reclock.script ${STAGEDIR}${PREFIX}/etc/ctdb/events/legacy/01.reclock.script .include diff --git a/net/samba413/files/patch-samba-4.14.14 b/net/samba413/files/patch-samba-4.14.14 new file mode 100644 index 000000000000..4127ab67308e --- /dev/null +++ b/net/samba413/files/patch-samba-4.14.14 @@ -0,0 +1,13366 @@ +From 5d958156c7e5d6c1da61d18fe4fd105b22639b56 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:09:53 +1200 +Subject: [PATCH 01/99] CVE-2022-32746 s4/dsdb/objectclass_attrs: Fix typo + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/dsdb/samdb/ldb_modules/objectclass_attrs.c source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +index 6ab46a729a2..2a77353cdfc 100644 +--- source4/dsdb/samdb/ldb_modules/objectclass_attrs.c ++++ source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +@@ -263,7 +263,7 @@ static int attr_handler(struct oc_context *ac) + LDB_CONTROL_AS_SYSTEM_OID); + if (!dsdb_module_am_system(ac->module) && !as_system) { + ldb_asprintf_errstring(ldb, +- "objectclass_attrs: attribute '%s' on entry '%s' must can only be modified as system", ++ "objectclass_attrs: attribute '%s' on entry '%s' can only be modified as system", + msg->elements[i].name, + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; +-- +2.25.1 + + +From 51cbeff886fe01db463448f8655a43d10040dc8b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 15:37:15 +1200 +Subject: [PATCH 02/99] CVE-2022-32746 s4:dsdb:tests: Add test for deleting a + disallowed SPN + +If an account has an SPN that requires Write Property to set, we should +still be able to delete it with just Validated Write. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + selftest/knownfail.d/acl-spn-delete | 1 + + source4/dsdb/tests/python/acl.py | 26 ++++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 selftest/knownfail.d/acl-spn-delete + +diff --git selftest/knownfail.d/acl-spn-delete selftest/knownfail.d/acl-spn-delete +new file mode 100644 +index 00000000000..32018413c49 +--- /dev/null ++++ selftest/knownfail.d/acl-spn-delete +@@ -0,0 +1 @@ ++^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\( +diff --git source4/dsdb/tests/python/acl.py source4/dsdb/tests/python/acl.py +index df0fe12bf29..d90d3b3923f 100755 +--- source4/dsdb/tests/python/acl.py ++++ source4/dsdb/tests/python/acl.py +@@ -2286,6 +2286,32 @@ class AclSPNTests(AclTests): + else: + self.fail(f'able to add disallowed SPN {not_allowed_spn}') + ++ def test_delete_disallowed_spn(self): ++ # Grant Validated-SPN property. ++ mod = f'(OA;;SW;{security.GUID_DRS_VALIDATE_SPN};;{self.user_sid1})' ++ self.sd_utils.dacl_add_ace(self.computerdn, mod) ++ ++ spn_base = f'HOST/{self.computername}' ++ ++ not_allowed_spn = f'{spn_base}/{self.dcctx.get_domain_name()}' ++ ++ # Add a disallowed SPN as admin. ++ msg = Message(Dn(self.ldb_admin, self.computerdn)) ++ msg['servicePrincipalName'] = MessageElement(not_allowed_spn, ++ FLAG_MOD_ADD, ++ 'servicePrincipalName') ++ self.ldb_admin.modify(msg) ++ ++ # Ensure we are able to delete a disallowed SPN. ++ msg = Message(Dn(self.ldb_user1, self.computerdn)) ++ msg['servicePrincipalName'] = MessageElement(not_allowed_spn, ++ FLAG_MOD_DELETE, ++ 'servicePrincipalName') ++ try: ++ self.ldb_user1.modify(msg) ++ except LdbError: ++ self.fail(f'unable to delete disallowed SPN {not_allowed_spn}') ++ + + # tests SEC_ADS_LIST vs. SEC_ADS_LIST_OBJECT + @DynamicTestCase +-- +2.25.1 + + +From a68553792a8512a2d266bbb86f064f78b5482a65 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:41:02 +1200 +Subject: [PATCH 03/99] CVE-2022-32746 s4/dsdb/partition: Fix LDB flags + comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(req_msg->elements[el_idx].flags & LDB_FLAG_MOD_MASK) != 0 + +which is true whenever any of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/partition.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git source4/dsdb/samdb/ldb_modules/partition.c source4/dsdb/samdb/ldb_modules/partition.c +index 2544a106d13..2d90ca5d1b3 100644 +--- source4/dsdb/samdb/ldb_modules/partition.c ++++ source4/dsdb/samdb/ldb_modules/partition.c +@@ -493,8 +493,8 @@ static int partition_copy_all_callback_action( + * them here too + */ + for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) { +- if (req_msg->elements[el_idx].flags & LDB_FLAG_MOD_DELETE +- || ((req_msg->elements[el_idx].flags & LDB_FLAG_MOD_REPLACE) && ++ if (LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_DELETE ++ || ((LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_REPLACE) && + req_msg->elements[el_idx].num_values == 0)) { + if (ldb_msg_find_element(modify_msg, + req_msg->elements[el_idx].name) != NULL) { +-- +2.25.1 + + +From 582ac171364f0c28f54eaf4f21b5bfa7569b5233 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:49:51 +1200 +Subject: [PATCH 04/99] CVE-2022-32746 s4:torture: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/torture/drs/rpc/dssync.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git source4/torture/drs/rpc/dssync.c source4/torture/drs/rpc/dssync.c +index cde9f78692b..ff7ce2d9074 100644 +--- source4/torture/drs/rpc/dssync.c ++++ source4/torture/drs/rpc/dssync.c +@@ -527,7 +527,9 @@ static bool test_analyse_objects(struct torture_context *tctx, + el = &new_msg->elements[idx]; + a = dsdb_attribute_by_lDAPDisplayName(ldap_schema, + el->name); +- if (!(el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE))) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + /* DRS only value */ + is_warning = false; + } else if (a->linkID & 1) { +-- +2.25.1 + + +From 0526d27e9eddd9c2a54434cf0dcdb136a6c659e4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 15:22:47 +1200 +Subject: [PATCH 05/99] CVE-2022-32746 s4/dsdb/acl: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set, so we +would not successfully return if the element was a DELETE. Correct the +expression to what it was intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + selftest/knownfail.d/acl-spn-delete | 1 - + source4/dsdb/samdb/ldb_modules/acl.c | 5 +++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + delete mode 100644 selftest/knownfail.d/acl-spn-delete + +diff --git selftest/knownfail.d/acl-spn-delete selftest/knownfail.d/acl-spn-delete +deleted file mode 100644 +index 32018413c49..00000000000 +--- selftest/knownfail.d/acl-spn-delete ++++ /dev/null +@@ -1 +0,0 @@ +-^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\( +diff --git source4/dsdb/samdb/ldb_modules/acl.c source4/dsdb/samdb/ldb_modules/acl.c +index 21e83276bfd..8016a2d4bd0 100644 +--- source4/dsdb/samdb/ldb_modules/acl.c ++++ source4/dsdb/samdb/ldb_modules/acl.c +@@ -734,8 +734,9 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, + * If not add or replace (eg delete), + * return success + */ +- if ((el->flags +- & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } +-- +2.25.1 + + +From 2869b5aa3148869edf0d079266542aef6e64608e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:43:52 +1300 +Subject: [PATCH 06/99] CVE-2022-32746 ldb:rdn_name: Use LDB_FLAG_MOD_TYPE() + for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/modules/rdn_name.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git lib/ldb/modules/rdn_name.c lib/ldb/modules/rdn_name.c +index e69ad9315ae..25cffe07591 100644 +--- lib/ldb/modules/rdn_name.c ++++ lib/ldb/modules/rdn_name.c +@@ -545,7 +545,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (e != NULL) { + ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_linearized(req->op.mod.message->dn)); +- if (e->flags == LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(e->flags) == LDB_FLAG_MOD_REPLACE) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; +-- +2.25.1 + + +From 535b5a366a2ad054f729e57e282e402cf13b2efc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 19:49:19 +1200 +Subject: [PATCH 07/99] CVE-2022-32746 s4/dsdb/repl_meta_data: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git source4/dsdb/samdb/ldb_modules/repl_meta_data.c source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index ab506cec488..29ffda75c87 100644 +--- source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3525,7 +3525,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_REPLACE) { + return ldb_module_operr(module); + } + +@@ -3558,11 +3558,11 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_DELETE) { + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[1].flags) != LDB_FLAG_MOD_ADD) { + return ldb_module_operr(module); + } + +@@ -3645,7 +3645,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[0].flags) != LDB_FLAG_MOD_ADD) { + talloc_free(ac); + return ldb_module_operr(module); + } +-- +2.25.1 + + +From bedd0b768c3f92645af033399aefd7ee971d9150 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:11:33 +1200 +Subject: [PATCH 08/99] CVE-2022-32746 s4/dsdb/tombstone_reanimate: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 64e05195798..5f8911c66be 100644 +--- source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -104,7 +104,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + if (el_dn == NULL) { + return false; + } +- if (el_dn->flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(el_dn->flags) != LDB_FLAG_MOD_REPLACE) { + return false; + } + if (el_dn->num_values != 1) { +@@ -117,7 +117,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + return false; + } + +- if (el_deleted->flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(el_deleted->flags) != LDB_FLAG_MOD_DELETE) { + return false; + } + +-- +2.25.1 + + +From 49dd9042f4ee380fa1dafcebcb54d0e1f0852463 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:12:39 +1200 +Subject: [PATCH 09/99] CVE-2022-32746 s4/registry: Use LDB_FLAG_MOD_TYPE() for + flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/lib/registry/ldb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/lib/registry/ldb.c source4/lib/registry/ldb.c +index e089355975b..db383a560da 100644 +--- source4/lib/registry/ldb.c ++++ source4/lib/registry/ldb.c +@@ -859,7 +859,7 @@ static WERROR ldb_set_value(struct hive_key *parent, + + /* Try first a "modify" and if this doesn't work do try an "add" */ + for (i = 0; i < msg->num_elements; i++) { +- if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) { + msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + } +-- +2.25.1 + + +From faa61ab3053d077ac9d0aa67e955217e85b660f4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:10:32 +1300 +Subject: [PATCH 10/99] CVE-2022-32746 ldb: Add flag to mark message element + values as shared + +When making a shallow copy of an ldb message, mark the message elements +of the copy as sharing their values with the message elements in the +original message. + +This flag value will be heeded in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 43 +++++++++++++++++++++++++++++++----- + lib/ldb/include/ldb_module.h | 6 +++++ + 2 files changed, 43 insertions(+), 6 deletions(-) + +diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c +index 57dfc5a04c2..2a9ce384bb9 100644 +--- lib/ldb/common/ldb_msg.c ++++ lib/ldb/common/ldb_msg.c +@@ -833,11 +833,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg) + ldb_msg_element_compare_name); + } + +-/* +- shallow copy a message - copying only the elements array so that the caller +- can safely add new elements without changing the message +-*/ +-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) + { + struct ldb_message *msg2; +@@ -863,6 +859,35 @@ failed: + return NULL; + } + ++/* ++ shallow copy a message - copying only the elements array so that the caller ++ can safely add new elements without changing the message ++*/ ++struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++ const struct ldb_message *msg) ++{ ++ struct ldb_message *msg2; ++ unsigned int i; ++ ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); ++ if (msg2 == NULL) { ++ return NULL; ++ } ++ ++ for (i = 0; i < msg2->num_elements; ++i) { ++ /* ++ * Mark this message's elements as sharing their values with the ++ * original message, so that we don't inadvertently modify or ++ * free them. We don't mark the original message element as ++ * shared, so the original message element should not be ++ * modified or freed while the shallow copy lives. ++ */ ++ struct ldb_message_element *el = &msg2->elements[i]; ++ el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES; ++ } ++ ++ return msg2; ++} + + /* + copy a message, allocating new memory for all parts +@@ -873,7 +898,7 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + struct ldb_message *msg2; + unsigned int i, j; + +- msg2 = ldb_msg_copy_shallow(mem_ctx, msg); ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); + if (msg2 == NULL) return NULL; + + if (msg2->dn != NULL) { +@@ -894,6 +919,12 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + goto failed; + } + } ++ ++ /* ++ * Since we copied this element's values, we can mark them as ++ * not shared. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; + } + + return msg2; +diff --git lib/ldb/include/ldb_module.h lib/ldb/include/ldb_module.h +index 8c1e5ee7936..4c7c85a17f0 100644 +--- lib/ldb/include/ldb_module.h ++++ lib/ldb/include/ldb_module.h +@@ -96,6 +96,12 @@ struct ldb_module; + */ + #define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100 + ++/* ++ * indicates that this element's values are shared with another element (for ++ * example, in a shallow copy of an ldb_message) and should not be freed ++ */ ++#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200 ++ + /* an extended match rule that always fails to match */ + #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1" + +-- +2.25.1 + + +From 4e5fb78c3dcff60aa8fd4b07dad4660bbb30532b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:35:13 +1300 +Subject: [PATCH 11/99] CVE-2022-32746 ldb: Ensure shallow copy modifications + do not affect original message + +Using the newly added ldb flag, we can now detect when a message has +been shallow-copied so that its elements share their values with the +original message elements. Then when adding values to the copied +message, we now make a copy of the shared values array first. + +This should prevent a use-after-free that occurred in LDB modules when +new values were added to a shallow copy of a message by calling +talloc_realloc() on the original values array, invalidating the 'values' +pointer in the original message element. The original values pointer can +later be used in the database audit logging module which logs database +requests, and potentially cause a crash. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 52 ++++++++++++++++++++++++++++++++------ + lib/ldb/include/ldb.h | 6 +++++ + source4/dsdb/common/util.c | 20 +++++---------- + 3 files changed, 56 insertions(+), 22 deletions(-) + +diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c +index 2a9ce384bb9..44d3b29e9a7 100644 +--- lib/ldb/common/ldb_msg.c ++++ lib/ldb/common/ldb_msg.c +@@ -417,6 +417,47 @@ int ldb_msg_add(struct ldb_message *msg, + return LDB_SUCCESS; + } + ++/* ++ * add a value to a message element ++ */ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val) ++{ ++ struct ldb_val *vals; ++ ++ if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) { ++ /* ++ * Another message is using this message element's values array, ++ * so we don't want to make any modifications to the original ++ * message, or potentially invalidate its own values by calling ++ * talloc_realloc(). Make a copy instead. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; ++ ++ vals = talloc_array(mem_ctx, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ if (el->values != NULL) { ++ memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val)); ++ } ++ } else { ++ vals = talloc_realloc(mem_ctx, el->values, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ } ++ el->values = vals; ++ el->values[el->num_values] = *val; ++ el->num_values++; ++ ++ return LDB_SUCCESS; ++} ++ + /* + add a value to a message + */ +@@ -426,7 +467,6 @@ int ldb_msg_add_value(struct ldb_message *msg, + struct ldb_message_element **return_el) + { + struct ldb_message_element *el; +- struct ldb_val *vals; + int ret; + + el = ldb_msg_find_element(msg, attr_name); +@@ -437,14 +477,10 @@ int ldb_msg_add_value(struct ldb_message *msg, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values+1); +- if (!vals) { +- return LDB_ERR_OPERATIONS_ERROR; ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; + } +- el->values = vals; +- el->values[el->num_values] = *val; +- el->num_values++; + + if (return_el) { + *return_el = el; +diff --git lib/ldb/include/ldb.h lib/ldb/include/ldb.h +index bc44157eaf4..129beefeaf5 100644 +--- lib/ldb/include/ldb.h ++++ lib/ldb/include/ldb.h +@@ -1981,6 +1981,12 @@ int ldb_msg_add_empty(struct ldb_message *msg, + int flags, + struct ldb_message_element **return_el); + ++/** ++ add a value to a message element ++*/ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val); + /** + add a element to a ldb_message + */ +diff --git source4/dsdb/common/util.c source4/dsdb/common/util.c +index 5ce4c0a5e33..577b2a33873 100644 +--- source4/dsdb/common/util.c ++++ source4/dsdb/common/util.c +@@ -816,7 +816,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -851,14 +851,10 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +@@ -872,7 +868,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -907,14 +903,10 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +-- +2.25.1 + + +From 512a2617b1593bdc16caeeeda4312a581cbb34e9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 16:30:03 +1300 +Subject: [PATCH 12/99] CVE-2022-32746 ldb: Add functions for appending to an + ldb_message + +Currently, there are many places where we use ldb_msg_add_empty() to add +an empty element to a message, and then call ldb_msg_add_value() or +similar to add values to that element. However, this performs an +unnecessary search of the message's elements to locate the new element. +Moreover, if an element with the same attribute name already exists +earlier in the message, the values will be added to that element, +instead of to the intended newly added element. + +A similar pattern exists where we add values to a message, and then call +ldb_msg_find_element() to locate that message element and sets its flags +to (e.g.) LDB_FLAG_MOD_REPLACE. This also performs an unnecessary +search, and may locate the wrong message element for setting the flags. + +To avoid these problems, add functions for appending a value to a +message, so that a particular value can be added to the end of a message +in a single operation. + +For ADD requests, it is important that no two message elements share the +same attribute name, otherwise things will break. (Normally, +ldb_msg_normalize() is called before processing the request to help +ensure this.) Thus, we must be careful not to append an attribute to an +ADD message, unless we are sure (e.g. through ldb_msg_find_element()) +that an existing element for that attribute is not present. + +These functions will be used in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++- + lib/ldb/include/ldb.h | 24 ++++++ + 2 files changed, 185 insertions(+), 4 deletions(-) + +diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c +index 44d3b29e9a7..9cd7998e21c 100644 +--- lib/ldb/common/ldb_msg.c ++++ lib/ldb/common/ldb_msg.c +@@ -509,12 +509,15 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + + + /* +- add a string element to a message ++ add a string element to a message, specifying flags + */ +-int ldb_msg_add_string(struct ldb_message *msg, +- const char *attr_name, const char *str) ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags) + { + struct ldb_val val; ++ int ret; ++ struct ldb_message_element *el = NULL; + + val.data = discard_const_p(uint8_t, str); + val.length = strlen(str); +@@ -524,7 +527,25 @@ int ldb_msg_add_string(struct ldb_message *msg, + return LDB_SUCCESS; + } + +- return ldb_msg_add_value(msg, attr_name, &val, NULL); ++ ret = ldb_msg_add_value(msg, attr_name, &val, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (flags != 0) { ++ el->flags = flags; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ add a string element to a message ++*/ ++int ldb_msg_add_string(struct ldb_message *msg, ++ const char *attr_name, const char *str) ++{ ++ return ldb_msg_add_string_flags(msg, attr_name, str, 0); + } + + /* +@@ -586,6 +607,142 @@ int ldb_msg_add_fmt(struct ldb_message *msg, + return ldb_msg_add_steal_value(msg, attr_name, &val); + } + ++static int ldb_msg_append_value_impl(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags, ++ struct ldb_message_element **return_el) ++{ ++ struct ldb_message_element *el = NULL; ++ int ret; ++ ++ ret = ldb_msg_add_empty(msg, attr_name, flags, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (return_el != NULL) { ++ *return_el = el; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ append a value to a message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags) ++{ ++ return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL); ++} ++ ++/* ++ append a value to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags) ++{ ++ int ret; ++ struct ldb_message_element *el = NULL; ++ ++ ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el); ++ if (ret == LDB_SUCCESS) { ++ talloc_steal(el->values, val->data); ++ } ++ return ret; ++} ++ ++/* ++ append a string element to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a string element to a message ++*/ ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = discard_const_p(uint8_t, str); ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a DN element to a message ++ WARNING: this uses the linearized string from the dn, and does not ++ copy the string. ++*/ ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags) ++{ ++ char *str = ldb_dn_alloc_linearized(msg, dn); ++ ++ if (str == NULL) { ++ /* we don't want to have unknown DNs added */ ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ return ldb_msg_append_steal_string(msg, attr_name, str, flags); ++} ++ ++/* ++ append a printf formatted element to a message ++*/ ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) ++{ ++ struct ldb_val val; ++ va_list ap; ++ char *str = NULL; ++ ++ va_start(ap, fmt); ++ str = talloc_vasprintf(msg, fmt, ap); ++ va_end(ap); ++ ++ if (str == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ + /* + compare two ldb_message_element structures + assumes case sensitive comparison +diff --git lib/ldb/include/ldb.h lib/ldb/include/ldb.h +index 129beefeaf5..63d8aedd672 100644 +--- lib/ldb/include/ldb.h ++++ lib/ldb/include/ldb.h +@@ -2002,12 +2002,36 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + struct ldb_val *val); + int ldb_msg_add_steal_string(struct ldb_message *msg, + const char *attr_name, char *str); ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); + int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str); + int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn); + int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); ++/** ++ append a element to a ldb_message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags); ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags); ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); + + /** + compare two message elements - return 0 on match +-- +2.25.1 + + +From f419753d1c7a373fb32ffe20930a6e084e44b44d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:27:37 +1300 +Subject: [PATCH 13/99] CVE-2022-32746 ldb: Make use of functions for appending + to an ldb_message + +This aims to minimise usage of the error-prone pattern of searching for +a just-added message element in order to make modifications to it (and +potentially finding the wrong element). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/ldb_map/ldb_map.c | 5 +- + lib/ldb/ldb_map/ldb_map_inbound.c | 9 +- + lib/ldb/modules/rdn_name.c | 22 +--- + source3/passdb/pdb_samba_dsdb.c | 14 +-- + source4/dns_server/dnsserver_common.c | 12 +- + source4/dsdb/common/util.c | 114 ++++++++++++++---- + source4/dsdb/samdb/ldb_modules/descriptor.c | 10 +- + source4/dsdb/samdb/ldb_modules/objectguid.c | 20 +-- + .../dsdb/samdb/ldb_modules/partition_init.c | 14 +-- + .../dsdb/samdb/ldb_modules/repl_meta_data.c | 24 +--- + source4/dsdb/samdb/ldb_modules/samldb.c | 78 +++++------- + .../samdb/ldb_modules/tombstone_reanimate.c | 12 +- + source4/nbt_server/wins/winsdb.c | 13 +- + source4/rpc_server/lsa/dcesrv_lsa.c | 55 +++------ + source4/winbind/idmap.c | 10 +- + 15 files changed, 183 insertions(+), 229 deletions(-) + +diff --git lib/ldb/ldb_map/ldb_map.c lib/ldb/ldb_map/ldb_map.c +index b453dff80d2..c7b0c228631 100644 +--- lib/ldb/ldb_map/ldb_map.c ++++ lib/ldb/ldb_map/ldb_map.c +@@ -946,10 +946,7 @@ struct ldb_request *map_build_fixup_req(struct map_context *ac, + if ( ! dn || ! ldb_dn_validate(msg->dn)) { + goto failed; + } +- if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { ++ if (ldb_msg_append_string(msg, IS_MAPPED, dn, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git lib/ldb/ldb_map/ldb_map_inbound.c lib/ldb/ldb_map/ldb_map_inbound.c +index 324295737da..50b9427c26c 100644 +--- lib/ldb/ldb_map/ldb_map_inbound.c ++++ lib/ldb/ldb_map/ldb_map_inbound.c +@@ -569,12 +569,9 @@ static int map_modify_do_local(struct map_context *ac) + /* No local record present, add it instead */ + /* Add local 'IS_MAPPED' */ + /* TODO: use GUIDs here instead */ +- if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED, +- LDB_FLAG_MOD_ADD, NULL) != 0) { +- return LDB_ERR_OPERATIONS_ERROR; +- } +- ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, +- ac->remote_req->op.mod.message->dn); ++ ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED, ++ ac->remote_req->op.mod.message->dn, ++ LDB_FLAG_MOD_ADD); + if (ret != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } +diff --git lib/ldb/modules/rdn_name.c lib/ldb/modules/rdn_name.c +index 25cffe07591..3cb62bf567b 100644 +--- lib/ldb/modules/rdn_name.c ++++ lib/ldb/modules/rdn_name.c +@@ -308,16 +308,10 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares) + } + rdn_val = ldb_val_dup(msg, rdn_val_p); + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } +- if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } + +@@ -466,11 +460,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +@@ -479,11 +469,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +diff --git source3/passdb/pdb_samba_dsdb.c source3/passdb/pdb_samba_dsdb.c +index 93e8f5bebe6..b2063825c04 100644 +--- source3/passdb/pdb_samba_dsdb.c ++++ source3/passdb/pdb_samba_dsdb.c +@@ -2855,18 +2855,10 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m, + } + + msg->num_elements = 0; +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_empty() failed\n")); +- TALLOC_FREE(tmp_ctx); +- ldb_transaction_cancel(state->ldb); +- return false; +- } +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &new_val, NULL); +- if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_value() failed\n")); ++ DEBUG(0, ("ldb_msg_append_value() failed\n")); + TALLOC_FREE(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return false; +diff --git source4/dns_server/dnsserver_common.c source4/dns_server/dnsserver_common.c +index bcb0d087faf..cb9a082ebf6 100644 +--- source4/dns_server/dnsserver_common.c ++++ source4/dns_server/dnsserver_common.c +@@ -1092,15 +1092,9 @@ WERROR dns_common_replace(struct ldb_context *samdb, + } + + if (was_tombstoned || become_tombstoned) { +- ret = ldb_msg_add_empty(msg, "dNSTombstoned", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- werr = DNS_ERR(SERVER_FAILURE); +- goto exit; +- } +- +- ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", +- become_tombstoned ? "TRUE" : "FALSE"); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "dNSTombstoned", "%s", ++ become_tombstoned ? "TRUE" : "FALSE"); + if (ret != LDB_SUCCESS) { + werr = DNS_ERR(SERVER_FAILURE); + goto exit; +diff --git source4/dsdb/common/util.c source4/dsdb/common/util.c +index 577b2a33873..10d6ea8883b 100644 +--- source4/dsdb/common/util.c ++++ source4/dsdb/common/util.c +@@ -924,6 +924,16 @@ int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct l + return ldb_msg_add_string(msg, attr_name, s); + } + ++int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_add_string_flags(msg, attr_name, s, flags); ++} ++ + /* + * Add an unsigned int element to a message + * +@@ -942,6 +952,12 @@ int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct + return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v); + } + ++int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ + /* + add a (signed) int64_t element to a message + */ +@@ -973,6 +989,68 @@ int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc + return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v); + } + ++/* ++ append a int element to a message ++*/ ++int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ ++/* ++ append a (signed) int64_t element to a message ++*/ ++int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int64_t v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int64_t (uint64_t) element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, uint64_t v, int flags) ++{ ++ return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags); ++} ++ + /* + add a samr_Password element to a message + */ +@@ -2814,15 +2892,8 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + tdo_msg->num_elements = 0; + TALLOC_FREE(tdo_msg->elements); + +- ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- ldb_transaction_cancel(ldb); +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming", +- &new_val, NULL); ++ ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(ldb); + TALLOC_FREE(frame); +@@ -3187,6 +3258,7 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb, + /* + adds the given GUID to the given ldb_message. This value is added + for the given attr_name (may be either "objectGUID" or "parentGUID"). ++ This function is used in processing 'add' requests. + */ + int dsdb_msg_add_guid(struct ldb_message *msg, + struct GUID *guid, +@@ -5656,7 +5728,8 @@ int dsdb_user_obj_set_defaults(struct ldb_context *ldb, + } + + /** +- * Sets 'sAMAccountType on user object based on userAccountControl ++ * Sets 'sAMAccountType on user object based on userAccountControl. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5668,21 +5741,19 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + { + int ret; + uint32_t account_type; +- struct ldb_message_element *el; + + account_type = ds_uf2atype(user_account_control); + if (account_type == 0) { + ldb_set_errstring(ldb, "dsdb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (account_type_p) { + *account_type_p = account_type; +@@ -5692,7 +5763,8 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + } + + /** +- * Determine and set primaryGroupID based on userAccountControl value ++ * Determine and set primaryGroupID based on userAccountControl value. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5704,17 +5776,15 @@ int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_messa + { + int ret; + uint32_t rid; +- struct ldb_message_element *el; + + rid = ds_uf2prim_group_rid(user_account_control); + +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "primaryGroupID", rid); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "primaryGroupID", rid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (group_rid_p) { + *group_rid_p = rid; +diff --git source4/dsdb/samdb/ldb_modules/descriptor.c source4/dsdb/samdb/ldb_modules/descriptor.c +index daa08c2ebc7..4b01961dcb0 100644 +--- source4/dsdb/samdb/ldb_modules/descriptor.c ++++ source4/dsdb/samdb/ldb_modules/descriptor.c +@@ -857,14 +857,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); + } + +- ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", +- LDB_FLAG_MOD_REPLACE, +- &sd_element); +- if (ret != LDB_SUCCESS) { +- return ldb_oom(ldb); +- } +- ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", +- sd, NULL); ++ ret = ldb_msg_append_value(msg, "nTSecurityDescriptor", ++ sd, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } +diff --git source4/dsdb/samdb/ldb_modules/objectguid.c source4/dsdb/samdb/ldb_modules/objectguid.c +index bc3260cf0d8..0fe995a5763 100644 +--- source4/dsdb/samdb/ldb_modules/objectguid.c ++++ source4/dsdb/samdb/ldb_modules/objectguid.c +@@ -41,7 +41,6 @@ + */ + static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + { +- struct ldb_message_element *el; + char *s; + int ret; + +@@ -54,16 +53,13 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + return LDB_ERR_OPERATIONS_ERROR; + } + +- ret = ldb_msg_add_string(msg, attr, s); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = ldb_msg_append_string(msg, attr, s, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +@@ -73,23 +69,19 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr, uint64_t v) + { +- struct ldb_message_element *el; + int ret; + + if (ldb_msg_find_element(msg, attr) != NULL) { + return LDB_SUCCESS; + } + +- ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = samdb_msg_append_uint64(ldb, msg, msg, attr, v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +diff --git source4/dsdb/samdb/ldb_modules/partition_init.c source4/dsdb/samdb/ldb_modules/partition_init.c +index 58c65ccedd0..484b5bffb27 100644 +--- source4/dsdb/samdb/ldb_modules/partition_init.c ++++ source4/dsdb/samdb/ldb_modules/partition_init.c +@@ -742,10 +742,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + + mod_msg->dn = ldb_dn_new(mod_msg, ldb, DSDB_PARTITION_DN); +- ret = ldb_msg_add_empty(mod_msg, DSDB_PARTITION_ATTR, LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } + + casefold_dn = ldb_dn_get_casefold(dn); + +@@ -785,18 +781,16 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + partition_record = talloc_asprintf(mod_msg, "%s:%s", casefold_dn, filename); + +- ret = ldb_msg_add_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record); ++ ret = ldb_msg_append_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { + /* this new partition is a partial replica */ +- ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } +- ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn)); ++ ret = ldb_msg_append_fmt(mod_msg, LDB_FLAG_MOD_ADD, ++ "partialReplica", "%s", ldb_dn_get_linearized(dn)); + if (ret != LDB_SUCCESS) { + return ret; + } +diff --git source4/dsdb/samdb/ldb_modules/repl_meta_data.c source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index 29ffda75c87..eec1e639856 100644 +--- source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3888,22 +3888,12 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are + ldb_operr(ldb)); + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); +@@ -5161,16 +5151,10 @@ static int replmd_name_modify(struct replmd_replicated_request *ar, + goto failed; + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git source4/dsdb/samdb/ldb_modules/samldb.c source4/dsdb/samdb/ldb_modules/samldb.c +index 5fb9c195c9a..107e643e492 100644 +--- source4/dsdb/samdb/ldb_modules/samldb.c ++++ source4/dsdb/samdb/ldb_modules/samldb.c +@@ -1103,14 +1103,11 @@ static int samldb_rodc_add(struct samldb_ctx *ac) + return LDB_ERR_OTHER; + + found: +- ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber", +- LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL); +- if (ret != LDB_SUCCESS) { +- return ldb_operr(ldb); +- } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "msDS-SecondaryKrbTgtNumber", krbtgt_number); ++ ldb_msg_remove_attr(ac->msg, "msDS-SecondaryKrbTgtNumber"); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "msDS-SecondaryKrbTgtNumber", krbtgt_number, ++ LDB_FLAG_INTERNAL_DISABLE_VALIDATION); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } +@@ -1792,7 +1789,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + void *skip_allocate_sids = ldb_get_opaque(ldb, + "skip_allocate_sids"); +- struct ldb_message_element *el, *el2; ++ struct ldb_message_element *el; + struct dom_sid *sid; + int ret; + +@@ -1926,23 +1923,17 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + /* "isCriticalSystemObject" might be set */ + if (user_account_control & + (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "TRUE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "TRUE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "FALSE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "FALSE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ +@@ -2018,14 +2009,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, ac->msg, ac->msg, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + break; + } +@@ -2945,26 +2935,23 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + + if (old_atype != new_atype) { +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", new_atype); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "sAMAccountType", new_atype, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ + if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { + /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */ + ldb_msg_remove_attr(ac->msg, "lockoutTime"); +- ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", +- (NTTIME)0); ++ ret = samdb_msg_append_uint64(ldb, ac->msg, ac->msg, "lockoutTime", ++ (NTTIME)0, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "lockoutTime"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* +@@ -2975,14 +2962,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + * creating the attribute. + */ + if (old_is_critical != new_is_critical || old_atype != new_atype) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- new_is_critical ? "TRUE": "FALSE"); ++ ret = ldb_msg_append_string(ac->msg, "isCriticalSystemObject", ++ new_is_critical ? "TRUE": "FALSE", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + if (!ldb_msg_find_element(ac->msg, "primaryGroupID") && +@@ -2995,14 +2980,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "primaryGroupID", new_pgrid); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "primaryGroupID", new_pgrid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Propagate eventual "userAccountControl" attribute changes */ +@@ -3205,13 +3188,12 @@ static int samldb_lockout_time(struct samldb_ctx *ac) + + /* lockoutTime == 0 resets badPwdCount */ + ldb_msg_remove_attr(ac->msg, "badPwdCount"); +- ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, +- "badPwdCount", 0); ++ ret = samdb_msg_append_int(ldb, ac->msg, ac->msg, ++ "badPwdCount", 0, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "badPwdCount"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +@@ -3309,13 +3291,11 @@ static int samldb_group_type_change(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType", +- account_type); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, "sAMAccountType", ++ account_type, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +diff --git source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 5f8911c66be..99c5955e9e7 100644 +--- source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -294,14 +294,13 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, + "reanimate: Unrecognized account type!"); + } +- ret = samdb_msg_add_uint(ldb, ac->mod_msg, ac->mod_msg, +- "sAMAccountType", account_type); ++ ret = samdb_msg_append_uint(ldb, ac->mod_msg, ac->mod_msg, ++ "sAMAccountType", account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, + "reanimate: Failed to add sAMAccountType to restored object."); + } +- el = ldb_msg_find_element(ac->mod_msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + /* Default values set by Windows */ + ret = samdb_find_or_add_attribute(ldb, ac->mod_msg, +@@ -324,12 +323,11 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ret; + } + +- ret = ldb_msg_add_string(ac->mod_msg, "objectCategory", value); ++ ret = ldb_msg_append_string(ac->mod_msg, "objectCategory", value, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->mod_msg, "objectCategory"); +- el->flags = LDB_FLAG_MOD_ADD; + } + + return LDB_SUCCESS; +diff --git source4/nbt_server/wins/winsdb.c source4/nbt_server/wins/winsdb.c +index e4a7c2042ed..2a05e96bca4 100644 +--- source4/nbt_server/wins/winsdb.c ++++ source4/nbt_server/wins/winsdb.c +@@ -102,13 +102,11 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion) + msg->dn = dn; + + +- ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_string(msg, "objectClass", "winsMaxVersion", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion"); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "maxVersion", "%llu", (long long)newMaxVersion); + if (ret != LDB_SUCCESS) goto failed; + + ret = ldb_modify(wins_db, msg); +@@ -779,8 +777,7 @@ static struct ldb_message *winsdb_message(struct ldb_context *ldb, + ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]); + } + if (rec->registered_by) { +- ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL); +- ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by); ++ ret |= ldb_msg_append_string(msg, "registeredBy", rec->registered_by, 0); + } + if (ret != LDB_SUCCESS) goto failed; + return msg; +diff --git source4/rpc_server/lsa/dcesrv_lsa.c source4/rpc_server/lsa/dcesrv_lsa.c +index 15b068aec62..a165ab2b9d6 100644 +--- source4/rpc_server/lsa/dcesrv_lsa.c ++++ source4/rpc_server/lsa/dcesrv_lsa.c +@@ -1778,12 +1778,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx, + goto done; + } + +- ret = ldb_msg_add_empty(dest, attribute, flags, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value); ++ ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -1874,13 +1869,7 @@ static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx, + continue; + } + +- ret = ldb_msg_add_empty(msg, attribute, +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = ldb_msg_add_value(msg, attribute, &v, NULL); ++ ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -2166,28 +2155,30 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call, + } + + if (add_incoming || del_incoming) { +- ret = ldb_msg_add_empty(msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_incoming) { +- ret = ldb_msg_add_value(msg, "trustAuthIncoming", +- &trustAuthIncoming, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthIncoming", ++ &trustAuthIncoming, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthIncoming", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + } + } + if (add_outgoing || del_outgoing) { +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_outgoing) { +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &trustAuthOutgoing, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -4635,14 +4626,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat + goto done; + } + +- ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo", +- &ft_blob, NULL); ++ ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo", ++ &ft_blob, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + status = NT_STATUS_NO_MEMORY; + goto done; +diff --git source4/winbind/idmap.c source4/winbind/idmap.c +index c4039be473a..c6375f8357a 100644 +--- source4/winbind/idmap.c ++++ source4/winbind/idmap.c +@@ -672,14 +672,8 @@ static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, + vals[1].data = (uint8_t *)hwm_string; + vals[1].length = strlen(hwm_string); + } else { +- ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD, +- NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NONE_MAPPED; +- goto failed; +- } +- +- ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string); ++ ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) + { + status = NT_STATUS_NONE_MAPPED; +-- +2.25.1 + + +From 7270b68386692829f97d5c51c50108db395b263e Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Tue, 14 Jun 2022 15:43:26 +1200 +Subject: [PATCH 14/99] CVE-2022-32746 ldb: Release LDB 2.3.4 + +* CVE-2022-32746 Use-after-free occurring in database audit logging module (bug 15009) + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Andrew Bartlett +--- + lib/ldb/ABI/ldb-2.3.4.sigs | 291 ++++++++++++++++++++++++++++++ + lib/ldb/ABI/pyldb-util-2.3.4.sigs | 3 + + lib/ldb/wscript | 2 +- + 3 files changed, 295 insertions(+), 1 deletion(-) + create mode 100644 lib/ldb/ABI/ldb-2.3.4.sigs + create mode 100644 lib/ldb/ABI/pyldb-util-2.3.4.sigs + +diff --git lib/ldb/ABI/ldb-2.3.4.sigs lib/ldb/ABI/ldb-2.3.4.sigs +new file mode 100644 +index 00000000000..40388d9e330 +--- /dev/null ++++ lib/ldb/ABI/ldb-2.3.4.sigs +@@ -0,0 +1,291 @@ ++ldb_add: int (struct ldb_context *, const struct ldb_message *) ++ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *) ++ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...) ++ldb_attr_casefold: char *(TALLOC_CTX *, const char *) ++ldb_attr_dn: int (const char *) ++ldb_attr_in_list: int (const char * const *, const char *) ++ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *) ++ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *) ++ldb_base64_decode: int (char *) ++ldb_base64_encode: char *(TALLOC_CTX *, const char *, int) ++ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *) ++ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val) ++ldb_binary_encode_string: char *(TALLOC_CTX *, const char *) ++ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) ++ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t) ++ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t) ++ldb_check_critical_controls: int (struct ldb_control **) ++ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) ++ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) ++ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **) ++ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *) ++ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *) ++ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) ++ldb_debug_add: void (struct ldb_context *, const char *, ...) ++ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level) ++ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) ++ldb_delete: int (struct ldb_context *, struct ldb_dn *) ++ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *) ++ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...) ++ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *) ++ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...) ++ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) ++ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *) ++ldb_dn_check_special: bool (struct ldb_dn *, const char *) ++ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *) ++ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *) ++ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val) ++ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *) ++ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *) ++ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *) ++ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *) ++ldb_dn_get_casefold: const char *(struct ldb_dn *) ++ldb_dn_get_comp_num: int (struct ldb_dn *) ++ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int) ++ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int) ++ldb_dn_get_extended_comp_num: int (struct ldb_dn *) ++ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *) ++ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int) ++ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *) ++ldb_dn_get_linearized: const char *(struct ldb_dn *) ++ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) ++ldb_dn_get_rdn_name: const char *(struct ldb_dn *) ++ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *) ++ldb_dn_has_extended: bool (struct ldb_dn *) ++ldb_dn_is_null: bool (struct ldb_dn *) ++ldb_dn_is_special: bool (struct ldb_dn *) ++ldb_dn_is_valid: bool (struct ldb_dn *) ++ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) ++ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) ++ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) ++ldb_dn_minimise: bool (struct ldb_dn *) ++ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *) ++ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...) ++ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int) ++ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int) ++ldb_dn_remove_extended_components: void (struct ldb_dn *) ++ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *) ++ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val) ++ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *) ++ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *) ++ldb_dn_validate: bool (struct ldb_dn *) ++ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *) ++ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int) ++ldb_errstring: const char *(struct ldb_context *) ++ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **) ++ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *) ++ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) ++ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *) ++ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *) ++ldb_get_create_perms: unsigned int (struct ldb_context *) ++ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *) ++ldb_get_event_context: struct tevent_context *(struct ldb_context *) ++ldb_get_flags: unsigned int (struct ldb_context *) ++ldb_get_opaque: void *(struct ldb_context *, const char *) ++ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *) ++ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *) ++ldb_global_init: int (void) ++ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *) ++ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) ++ldb_handle_use_global_event_context: void (struct ldb_handle *) ++ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) ++ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) ++ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *) ++ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) ++ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) ++ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **) ++ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) ++ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) ++ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *) ++ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *) ++ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **) ++ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *) ++ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *) ++ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) ++ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) ++ldb_load_modules: int (struct ldb_context *, const char **) ++ldb_map_add: int (struct ldb_module *, struct ldb_request *) ++ldb_map_delete: int (struct ldb_module *, struct ldb_request *) ++ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *) ++ldb_map_modify: int (struct ldb_module *, struct ldb_request *) ++ldb_map_rename: int (struct ldb_module *, struct ldb_request *) ++ldb_map_search: int (struct ldb_module *, struct ldb_request *) ++ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) ++ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) ++ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) ++ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) ++ldb_mod_register_control: int (struct ldb_module *, const char *) ++ldb_modify: int (struct ldb_context *, const struct ldb_message *) ++ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) ++ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *) ++ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) ++ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) ++ldb_module_flags: uint32_t (struct ldb_context *) ++ldb_module_get_ctx: struct ldb_context *(struct ldb_module *) ++ldb_module_get_name: const char *(struct ldb_module *) ++ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *) ++ldb_module_get_private: void *(struct ldb_module *) ++ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *) ++ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) ++ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) ++ldb_module_next: struct ldb_module *(struct ldb_module *) ++ldb_module_popt_options: struct poptOption **(struct ldb_context *) ++ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **) ++ldb_module_send_referral: int (struct ldb_request *, char *) ++ldb_module_set_next: void (struct ldb_module *, struct ldb_module *) ++ldb_module_set_private: void (struct ldb_module *, void *) ++ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type) ++ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *) ++ldb_modules_load: int (const char *, const char *) ++ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int) ++ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **) ++ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...) ++ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *) ++ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *) ++ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *) ++ldb_msg_add_string: int (struct ldb_message *, const char *, const char *) ++ldb_msg_add_string_flags: int (struct ldb_message *, const char *, const char *, int) ++ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **) ++ldb_msg_append_fmt: int (struct ldb_message *, int, const char *, const char *, ...) ++ldb_msg_append_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *, int) ++ldb_msg_append_steal_string: int (struct ldb_message *, const char *, char *, int) ++ldb_msg_append_steal_value: int (struct ldb_message *, const char *, struct ldb_val *, int) ++ldb_msg_append_string: int (struct ldb_message *, const char *, const char *, int) ++ldb_msg_append_value: int (struct ldb_message *, const char *, const struct ldb_val *, int) ++ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *) ++ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *) ++ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) ++ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *) ++ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) ++ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *) ++ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **) ++ldb_msg_element_add_value: int (TALLOC_CTX *, struct ldb_message_element *, const struct ldb_val *) ++ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *) ++ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *) ++ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *) ++ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int) ++ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *) ++ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double) ++ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int) ++ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t) ++ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *) ++ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int) ++ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t) ++ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) ++ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t) ++ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *) ++ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *) ++ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *) ++ldb_msg_new: struct ldb_message *(TALLOC_CTX *) ++ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **) ++ldb_msg_remove_attr: void (struct ldb_message *, const char *) ++ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *) ++ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *) ++ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *) ++ldb_msg_sort_elements: void (struct ldb_message *) ++ldb_next_del_trans: int (struct ldb_module *) ++ldb_next_end_trans: int (struct ldb_module *) ++ldb_next_init: int (struct ldb_module *) ++ldb_next_prepare_commit: int (struct ldb_module *) ++ldb_next_read_lock: int (struct ldb_module *) ++ldb_next_read_unlock: int (struct ldb_module *) ++ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *) ++ldb_next_request: int (struct ldb_module *, struct ldb_request *) ++ldb_next_start_trans: int (struct ldb_module *) ++ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *) ++ldb_options_copy: const char **(TALLOC_CTX *, const char **) ++ldb_options_find: const char *(struct ldb_context *, const char **, const char *) ++ldb_options_get: const char **(struct ldb_context *) ++ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) ++ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *) ++ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **) ++ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *) ++ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *) ++ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *) ++ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *) ++ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) ++ldb_register_backend: int (const char *, ldb_connect_fn, bool) ++ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *) ++ldb_register_hook: int (ldb_hook_fn) ++ldb_register_module: int (const struct ldb_module_ops *) ++ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *) ++ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *) ++ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *) ++ldb_req_get_custom_flags: uint32_t (struct ldb_request *) ++ldb_req_is_untrusted: bool (struct ldb_request *) ++ldb_req_location: const char *(struct ldb_request *) ++ldb_req_mark_trusted: void (struct ldb_request *) ++ldb_req_mark_untrusted: void (struct ldb_request *) ++ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t) ++ldb_req_set_location: void (struct ldb_request *, const char *) ++ldb_request: int (struct ldb_context *, struct ldb_request *) ++ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *) ++ldb_request_done: int (struct ldb_request *, int) ++ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *) ++ldb_request_get_status: int (struct ldb_request *) ++ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *) ++ldb_request_set_state: void (struct ldb_request *, int) ++ldb_reset_err_string: void (struct ldb_context *) ++ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***) ++ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *) ++ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *) ++ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *) ++ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *) ++ldb_schema_attribute_remove: void (struct ldb_context *, const char *) ++ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int) ++ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *) ++ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) ++ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) ++ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...) ++ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *) ++ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *) ++ldb_set_create_perms: void (struct ldb_context *, unsigned int) ++ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *) ++ldb_set_debug_stderr: int (struct ldb_context *) ++ldb_set_default_dns: void (struct ldb_context *) ++ldb_set_errstring: void (struct ldb_context *, const char *) ++ldb_set_event_context: void (struct ldb_context *, struct tevent_context *) ++ldb_set_flags: void (struct ldb_context *, unsigned int) ++ldb_set_modules_dir: void (struct ldb_context *, const char *) ++ldb_set_opaque: int (struct ldb_context *, const char *, void *) ++ldb_set_require_private_event_context: void (struct ldb_context *) ++ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int) ++ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *) ++ldb_set_utf8_default: void (struct ldb_context *) ++ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t)) ++ldb_setup_wellknown_attributes: int (struct ldb_context *) ++ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *) ++ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) ++ldb_strerror: const char *(int) ++ldb_string_to_time: time_t (const char *) ++ldb_string_utc_to_time: time_t (const char *) ++ldb_timestring: char *(TALLOC_CTX *, time_t) ++ldb_timestring_utc: char *(TALLOC_CTX *, time_t) ++ldb_transaction_cancel: int (struct ldb_context *) ++ldb_transaction_cancel_noerr: int (struct ldb_context *) ++ldb_transaction_commit: int (struct ldb_context *) ++ldb_transaction_prepare_commit: int (struct ldb_context *) ++ldb_transaction_start: int (struct ldb_context *) ++ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *) ++ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) ++ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) ++ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) ++ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) ++ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) ++ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) ++ldb_val_string_cmp: int (const struct ldb_val *, const char *) ++ldb_val_to_time: int (const struct ldb_val *, time_t *) ++ldb_valid_attr_name: int (const char *) ++ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list) ++ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) +diff --git lib/ldb/ABI/pyldb-util-2.3.4.sigs lib/ldb/ABI/pyldb-util-2.3.4.sigs +new file mode 100644 +index 00000000000..164a806b2ff +--- /dev/null ++++ lib/ldb/ABI/pyldb-util-2.3.4.sigs +@@ -0,0 +1,3 @@ ++pyldb_Dn_FromDn: PyObject *(struct ldb_dn *) ++pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **) ++pyldb_check_type: bool (PyObject *, const char *) + +-- +2.25.1 + + +From 6237c85565332e0be1890dd57cc7e25fb76571d7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 17:03:10 +1300 +Subject: [PATCH 15/99] CVE-2022-32745 s4/dsdb/samldb: Check for empty values + array + +This avoids potentially trying to access the first element of an empty +array. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/samldb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git source4/dsdb/samdb/ldb_modules/samldb.c source4/dsdb/samdb/ldb_modules/samldb.c +index 107e643e492..3625bb42e58 100644 +--- source4/dsdb/samdb/ldb_modules/samldb.c ++++ source4/dsdb/samdb/ldb_modules/samldb.c +@@ -751,7 +751,7 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac) + return ret; + } + +- if (el == NULL) { ++ if (el == NULL || el->num_values == 0) { + return LDB_SUCCESS; + } + +@@ -919,7 +919,7 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) + return ret; + } + +- if (el == NULL) { ++ if (el == NULL || el->num_values == 0) { + return LDB_SUCCESS; + } + +-- +2.25.1 + + +From 7c8427e5d2f247921ab44996829acfed1f5f2360 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 17 Feb 2022 11:11:53 +1300 +Subject: [PATCH 16/99] CVE-2022-32745 s4/dsdb/util: Use correct value for loop + count limit + +Currently, we can crash the server by sending a large number of values +of a specific attribute (such as sAMAccountName) spread across a few +message elements. If val_count is larger than the total number of +elements, we get an access beyond the elements array. + +Similarly, we can include unrelated message elements prior to the +message elements of the attribute in question, so that not all of the +attribute's values are copied into the returned elements values array. +This can cause the server to access uninitialised data, likely resulting +in a crash or unexpected behaviour. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c +index 405febf0b3d..14947746837 100644 +--- source4/dsdb/samdb/ldb_modules/util.c ++++ source4/dsdb/samdb/ldb_modules/util.c +@@ -1546,7 +1546,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + + v = _el->values; + +- for (i = 0; i < val_count; i++) { ++ for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + if ((operation == LDB_MODIFY) && + (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) +-- +2.25.1 + + +From 4d2d30c21b16a53d5547cb803efe49cb6304ce37 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 17 Feb 2022 11:13:38 +1300 +Subject: [PATCH 17/99] CVE-2022-32745 s4/dsdb/util: Don't call memcpy() with a + NULL pointer + +Doing so is undefined behaviour. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c +index 14947746837..35ae110b5ef 100644 +--- source4/dsdb/samdb/ldb_modules/util.c ++++ source4/dsdb/samdb/ldb_modules/util.c +@@ -1548,15 +1548,19 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { ++ const struct ldb_message_element *tmp_el = &msg->elements[i]; + if ((operation == LDB_MODIFY) && +- (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) ++ (LDB_FLAG_MOD_TYPE(tmp_el->flags) + == LDB_FLAG_MOD_DELETE)) { + continue; + } ++ if (tmp_el->values == NULL || tmp_el->num_values == 0) { ++ continue; ++ } + memcpy(v, +- msg->elements[i].values, +- msg->elements[i].num_values); +- v += msg->elements[i].num_values; ++ tmp_el->values, ++ tmp_el->num_values); ++ v += tmp_el->num_values; + } + } + +-- +2.25.1 + + +From 65d96369fa4f915f01e203cfc8b15e48c5b4b440 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 3 Jun 2022 16:16:31 +1200 +Subject: [PATCH 18/99] CVE-2022-32745 s4/dsdb/util: Correctly copy values into + message element + +To use memcpy(), we need to specify the number of bytes to copy, rather +than the number of ldb_val structures. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c +index 35ae110b5ef..e7fe8f855df 100644 +--- source4/dsdb/samdb/ldb_modules/util.c ++++ source4/dsdb/samdb/ldb_modules/util.c +@@ -1559,7 +1559,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + } + memcpy(v, + tmp_el->values, +- tmp_el->num_values); ++ tmp_el->num_values * sizeof(*v)); + v += tmp_el->num_values; + } + } +-- +2.25.1 + + +From 34eb92a2066cc403aac5a3708257b04a40ba19ee Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Sat, 19 Sep 2020 14:16:20 +0200 +Subject: [PATCH 19/99] s4:mit-kdb: Force canonicalization for looking up + principals + +See also +https://github.com/krb5/krb5/commit/ac8865a22138ab0c657208c41be8fd6bc7968148 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Isaac Boukris +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon Nov 29 09:32:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 90febd2a33b88af49af595fe0e995d6ba0f33a1b) + +[jsutton@samba.org Removed MIT knownfail changes] +--- + source4/heimdal/lib/hdb/hdb.h | 1 + + source4/kdc/db-glue.c | 7 ++++++- + source4/kdc/mit_samba.c | 8 ++++++++ + source4/kdc/sdb.h | 1 + + 4 files changed, 16 insertions(+), 1 deletion(-) + +diff --git source4/heimdal/lib/hdb/hdb.h source4/heimdal/lib/hdb/hdb.h +index 5ef9d9565f3..dafaffc6c2d 100644 +--- source4/heimdal/lib/hdb/hdb.h ++++ source4/heimdal/lib/hdb/hdb.h +@@ -63,6 +63,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; + #define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */ + #define HDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define HDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define HDB_F_FORCE_CANON 16384 /* force canonicalition */ + + /* hdb_capability_flags */ + #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index 3a7e2176653..ac47fe78373 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -957,11 +957,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + krb5_clear_error_message(context); + goto out; + } +- } else if ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) { ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ + * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. + */ + ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); + if (ret) { +diff --git source4/kdc/mit_samba.c source4/kdc/mit_samba.c +index e015c5a52db..c2a604045d9 100644 +--- source4/kdc/mit_samba.c ++++ source4/kdc/mit_samba.c +@@ -195,6 +195,14 @@ int mit_samba_get_principal(struct mit_samba_context *ctx, + return ENOMEM; + } + ++#if KRB5_KDB_API_VERSION >= 10 ++ /* ++ * The MIT KDC code that wants the canonical name in all lookups, and ++ * takes care to canonicalize only when appropriate. ++ */ ++ sflags |= SDB_F_FORCE_CANON; ++#endif ++ + if (kflags & KRB5_KDB_FLAG_CANONICALIZE) { + sflags |= SDB_F_CANON; + } +diff --git source4/kdc/sdb.h source4/kdc/sdb.h +index c929acccce6..a9115ec23d7 100644 +--- source4/kdc/sdb.h ++++ source4/kdc/sdb.h +@@ -116,6 +116,7 @@ struct sdb_entry_ex { + #define SDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */ + #define SDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define SDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define SDB_F_FORCE_CANON 16384 /* force canonicalition */ + + void sdb_free_entry(struct sdb_entry_ex *e); + void free_sdb_entry(struct sdb_entry *s); +-- +2.25.1 + + +From 06a0a75b16bace9c29568653d9e4bde4050c5ee5 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 21 Dec 2021 12:17:11 +0100 +Subject: [PATCH 20/99] s4:kdc: Also cannoicalize krbtgt principals when + enforcing canonicalization + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit f1ec950aeb47283a504018bafa21f54c3282e70c) +--- + source4/kdc/db-glue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index ac47fe78373..d017741e30a 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -920,7 +920,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; + +- if (flags & (SDB_F_CANON)) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { + /* + * When requested to do so, ensure that the + * both realm values in the principal are set +-- +2.25.1 + + +From b4005403032b0b33ca88d3abcbf085621b32bd5b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:30:38 +1300 +Subject: [PATCH 21/99] selftest: Check received LDB error code when + STRICT_CHECKING=0 + +We were instead only checking the expected error. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ad4d6fb01fd8083e68f07c427af8932574810cdc) +--- + source4/dsdb/tests/python/priv_attrs.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/dsdb/tests/python/priv_attrs.py source4/dsdb/tests/python/priv_attrs.py +index aa35dcc1317..4dfdfb9cbb8 100644 +--- source4/dsdb/tests/python/priv_attrs.py ++++ source4/dsdb/tests/python/priv_attrs.py +@@ -167,7 +167,7 @@ class PrivAttrsTests(samba.tests.TestCase): + creds_tmp.set_kerberos_state(DONT_USE_KERBEROS) # kinit is too expensive to use in a tight loop + return creds_tmp + +- def assertGotLdbError(self, got, wanted): ++ def assertGotLdbError(self, wanted, got): + if not self.strict_checking: + self.assertNotEqual(got, ldb.SUCCESS) + else: +-- +2.25.1 + + +From 6a4ed078902dcc57ab14f701c88e76ec0ac375e7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:53:18 +1300 +Subject: [PATCH 22/99] tests/krb5: Remove unused variable + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 57b1b76154d699b9d70ad04fa5e94c4b30f0e4bf) +--- + python/samba/tests/krb5/raw_testcase.py | 2 -- + 1 file changed, 2 deletions(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 42f2e94f5aa..36a6134e6c9 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -2855,7 +2855,6 @@ class RawKerberosTest(TestCaseInTempDir): + + expect_etype_info2 = () + expect_etype_info = False +- unexpect_etype_info = True + expected_aes_type = 0 + expected_rc4_type = 0 + if kcrypto.Enctype.RC4 in proposed_etypes: +@@ -2868,7 +2867,6 @@ class RawKerberosTest(TestCaseInTempDir): + if etype > expected_aes_type: + expected_aes_type = etype + if etype in (kcrypto.Enctype.RC4,) and error_code != 0: +- unexpect_etype_info = False + if etype > expected_rc4_type: + expected_rc4_type = etype + +-- +2.25.1 + + +From 837453d34799f44653d0d6d690d3e3d5eb074993 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:34:11 +1300 +Subject: [PATCH 23/99] tests/krb5: Deduplicate AS-REQ tests + +salt_tests was running the tests defined in the base class as well as +its own tests. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit f0b222e3ecf72c8562bc97bedd9f3a92980b60d5) +--- + python/samba/tests/krb5/as_req_tests.py | 163 ++++++++++++------------ + python/samba/tests/krb5/salt_tests.py | 4 +- + 2 files changed, 85 insertions(+), 82 deletions(-) + +diff --git python/samba/tests/krb5/as_req_tests.py python/samba/tests/krb5/as_req_tests.py +index 08081928363..315720f85d6 100755 +--- python/samba/tests/krb5/as_req_tests.py ++++ python/samba/tests/krb5/as_req_tests.py +@@ -38,87 +38,8 @@ from samba.tests.krb5.rfc4120_constants import ( + global_asn1_print = False + global_hexdump = False + +-@DynamicTestCase +-class AsReqKerberosTests(KDCBaseTest): +- +- @classmethod +- def setUpDynamicTestCases(cls): +- for (name, idx) in cls.etype_test_permutation_name_idx(): +- for pac in [None, True, False]: +- tname = "%s_pac_%s" % (name, pac) +- targs = (idx, pac) +- cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs) +- +- def setUp(self): +- super(AsReqKerberosTests, self).setUp() +- self.do_asn1_print = global_asn1_print +- self.do_hexdump = global_hexdump +- +- def _test_as_req_nopreauth(self, +- initial_etypes, +- pac=None, +- initial_kdc_options=None): +- client_creds = self.get_client_creds() +- client_account = client_creds.get_username() +- client_as_etypes = self.get_default_enctypes() +- krbtgt_creds = self.get_krbtgt_creds(require_keys=False) +- krbtgt_account = krbtgt_creds.get_username() +- realm = krbtgt_creds.get_realm() +- +- cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[client_account]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=[krbtgt_account, realm]) +- +- expected_crealm = realm +- expected_cname = cname +- expected_srealm = realm +- expected_sname = sname +- expected_salt = client_creds.get_salt() +- +- if any(etype in client_as_etypes and etype in initial_etypes +- for etype in (kcrypto.Enctype.AES256, +- kcrypto.Enctype.AES128, +- kcrypto.Enctype.RC4)): +- expected_error_mode = KDC_ERR_PREAUTH_REQUIRED +- else: +- expected_error_mode = KDC_ERR_ETYPE_NOSUPP +- +- kdc_exchange_dict = self.as_exchange_dict( +- expected_crealm=expected_crealm, +- expected_cname=expected_cname, +- expected_srealm=expected_srealm, +- expected_sname=expected_sname, +- generate_padata_fn=None, +- check_error_fn=self.generic_check_kdc_error, +- check_rep_fn=None, +- expected_error_mode=expected_error_mode, +- client_as_etypes=client_as_etypes, +- expected_salt=expected_salt, +- kdc_options=str(initial_kdc_options), +- pac_request=pac) +- +- self._generic_kdc_exchange(kdc_exchange_dict, +- cname=cname, +- realm=realm, +- sname=sname, +- etypes=initial_etypes) +- +- def _test_as_req_no_preauth_with_args(self, etype_idx, pac): +- name, etypes = self.etype_test_permutation_by_idx(etype_idx) +- self._test_as_req_nopreauth( +- pac=pac, +- initial_etypes=etypes, +- initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) +- +- def test_as_req_enc_timestamp(self): +- client_creds = self.get_client_creds() +- self._run_as_req_enc_timestamp(client_creds) +- +- def test_as_req_enc_timestamp_mac(self): +- client_creds = self.get_mach_creds() +- self._run_as_req_enc_timestamp(client_creds) + ++class AsReqBaseTest(KDCBaseTest): + def _run_as_req_enc_timestamp(self, client_creds): + client_account = client_creds.get_username() + client_as_etypes = self.get_default_enctypes() +@@ -207,6 +128,88 @@ class AsReqKerberosTests(KDCBaseTest): + return etype_info2 + + ++@DynamicTestCase ++class AsReqKerberosTests(AsReqBaseTest): ++ ++ @classmethod ++ def setUpDynamicTestCases(cls): ++ for (name, idx) in cls.etype_test_permutation_name_idx(): ++ for pac in [None, True, False]: ++ tname = "%s_pac_%s" % (name, pac) ++ targs = (idx, pac) ++ cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs) ++ ++ def setUp(self): ++ super(AsReqKerberosTests, self).setUp() ++ self.do_asn1_print = global_asn1_print ++ self.do_hexdump = global_hexdump ++ ++ def _test_as_req_nopreauth(self, ++ initial_etypes, ++ pac=None, ++ initial_kdc_options=None): ++ client_creds = self.get_client_creds() ++ client_account = client_creds.get_username() ++ client_as_etypes = self.get_default_enctypes() ++ krbtgt_creds = self.get_krbtgt_creds(require_keys=False) ++ krbtgt_account = krbtgt_creds.get_username() ++ realm = krbtgt_creds.get_realm() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[client_account]) ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) ++ ++ expected_crealm = realm ++ expected_cname = cname ++ expected_srealm = realm ++ expected_sname = sname ++ expected_salt = client_creds.get_salt() ++ ++ if any(etype in client_as_etypes and etype in initial_etypes ++ for etype in (kcrypto.Enctype.AES256, ++ kcrypto.Enctype.AES128, ++ kcrypto.Enctype.RC4)): ++ expected_error_mode = KDC_ERR_PREAUTH_REQUIRED ++ else: ++ expected_error_mode = KDC_ERR_ETYPE_NOSUPP ++ ++ kdc_exchange_dict = self.as_exchange_dict( ++ expected_crealm=expected_crealm, ++ expected_cname=expected_cname, ++ expected_srealm=expected_srealm, ++ expected_sname=expected_sname, ++ generate_padata_fn=None, ++ check_error_fn=self.generic_check_kdc_error, ++ check_rep_fn=None, ++ expected_error_mode=expected_error_mode, ++ client_as_etypes=client_as_etypes, ++ expected_salt=expected_salt, ++ kdc_options=str(initial_kdc_options), ++ pac_request=pac) ++ ++ self._generic_kdc_exchange(kdc_exchange_dict, ++ cname=cname, ++ realm=realm, ++ sname=sname, ++ etypes=initial_etypes) ++ ++ def _test_as_req_no_preauth_with_args(self, etype_idx, pac): ++ name, etypes = self.etype_test_permutation_by_idx(etype_idx) ++ self._test_as_req_nopreauth( ++ pac=pac, ++ initial_etypes=etypes, ++ initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) ++ ++ def test_as_req_enc_timestamp(self): ++ client_creds = self.get_client_creds() ++ self._run_as_req_enc_timestamp(client_creds) ++ ++ def test_as_req_enc_timestamp_mac(self): ++ client_creds = self.get_mach_creds() ++ self._run_as_req_enc_timestamp(client_creds) ++ ++ + if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False +diff --git python/samba/tests/krb5/salt_tests.py python/samba/tests/krb5/salt_tests.py +index ecbf618e40e..db777f8b7bc 100755 +--- python/samba/tests/krb5/salt_tests.py ++++ python/samba/tests/krb5/salt_tests.py +@@ -21,7 +21,7 @@ import os + + import ldb + +-from samba.tests.krb5.as_req_tests import AsReqKerberosTests ++from samba.tests.krb5.as_req_tests import AsReqBaseTest + import samba.tests.krb5.kcrypto as kcrypto + + sys.path.insert(0, "bin/python") +@@ -31,7 +31,7 @@ global_asn1_print = False + global_hexdump = False + + +-class SaltTests(AsReqKerberosTests): ++class SaltTests(AsReqBaseTest): + + def setUp(self): + super().setUp() +-- +2.25.1 + + +From 3d48ade670bb5b026d7bc0a26a4fa6775b21653b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 16:02:00 +1300 +Subject: [PATCH 24/99] tests/krb5: Run test_rpc against member server + +We were instead always running against the DC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 167bd2070483004cd0b9a96ffb40ea73c6ddf579) +--- + python/samba/tests/krb5/test_rpc.py | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git python/samba/tests/krb5/test_rpc.py python/samba/tests/krb5/test_rpc.py +index 03c125f518a..2d483986e83 100755 +--- python/samba/tests/krb5/test_rpc.py ++++ python/samba/tests/krb5/test_rpc.py +@@ -58,7 +58,7 @@ class RpcTests(KDCBaseTest): + + samdb = self.get_samdb() + +- mach_name = samdb.host_dns_name() ++ mach_name = self.host + service = "cifs" + + # Create the user account. +@@ -67,7 +67,7 @@ class RpcTests(KDCBaseTest): + use_cache=False) + user_name = user_credentials.get_username() + +- mach_credentials = self.get_dc_creds() ++ mach_credentials = self.get_server_creds() + + # Talk to the KDC to obtain the service ticket, which gets placed into + # the cache. The machine account name has to match the name in the +@@ -114,8 +114,7 @@ class RpcTests(KDCBaseTest): + self.assertEqual(user_name, account_name.string) + + def test_rpc_anonymous(self): +- samdb = self.get_samdb() +- mach_name = samdb.host_dns_name() ++ mach_name = self.host + + anon_creds = credentials.Credentials() + anon_creds.set_anonymous() +@@ -125,7 +124,7 @@ class RpcTests(KDCBaseTest): + + (account_name, _) = conn.GetUserName(None, None, None) + +- self.assertEqual('ANONYMOUS LOGON', account_name.string) ++ self.assertEqual('ANONYMOUS LOGON', account_name.string.upper()) + + + if __name__ == "__main__": +-- +2.25.1 + + +From bf1aa0927895b1007ecea738681235b5be2e6208 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:37:35 +1300 +Subject: [PATCH 25/99] tests/krb5: Allow PasswordKey_create() to use s2kparams + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit a560c2e9ad8abb824d1805c86c656943745f81eb) +--- + python/samba/tests/krb5/raw_testcase.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 36a6134e6c9..da3f69c79c6 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -1167,10 +1167,11 @@ class RawKerberosTest(TestCaseInTempDir): + key = kcrypto.Key(etype, contents) + return RodcPacEncryptionKey(key, kvno) + +- def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None): ++ def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None, ++ params=None): + self.assertIsNotNone(pwd) + self.assertIsNotNone(salt) +- key = kcrypto.string_to_key(etype, pwd, salt) ++ key = kcrypto.string_to_key(etype, pwd, salt, params=params) + return RodcPacEncryptionKey(key, kvno) + + def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): +@@ -1182,9 +1183,11 @@ class RawKerberosTest(TestCaseInTempDir): + nthash = creds.get_nt_hash() + return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno) + ++ params = etype_info2.get('s2kparams') ++ + password = creds.get_password() + return self.PasswordKey_create( +- etype=e, pwd=password, salt=salt, kvno=kvno) ++ etype=e, pwd=password, salt=salt, kvno=kvno, params=params) + + def TicketDecryptionKey_from_creds(self, creds, etype=None): + +-- +2.25.1 + + +From 651db77b1c19c036cf229c44b764b0155e1dc399 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:40:35 +1300 +Subject: [PATCH 26/99] tests/krb5: Split out methods to create renewable or + invalid tickets + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit e930274aa43810d6485c3c8a7c82958ecb409630) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 68 +++++++++++++----------- + 1 file changed, 36 insertions(+), 32 deletions(-) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index abac5a47a56..0578969ba69 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1786,6 +1786,40 @@ class KdcTgsTests(KDCBaseTest): + + self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) + ++ def _modify_renewable(self, enc_part): ++ # Set the renewable flag. ++ renewable_flag = krb5_asn1.TicketFlags('renewable') ++ pos = len(tuple(renewable_flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + '1' + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ # Set the renew-till time to be in the future. ++ renew_till = self.get_KerberosTime(offset=100 * 60 * 60) ++ enc_part['renew-till'] = renew_till ++ ++ return enc_part ++ ++ def _modify_invalid(self, enc_part): ++ # Set the invalid flag. ++ invalid_flag = krb5_asn1.TicketFlags('invalid') ++ pos = len(tuple(invalid_flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + '1' + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ # Set the ticket start time to be in the past. ++ past_time = self.get_KerberosTime(offset=-100 * 60 * 60) ++ enc_part['starttime'] = past_time ++ ++ return enc_part ++ + def _get_tgt(self, + client_creds, + renewable=False, +@@ -1880,39 +1914,9 @@ class KdcTgsTests(KDCBaseTest): + } + + if renewable: +- def flags_modify_fn(enc_part): +- # Set the renewable flag. +- renewable_flag = krb5_asn1.TicketFlags('renewable') +- pos = len(tuple(renewable_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags +- +- # Set the renew-till time to be in the future. +- renew_till = self.get_KerberosTime(offset=100 * 60 * 60) +- enc_part['renew-till'] = renew_till +- +- return enc_part ++ flags_modify_fn = self._modify_renewable + elif invalid: +- def flags_modify_fn(enc_part): +- # Set the invalid flag. +- invalid_flag = krb5_asn1.TicketFlags('invalid') +- pos = len(tuple(invalid_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags +- +- # Set the ticket start time to be in the past. +- past_time = self.get_KerberosTime(offset=-100 * 60 * 60) +- enc_part['starttime'] = past_time +- +- return enc_part ++ flags_modify_fn = self._modify_invalid + else: + flags_modify_fn = None + +-- +2.25.1 + + +From 1e9ad4246ce7fe7a212da4357e6e11c5ac22a8b2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:52:31 +1300 +Subject: [PATCH 27/99] tests/krb5: Adjust error codes to better match Windows + with PacRequestorEnforcement=2 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit d95705172bcf6fe24817800a4c0009e9cc8be595) + +[jsutton@samba.org Fixed MIT knownfail conflict] +--- + python/samba/tests/krb5/alias_tests.py | 7 +- + python/samba/tests/krb5/kdc_tgs_tests.py | 130 ++++++++---------- + .../ms_kile_client_principal_lookup_tests.py | 39 ++---- + python/samba/tests/krb5/s4u_tests.py | 57 ++++---- + python/samba/tests/krb5/test_rpc.py | 8 +- + selftest/knownfail_heimdal_kdc | 64 +++++++++ + selftest/knownfail_mit_kdc | 9 ++ + 7 files changed, 181 insertions(+), 133 deletions(-) + +diff --git python/samba/tests/krb5/alias_tests.py python/samba/tests/krb5/alias_tests.py +index 60213845a44..1f63775c189 100755 +--- python/samba/tests/krb5/alias_tests.py ++++ python/samba/tests/krb5/alias_tests.py +@@ -28,7 +28,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, +- KDC_ERR_CLIENT_NAME_MISMATCH, ++ KDC_ERR_TGT_REVOKED, + NT_PRINCIPAL, + ) + +@@ -168,7 +168,7 @@ class AliasTests(KDCBaseTest): + ctype=None) + return [padata], req_body + +- expected_error_mode = KDC_ERR_CLIENT_NAME_MISMATCH ++ expected_error_mode = KDC_ERR_TGT_REVOKED + + # Make a request using S4U2Self. The request should fail. + kdc_exchange_dict = self.tgs_exchange_dict( +@@ -184,7 +184,8 @@ class AliasTests(KDCBaseTest): + tgt=tgt, + authenticator_subkey=authenticator_subkey, + kdc_options='0', +- expect_pac=True) ++ expect_pac=True, ++ expect_edata=False) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 0578969ba69..7ea15f0fbab 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -23,7 +23,7 @@ import os + import ldb + + +-from samba import dsdb, ntstatus ++from samba import dsdb + + from samba.dcerpc import krb5pac, security + +@@ -38,8 +38,6 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_ERROR, + KRB_TGS_REP, + KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION, +- KDC_ERR_CLIENT_NAME_MISMATCH, + KDC_ERR_GENERIC, + KDC_ERR_MODIFIED, + KDC_ERR_POLICY, +@@ -262,7 +260,7 @@ class KdcTgsTests(KDCBaseTest): + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + + if expect_error: +- expected_error_mode = KDC_ERR_BADOPTION ++ expected_error_mode = KDC_ERR_TGT_REVOKED + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: +@@ -288,7 +286,8 @@ class KdcTgsTests(KDCBaseTest): + authenticator_subkey=authenticator_subkey, + kdc_options=kdc_options, + pac_request=pac_request, +- expect_pac=expect_pac) ++ expect_pac=expect_pac, ++ expect_edata=False) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=cname, +@@ -516,8 +515,7 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) + +- self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=False) # Note: not expected ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_req_no_pac_attrs(self): + creds = self._get_creds() +@@ -531,11 +529,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, remove_requester_sid=True) + +- samdb = self.get_samdb() +- sid = self.get_objectSid(samdb, creds.get_dn()) +- +- self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=True, expected_sid=sid) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_req_from_rodc_no_pac_attrs(self): + creds = self._get_creds(replication_allowed=True, +@@ -548,101 +542,99 @@ class KdcTgsTests(KDCBaseTest): + def test_tgs_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True, remove_pac=True) +- self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True, remove_pac=True) +- self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) + self._s4u2self(tgt, creds, +- expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), +- expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, +- expect_edata=True) ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expect_edata=False) + + def test_user2user_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) +- self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION) ++ self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test making a request with authdata and without a PAC. + def test_tgs_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True, remove_pac=True, + allow_empty_authdata=True) +- self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True, remove_pac=True, + allow_empty_authdata=True) +- self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) + self._s4u2self(tgt, creds, +- expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), +- expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, +- expect_edata=True) ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expect_edata=False) + + def test_user2user_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) +- self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION) ++ self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test changing the SID in the PAC to that of another account. + def test_tgs_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, renewable=True, new_rid=existing_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, invalid=True, new_rid=existing_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) + self._s4u2self(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_requester_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_logon_info_sid_mismatch_existing(self): + creds = self._get_creds() +@@ -656,49 +648,49 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test changing the SID in the PAC to a non-existent one. + def test_tgs_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, renewable=True, + new_rid=nonexistent_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, invalid=True, + new_rid=nonexistent_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) + self._s4u2self(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_logon_info_sid_mismatch_nonexisting(self): + creds = self._get_creds() +@@ -712,7 +704,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the client is revealed to the RODC. + def test_tgs_rodc_revealed(self): +@@ -753,7 +745,7 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -762,7 +754,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True, + new_rid=existing_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -771,7 +763,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True, + new_rid=existing_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -779,7 +771,7 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) +- self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -788,7 +780,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_requester_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -797,7 +789,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_logon_info_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -815,7 +807,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the SID in the PAC is changed to a + # non-existent one. +@@ -824,7 +816,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -832,7 +824,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, renewable=True, from_rodc=True, + new_rid=nonexistent_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -840,14 +832,14 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, invalid=True, from_rodc=True, + new_rid=nonexistent_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) +- self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -855,7 +847,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -863,7 +855,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_logon_info_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -879,7 +871,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the client is not revealed to the + # RODC. +@@ -1111,8 +1103,7 @@ class KdcTgsTests(KDCBaseTest): + names=[user_name]) + + self._user2user(tgt, creds, sname=sname, +- expected_error=(KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION)) ++ expected_error=KDC_ERR_BADMATCH) + + def test_user2user_other_sname(self): + other_name = self.get_new_username() +@@ -1134,8 +1125,7 @@ class KdcTgsTests(KDCBaseTest): + sname = self.get_krbtgt_sname() + + self._user2user(tgt, creds, sname=sname, +- expected_error=(KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION)) ++ expected_error=KDC_ERR_BADMATCH) + + def test_user2user_wrong_srealm(self): + creds = self._get_creds() +@@ -1206,7 +1196,9 @@ class KdcTgsTests(KDCBaseTest): + + tgt = self._modify_tgt(tgt, cname=cname) + +- self._user2user(tgt, creds, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) ++ self._user2user(tgt, creds, ++ expected_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_C_PRINCIPAL_UNKNOWN)) + + def test_user2user_non_existent_sname(self): + creds = self._get_creds() +@@ -1522,8 +1514,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, renewable=True, + remove_requester_sid=True) + +- self._renew_tgt(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=False) # Note: not expected ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_requester_sid_missing_rodc_renew(self): + creds = self._get_creds(replication_allowed=True, +@@ -1539,9 +1530,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True, + remove_requester_sid=True) + +- self._renew_tgt(tgt, expected_error=0, expect_pac=True, +- expected_sid=sid, +- expect_requester_sid=True) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_pac_request_none(self): + creds = self._get_creds() +@@ -1655,10 +1644,10 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + +- ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=False) ++ ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=True) + +- pac = self.get_ticket_pac(ticket, expect_pac=False) +- self.assertIsNone(pac) ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) + + def test_s4u2self_pac_request_true(self): + creds = self._get_creds() +@@ -1753,10 +1742,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, from_rodc=True) + +- ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket, expect_pac=False) +- self.assertIsNone(pac) ++ self.assertIsNotNone(pac) + + def test_tgs_rodc_pac_request_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1784,7 +1773,8 @@ class KdcTgsTests(KDCBaseTest): + 'sAMAccountName') + samdb.modify(msg) + +- self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) ++ self._run_tgs(tgt, expected_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_C_PRINCIPAL_UNKNOWN)) + + def _modify_renewable(self, enc_part): + # Set the renewable flag. +diff --git python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +index 0aa3309b814..e6b90d3e16a 100755 +--- python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py ++++ python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +@@ -32,6 +32,7 @@ from samba.tests.krb5.rfc4120_constants import ( + NT_PRINCIPAL, + NT_SRV_INST, + KDC_ERR_C_PRINCIPAL_UNKNOWN, ++ KDC_ERR_TGT_REVOKED, + ) + + global_asn1_print = False +@@ -322,21 +323,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype, +- service_creds=mc, expect_pac=False) +- self.check_tgs_reply(rep) +- +- # Check the contents of the service ticket +- ticket = rep['ticket'] +- enc_part = self.decode_service_ticket(mc, ticket) +- # +- # We get an empty authorization-data element in the ticket. +- # i.e. no PAC +- self.assertEqual([], enc_part['authorization-data']) +- # check the crealm and cname +- cname = enc_part['cname'] +- self.assertEqual(NT_PRINCIPAL, cname['name-type']) +- self.assertEqual(alt_name.encode('UTF8'), cname['name-string'][0]) +- self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) ++ service_creds=mc, expect_pac=False, ++ expect_edata=False, ++ expected_error_mode=KDC_ERR_TGT_REVOKED) ++ self.check_error_rep(rep, KDC_ERR_TGT_REVOKED) + + def test_nt_principal_step_4_b(self): + ''' Step 4, pre-authentication +@@ -703,21 +693,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype, +- service_creds=mc, expect_pac=False) +- self.check_tgs_reply(rep) +- +- # Check the contents of the service ticket +- ticket = rep['ticket'] +- enc_part = self.decode_service_ticket(mc, ticket) +- # +- # We get an empty authorization-data element in the ticket. +- # i.e. no PAC +- self.assertEqual([], enc_part['authorization-data']) +- # check the crealm and cname +- cname = enc_part['cname'] +- self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) +- self.assertEqual(ename.encode('UTF8'), cname['name-string'][0]) +- self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) ++ service_creds=mc, expect_pac=False, ++ expect_edata=False, ++ expected_error_mode=KDC_ERR_TGT_REVOKED) ++ self.check_error_rep(rep, KDC_ERR_TGT_REVOKED) + + def test_nt_enterprise_principal_step_6_b(self): + ''' Step 4, pre-authentication +diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py +index a80a7b3427e..5f37525f393 100755 +--- python/samba/tests/krb5/s4u_tests.py ++++ python/samba/tests/krb5/s4u_tests.py +@@ -42,6 +42,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_INAPP_CKSUM, + KDC_ERR_MODIFIED, + KDC_ERR_SUMTYPE_NOSUPP, ++ KDC_ERR_TGT_REVOKED, + KU_PA_ENC_TIMESTAMP, + KU_AS_REP_ENC_PART, + KU_TGS_REP_ENC_PART_SUB_KEY, +@@ -278,6 +279,8 @@ class S4UKerberosTests(KDCBaseTest): + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) + ++ expect_edata = kdc_dict.pop('expect_edata', None) ++ + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): +@@ -309,7 +312,8 @@ class S4UKerberosTests(KDCBaseTest): + tgt=service_tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=str(kdc_options), +- expect_claims=False) ++ expect_claims=False, ++ expect_edata=expect_edata) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, +@@ -343,15 +347,14 @@ class S4UKerberosTests(KDCBaseTest): + + self._run_s4u2self_test( + { +- 'expected_error_mode': (KDC_ERR_GENERIC, +- KDC_ERR_BADOPTION), +- 'expected_status': ntstatus.NT_STATUS_INVALID_PARAMETER, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'client_opts': { + 'not_delegated': False + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': forwardable_no_pac, +- 'expected_flags': 'forwardable' ++ 'expected_flags': 'forwardable', ++ 'expect_edata': False + }) + + # Test performing an S4U2Self operation without requesting a forwardable +@@ -674,8 +677,8 @@ class S4UKerberosTests(KDCBaseTest): + # contain a PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': (KDC_ERR_MODIFIED, ++ KDC_ERR_TGT_REVOKED), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False +@@ -686,9 +689,10 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': 0, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_delegation': True, +- 'modify_service_tgt_fn': self.remove_ticket_pac ++ 'modify_service_tgt_fn': self.remove_ticket_pac, ++ 'expect_edata': False + }) + + def test_constrained_delegation_no_client_pac_no_auth_data_required(self): +@@ -696,8 +700,8 @@ class S4UKerberosTests(KDCBaseTest): + # contain a PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': (KDC_ERR_MODIFIED, ++ KDC_ERR_BADOPTION), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False, +@@ -711,13 +715,14 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_delegation': True, + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True +- } ++ }, ++ 'expect_pac': False, ++ 'expect_edata': False + }) + + def test_constrained_delegation_non_forwardable(self): +@@ -812,12 +817,11 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': KDC_ERR_BADOPTION, +- 'expected_status': +- ntstatus.NT_STATUS_NOT_FOUND, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD +- 'modify_service_tgt_fn': self.remove_ticket_pac ++ 'modify_service_tgt_fn': self.remove_ticket_pac, ++ 'expect_edata': False + }) + + def test_rbcd_no_client_pac_no_auth_data_required_a(self): +@@ -858,15 +862,14 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': KDC_ERR_BADOPTION, +- 'expected_status': +- ntstatus.NT_STATUS_NOT_FOUND, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True +- } ++ }, ++ 'expect_edata': False + }) + + def test_rbcd_non_forwardable(self): +@@ -941,8 +944,8 @@ class S4UKerberosTests(KDCBaseTest): + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + if checksum == krb5pac.PAC_TYPE_TICKET_CHECKSUM: +- expected_error_mode = (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED) ++ expected_error_mode = (KDC_ERR_MODIFIED, ++ KDC_ERR_BADOPTION) + else: + expected_error_mode = KDC_ERR_GENERIC + +@@ -1061,8 +1064,7 @@ class S4UKerberosTests(KDCBaseTest): + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM: +- expected_error_mode = (KDC_ERR_MODIFIED, +- KDC_ERR_BAD_INTEGRITY) ++ expected_error_mode = KDC_ERR_MODIFIED + expected_status = ntstatus.NT_STATUS_WRONG_PASSWORD + else: + expected_error_mode = 0 +@@ -1162,8 +1164,7 @@ class S4UKerberosTests(KDCBaseTest): + with self.subTest(checksum=checksum, ctype=ctype): + if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM: + if ctype == Cksumtype.SHA1: +- expected_error_mode = (KDC_ERR_SUMTYPE_NOSUPP, +- KDC_ERR_BAD_INTEGRITY) ++ expected_error_mode = KDC_ERR_SUMTYPE_NOSUPP + expected_status = ntstatus.NT_STATUS_LOGON_FAILURE + else: + expected_error_mode = KDC_ERR_GENERIC +diff --git python/samba/tests/krb5/test_rpc.py python/samba/tests/krb5/test_rpc.py +index 2d483986e83..5a3c7339cea 100755 +--- python/samba/tests/krb5/test_rpc.py ++++ python/samba/tests/krb5/test_rpc.py +@@ -24,7 +24,10 @@ import ldb + + from samba import NTSTATUSError, credentials + from samba.dcerpc import lsa +-from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN ++from samba.ntstatus import ( ++ NT_STATUS_ACCESS_DENIED, ++ NT_STATUS_NO_IMPERSONATION_TOKEN ++) + + from samba.tests.krb5.kdc_base_test import KDCBaseTest + +@@ -103,7 +106,8 @@ class RpcTests(KDCBaseTest): + self.fail() + + enum, _ = e.args +- self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum) ++ self.assertIn(enum, {NT_STATUS_ACCESS_DENIED, ++ NT_STATUS_NO_IMPERSONATION_TOKEN}) + return + + (account_name, _) = conn.GetUserName(None, None, None) +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 7eba899966e..1b7e159c381 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -233,16 +233,21 @@ + # S4U tests + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required) + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$ ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -259,3 +264,62 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed ++# ++# Alias tests ++# ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename ++# ++# KDC TGS tests ++# ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 8cd36fe2d96..cc12499bb50 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -390,6 +390,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # KDC TGT tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied +@@ -401,6 +403,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req +@@ -418,6 +422,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link +@@ -427,6 +432,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname +@@ -462,6 +469,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # + # PAC attributes tests + # +-- +2.25.1 + + +From ea82822a5c451df50feed15c5da3501df2b5c106 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:04:36 +1300 +Subject: [PATCH 28/99] tests/krb5: Remove unnecessary expect_pac arguments + +The value of expect_pac is not considered if we are expecting an error. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 28d501875a98fa2817262eb8ec68bf91528428c2) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 7ea15f0fbab..6160ef649e8 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -412,7 +412,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_remove_pac_client_no_auth_data_required(self): + client_creds = self.get_cached_creds( +@@ -427,7 +427,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_remove_pac(self): + client_creds = self.get_client_creds() +@@ -440,7 +440,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_upn_dns_info_ex_user(self): + client_creds = self.get_client_creds() +-- +2.25.1 + + +From eb0ed5f4f6d725c49fda97bc8f7aae89f90bd913 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 30 Nov 2021 09:26:40 +1300 +Subject: [PATCH 29/99] tests/krb5: Add tests for invalid TGTs + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 7574ba9f580fca552b80532a49d00e657fbdf4fd) + +[jsutton@samba.org Removed some MIT knownfail changes] +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 16 ++++++++++++++++ + python/samba/tests/krb5/rfc4120_constants.py | 1 + + selftest/knownfail_mit_kdc | 1 + + 3 files changed, 18 insertions(+) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 6160ef649e8..f5f091610ac 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -44,6 +44,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_C_PRINCIPAL_UNKNOWN, + KDC_ERR_S_PRINCIPAL_UNKNOWN, + KDC_ERR_TGT_REVOKED, ++ KRB_ERR_TKT_NYV, + KDC_ERR_WRONG_REALM, + NT_PRINCIPAL, + NT_SRV_INST, +@@ -511,6 +512,21 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds) + self._user2user(tgt, creds, expected_error=0) + ++ def test_tgs_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._run_tgs(tgt, expected_error=KRB_ERR_TKT_NYV) ++ ++ def test_s4u2self_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._s4u2self(tgt, creds, expected_error=KRB_ERR_TKT_NYV) ++ ++ def test_user2user_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV) ++ + def test_tgs_req_no_requester_sid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) +diff --git python/samba/tests/krb5/rfc4120_constants.py python/samba/tests/krb5/rfc4120_constants.py +index 5251e291fde..a9fdc5735dd 100644 +--- python/samba/tests/krb5/rfc4120_constants.py ++++ python/samba/tests/krb5/rfc4120_constants.py +@@ -76,6 +76,7 @@ KDC_ERR_TGT_REVOKED = 20 + KDC_ERR_PREAUTH_FAILED = 24 + KDC_ERR_PREAUTH_REQUIRED = 25 + KDC_ERR_BAD_INTEGRITY = 31 ++KRB_ERR_TKT_NYV = 33 + KDC_ERR_NOT_US = 35 + KDC_ERR_BADMATCH = 36 + KDC_ERR_SKEW = 37 +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index cc12499bb50..3aacec00870 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -422,6 +422,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_invalid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied +-- +2.25.1 + + +From 645d30ff371fdf3e16cb1fa69f2e93a848d20bdb Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:10:45 +1300 +Subject: [PATCH 30/99] tests/krb5: Add tests for TGS requests with a non-TGT + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 778029c1dc443b87f4ed4b9d2c613d0e6fc45b0d) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 51 ++++++++++++++++++++++++ + selftest/knownfail_mit_kdc | 2 + + 2 files changed, 53 insertions(+) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index f5f091610ac..52297c963e8 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -40,6 +40,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_BADMATCH, + KDC_ERR_GENERIC, + KDC_ERR_MODIFIED, ++ KDC_ERR_NOT_US, + KDC_ERR_POLICY, + KDC_ERR_C_PRINCIPAL_UNKNOWN, + KDC_ERR_S_PRINCIPAL_UNKNOWN, +@@ -1234,6 +1235,56 @@ class KdcTgsTests(KDCBaseTest): + expected_error=(KDC_ERR_GENERIC, + KDC_ERR_S_PRINCIPAL_UNKNOWN)) + ++ def test_tgs_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._run_tgs(service_ticket, ++ expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY)) ++ ++ def test_renew_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ service_ticket = self.modified_ticket( ++ service_ticket, ++ modify_fn=self._modify_renewable, ++ checksum_keys=self.get_krbtgt_checksum_key()) ++ ++ self._renew_tgt(service_ticket, ++ expected_error=KDC_ERR_POLICY) ++ ++ def test_validate_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ service_ticket = self.modified_ticket( ++ service_ticket, ++ modify_fn=self._modify_invalid, ++ checksum_keys=self.get_krbtgt_checksum_key()) ++ ++ self._validate_tgt(service_ticket, ++ expected_error=KDC_ERR_POLICY) ++ ++ def test_s4u2self_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._s4u2self(service_ticket, creds, ++ expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY)) ++ + def test_user2user_service_ticket(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 3aacec00870..98e8a34cd5f 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -403,6 +403,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac +@@ -470,6 +471,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # +-- +2.25.1 + + +From 1d616e8e9c0dceabebd1f079fc4d652d6bf2060d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:09:18 +1300 +Subject: [PATCH 31/99] tests/krb5: Add TGS-REQ tests with FAST + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ec823c2a83c639f1d7c422153a53d366750e5f2a) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 184 ++++++++++++++++++++++- + selftest/knownfail_heimdal_kdc | 13 ++ + selftest/knownfail_mit_kdc | 17 +++ + 3 files changed, 212 insertions(+), 2 deletions(-) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 52297c963e8..99a91528fa8 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -32,6 +32,7 @@ os.environ["PYTHONUNBUFFERED"] = "1" + + import samba.tests.krb5.kcrypto as kcrypto + from samba.tests.krb5.kdc_base_test import KDCBaseTest ++from samba.tests.krb5.raw_testcase import Krb5EncryptionKey + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, +@@ -513,6 +514,11 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds) + self._user2user(tgt, creds, expected_error=0) + ++ def test_fast_req(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ self._fast(tgt, creds, expected_error=0) ++ + def test_tgs_req_invalid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True) +@@ -528,6 +534,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, invalid=True) + self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV) + ++ def test_fast_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._fast(tgt, creds, expected_error=KRB_ERR_TKT_NYV, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_req_no_requester_sid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) +@@ -583,6 +595,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, remove_pac=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_no_pac(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, remove_pac=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test making a request with authdata and without a PAC. + def test_tgs_authdata_no_pac(self): + creds = self._get_creds() +@@ -613,6 +631,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_authdata_no_pac(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test changing the SID in the PAC to that of another account. + def test_tgs_sid_mismatch_existing(self): + creds = self._get_creds() +@@ -646,6 +670,14 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_sid_mismatch_existing(self): ++ creds = self._get_creds() ++ existing_rid = self._get_existing_rid() ++ tgt = self._get_tgt(creds, new_rid=existing_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_requester_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() +@@ -702,6 +734,14 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_sid_mismatch_nonexisting(self): ++ creds = self._get_creds() ++ nonexistent_rid = self._get_non_existent_rid() ++ tgt = self._get_tgt(creds, new_rid=nonexistent_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() +@@ -799,6 +839,16 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_sid_mismatch_existing(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ existing_rid = self._get_existing_rid(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_rodc_requester_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -866,6 +916,15 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_sid_mismatch_nonexisting(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ nonexistent_rid = self._get_non_existent_rid() ++ tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_rodc_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -955,6 +1014,14 @@ class KdcTgsTests(KDCBaseTest): + self._remove_rodc_partial_secrets() + self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + ++ def test_fast_rodc_no_partial_secrets(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._remove_rodc_partial_secrets() ++ self._fast(tgt, creds, expected_error=KDC_ERR_POLICY, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the RODC account does not have an + # msDS-KrbTgtLink. + def test_tgs_rodc_no_krbtgt_link(self): +@@ -992,6 +1059,14 @@ class KdcTgsTests(KDCBaseTest): + self._remove_rodc_krbtgt_link() + self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + ++ def test_fast_rodc_no_krbtgt_link(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._remove_rodc_krbtgt_link() ++ self._fast(tgt, creds, expected_error=KDC_ERR_POLICY, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is not allowed to + # replicate to the RODC. + def test_tgs_rodc_not_allowed(self): +@@ -1019,6 +1094,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_not_allowed(self): ++ creds = self._get_creds(revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is denied from + # replicating to the RODC. + def test_tgs_rodc_denied(self): +@@ -1051,6 +1132,13 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_denied(self): ++ creds = self._get_creds(replication_denied=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is both allowed and + # denied replicating to the RODC. + def test_tgs_rodc_allowed_denied(self): +@@ -1088,6 +1176,14 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_allowed_denied(self): ++ creds = self._get_creds(replication_allowed=True, ++ replication_denied=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test user-to-user with incorrect service principal names. + def test_user2user_matching_sname_host(self): + creds = self._get_creds() +@@ -1295,6 +1391,17 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(service_ticket, creds, + expected_error=(KDC_ERR_MODIFIED, KDC_ERR_POLICY)) + ++ # Expected to fail against Windows, which does not produce a policy error. ++ def test_fast_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._fast(service_ticket, creds, ++ expected_error=KDC_ERR_POLICY) ++ + def test_pac_attrs_none(self): + creds = self._get_creds() + self.get_tgt(creds, pac_request=None, +@@ -1792,6 +1899,34 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_fast_pac_request_none(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=None) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_fast_pac_request_false(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=False) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, ++ expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket, expect_pac=True) ++ self.assertIsNotNone(pac) ++ ++ def test_fast_pac_request_true(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=True) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_tgs_rodc_pac_request_none(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -2192,13 +2327,28 @@ class KdcTgsTests(KDCBaseTest): + srealm=srealm, + expect_pac=expect_pac) + ++ def _fast(self, armor_tgt, armor_tgt_creds, expected_error, ++ expected_sname=None, expect_pac=True): ++ user_creds = self._get_mach_creds() ++ user_tgt = self.get_tgt(user_creds) ++ ++ target_creds = self.get_service_creds() ++ ++ return self._tgs_req(user_tgt, expected_error, target_creds, ++ armor_tgt=armor_tgt, ++ expected_sname=expected_sname, ++ expect_pac=expect_pac) ++ + def _tgs_req(self, tgt, expected_error, target_creds, ++ armor_tgt=None, + kdc_options='0', + expected_cname=None, ++ expected_sname=None, + additional_ticket=None, + generate_padata_fn=None, + sname=None, + srealm=None, ++ use_fast=False, + expect_claims=True, + expect_pac=True, + expect_pac_attrs=None, +@@ -2214,7 +2364,8 @@ class KdcTgsTests(KDCBaseTest): + + if sname is False: + sname = None +- expected_sname = self.get_krbtgt_sname() ++ if expected_sname is None: ++ expected_sname = self.get_krbtgt_sname() + else: + if sname is None: + target_name = target_creds.get_username() +@@ -2229,7 +2380,8 @@ class KdcTgsTests(KDCBaseTest): + name_type=NT_PRINCIPAL, + names=['host', target_name]) + +- expected_sname = sname ++ if expected_sname is None: ++ expected_sname = sname + + if additional_ticket is not None: + additional_tickets = [additional_ticket.ticket] +@@ -2241,6 +2393,28 @@ class KdcTgsTests(KDCBaseTest): + + subkey = self.RandomKey(tgt.session_key.etype) + ++ if armor_tgt is not None: ++ armor_subkey = self.RandomKey(subkey.etype) ++ explicit_armor_key = self.generate_armor_key(armor_subkey, ++ armor_tgt.session_key) ++ armor_key = kcrypto.cf2(explicit_armor_key.key, ++ subkey.key, ++ b'explicitarmor', ++ b'tgsarmor') ++ armor_key = Krb5EncryptionKey(armor_key, None) ++ ++ generate_fast_fn = self.generate_simple_fast ++ generate_fast_armor_fn = self.generate_ap_req ++ ++ pac_options = '1' # claims support ++ else: ++ armor_subkey = None ++ armor_key = None ++ generate_fast_fn = None ++ generate_fast_armor_fn = None ++ ++ pac_options = None ++ + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + if expected_error: +@@ -2260,12 +2434,18 @@ class KdcTgsTests(KDCBaseTest): + expected_sname=expected_sname, + ticket_decryption_key=decryption_key, + generate_padata_fn=generate_padata_fn, ++ generate_fast_fn=generate_fast_fn, ++ generate_fast_armor_fn=generate_fast_armor_fn, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error, + expected_status=expected_status, + tgt=tgt, ++ armor_key=armor_key, ++ armor_tgt=armor_tgt, ++ armor_subkey=armor_subkey, ++ pac_options=pac_options, + authenticator_subkey=subkey, + kdc_options=kdc_options, + expect_edata=expect_edata, +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 1b7e159c381..61de06659be 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -274,6 +274,19 @@ + # + # KDC TGS tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 98e8a34cd5f..3e19ee6c8b9 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -390,6 +390,23 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # KDC TGT tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac +-- +2.25.1 + + +From 5375e2b99cd5fd9e40d6d5f94eb7d46f366f525e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:37:08 +1300 +Subject: [PATCH 32/99] tests/krb5: Align PAC buffer checking to more closely + match Windows with PacRequestorEnforcement=2 + +We set EXPECT_EXTRA_PAC_BUFFERS to 0 for the moment. This signifies that +these checks are currently not enforced, which avoids a lot of test +failures. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ebc9137cee94dee9dcf0e47d5bc0dc83de7aaaa1) + +[jsutton@samba.org Fixed conflicts] +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 121 ++++++++++++++++------- + python/samba/tests/krb5/raw_testcase.py | 39 ++++++-- + selftest/knownfail_heimdal_kdc | 9 ++ + selftest/knownfail_mit_kdc | 6 ++ + source4/selftest/tests.py | 58 +++++++---- + 5 files changed, 168 insertions(+), 65 deletions(-) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 99a91528fa8..f14439a4ab5 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -497,12 +497,18 @@ class KdcTgsTests(KDCBaseTest): + def test_renew_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True) +- self._renew_tgt(tgt, expected_error=0) ++ self._renew_tgt(tgt, expected_error=0, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_validate_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True) +- self._validate_tgt(tgt, expected_error=0) ++ self._validate_tgt(tgt, expected_error=0, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_s4u2self_req(self): + creds = self._get_creds() +@@ -774,13 +780,17 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) +- self._renew_tgt(tgt, expected_error=0) ++ self._renew_tgt(tgt, expected_error=0, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_validate_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) +- self._validate_tgt(tgt, expected_error=0) ++ self._validate_tgt(tgt, expected_error=0, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_s4u2self_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, +@@ -1434,7 +1444,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + def test_pac_attrs_renew_false(self): + creds = self._get_creds() +@@ -1447,7 +1458,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=False) ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + def test_pac_attrs_renew_true(self): + creds = self._get_creds() +@@ -1460,7 +1472,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, +@@ -1473,8 +1486,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, +@@ -1487,8 +1500,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1501,8 +1514,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_none(self): + creds = self._get_creds() +@@ -1515,7 +1528,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_false(self): + creds = self._get_creds() +@@ -1528,7 +1542,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_true(self): + creds = self._get_creds() +@@ -1541,7 +1556,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, +@@ -1555,7 +1571,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, +@@ -1569,7 +1586,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1583,7 +1601,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_tgs_pac_attrs_none(self): + creds = self._get_creds() +@@ -1593,8 +1612,7 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs_pac_request=None) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs=False) + + def test_tgs_pac_attrs_false(self): + creds = self._get_creds() +@@ -1603,7 +1621,8 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + +- self._run_tgs(tgt, expected_error=0, expect_pac=False) ++ self._run_tgs(tgt, expected_error=0, expect_pac=False, ++ expect_pac_attrs=False) + + def test_tgs_pac_attrs_true(self): + creds = self._get_creds() +@@ -1613,8 +1632,7 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs_pac_request=True) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs=False) + + def test_as_requester_sid(self): + creds = self._get_creds() +@@ -1639,8 +1657,7 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=True) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expected_sid=sid, +- expect_requester_sid=True) ++ expect_requester_sid=False) + + def test_tgs_requester_sid_renew(self): + creds = self._get_creds() +@@ -1655,6 +1672,8 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, + expected_sid=sid, + expect_requester_sid=True) + +@@ -1672,6 +1691,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=False, + expected_sid=sid, + expect_requester_sid=True) + +@@ -1738,7 +1758,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=None) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1750,7 +1773,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + +@@ -1762,7 +1788,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=True) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1774,7 +1803,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=None) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1786,7 +1818,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + +@@ -1798,7 +1833,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=True) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1946,7 +1984,7 @@ class KdcTgsTests(KDCBaseTest): + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +- pac = self.get_ticket_pac(ticket, expect_pac=False) ++ pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_tgs_rodc_pac_request_true(self): +@@ -2279,12 +2317,21 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + +- def _validate_tgt(self, tgt, expected_error, expect_pac=True): ++ def _validate_tgt(self, tgt, expected_error, expect_pac=True, ++ expect_pac_attrs=None, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=None, ++ expected_sid=None): + krbtgt_creds = self.get_krbtgt_creds() + kdc_options = str(krb5_asn1.KDCOptions('validate')) +- return self._tgs_req(tgt, expected_error, krbtgt_creds, +- kdc_options=kdc_options, +- expect_pac=expect_pac) ++ return self._tgs_req( ++ tgt, expected_error, krbtgt_creds, ++ kdc_options=kdc_options, ++ expect_pac=expect_pac, ++ expect_pac_attrs=expect_pac_attrs, ++ expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, ++ expect_requester_sid=expect_requester_sid, ++ expected_sid=expected_sid) + + def _s4u2self(self, tgt, tgt_creds, expected_error, expect_pac=True, + expect_edata=False, expected_status=None): +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index da3f69c79c6..14e655313fc 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -602,6 +602,13 @@ class RawKerberosTest(TestCaseInTempDir): + expect_pac = '1' + cls.expect_pac = bool(int(expect_pac)) + ++ expect_extra_pac_buffers = samba.tests.env_get_var_value( ++ 'EXPECT_EXTRA_PAC_BUFFERS', ++ allow_missing=True) ++ if expect_extra_pac_buffers is None: ++ expect_extra_pac_buffers = '1' ++ cls.expect_extra_pac_buffers = bool(int(expect_extra_pac_buffers)) ++ + def setUp(self): + super().setUp() + self.do_asn1_print = False +@@ -2624,17 +2631,34 @@ class RawKerberosTest(TestCaseInTempDir): + if not self.tkt_sig_support: + require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + ++ expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP ++ + expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs'] ++ ++ if expect_pac_attrs: ++ expect_pac_attrs_pac_request = kdc_exchange_dict[ ++ 'expect_pac_attrs_pac_request'] ++ else: ++ expect_pac_attrs_pac_request = kdc_exchange_dict[ ++ 'pac_request'] ++ ++ if expect_pac_attrs is None: ++ if self.expect_extra_pac_buffers: ++ expect_pac_attrs = expect_extra_pac_buffers ++ else: ++ require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) + if expect_pac_attrs: + expected_types.append(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) +- elif expect_pac_attrs is None: +- require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) + + expect_requester_sid = kdc_exchange_dict['expect_requester_sid'] ++ ++ if expect_requester_sid is None: ++ if self.expect_extra_pac_buffers: ++ expect_requester_sid = expect_extra_pac_buffers ++ else: ++ require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID) + if expect_requester_sid: + expected_types.append(krb5pac.PAC_TYPE_REQUESTER_SID) +- elif expect_requester_sid is None: +- require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID) + + buffer_types = [pac_buffer.type + for pac_buffer in pac.buffers] +@@ -2722,9 +2746,6 @@ class RawKerberosTest(TestCaseInTempDir): + requested_pac = bool(flags & 1) + given_pac = bool(flags & 2) + +- expect_pac_attrs_pac_request = kdc_exchange_dict[ +- 'expect_pac_attrs_pac_request'] +- + self.assertEqual(expect_pac_attrs_pac_request is True, + requested_pac) + self.assertEqual(expect_pac_attrs_pac_request is None, +@@ -2734,8 +2755,8 @@ class RawKerberosTest(TestCaseInTempDir): + and expect_requester_sid): + requester_sid = pac_buffer.info.sid + +- self.assertIsNotNone(expected_sid) +- self.assertEqual(expected_sid, str(requester_sid)) ++ if expected_sid is not None: ++ self.assertEqual(expected_sid, str(requester_sid)) + + def generic_check_kdc_error(self, + kdc_exchange_dict, +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 61de06659be..294e06027b1 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -289,11 +289,15 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +@@ -309,10 +313,14 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +@@ -332,6 +340,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 3e19ee6c8b9..6c74657e87d 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -411,6 +411,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_krbtgt_link +@@ -479,6 +482,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_krbtgt_link + +From 3fdfbd08b9460fb486f100d7091984f41ebd9429 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 13:10:52 +1300 +Subject: [PATCH 33/99] tests/krb5: Add tests for validation with requester SID + PAC buffer + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ca80c47406e0f2b6fac2c55229306e21ccef9745) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 67 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 3 ++ + selftest/knownfail_mit_kdc | 4 ++ + 3 files changed, 74 insertions(+) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index f14439a4ab5..50079a1710c 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1726,6 +1726,73 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_tgs_requester_sid_validate(self): ++ creds = self._get_creds() ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, invalid=True) ++ ++ self._validate_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ ++ def test_tgs_requester_sid_rodc_validate(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True) ++ ++ self._validate_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=False, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ ++ def test_tgs_requester_sid_missing_validate(self): ++ creds = self._get_creds() ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, invalid=True, ++ remove_requester_sid=True) ++ ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) ++ ++ def test_tgs_requester_sid_missing_rodc_validate(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True, ++ remove_requester_sid=True) ++ ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) ++ + def test_tgs_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 294e06027b1..f7c5feda872 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -320,7 +320,10 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 6c74657e87d..ff287e6cd9d 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -546,8 +546,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing +-- +2.25.1 + + +From 69233dd323b1ce715387e6015542ed234d909295 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 15:32:32 +1300 +Subject: [PATCH 34/99] tests/krb5: Add comments for tests that fail against + Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 749349efab9b401d33a4fc286473a924364a41c9) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 50079a1710c..ecc38538e61 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -792,6 +792,8 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs=False, + expect_requester_sid=True) + ++ # This test fails on Windows, which gives KDC_ERR_C_PRINCIPAL_UNKNOWN when ++ # attempting to use S4U2Self with a TGT from an RODC. + def test_s4u2self_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -2370,6 +2372,8 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + ++ # These tests fail against Windows, which does not implement ticket ++ # renewal. + def _renew_tgt(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, expected_sid=None): +@@ -2384,6 +2388,8 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + ++ # These tests fail against Windows, which does not implement ticket ++ # validation. + def _validate_tgt(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, +-- +2.25.1 + + +From 6dbed53756f6bac8f63847644b3e9cbb7b6181b0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 18 Nov 2021 13:14:51 +1300 +Subject: [PATCH 35/99] heimdal:kdc: Fix error message for user-to-user + +We were checking the wrong variable to see whether a PAC was found or not. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 11fb9476ad3c09415d12b3cdf7934c293cbefcb2) +--- + source4/heimdal/kdc/krb5tgs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c +index fb2ef8230c9..cde68b41714 100644 +--- source4/heimdal/kdc/krb5tgs.c ++++ source4/heimdal/kdc/krb5tgs.c +@@ -1629,7 +1629,7 @@ server_lookup: + ret = KRB5KDC_ERR_BADOPTION; + kdc_log(context, config, 0, + "Ticket not signed with PAC; user-to-user failed (%s).", +- mspac ? "Ticket unsigned" : "No PAC"); ++ user2user_pac ? "Ticket unsigned" : "No PAC"); + goto out; + } + +-- +2.25.1 + + +From 33d5e5ad3a06ca6a1a62e64d323580ca60f068b8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 18 Nov 2021 16:22:34 +1300 +Subject: [PATCH 36/99] s4:torture: Fix typo + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9cfb88ba04818b5e9cec3c96422e8e4a3080d490) +--- + source4/torture/krb5/kdc-canon-heimdal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git source4/torture/krb5/kdc-canon-heimdal.c source4/torture/krb5/kdc-canon-heimdal.c +index cd47182c0ef..059078a4ffb 100644 +--- source4/torture/krb5/kdc-canon-heimdal.c ++++ source4/torture/krb5/kdc-canon-heimdal.c +@@ -262,7 +262,7 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ + KRB5_NT_PRINCIPAL, + "krb5 libs unexpectedly " + "did not set principal " +- "as NT_SRV_HST!"); ++ "as NT_PRINCIPAL!"); + } else { + torture_assert_int_equal(test_context->tctx, + test_context->as_req.req_body.cname->name_type, +-- +2.25.1 + + +From 02ceb9be33dca0e3a885fd7d85b1199f76e04670 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:34 +1300 +Subject: [PATCH 37/99] heimdal:kdc: Adjust no-PAC error code to match Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit f7a2fef8f49a86f63c3dc2f6a2d7d979fb53238a) +--- + selftest/knownfail_heimdal_kdc | 19 ------------------- + source4/heimdal/kdc/krb5tgs.c | 2 +- + 2 files changed, 1 insertion(+), 20 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index f7c5feda872..9ff85fe18fc 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -233,21 +233,15 @@ + # S4U tests + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required) +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$ +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -292,11 +286,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting +@@ -304,15 +293,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +@@ -333,16 +318,12 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting +diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c +index cde68b41714..6c5c51aa448 100644 +--- source4/heimdal/kdc/krb5tgs.c ++++ source4/heimdal/kdc/krb5tgs.c +@@ -78,7 +78,7 @@ check_PAC(krb5_context context, + return ret; + + if (pac == NULL) +- return KRB5KDC_ERR_BADOPTION; ++ return KRB5KDC_ERR_TGT_REVOKED; + + /* Verify the server signature. */ + ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal, +-- +2.25.1 + + +From 5556f97c782c9be9af47c76f2432bb8480bc0622 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:45 +1300 +Subject: [PATCH 38/99] kdc: Adjust SID mismatch error code to match Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit d5d22bf84a71492342287e54b555c9f024e7e71c) +--- + selftest/knownfail_heimdal_kdc | 35 ---------------------------------- + selftest/knownfail_mit_kdc | 8 -------- + source4/kdc/pac-glue.c | 6 +----- + 3 files changed, 1 insertion(+), 48 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 9ff85fe18fc..bc644587319 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -259,13 +259,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed + # +-# Alias tests +-# +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename +-# + # KDC TGS tests + # + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac +@@ -281,23 +274,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +@@ -309,23 +290,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index ff287e6cd9d..c6dc1285837 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -407,8 +407,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none +@@ -424,8 +422,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req +@@ -454,8 +450,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname +@@ -495,8 +489,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # + # PAC attributes tests + # +diff --git source4/kdc/pac-glue.c source4/kdc/pac-glue.c +index e0e483662c0..2a96a683cd9 100644 +--- source4/kdc/pac-glue.c ++++ source4/kdc/pac-glue.c +@@ -1237,11 +1237,7 @@ krb5_error_code samba_kdc_validate_pac_blob( + "PAC[%s] != CLI[%s]\n", + dom_sid_str_buf(&pac_sid, &buf1), + dom_sid_str_buf(client_sid, &buf2)); +-#if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */ +- code = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; +-#else /* Heimdal (where this is an enum) */ +- code = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; +-#endif ++ code = KRB5KDC_ERR_TGT_REVOKED; + goto out; + } + +-- +2.25.1 + + +From c62a2b7a218e2c4bdbd476a055049e78b8c0f4ce Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:05:17 +1300 +Subject: [PATCH 39/99] tests/krb5: Add test for S4U2Self with wrong sname + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit bac5f75059450898937be891e863826e1350b62c) +--- + python/samba/tests/krb5/s4u_tests.py | 32 +++++++++++++++++++++++++++- + selftest/knownfail_heimdal_kdc | 1 + + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py +index 5f37525f393..2953766ef21 100755 +--- python/samba/tests/krb5/s4u_tests.py ++++ python/samba/tests/krb5/s4u_tests.py +@@ -36,6 +36,7 @@ from samba.tests.krb5.raw_testcase import ( + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, ++ KDC_ERR_BADMATCH, + KDC_ERR_BADOPTION, + KDC_ERR_BAD_INTEGRITY, + KDC_ERR_GENERIC, +@@ -243,7 +244,9 @@ class S4UKerberosTests(KDCBaseTest): + client_dn = client_creds.get_dn() + sid = self.get_objectSid(samdb, client_dn) + +- service_name = service_creds.get_username()[:-1] ++ service_name = kdc_dict.pop('service_name', None) ++ if service_name is None: ++ service_name = service_creds.get_username()[:-1] + service_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', service_name]) + +@@ -474,6 +477,33 @@ class S4UKerberosTests(KDCBaseTest): + 'expected_flags': 'forwardable' + }) + ++ # Do an S4U2Self with the sname in the request different to that of the ++ # service. We expect an error. ++ def test_s4u2self_wrong_sname(self): ++ other_creds = self.get_cached_creds( ++ account_type=self.AccountType.COMPUTER, ++ opts={ ++ 'trusted_to_auth_for_delegation': True, ++ 'id': 0 ++ }) ++ other_sname = other_creds.get_username()[:-1] ++ ++ self._run_s4u2self_test( ++ { ++ 'expected_error_mode': KDC_ERR_BADMATCH, ++ 'expect_edata': False, ++ 'client_opts': { ++ 'not_delegated': False ++ }, ++ 'service_opts': { ++ 'trusted_to_auth_for_delegation': True ++ }, ++ 'service_name': other_sname, ++ 'kdc_options': 'forwardable', ++ 'modify_service_tgt_fn': functools.partial( ++ self.set_ticket_forwardable, flag=True) ++ }) ++ + def _run_delegation_test(self, kdc_dict): + client_opts = kdc_dict.pop('client_opts', None) + client_creds = self.get_cached_creds( +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index bc644587319..483145f1473 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -243,6 +243,7 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +-- +2.25.1 + + +From 46b05cbf803c54cf56dca228fe95a3454027d0cc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:00:07 +1300 +Subject: [PATCH 40/99] kdc: Match Windows error code for mismatching sname + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit b6a25f5f016aef39c3b1d7be8b3ecfe021c03c83) +--- + selftest/knownfail_heimdal_kdc | 3 --- + source4/kdc/db-glue.c | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 483145f1473..981d7894158 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -243,7 +243,6 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -292,6 +291,4 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index d017741e30a..bed0ff773f9 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -2599,7 +2599,7 @@ samba_kdc_check_s4u2self(krb5_context context, + */ + if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { + talloc_free(frame); +- return KRB5KDC_ERR_BADOPTION; ++ return KRB5KRB_AP_ERR_BADMATCH; + } + + talloc_free(frame); +-- +2.25.1 + + +From 93a5264dd68da57e172af50020f670631eeef263 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:15:41 +1300 +Subject: [PATCH 41/99] kdc: Always add the PAC if the header TGT is from an + RODC + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 690a00a40c0a3f77da6e4dca42b630f2793a98b8) +--- + selftest/knownfail_heimdal_kdc | 1 - + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 981d7894158..94a4509f45a 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -290,5 +290,4 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c +index ecd182702c3..8c3ce71529c 100644 +--- source4/kdc/wdc-samba4.c ++++ source4/kdc/wdc-samba4.c +@@ -471,7 +471,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!server_skdc_entry->is_krbtgt) { ++ if (!is_untrusted && !server_skdc_entry->is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +-- +2.25.1 + + +From 4cd44326ce38187965c46c71322caedb7a2fbf6c Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:32:44 +1300 +Subject: [PATCH 42/99] tests/krb5: Add tests for renewal and validation of + RODC TGTs with PAC requests + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 73a48063469205099f02efdf3b8f0f1040dc7a3d) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 90 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 6 ++ + selftest/knownfail_mit_kdc | 6 ++ + 3 files changed, 102 insertions(+) + +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index ecc38538e61..2923d53772a 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1867,6 +1867,51 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_rodc_renew_pac_request_none(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=None) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_renew_pac_request_false(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_renew_pac_request_true(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=True) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_validate_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +@@ -1912,6 +1957,51 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_rodc_validate_pac_request_none(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=None) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_validate_pac_request_false(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_validate_pac_request_true(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=True) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_s4u2self_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 94a4509f45a..2de898e73c2 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -278,6 +278,12 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index c6dc1285837..73e64145e42 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -422,6 +422,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req +-- +2.25.1 + + +From 925f63f3e464c0fdb91aaa5ed523a6ddb481bfff Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 13:24:57 +1300 +Subject: [PATCH 43/99] Revert "CVE-2020-25719 s4/torture: Expect additional + PAC buffers" + +This reverts commit fa4c9bcefdeed0a7106aab84df20b02435febc1f. + +We should not be generating these additional PAC buffers for service +tickets, only for TGTs. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit e61983c7f2c4daade83b237efb990d0c0645b3a3) +--- + selftest/knownfail_heimdal_kdc | 39 ++++++++++++++++++++++++++++++++ + source4/torture/rpc/remote_pac.c | 24 ++------------------ + 2 files changed, 41 insertions(+), 22 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 2de898e73c2..65e4fee9510 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -297,3 +297,42 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed ++# ++# PAC tests ++# ++^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local ++^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc +diff --git source4/torture/rpc/remote_pac.c source4/torture/rpc/remote_pac.c +index c94decef5ce..14c23f674f1 100644 +--- source4/torture/rpc/remote_pac.c ++++ source4/torture/rpc/remote_pac.c +@@ -266,7 +266,7 @@ static bool test_PACVerify(struct torture_context *tctx, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed"); + +- num_pac_buffers = 7; ++ num_pac_buffers = 5; + if (expect_pac_upn_dns_info) { + num_pac_buffers += 1; + } +@@ -323,18 +323,6 @@ static bool test_PACVerify(struct torture_context *tctx, + pac_buf->info != NULL, + "PAC_TYPE_TICKET_CHECKSUM info"); + +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO"); +- torture_assert(tctx, +- pac_buf->info != NULL, +- "PAC_TYPE_ATTRIBUTES_INFO info"); +- +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID"); +- torture_assert(tctx, +- pac_buf->info != NULL, +- "PAC_TYPE_REQUESTER_SID info"); +- + ok = netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name, + negotiate_flags, pac_data, session_info); + +@@ -1094,7 +1082,7 @@ static bool test_S4U2Proxy(struct torture_context *tctx, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed"); + +- num_pac_buffers = 9; ++ num_pac_buffers = 7; + + torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version"); + torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers"); +@@ -1134,14 +1122,6 @@ static bool test_S4U2Proxy(struct torture_context *tctx, + talloc_asprintf(tctx, "%s@%s", self_princ, cli_credentials_get_realm(credentials)), + "wrong transited_services[0]"); + +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO"); +- torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_ATTRIBUTES_INFO info"); +- +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID"); +- torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_REQUESTER_SID info"); +- + return netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name, + negotiate_flags, pac_data, session_info); + } +-- +2.25.1 + + +From 72afa2641c24bd18a32463f0b0de7e91feb54290 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:42:22 +1300 +Subject: [PATCH 44/99] kdc: Don't include extra PAC buffers in service tickets + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 90025b6a4d250a15c0f988a9a9150ecfb63069ef) +--- + selftest/knownfail_heimdal_kdc | 42 ---------------------------------- + source4/kdc/wdc-samba4.c | 31 +++++++++++++++++-------- + 2 files changed, 21 insertions(+), 52 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 65e4fee9510..ea08cb44122 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -285,11 +285,8 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +@@ -297,42 +294,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +-# +-# PAC tests +-# +-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local +-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc +diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c +index 8c3ce71529c..17af76f4edb 100644 +--- source4/kdc/wdc-samba4.c ++++ source4/kdc/wdc-samba4.c +@@ -132,6 +132,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + krb5_error_code ret; + NTSTATUS nt_status; + bool is_in_db, is_untrusted; ++ bool is_krbtgt; + size_t num_types = 0; + uint32_t *types = NULL; + uint32_t forced_next_type = 0; +@@ -471,7 +472,9 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!is_untrusted && !server_skdc_entry->is_krbtgt) { ++ is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); ++ ++ if (!is_untrusted && !is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +@@ -576,17 +579,25 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- /* just copy... */ +- break; ++ if (is_krbtgt) { ++ /* just copy... */ ++ break; ++ } else { ++ continue; ++ } + case PAC_TYPE_REQUESTER_SID: +- /* +- * Replace in the RODC case, otherwise +- * requester_sid_blob is NULL and we just copy. +- */ +- if (requester_sid_blob != NULL) { +- type_blob = *requester_sid_blob; ++ if (is_krbtgt) { ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; ++ } else { ++ continue; + } +- break; + default: + /* just copy... */ + break; +-- +2.25.1 + + +From 29f15fe2d92831dcf5f4eb6d295df866ff689ee3 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:53:49 +1300 +Subject: [PATCH 45/99] kdc: Remove PAC_TYPE_ATTRIBUTES_INFO from RODC-issued + tickets + +Windows ignores PAC_TYPE_ATTRIBUTES_INFO and always issues a PAC when +presented with an RODC-issued TGT. By removing this PAC buffer from +RODC-issued tickets, we ensure that an RODC-issued ticket will still +result in a PAC if it is first renewed or validated by the main DC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4b60e9516497c2e7f1545fe50887d0336b9893f2) +--- + selftest/knownfail_heimdal_kdc | 13 ------------- + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 14 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index ea08cb44122..5e94cb63d7a 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -274,16 +274,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +@@ -291,6 +281,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c +index 17af76f4edb..713720bcb99 100644 +--- source4/kdc/wdc-samba4.c ++++ source4/kdc/wdc-samba4.c +@@ -579,7 +579,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- if (is_krbtgt) { ++ if (!is_untrusted && is_krbtgt) { + /* just copy... */ + break; + } else { +-- +2.25.1 + + +From d3436300745c41226d7ed146f269c929133f8f49 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 12:46:40 +1300 +Subject: [PATCH 46/99] tests/krb5: Add a test for S4U2Self with no + authorization data required + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 192d6edfe912105ec344dc554f872a24c03540a3) +--- + python/samba/tests/krb5/s4u_tests.py | 34 ++++++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 1 + + 2 files changed, 35 insertions(+) + +diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py +index 2953766ef21..6ec9af11423 100755 +--- python/samba/tests/krb5/s4u_tests.py ++++ python/samba/tests/krb5/s4u_tests.py +@@ -324,6 +324,13 @@ class S4UKerberosTests(KDCBaseTest): + sname=service_sname, + etypes=etypes) + ++ if not expected_error_mode: ++ # Check that the ticket contains a PAC. ++ ticket = kdc_exchange_dict['rep_ticket_creds'] ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + +@@ -504,6 +511,24 @@ class S4UKerberosTests(KDCBaseTest): + self.set_ticket_forwardable, flag=True) + }) + ++ # Do an S4U2Self where the service does not require authorization data. The ++ # resulting ticket should still contain a PAC. ++ def test_s4u2self_no_auth_data_required(self): ++ self._run_s4u2self_test( ++ { ++ 'client_opts': { ++ 'not_delegated': False ++ }, ++ 'service_opts': { ++ 'trusted_to_auth_for_delegation': True, ++ 'no_auth_data_required': True ++ }, ++ 'kdc_options': 'forwardable', ++ 'modify_service_tgt_fn': functools.partial( ++ self.set_ticket_forwardable, flag=True), ++ 'expected_flags': 'forwardable' ++ }) ++ + def _run_delegation_test(self, kdc_dict): + client_opts = kdc_dict.pop('client_opts', None) + client_creds = self.get_cached_creds( +@@ -654,6 +679,15 @@ class S4UKerberosTests(KDCBaseTest): + etypes=etypes, + additional_tickets=additional_tickets) + ++ if not expected_error_mode: ++ # Check whether the ticket contains a PAC. ++ ticket = kdc_exchange_dict['rep_ticket_creds'] ++ pac = self.get_ticket_pac(ticket, expect_pac=expect_pac) ++ if expect_pac: ++ self.assertIsNotNone(pac) ++ else: ++ self.assertIsNone(pac) ++ + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 5e94cb63d7a..2025032a278 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -242,6 +242,7 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +-- +2.25.1 + + +From 8f97f78dd8023d88d76fc7de063661d94ebe5400 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 17:30:50 +1300 +Subject: [PATCH 47/99] heimdal:kdc: Always generate a PAC for S4U2Self + +If we decided not to put a PAC into the ticket, mspac would be NULL +here, and the resulting ticket would not contain a PAC. This could +happen if there was a request to omit the PAC or the service did not +require authorization data. Ensure that we always generate a PAC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1f4f3018c5001b289b91959a72d00575c8fc0ac1) +--- + selftest/knownfail_heimdal_kdc | 2 -- + source4/heimdal/kdc/krb5tgs.c | 13 +++++++------ + 2 files changed, 7 insertions(+), 8 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 2025032a278..53cc8e6b6a2 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -242,7 +242,6 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -275,7 +274,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c +index 6c5c51aa448..dc356b4daa5 100644 +--- source4/heimdal/kdc/krb5tgs.c ++++ source4/heimdal/kdc/krb5tgs.c +@@ -1846,12 +1846,13 @@ server_lookup: + if (mspac) { + krb5_pac_free(context, mspac); + mspac = NULL; +- ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); +- if (ret) { +- kdc_log(context, config, 0, "PAC generation failed for -- %s", +- tpn); +- goto out; +- } ++ } ++ ++ ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); ++ if (ret) { ++ kdc_log(context, config, 0, "PAC generation failed for -- %s", ++ tpn); ++ goto out; + } + + /* +-- +2.25.1 + + +From 8585333a8ef54295a60faf47689a8978c0740361 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 09:29:42 +1300 +Subject: [PATCH 48/99] selftest: Properly check extra PAC buffers with Heimdal + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ee4aa21c487fa80082a548b2e4f115a791e30340) + +[jsutton@samba.org Fixed conflicts] +--- + selftest/knownfail_heimdal_kdc | 12 ++++++++++++ + source4/selftest/tests.py | 2 +- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 53cc8e6b6a2..f71b95f306e 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -241,8 +241,15 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -274,6 +281,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + + +From 65bb0e3201d60d87a3f228ea161644d9a5f918c5 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 19:38:35 +1300 +Subject: [PATCH 49/99] heimdal:kdc: Do not generate extra PAC buffers for + S4U2Self service ticket + +Normally samba_wdc_get_pac() is used to generate the PAC for a TGT, but +when generating a service ticket for S4U2Self, we want to avoid adding +the additional PAC_ATTRIBUTES_INFO and PAC_REQUESTER_SID buffers. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9bd26804852d957f81cb311e5142f9190f9afa65) +--- + selftest/knownfail_heimdal_kdc | 12 ------------ + source4/heimdal/kdc/kerberos5.c | 2 +- + source4/heimdal/kdc/krb5tgs.c | 3 ++- + source4/heimdal/kdc/windc.c | 5 +++-- + source4/heimdal/kdc/windc_plugin.h | 2 ++ + source4/kdc/wdc-samba4.c | 11 ++++++++--- + 6 files changed, 16 insertions(+), 19 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index f71b95f306e..53cc8e6b6a2 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -241,15 +241,8 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -281,11 +274,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +diff --git source4/heimdal/kdc/kerberos5.c source4/heimdal/kdc/kerberos5.c +index 9684364c519..a9e81336615 100644 +--- source4/heimdal/kdc/kerberos5.c ++++ source4/heimdal/kdc/kerberos5.c +@@ -1776,7 +1776,7 @@ _kdc_as_rep(krb5_context context, + + sent_pac_request = send_pac_p(context, req, &pac_request); + +- ret = _kdc_pac_generate(context, client, pk_reply_key, ++ ret = _kdc_pac_generate(context, client, server, pk_reply_key, + sent_pac_request ? &pac_request : NULL, + &p); + if (ret) { +diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c +index dc356b4daa5..38dba8493ae 100644 +--- source4/heimdal/kdc/krb5tgs.c ++++ source4/heimdal/kdc/krb5tgs.c +@@ -1848,7 +1848,8 @@ server_lookup: + mspac = NULL; + } + +- ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); ++ ret = _kdc_pac_generate(context, s4u2self_impersonated_client, server, ++ NULL, NULL, &mspac); + if (ret) { + kdc_log(context, config, 0, "PAC generation failed for -- %s", + tpn); +diff --git source4/heimdal/kdc/windc.c source4/heimdal/kdc/windc.c +index 93b973f576b..0a5ae5025ec 100644 +--- source4/heimdal/kdc/windc.c ++++ source4/heimdal/kdc/windc.c +@@ -73,6 +73,7 @@ krb5_kdc_windc_init(krb5_context context) + krb5_error_code + _kdc_pac_generate(krb5_context context, + hdb_entry_ex *client, ++ hdb_entry_ex *server, + const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, + krb5_pac *pac) +@@ -88,9 +89,9 @@ _kdc_pac_generate(krb5_context context, + + if (windcft->pac_pk_generate != NULL && pk_reply_key != NULL) + return (windcft->pac_pk_generate)(windcctx, context, +- client, pk_reply_key, ++ client, server, pk_reply_key, + pac_request, pac); +- return (windcft->pac_generate)(windcctx, context, client, ++ return (windcft->pac_generate)(windcctx, context, client, server, + pac_request, pac); + } + +diff --git source4/heimdal/kdc/windc_plugin.h source4/heimdal/kdc/windc_plugin.h +index c7f2bcb5ed9..d239d0260e7 100644 +--- source4/heimdal/kdc/windc_plugin.h ++++ source4/heimdal/kdc/windc_plugin.h +@@ -55,12 +55,14 @@ struct hdb_entry_ex; + typedef krb5_error_code + (*krb5plugin_windc_pac_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ ++ struct hdb_entry_ex *, /* server */ + const krb5_boolean *, /* pac_request */ + krb5_pac *); + + typedef krb5_error_code + (*krb5plugin_windc_pac_pk_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ ++ struct hdb_entry_ex *, /* server */ + const krb5_keyblock *, /* pk_replykey */ + const krb5_boolean *, /* pac_request */ + krb5_pac *); +diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c +index 713720bcb99..b1d011c09a9 100644 +--- source4/kdc/wdc-samba4.c ++++ source4/kdc/wdc-samba4.c +@@ -37,6 +37,7 @@ + */ + static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, + const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, + krb5_pac *pac) +@@ -55,6 +56,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + struct samba_kdc_entry *skdc_entry = + talloc_get_type_abort(client->ctx, + struct samba_kdc_entry); ++ bool is_krbtgt; + + mem_ctx = talloc_named(client->ctx, 0, "samba_get_pac context"); + if (!mem_ctx) { +@@ -65,13 +67,15 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + cred_ndr_ptr = &cred_ndr; + } + ++ is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); ++ + nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry, + &logon_blob, + cred_ndr_ptr, + &upn_blob, +- &pac_attrs_blob, ++ is_krbtgt ? &pac_attrs_blob : NULL, + pac_request, +- &requester_sid_blob, ++ is_krbtgt ? &requester_sid_blob : NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); +@@ -101,10 +105,11 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + + static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context, + struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, + const krb5_boolean *pac_request, + krb5_pac *pac) + { +- return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac); ++ return samba_wdc_get_pac(priv, context, client, server, NULL, pac_request, pac); + } + + static krb5_error_code samba_wdc_reget_pac2(krb5_context context, +-- +2.25.1 + + +From 49aafce0a705d47ffd4753ce6c6f452c4f7aa882 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:54 +1300 +Subject: [PATCH 50/99] kdc: Require that PAC_REQUESTER_SID buffer is present + for TGTs + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Nov 30 03:33:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 38c5bad4a853b19fe9a51fb059e150b153c4632a) +--- + selftest/knownfail_heimdal_kdc | 6 ------ + source4/kdc/wdc-samba4.c | 6 ++++++ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 53cc8e6b6a2..32465cb6042 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -274,9 +274,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c +index b1d011c09a9..d7ce34fb3a9 100644 +--- source4/kdc/wdc-samba4.c ++++ source4/kdc/wdc-samba4.c +@@ -459,6 +459,12 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + talloc_free(mem_ctx); + return EINVAL; + } ++ if (delegated_proxy_principal == NULL && requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return KRB5KDC_ERR_TGT_REVOKED; ++ } + + /* + * The server account may be set not to want the PAC. +-- +2.25.1 + + +From 3fc519edec0159535baa0b659861b73f40632110 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 7 Dec 2021 13:15:38 +1300 +Subject: [PATCH 51/99] kdc: Canonicalize realm for enterprise principals + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Dec 7 04:54:35 UTC 2021 on sn-devel-184 + +(cherry picked from commit 8bd7b316bd61ef35f6e0baa0b65f0ef00910112c) +--- + selftest/knownfail.d/kdc-enterprise | 63 ----------------------------- + selftest/knownfail_heimdal_kdc | 3 -- + selftest/knownfail_mit_kdc | 36 +++++++++++++++++ + source4/kdc/db-glue.c | 24 +++++------ + 4 files changed, 47 insertions(+), 79 deletions(-) + delete mode 100644 selftest/knownfail.d/kdc-enterprise + +diff --git selftest/knownfail.d/kdc-enterprise selftest/knownfail.d/kdc-enterprise +deleted file mode 100644 +index c9b6c98a2ee..00000000000 +--- selftest/knownfail.d/kdc-enterprise ++++ /dev/null +@@ -1,63 +0,0 @@ +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_UPN\( +- +- +- +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 32465cb6042..424a8b81c38 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -5,9 +5,6 @@ + # + # Heimdal currently fails the following MS-KILE client principal lookup + # tests +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_1_3 +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_4 +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_5 + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_6_a + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_enterprise_principal_step_6_b + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_4_a +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 73e64145e42..4d685af7140 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -56,17 +56,53 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN_RemoveDollar\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_RemoveDollar\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN\( +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index bed0ff773f9..5752ffb821c 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -980,19 +980,17 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + goto out; + } + +- if (smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) { +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ krb5_clear_error_message(context); ++ goto out; + } + } + +-- +2.25.1 + + +From 787405ef59b70cef011f005a6ed98898c5d43adb Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Dec 2021 19:16:00 +1300 +Subject: [PATCH 52/99] tests/krb5: Correctly determine whether tickets are + service tickets + +Previously we expected tickets to contain a ticket checksum if the sname +was not the krbtgt. However, the ticket checksum should not be present +if we are performing an AS-REQ to our own account. Now we determine a +ticket is a service ticket only if the request is also a TGS-REQ. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 100be7eb8e70ba270a8e92957a5e47466160a901) +--- + python/samba/tests/krb5/compatability_tests.py | 10 ++++++---- + python/samba/tests/krb5/kdc_base_test.py | 2 +- + python/samba/tests/krb5/raw_testcase.py | 18 ++++++++++-------- + python/samba/tests/krb5/rodc_tests.py | 4 ++-- + 4 files changed, 19 insertions(+), 15 deletions(-) + +diff --git python/samba/tests/krb5/compatability_tests.py python/samba/tests/krb5/compatability_tests.py +index ed2dc565b6d..65e9e3788d5 100755 +--- python/samba/tests/krb5/compatability_tests.py ++++ python/samba/tests/krb5/compatability_tests.py +@@ -132,13 +132,14 @@ class SimpleKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, key) ++ self.verify_ticket(tgt, key, service_ticket=False) + + # Get a service ticket from the DC. + service_ticket = self.get_service_ticket(tgt, target_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(service_ticket, key, expect_ticket_checksum=True) ++ self.verify_ticket(service_ticket, key, service_ticket=True, ++ expect_ticket_checksum=True) + + def test_mit_ticket_signature(self): + # Ensure that a DC does not issue tickets signed with its krbtgt key. +@@ -152,13 +153,14 @@ class SimpleKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, key) ++ self.verify_ticket(tgt, key, service_ticket=False) + + # Get a service ticket from the DC. + service_ticket = self.get_service_ticket(tgt, target_creds) + + # Ensure the PAC does not contain the expected checksums. +- self.verify_ticket(service_ticket, key, expect_ticket_checksum=False) ++ self.verify_ticket(service_ticket, key, service_ticket=True, ++ expect_ticket_checksum=False) + + def as_pre_auth_req(self, creds, etypes): + user = creds.get_username() +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 6e96b982167..9506048ee2a 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -1395,7 +1395,7 @@ class KDCBaseTest(RawKerberosTest): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + self.verify_ticket(service_ticket_creds, krbtgt_key, +- expect_pac=expect_pac, ++ service_ticket=True, expect_pac=expect_pac, + expect_ticket_checksum=self.tkt_sig_support) + + self.tkt_cache[cache_key] = service_ticket_creds +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 14e655313fc..a2241707d44 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -2587,7 +2587,11 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertIsNotNone(ticket_decryption_key) + + if ticket_decryption_key is not None: +- self.verify_ticket(ticket_creds, krbtgt_keys, expect_pac=expect_pac, ++ service_ticket = (not self.is_tgs(expected_sname) ++ and rep_msg_type == KRB_TGS_REP) ++ self.verify_ticket(ticket_creds, krbtgt_keys, ++ service_ticket=service_ticket, ++ expect_pac=expect_pac, + expect_ticket_checksum=expect_ticket_checksum + or self.tkt_sig_support) + +@@ -2624,14 +2628,14 @@ class RawKerberosTest(TestCaseInTempDir): + expected_types.append(krb5pac.PAC_TYPE_DEVICE_INFO) + expected_types.append(krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO) + +- if not self.is_tgs(expected_sname): ++ if not self.is_tgs(expected_sname) and rep_msg_type == KRB_TGS_REP: + expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + + require_strict = {krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO} + if not self.tkt_sig_support: + require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + +- expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP ++ expect_extra_pac_buffers = self.is_tgs(expected_sname) + + expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs'] + +@@ -3233,11 +3237,9 @@ class RawKerberosTest(TestCaseInTempDir): + ticket_blob) + self.assertEqual(expected_checksum, checksum) + +- def verify_ticket(self, ticket, krbtgt_keys, expect_pac=True, ++ def verify_ticket(self, ticket, krbtgt_keys, service_ticket, ++ expect_pac=True, + expect_ticket_checksum=True): +- # Check if the ticket is a TGT. +- is_tgt = self.is_tgt(ticket) +- + # Decrypt the ticket. + + key = ticket.decryption_key +@@ -3336,7 +3338,7 @@ class RawKerberosTest(TestCaseInTempDir): + kdc_ctype, + kdc_checksum) + +- if is_tgt: ++ if not service_ticket: + self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums) + else: + ticket_checksum, ticket_ctype = checksums.get( +diff --git python/samba/tests/krb5/rodc_tests.py python/samba/tests/krb5/rodc_tests.py +index 0e252d90262..83ee35d650a 100755 +--- python/samba/tests/krb5/rodc_tests.py ++++ python/samba/tests/krb5/rodc_tests.py +@@ -58,14 +58,14 @@ class RodcKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds, to_rodc=True) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, rodc_key) ++ self.verify_ticket(tgt, rodc_key, service_ticket=False) + + # Get a service ticket from the RODC. + service_ticket = self.get_service_ticket(tgt, target_creds, + to_rodc=True) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(service_ticket, rodc_key) ++ self.verify_ticket(service_ticket, rodc_key, service_ticket=True) + + + if __name__ == "__main__": +-- +2.25.1 + + +From c0977bee5b8c2f72cb5467e95a6ab034f696eee7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 8 Feb 2022 12:15:36 +1300 +Subject: [PATCH 53/99] tests/krb5: Add helper function to modify ticket flags + +Signed-off-by: Joseph Sutton +Reviewed-by: Stefan Metzmacher +(cherry picked from commit ded5115f73dff5b8b2f3212988e03f9dbe0c2aa3) +--- + python/samba/tests/krb5/kdc_base_test.py | 14 ++++++++++++++ + python/samba/tests/krb5/kdc_tgs_tests.py | 18 ++---------------- + python/samba/tests/krb5/s4u_tests.py | 17 +++-------------- + 3 files changed, 19 insertions(+), 30 deletions(-) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 9506048ee2a..58b87eab25b 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -1602,6 +1602,20 @@ class KDCBaseTest(RawKerberosTest): + enc_part, asn1Spec=krb5_asn1.EncTicketPart()) + return enc_ticket_part + ++ def modify_ticket_flag(self, enc_part, flag, value): ++ self.assertIsInstance(value, bool) ++ ++ flag = krb5_asn1.TicketFlags(flag) ++ pos = len(tuple(flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + str(int(value)) + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ return enc_part ++ + def get_objectSid(self, samdb, dn): + ''' Get the objectSID for a DN + Note: performs an Ldb query. +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 2923d53772a..8cd27dec2aa 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -2177,14 +2177,7 @@ class KdcTgsTests(KDCBaseTest): + + def _modify_renewable(self, enc_part): + # Set the renewable flag. +- renewable_flag = krb5_asn1.TicketFlags('renewable') +- pos = len(tuple(renewable_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags ++ enc_part = self.modify_ticket_flag(enc_part, 'renewable', value=True) + + # Set the renew-till time to be in the future. + renew_till = self.get_KerberosTime(offset=100 * 60 * 60) +@@ -2194,14 +2187,7 @@ class KdcTgsTests(KDCBaseTest): + + def _modify_invalid(self, enc_part): + # Set the invalid flag. +- invalid_flag = krb5_asn1.TicketFlags('invalid') +- pos = len(tuple(invalid_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags ++ enc_part = self.modify_ticket_flag(enc_part, 'invalid', value=True) + + # Set the ticket start time to be in the past. + past_time = self.get_KerberosTime(offset=-100 * 60 * 60) +diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py +index 6ec9af11423..49dd89cd764 100755 +--- python/samba/tests/krb5/s4u_tests.py ++++ python/samba/tests/krb5/s4u_tests.py +@@ -1336,20 +1336,9 @@ class S4UKerberosTests(KDCBaseTest): + modify_pac_fn=modify_pac_fn) + + def set_ticket_forwardable(self, ticket, flag, update_pac_checksums=True): +- flag = '1' if flag else '0' +- +- def modify_fn(enc_part): +- # Reset the forwardable flag +- forwardable_pos = (len(tuple(krb5_asn1.TicketFlags('forwardable'))) +- - 1) +- +- flags = enc_part['flags'] +- self.assertLessEqual(forwardable_pos, len(flags)) +- enc_part['flags'] = (flags[:forwardable_pos] + +- flag + +- flags[forwardable_pos+1:]) +- +- return enc_part ++ modify_fn = functools.partial(self.modify_ticket_flag, ++ flag='forwardable', ++ value=flag) + + if update_pac_checksums: + checksum_keys = self.get_krbtgt_checksum_key() +-- +2.25.1 + + +From c0395578c50fbc4f1946e2f5a065d94f67212eb0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 15 Jun 2022 19:37:39 +1200 +Subject: [PATCH 55/99] CVE-2022-2031 s4:kdc: Add MIT support for + ATTRIBUTES_INFO and REQUESTER_SID PAC buffers + +So that we do not confuse TGTs and kpasswd tickets, it is critical to +check that the REQUESTER_SID buffer exists in TGTs, and to ensure that +it is not propagated to service tickets. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton + +[jsutton@samba.org Brought in changes to add ATTRIBUTES_INFO and + REQUESTER_SID buffers to new PACs, and updated knownfails] + +[jsutton@samba.org Adjusted MIT knownfails] +--- + selftest/knownfail_mit_kdc | 17 ----- + source4/kdc/mit-kdb/kdb_samba_policies.c | 5 +- + source4/kdc/mit_samba.c | 93 +++++++++++++++++++++++- + source4/kdc/mit_samba.h | 1 + + 4 files changed, 94 insertions(+), 22 deletions(-) + +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 4d685af7140..108c6055d0c 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -445,7 +445,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied +@@ -482,7 +481,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_invalid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link +@@ -518,7 +516,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied +@@ -536,21 +533,17 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_pac_attrs + # +@@ -571,21 +564,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # PAC requester SID tests + # +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_as_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing +diff --git source4/kdc/mit-kdb/kdb_samba_policies.c source4/kdc/mit-kdb/kdb_samba_policies.c +index 7bc9a7b3347..3b25fff410b 100644 +--- source4/kdc/mit-kdb/kdb_samba_policies.c ++++ source4/kdc/mit-kdb/kdb_samba_policies.c +@@ -159,6 +159,7 @@ done: + + static krb5_error_code ks_get_pac(krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -173,6 +174,7 @@ static krb5_error_code ks_get_pac(krb5_context context, + code = mit_samba_get_pac(mit_ctx, + context, + client, ++ server, + client_key, + pac); + if (code != 0) { +@@ -439,7 +441,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + */ + if (with_pac && generate_pac) { + DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name); +- code = ks_get_pac(context, client_entry, client_key, &pac); ++ code = ks_get_pac(context, client_entry, server, client_key, &pac); + if (code != 0) { + goto done; + } +@@ -490,6 +492,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + + code = ks_get_pac(context, + client_entry, ++ server, + client_key, + &pac); + if (code != 0 && code != ENOENT) { +diff --git source4/kdc/mit_samba.c source4/kdc/mit_samba.c +index c2a604045d9..df2ba0a906f 100644 +--- source4/kdc/mit_samba.c ++++ source4/kdc/mit_samba.c +@@ -407,6 +407,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -417,9 +418,12 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + DATA_BLOB **cred_ndr_ptr = NULL; + DATA_BLOB cred_blob = data_blob_null; + DATA_BLOB *pcred_blob = NULL; ++ DATA_BLOB *pac_attrs_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + NTSTATUS nt_status; + krb5_error_code code; + struct samba_kdc_entry *skdc_entry; ++ bool is_krbtgt; + + skdc_entry = talloc_get_type_abort(client->e_data, + struct samba_kdc_entry); +@@ -438,12 +442,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + } + #endif + ++ is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ); ++ + nt_status = samba_kdc_get_pac_blobs(tmp_ctx, + skdc_entry, + &logon_info_blob, + cred_ndr_ptr, + &upn_dns_info_blob, +- NULL, NULL, NULL, ++ is_krbtgt ? &pac_attrs_blob : NULL, ++ NULL, ++ is_krbtgt ? &requester_sid_blob : NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); +@@ -471,8 +479,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + logon_info_blob, + pcred_blob, + upn_dns_info_blob, +- NULL, +- NULL, ++ pac_attrs_blob, ++ requester_sid_blob, + NULL, + pac); + +@@ -496,6 +504,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *deleg_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + struct samba_kdc_entry *client_skdc_entry = NULL; + struct samba_kdc_entry *krbtgt_skdc_entry = NULL; + struct samba_kdc_entry *server_skdc_entry = NULL; +@@ -511,8 +520,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + ssize_t upn_dns_info_idx = -1; + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; ++ ssize_t tkt_checksum_idx = -1; ++ ssize_t attrs_info_idx = -1; ++ ssize_t requester_sid_idx = -1; + krb5_pac new_pac = NULL; + bool ok; ++ bool is_krbtgt; + + /* Create a memory context early so code can use talloc_stackframe() */ + tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); +@@ -520,6 +533,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + return ENOMEM; + } + ++ is_krbtgt = ks_is_tgs_principal(ctx, server->princ); ++ + if (client != NULL) { + client_skdc_entry = + talloc_get_type_abort(client->e_data, +@@ -578,7 +593,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + NULL, + &upn_blob, + NULL, NULL, +- NULL, ++ &requester_sid_blob, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; +@@ -737,6 +752,45 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + kdc_checksum_idx = i; + break; ++ case PAC_TYPE_TICKET_CHECKSUM: ++ if (tkt_checksum_idx != -1) { ++ DBG_WARNING("ticket checksum type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ tkt_checksum_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ tkt_checksum_idx = i; ++ break; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (attrs_info_idx != -1) { ++ DBG_WARNING("attributes info type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ attrs_info_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ attrs_info_idx = i; ++ break; ++ case PAC_TYPE_REQUESTER_SID: ++ if (requester_sid_idx != -1) { ++ DBG_WARNING("requester sid type[%u] twice" ++ "[%zd] and [%zu]: \n", ++ types[i], ++ requester_sid_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ requester_sid_idx = i; ++ break; + default: + continue; + } +@@ -766,6 +820,13 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + code = EINVAL; + goto done; + } ++ if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) && ++ requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ code = KRB5KDC_ERR_TGT_REVOKED; ++ goto done; ++ } + + /* Build an updated PAC */ + code = krb5_pac_init(context, &new_pac); +@@ -831,6 +892,10 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + break; + case PAC_TYPE_SRV_CHECKSUM: ++ if (requester_sid_idx == -1 && requester_sid_blob != NULL) { ++ /* inject REQUESTER_SID */ ++ forced_next_type = PAC_TYPE_REQUESTER_SID; ++ } + /* + * This is generated in the main KDC code + */ +@@ -840,6 +905,26 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + * This is generated in the main KDC code + */ + continue; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (!is_untrusted && is_krbtgt) { ++ /* just copy... */ ++ break; ++ } ++ ++ continue; ++ case PAC_TYPE_REQUESTER_SID: ++ if (!is_krbtgt) { ++ continue; ++ } ++ ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; + default: + /* just copy... */ + break; +diff --git source4/kdc/mit_samba.h source4/kdc/mit_samba.h +index 636c77ec97c..4431e82a1b2 100644 +--- source4/kdc/mit_samba.h ++++ source4/kdc/mit_samba.h +@@ -50,6 +50,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac); + +-- +2.25.1 + + +From 6843c44a45044808f90687f85183e7111a465d1f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 16 Jun 2022 10:33:29 +1200 +Subject: [PATCH 56/99] heimdal:kdc: Accommodate NULL data parameter in + krb5_pac_get_buffer() + +Signed-off-by: Joseph Sutton +--- + source4/heimdal/lib/krb5/pac.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git source4/heimdal/lib/krb5/pac.c source4/heimdal/lib/krb5/pac.c +index 05bcc523080..100de904662 100644 +--- source4/heimdal/lib/krb5/pac.c ++++ source4/heimdal/lib/krb5/pac.c +@@ -394,10 +394,12 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, + if (p->pac->buffers[i].type != type) + continue; + +- ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); +- if (ret) { +- krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); +- return ret; ++ if (data) { ++ ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); ++ if (ret) { ++ krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); ++ return ret; ++ } + } + return 0; + } +-- +2.25.1 + + +From 1b38a28bcaebdae0128518605a422a194747a60f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:17:02 +1200 +Subject: [PATCH 57/99] CVE-2022-2031 s4:kpasswd: Account for missing target + principal + +This field is supposed to be optional. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c +index 2117c1c1696..b53c1a4618a 100644 +--- source4/kdc/kpasswd-service-mit.c ++++ source4/kdc/kpasswd-service-mit.c +@@ -143,16 +143,18 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + +- target_realm = smb_krb5_principal_get_realm( +- mem_ctx, context, target_principal); +- code = krb5_unparse_name_flags(context, +- target_principal, +- KRB5_PRINCIPAL_UNPARSE_NO_REALM, +- &target_name); +- if (code != 0) { +- DBG_WARNING("Failed to parse principal\n"); +- *error_string = "String conversion failed"; +- return KRB5_KPASSWD_HARDERROR; ++ if (target_principal != NULL) { ++ target_realm = smb_krb5_principal_get_realm( ++ mem_ctx, context, target_principal); ++ code = krb5_unparse_name_flags(context, ++ target_principal, ++ KRB5_PRINCIPAL_UNPARSE_NO_REALM, ++ &target_name); ++ if (code != 0) { ++ DBG_WARNING("Failed to parse principal\n"); ++ *error_string = "String conversion failed"; ++ return KRB5_KPASSWD_HARDERROR; ++ } + } + + if ((target_name != NULL && target_realm == NULL) || +-- +2.25.1 + + +From f6c5a60336de8fd67a2ef371dd2ee4cf75c53904 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:17:41 +1200 +Subject: [PATCH 58/99] CVE-2022-2031 s4:kpasswd: Add MIT fallback for decoding + setpw structure + +The target principal and realm fields of the setpw structure are +supposed to be optional, but in MIT Kerberos they are mandatory. For +better compatibility and ease of testing, fall back to parsing the +simpler (containing only the new password) structure if the MIT function +fails to decode it. + +Although the target principal and realm fields should be optional, one +is not supposed to specified without the other, so we don't have to deal +with the case where only one is specified. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 94 ++++++++++++++++++++++++++----- + 1 file changed, 79 insertions(+), 15 deletions(-) + +diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c +index b53c1a4618a..9c4d2801669 100644 +--- source4/kdc/kpasswd-service-mit.c ++++ source4/kdc/kpasswd-service-mit.c +@@ -28,6 +28,7 @@ + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "../lib/util/asn1.h" + + #define RFC3244_VERSION 0xff80 + +@@ -35,6 +36,52 @@ krb5_error_code decode_krb5_setpw_req(const krb5_data *code, + krb5_data **password_out, + krb5_principal *target_out); + ++/* ++ * A fallback for when MIT refuses to parse a setpw structure without the ++ * (optional) target principal and realm ++ */ ++static bool decode_krb5_setpw_req_simple(TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *decoded_data, ++ DATA_BLOB *clear_data) ++{ ++ struct asn1_data *asn1 = NULL; ++ bool ret; ++ ++ asn1 = asn1_init(mem_ctx, 3); ++ if (asn1 == NULL) { ++ return false; ++ } ++ ++ ret = asn1_load(asn1, *decoded_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_start_tag(asn1, ASN1_SEQUENCE(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_start_tag(asn1, ASN1_CONTEXT(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_read_OctetString(asn1, mem_ctx, clear_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_end_tag(asn1); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_end_tag(asn1); ++ ++out: ++ asn1_free(asn1); ++ ++ return ret; ++} ++ + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, +@@ -93,9 +140,10 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + const char **error_string) + { + krb5_context context = kdc->smb_krb5_context->krb5_context; ++ DATA_BLOB clear_data; + krb5_data k_dec_data; +- krb5_data *k_clear_data; +- krb5_principal target_principal; ++ krb5_data *k_clear_data = NULL; ++ krb5_principal target_principal = NULL; + krb5_error_code code; + DATA_BLOB password; + char *target_realm = NULL; +@@ -114,29 +162,45 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + code = decode_krb5_setpw_req(&k_dec_data, + &k_clear_data, + &target_principal); +- if (code != 0) { +- DBG_WARNING("decode_krb5_setpw_req failed: %s\n", +- error_message(code)); +- ok = kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to decode packet", +- kpasswd_reply); ++ if (code == 0) { ++ clear_data.data = (uint8_t *)k_clear_data->data; ++ clear_data.length = k_clear_data->length; ++ } else { ++ target_principal = NULL; ++ ++ /* ++ * The MIT decode failed, so fall back to trying the simple ++ * case, without target_principal. ++ */ ++ ok = decode_krb5_setpw_req_simple(mem_ctx, ++ decoded_data, ++ &clear_data); + if (!ok) { +- *error_string = "Failed to create reply"; +- return KRB5_KPASSWD_HARDERROR; ++ DBG_WARNING("decode_krb5_setpw_req failed: %s\n", ++ error_message(code)); ++ ok = kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to decode packet", ++ kpasswd_reply); ++ if (!ok) { ++ *error_string = "Failed to create reply"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ return 0; + } +- return 0; + } + + ok = convert_string_talloc_handle(mem_ctx, + lpcfg_iconv_handle(kdc->task->lp_ctx), + CH_UTF8, + CH_UTF16, +- (const char *)k_clear_data->data, +- k_clear_data->length, ++ clear_data.data, ++ clear_data.length, + (void **)&password.data, + &password.length); +- krb5_free_data(context, k_clear_data); ++ if (k_clear_data != NULL) { ++ krb5_free_data(context, k_clear_data); ++ } + if (!ok) { + DBG_WARNING("String conversion failed\n"); + *error_string = "String conversion failed"; +-- +2.25.1 + + +From 6305a55870287191ce4268f6af7fe278ca7f2a30 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:34:01 +1200 +Subject: [PATCH 59/99] CVE-2022-32744 tests/krb5: Correctly handle specifying + account kvno + +The environment variable is a string, but we expect an integer. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index a2241707d44..4120edf93b9 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -724,7 +724,7 @@ class RawKerberosTest(TestCaseInTempDir): + fallback_default=False, + allow_missing=kvno_allow_missing) + if kvno is not None: +- c.set_kvno(kvno) ++ c.set_kvno(int(kvno)) + aes256_key = self.env_get_var('AES256_KEY_HEX', prefix, + fallback_default=False, + allow_missing=aes256_allow_missing) +-- +2.25.1 + + +From 8917979641abb03ef858ba72b652178475b6e918 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 20:52:04 +1200 +Subject: [PATCH 60/99] CVE-2022-2031 tests/krb5: Split out _make_tgs_request() + +This allows us to make use of it in other tests. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to having older version of + _make_tgs_request()] +--- + python/samba/tests/krb5/kdc_base_test.py | 77 ++++++++++++++++++++++++ + python/samba/tests/krb5/kdc_tgs_tests.py | 76 ----------------------- + 2 files changed, 77 insertions(+), 76 deletions(-) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 58b87eab25b..2117663b26b 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -67,6 +67,7 @@ from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_PREAUTH_REQUIRED, ++ KDC_ERR_TGT_REVOKED, + KRB_AS_REP, + KRB_TGS_REP, + KRB_ERROR, +@@ -1538,6 +1539,82 @@ class KDCBaseTest(RawKerberosTest): + + return ticket_creds + ++ def _make_tgs_request(self, client_creds, service_creds, tgt, ++ pac_request=None, expect_pac=True, ++ expect_error=False, ++ expected_account_name=None, ++ expected_upn_name=None, ++ expected_sid=None): ++ client_account = client_creds.get_username() ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[client_account]) ++ ++ service_account = service_creds.get_username() ++ sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[service_account]) ++ ++ realm = service_creds.get_realm() ++ ++ expected_crealm = realm ++ expected_cname = cname ++ expected_srealm = realm ++ expected_sname = sname ++ ++ expected_supported_etypes = service_creds.tgs_supported_enctypes ++ ++ etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) ++ ++ kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) ++ ++ target_decryption_key = self.TicketDecryptionKey_from_creds( ++ service_creds) ++ ++ authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) ++ ++ if expect_error: ++ expected_error_mode = KDC_ERR_TGT_REVOKED ++ check_error_fn = self.generic_check_kdc_error ++ check_rep_fn = None ++ else: ++ expected_error_mode = 0 ++ check_error_fn = None ++ check_rep_fn = self.generic_check_kdc_rep ++ ++ kdc_exchange_dict = self.tgs_exchange_dict( ++ expected_crealm=expected_crealm, ++ expected_cname=expected_cname, ++ expected_srealm=expected_srealm, ++ expected_sname=expected_sname, ++ expected_account_name=expected_account_name, ++ expected_upn_name=expected_upn_name, ++ expected_sid=expected_sid, ++ expected_supported_etypes=expected_supported_etypes, ++ ticket_decryption_key=target_decryption_key, ++ check_error_fn=check_error_fn, ++ check_rep_fn=check_rep_fn, ++ check_kdc_private_fn=self.generic_check_kdc_private, ++ expected_error_mode=expected_error_mode, ++ tgt=tgt, ++ authenticator_subkey=authenticator_subkey, ++ kdc_options=kdc_options, ++ pac_request=pac_request, ++ expect_pac=expect_pac, ++ expect_edata=False) ++ ++ rep = self._generic_kdc_exchange(kdc_exchange_dict, ++ cname=cname, ++ realm=realm, ++ sname=sname, ++ etypes=etypes) ++ if expect_error: ++ self.check_error_rep(rep, expected_error_mode) ++ ++ return None ++ else: ++ self.check_reply(rep, KRB_TGS_REP) ++ ++ return kdc_exchange_dict['rep_ticket_creds'] ++ + # Named tuple to contain values of interest when the PAC is decoded. + PacData = namedtuple( + "PacData", +diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py +index 8cd27dec2aa..e52f46152fa 100755 +--- python/samba/tests/krb5/kdc_tgs_tests.py ++++ python/samba/tests/krb5/kdc_tgs_tests.py +@@ -230,82 +230,6 @@ class KdcTgsTests(KDCBaseTest): + pac_data.account_sid, + "rep = {%s},%s" % (rep, pac_data)) + +- def _make_tgs_request(self, client_creds, service_creds, tgt, +- pac_request=None, expect_pac=True, +- expect_error=False, +- expected_account_name=None, +- expected_upn_name=None, +- expected_sid=None): +- client_account = client_creds.get_username() +- cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[client_account]) +- +- service_account = service_creds.get_username() +- sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[service_account]) +- +- realm = service_creds.get_realm() +- +- expected_crealm = realm +- expected_cname = cname +- expected_srealm = realm +- expected_sname = sname +- +- expected_supported_etypes = service_creds.tgs_supported_enctypes +- +- etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) +- +- kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) +- +- target_decryption_key = self.TicketDecryptionKey_from_creds( +- service_creds) +- +- authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) +- +- if expect_error: +- expected_error_mode = KDC_ERR_TGT_REVOKED +- check_error_fn = self.generic_check_kdc_error +- check_rep_fn = None +- else: +- expected_error_mode = 0 +- check_error_fn = None +- check_rep_fn = self.generic_check_kdc_rep +- +- kdc_exchange_dict = self.tgs_exchange_dict( +- expected_crealm=expected_crealm, +- expected_cname=expected_cname, +- expected_srealm=expected_srealm, +- expected_sname=expected_sname, +- expected_account_name=expected_account_name, +- expected_upn_name=expected_upn_name, +- expected_sid=expected_sid, +- expected_supported_etypes=expected_supported_etypes, +- ticket_decryption_key=target_decryption_key, +- check_error_fn=check_error_fn, +- check_rep_fn=check_rep_fn, +- check_kdc_private_fn=self.generic_check_kdc_private, +- expected_error_mode=expected_error_mode, +- tgt=tgt, +- authenticator_subkey=authenticator_subkey, +- kdc_options=kdc_options, +- pac_request=pac_request, +- expect_pac=expect_pac, +- expect_edata=False) +- +- rep = self._generic_kdc_exchange(kdc_exchange_dict, +- cname=cname, +- realm=realm, +- sname=sname, +- etypes=etypes) +- if expect_error: +- self.check_error_rep(rep, expected_error_mode) +- +- return None +- else: +- self.check_reply(rep, KRB_TGS_REP) +- +- return kdc_exchange_dict['rep_ticket_creds'] +- + def test_request(self): + client_creds = self.get_client_creds() + service_creds = self.get_service_creds() +-- +2.25.1 + + +From 245d9a42329a1bfeb3db8431ef105e7758080e14 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:06:53 +1200 +Subject: [PATCH 61/99] CVE-2022-32744 tests/krb5: Correctly calculate salt for + pre-existing accounts + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 1 + + python/samba/tests/krb5/raw_testcase.py | 1 + + 2 files changed, 2 insertions(+) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 2117663b26b..685a6f71f88 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -1048,6 +1048,7 @@ class KDCBaseTest(RawKerberosTest): + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) ++ creds.set_workstation(username[:-1]) + creds.set_dn(dn) + + keys = self.get_keys(samdb, dn) +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 4120edf93b9..a9a98c36cbf 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -834,6 +834,7 @@ class RawKerberosTest(TestCaseInTempDir): + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) + c.set_gensec_features(c.get_gensec_features() | FEATURE_SEAL) ++ c.set_workstation('') + return c + + def get_rodc_krbtgt_creds(self, +-- +2.25.1 + + +From f7fad997cc06a14c9ffd101b26e16598f334148b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:13:54 +1200 +Subject: [PATCH 62/99] CVE-2022-2031 tests/krb5: Add new definitions for + kpasswd + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/rfc4120.asn1 | 6 ++++++ + python/samba/tests/krb5/rfc4120_constants.py | 13 +++++++++++++ + python/samba/tests/krb5/rfc4120_pyasn1.py | 13 ++++++++++++- + 3 files changed, 31 insertions(+), 1 deletion(-) + +diff --git python/samba/tests/krb5/rfc4120.asn1 python/samba/tests/krb5/rfc4120.asn1 +index e0831e1f86f..cac884be985 100644 +--- python/samba/tests/krb5/rfc4120.asn1 ++++ python/samba/tests/krb5/rfc4120.asn1 +@@ -567,6 +567,12 @@ PA-FX-FAST-REPLY ::= CHOICE { + ... + } + ++ChangePasswdDataMS ::= SEQUENCE { ++ newpasswd [0] OCTET STRING, ++ targname [1] PrincipalName OPTIONAL, ++ targrealm [2] Realm OPTIONAL ++} ++ + -- MS-KILE End + -- + -- +diff --git python/samba/tests/krb5/rfc4120_constants.py python/samba/tests/krb5/rfc4120_constants.py +index a9fdc5735dd..7f0f44500c7 100644 +--- python/samba/tests/krb5/rfc4120_constants.py ++++ python/samba/tests/krb5/rfc4120_constants.py +@@ -27,11 +27,13 @@ ARCFOUR_HMAC_MD5 = int( + + # Message types + KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) ++KRB_AP_REP = int(krb5_asn1.MessageTypeValues('krb-ap-rep')) + KRB_AP_REQ = int(krb5_asn1.MessageTypeValues('krb-ap-req')) + KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) + KRB_AS_REQ = int(krb5_asn1.MessageTypeValues('krb-as-req')) + KRB_TGS_REP = int(krb5_asn1.MessageTypeValues('krb-tgs-rep')) + KRB_TGS_REQ = int(krb5_asn1.MessageTypeValues('krb-tgs-req')) ++KRB_PRIV = int(krb5_asn1.MessageTypeValues('krb-priv')) + + # PAData types + PADATA_ENC_TIMESTAMP = int( +@@ -76,6 +78,7 @@ KDC_ERR_TGT_REVOKED = 20 + KDC_ERR_PREAUTH_FAILED = 24 + KDC_ERR_PREAUTH_REQUIRED = 25 + KDC_ERR_BAD_INTEGRITY = 31 ++KDC_ERR_TKT_EXPIRED = 32 + KRB_ERR_TKT_NYV = 33 + KDC_ERR_NOT_US = 35 + KDC_ERR_BADMATCH = 36 +@@ -87,6 +90,16 @@ KDC_ERR_WRONG_REALM = 68 + KDC_ERR_CLIENT_NAME_MISMATCH = 75 + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 + ++# Kpasswd error codes ++KPASSWD_SUCCESS = 0 ++KPASSWD_MALFORMED = 1 ++KPASSWD_HARDERROR = 2 ++KPASSWD_AUTHERROR = 3 ++KPASSWD_SOFTERROR = 4 ++KPASSWD_ACCESSDENIED = 5 ++KPASSWD_BAD_VERSION = 6 ++KPASSWD_INITIAL_FLAG_NEEDED = 7 ++ + # Extended error types + KERB_AP_ERR_TYPE_SKEW_RECOVERY = int( + krb5_asn1.KerbErrorDataTypeValues('kERB-AP-ERR-TYPE-SKEW-RECOVERY')) +diff --git python/samba/tests/krb5/rfc4120_pyasn1.py python/samba/tests/krb5/rfc4120_pyasn1.py +index 348dd8c63fb..3c02b0efbc1 100644 +--- python/samba/tests/krb5/rfc4120_pyasn1.py ++++ python/samba/tests/krb5/rfc4120_pyasn1.py +@@ -1,5 +1,5 @@ + # Auto-generated by asn1ate v.0.6.1.dev0 from rfc4120.asn1 +-# (last modified on 2021-06-25 12:10:34.484667) ++# (last modified on 2022-05-13 20:03:06.039817) + + # KerberosV5Spec2 + from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful +@@ -364,6 +364,17 @@ Authenticator.componentType = namedtype.NamedTypes( + ) + + ++class ChangePasswdDataMS(univ.Sequence): ++ pass ++ ++ ++ChangePasswdDataMS.componentType = namedtype.NamedTypes( ++ namedtype.NamedType('newpasswd', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), ++ namedtype.OptionalNamedType('targname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), ++ namedtype.OptionalNamedType('targrealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) ++) ++ ++ + class ChecksumTypeValues(univ.Integer): + pass + +-- +2.25.1 + + +From 695c662bdc286d7a4699025f00656f8339ceecd8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:17:45 +1200 +Subject: [PATCH 63/99] CVE-2022-2031 tests/krb5: Add methods to create ASN1 + kpasswd structures + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 95 +++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index a9a98c36cbf..df41dff688d 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -54,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_AS_REP, + KRB_AS_REQ, + KRB_ERROR, ++ KRB_PRIV, + KRB_TGS_REP, + KRB_TGS_REQ, + KU_AP_REQ_AUTH, +@@ -63,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KU_FAST_FINISHED, + KU_FAST_REP, + KU_FAST_REQ_CHKSUM, ++ KU_KRB_PRIV, + KU_NON_KERB_CKSUM_SALT, + KU_TGS_REP_ENC_PART_SESSION, + KU_TGS_REP_ENC_PART_SUB_KEY, +@@ -1780,6 +1782,99 @@ class RawKerberosTest(TestCaseInTempDir): + PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) + return self.PA_DATA_create(PADATA_FOR_USER, pa_s4u2self) + ++ def ChangePasswdDataMS_create(self, ++ new_password, ++ target_princ=None, ++ target_realm=None): ++ ChangePasswdDataMS_obj = { ++ 'newpasswd': new_password, ++ } ++ if target_princ is not None: ++ ChangePasswdDataMS_obj['targname'] = target_princ ++ if target_realm is not None: ++ ChangePasswdDataMS_obj['targrealm'] = target_realm ++ ++ change_password_data = self.der_encode( ++ ChangePasswdDataMS_obj, asn1Spec=krb5_asn1.ChangePasswdDataMS()) ++ ++ return change_password_data ++ ++ def KRB_PRIV_create(self, ++ subkey, ++ user_data, ++ s_address, ++ timestamp=None, ++ usec=None, ++ seq_number=None, ++ r_address=None): ++ EncKrbPrivPart_obj = { ++ 'user-data': user_data, ++ 's-address': s_address, ++ } ++ if timestamp is not None: ++ EncKrbPrivPart_obj['timestamp'] = timestamp ++ if usec is not None: ++ EncKrbPrivPart_obj['usec'] = usec ++ if seq_number is not None: ++ EncKrbPrivPart_obj['seq-number'] = seq_number ++ if r_address is not None: ++ EncKrbPrivPart_obj['r-address'] = r_address ++ ++ enc_krb_priv_part = self.der_encode( ++ EncKrbPrivPart_obj, asn1Spec=krb5_asn1.EncKrbPrivPart()) ++ ++ enc_data = self.EncryptedData_create(subkey, ++ KU_KRB_PRIV, ++ enc_krb_priv_part) ++ ++ KRB_PRIV_obj = { ++ 'pvno': 5, ++ 'msg-type': KRB_PRIV, ++ 'enc-part': enc_data, ++ } ++ ++ krb_priv = self.der_encode( ++ KRB_PRIV_obj, asn1Spec=krb5_asn1.KRB_PRIV()) ++ ++ return krb_priv ++ ++ def kpasswd_create(self, ++ subkey, ++ user_data, ++ version, ++ seq_number, ++ ap_req, ++ local_address, ++ remote_address): ++ self.assertIsNotNone(self.s, 'call self.connect() first') ++ ++ timestamp, usec = self.get_KerberosTimeWithUsec() ++ ++ krb_priv = self.KRB_PRIV_create(subkey, ++ user_data, ++ s_address=local_address, ++ timestamp=timestamp, ++ usec=usec, ++ seq_number=seq_number, ++ r_address=remote_address) ++ ++ size = 6 + len(ap_req) + len(krb_priv) ++ self.assertLess(size, 0x10000) ++ ++ msg = bytearray() ++ msg.append(size >> 8) ++ msg.append(size & 0xff) ++ msg.append(version >> 8) ++ msg.append(version & 0xff) ++ msg.append(len(ap_req) >> 8) ++ msg.append(len(ap_req) & 0xff) ++ # Note: for sets, there could be a little-endian four-byte length here. ++ ++ msg.extend(ap_req) ++ msg.extend(krb_priv) ++ ++ return msg ++ + def _generic_kdc_exchange(self, + kdc_exchange_dict, # required + cname=None, # optional +-- +2.25.1 + + +From ae7dd875cd4362ed4346716db493164c421b889f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:21:37 +1200 +Subject: [PATCH 64/99] CVE-2022-2031 tests/krb5: Add 'port' parameter to + connect() + +This allows us to use the kpasswd port, 464. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index df41dff688d..421143781ae 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -638,10 +638,11 @@ class RawKerberosTest(TestCaseInTempDir): + if self.do_hexdump: + sys.stderr.write("disconnect[%s]\n" % reason) + +- def _connect_tcp(self, host): +- tcp_port = 88 ++ def _connect_tcp(self, host, port=None): ++ if port is None: ++ port = 88 + try: +- self.a = socket.getaddrinfo(host, tcp_port, socket.AF_UNSPEC, ++ self.a = socket.getaddrinfo(host, 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]) +@@ -654,9 +655,9 @@ class RawKerberosTest(TestCaseInTempDir): + self.s.close() + raise + +- def connect(self, host): ++ def connect(self, host, port=None): + self.assertNotConnected() +- self._connect_tcp(host) ++ self._connect_tcp(host, port) + if self.do_hexdump: + sys.stderr.write("connected[%s]\n" % host) + +-- +2.25.1 + + +From 13fe7e013eccca2c86258084f4443ddb7abaf089 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:20:28 +1200 +Subject: [PATCH 65/99] CVE-2022-2031 tests/krb5: Add methods to send and + receive generic messages + +This allows us to send and receive kpasswd messages, while avoiding the +existing logic for encoding and decoding other Kerberos message types. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 44 +++++++++++++++---------- + 1 file changed, 27 insertions(+), 17 deletions(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 421143781ae..2aed5530455 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -920,24 +920,28 @@ class RawKerberosTest(TestCaseInTempDir): + return blob + + def send_pdu(self, req, asn1_print=None, hexdump=None): ++ k5_pdu = self.der_encode( ++ req, native_decode=False, asn1_print=asn1_print, hexdump=False) ++ self.send_msg(k5_pdu, hexdump=hexdump) ++ ++ def send_msg(self, msg, hexdump=None): ++ header = struct.pack('>I', len(msg)) ++ req_pdu = header ++ req_pdu += msg ++ self.hex_dump("send_msg", header, hexdump=hexdump) ++ self.hex_dump("send_msg", msg, hexdump=hexdump) ++ + try: +- k5_pdu = self.der_encode( +- req, native_decode=False, asn1_print=asn1_print, hexdump=False) +- header = struct.pack('>I', len(k5_pdu)) +- req_pdu = header +- req_pdu += k5_pdu +- self.hex_dump("send_pdu", header, hexdump=hexdump) +- self.hex_dump("send_pdu", k5_pdu, hexdump=hexdump) + while True: + sent = self.s.send(req_pdu, 0) + if sent == len(req_pdu): +- break ++ return + req_pdu = req_pdu[sent:] + except socket.error as e: +- self._disconnect("send_pdu: %s" % e) ++ self._disconnect("send_msg: %s" % e) + raise + except IOError as e: +- self._disconnect("send_pdu: %s" % e) ++ self._disconnect("send_msg: %s" % e) + raise + + def recv_raw(self, num_recv=0xffff, hexdump=None, timeout=None): +@@ -963,16 +967,14 @@ class RawKerberosTest(TestCaseInTempDir): + return rep_pdu + + def recv_pdu_raw(self, asn1_print=None, hexdump=None, timeout=None): +- rep_pdu = None +- rep = None + raw_pdu = self.recv_raw( + num_recv=4, hexdump=hexdump, timeout=timeout) + if raw_pdu is None: +- return (None, None) ++ return None + header = struct.unpack(">I", raw_pdu[0:4]) + k5_len = header[0] + if k5_len == 0: +- return (None, "") ++ return "" + missing = k5_len + rep_pdu = b'' + while missing > 0: +@@ -981,6 +983,14 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertGreaterEqual(len(raw_pdu), 1) + rep_pdu += raw_pdu + missing = k5_len - len(rep_pdu) ++ return rep_pdu ++ ++ def recv_reply(self, asn1_print=None, hexdump=None, timeout=None): ++ rep_pdu = self.recv_pdu_raw(asn1_print=asn1_print, ++ hexdump=hexdump, ++ timeout=timeout) ++ if not rep_pdu: ++ return None, rep_pdu + k5_raw = self.der_decode( + rep_pdu, + asn1Spec=None, +@@ -1002,9 +1012,9 @@ class RawKerberosTest(TestCaseInTempDir): + return (rep, rep_pdu) + + def recv_pdu(self, asn1_print=None, hexdump=None, timeout=None): +- (rep, rep_pdu) = self.recv_pdu_raw(asn1_print=asn1_print, +- hexdump=hexdump, +- timeout=timeout) ++ (rep, rep_pdu) = self.recv_reply(asn1_print=asn1_print, ++ hexdump=hexdump, ++ timeout=timeout) + return rep + + def assertIsConnected(self): +-- +2.25.1 + + +From ca582250fcaf2ad3c585f7e31a1a4ce568b7ddb7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:26:56 +1200 +Subject: [PATCH 66/99] tests/krb5: Fix enum typo + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 685a6f71f88..14f1d1a243d 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -248,9 +248,9 @@ class KDCBaseTest(RawKerberosTest): + which is used by tearDownClass to clean up the created accounts. + ''' + if ou is None: +- if account_type is account_type.COMPUTER: ++ if account_type is self.AccountType.COMPUTER: + guid = DS_GUID_COMPUTERS_CONTAINER +- elif account_type is account_type.SERVER: ++ elif account_type is self.AccountType.SERVER: + guid = DS_GUID_DOMAIN_CONTROLLERS_CONTAINER + else: + guid = DS_GUID_USERS_CONTAINER +-- +2.25.1 + + +From 5b030b176b853938b1895ec255e838147d8e7fa9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:30:12 +1200 +Subject: [PATCH 67/99] tests/krb5: Add option for creating accounts with + expired passwords + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 14f1d1a243d..777b3b4aaf1 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -242,7 +242,8 @@ class KDCBaseTest(RawKerberosTest): + + def create_account(self, samdb, name, account_type=AccountType.USER, + spn=None, upn=None, additional_details=None, +- ou=None, account_control=0, add_dollar=True): ++ ou=None, account_control=0, add_dollar=True, ++ expired_password=False): + '''Create an account for testing. + The dn of the created account is added to self.accounts, + which is used by tearDownClass to clean up the created accounts. +@@ -294,6 +295,8 @@ class KDCBaseTest(RawKerberosTest): + details["servicePrincipalName"] = spn + if upn is not None: + details["userPrincipalName"] = upn ++ if expired_password: ++ details["pwdLastSet"] = "0" + if additional_details is not None: + details.update(additional_details) + samdb.add(details) +@@ -653,6 +656,7 @@ class KDCBaseTest(RawKerberosTest): + 'revealed_to_rodc': False, + 'revealed_to_mock_rodc': False, + 'no_auth_data_required': False, ++ 'expired_password': False, + 'supported_enctypes': None, + 'not_delegated': False, + 'delegation_to_spn': None, +@@ -695,6 +699,7 @@ class KDCBaseTest(RawKerberosTest): + revealed_to_rodc, + revealed_to_mock_rodc, + no_auth_data_required, ++ expired_password, + supported_enctypes, + not_delegated, + delegation_to_spn, +@@ -754,7 +759,8 @@ class KDCBaseTest(RawKerberosTest): + spn=spn, + additional_details=details, + account_control=user_account_control, +- add_dollar=add_dollar) ++ add_dollar=add_dollar, ++ expired_password=expired_password) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) +-- +2.25.1 + + +From 5c41e20fae268e04aa05e821c7f388ea090727af Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:34:59 +1200 +Subject: [PATCH 68/99] CVE-2022-2031 tests/krb5: Allow requesting a TGT to a + different sname and realm + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflict due to lacking rc4_support parameter] + +[jsutton@samba.org Fixed conflicts due to lacking client_name_type and + expected_cname parameters] +--- + python/samba/tests/krb5/kdc_base_test.py | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index 777b3b4aaf1..c0ca881985a 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -1344,10 +1344,12 @@ class KDCBaseTest(RawKerberosTest): + expected_flags=None, unexpected_flags=None, + pac_request=True, expect_pac=True, fresh=False): + user_name = tgt.cname['name-string'][0] ++ ticket_sname = tgt.sname + if target_name is None: + target_name = target_creds.get_username()[:-1] + cache_key = (user_name, target_name, service, to_rodc, kdc_options, + pac_request, str(expected_flags), str(unexpected_flags), ++ str(ticket_sname), + expect_pac) + + if not fresh: +@@ -1414,6 +1416,7 @@ class KDCBaseTest(RawKerberosTest): + expected_flags=None, unexpected_flags=None, + expected_account_name=None, expected_upn_name=None, + expected_sid=None, ++ sname=None, realm=None, + pac_request=True, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, +@@ -1422,6 +1425,7 @@ class KDCBaseTest(RawKerberosTest): + cache_key = (user_name, to_rodc, kdc_options, pac_request, + str(expected_flags), str(unexpected_flags), + expected_account_name, expected_upn_name, expected_sid, ++ str(sname), str(realm), + expect_pac, expect_pac_attrs, + expect_pac_attrs_pac_request, expect_requester_sid) + +@@ -1431,15 +1435,21 @@ class KDCBaseTest(RawKerberosTest): + if tgt is not None: + return tgt + +- realm = creds.get_realm() ++ if realm is None: ++ realm = creds.get_realm() + + salt = creds.get_salt() + + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=['krbtgt', realm]) ++ if sname is None: ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ expected_sname = self.PrincipalName_create( ++ name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) ++ else: ++ expected_sname = sname + + till = self.get_KerberosTime(offset=36000) + +@@ -1505,9 +1515,6 @@ class KDCBaseTest(RawKerberosTest): + + expected_realm = realm.upper() + +- expected_sname = self.PrincipalName_create( +- name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) +- + rep, kdc_exchange_dict = self._test_as_exchange( + cname=cname, + realm=realm, +-- +2.25.1 + + +From 668825ad56ff70715c626bc3209a6868409e4969 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:57:57 +1200 +Subject: [PATCH 69/99] CVE-2022-2031 tests/krb5: Add kpasswd_exchange() method + +Now we can test the kpasswd service from Python. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts in imports] +--- + python/samba/tests/krb5/raw_testcase.py | 264 ++++++++++++++++++++++-- + 1 file changed, 251 insertions(+), 13 deletions(-) + +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 2aed5530455..57010ae73bd 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -26,6 +26,8 @@ import binascii + import itertools + import collections + ++from enum import Enum ++ + from pyasn1.codec.der.decoder import decode as pyasn1_der_decode + from pyasn1.codec.der.encoder import encode as pyasn1_der_encode + from pyasn1.codec.native.decoder import decode as pyasn1_native_decode +@@ -33,6 +35,8 @@ from pyasn1.codec.native.encoder import encode as pyasn1_native_encode + + from pyasn1.codec.ber.encoder import BitStringEncoder + ++from pyasn1.error import PyAsn1Error ++ + from samba.credentials import Credentials + from samba.dcerpc import krb5pac, security + from samba.gensec import FEATURE_SEAL +@@ -50,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_PREAUTH_FAILED, + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, + KERB_ERR_TYPE_EXTENDED, ++ KRB_AP_REP, + KRB_AP_REQ, + KRB_AS_REP, + KRB_AS_REQ, +@@ -59,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_TGS_REQ, + KU_AP_REQ_AUTH, + KU_AS_REP_ENC_PART, ++ KU_AP_REQ_ENC_PART, + KU_ENC_CHALLENGE_KDC, + KU_FAST_ENC, + KU_FAST_FINISHED, +@@ -73,6 +79,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KU_TGS_REQ_AUTH_DAT_SESSION, + KU_TGS_REQ_AUTH_DAT_SUBKEY, + KU_TICKET, ++ NT_PRINCIPAL, + NT_SRV_INST, + NT_WELLKNOWN, + PADATA_ENCRYPTED_CHALLENGE, +@@ -515,6 +522,10 @@ class KerberosTicketCreds: + class RawKerberosTest(TestCaseInTempDir): + """A raw Kerberos Test case.""" + ++ class KpasswdMode(Enum): ++ SET = object() ++ CHANGE = object() ++ + pac_checksum_types = {krb5pac.PAC_TYPE_SRV_CHECKSUM, + krb5pac.PAC_TYPE_KDC_CHECKSUM, + krb5pac.PAC_TYPE_TICKET_CHECKSUM} +@@ -1886,6 +1897,224 @@ class RawKerberosTest(TestCaseInTempDir): + + return msg + ++ def get_enc_part(self, obj, key, usage): ++ self.assertElementEqual(obj, 'pvno', 5) ++ ++ enc_part = obj['enc-part'] ++ self.assertElementEqual(enc_part, 'etype', key.etype) ++ self.assertElementKVNO(enc_part, 'kvno', key.kvno) ++ ++ enc_part = key.decrypt(usage, enc_part['cipher']) ++ ++ return enc_part ++ ++ def kpasswd_exchange(self, ++ ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode, ++ target_princ=None, ++ target_realm=None, ++ ap_options=None, ++ send_seq_number=True): ++ if mode is self.KpasswdMode.SET: ++ version = 0xff80 ++ user_data = self.ChangePasswdDataMS_create(new_password, ++ target_princ, ++ target_realm) ++ elif mode is self.KpasswdMode.CHANGE: ++ self.assertIsNone(target_princ, ++ 'target_princ only valid for pw set') ++ self.assertIsNone(target_realm, ++ 'target_realm only valid for pw set') ++ ++ version = 1 ++ user_data = new_password.encode('utf-8') ++ else: ++ self.fail(f'invalid mode {mode}') ++ ++ subkey = self.RandomKey(kcrypto.Enctype.AES256) ++ ++ if ap_options is None: ++ ap_options = '0' ++ ap_options = str(krb5_asn1.APOptions(ap_options)) ++ ++ kdc_exchange_dict = { ++ 'tgt': ticket, ++ 'authenticator_subkey': subkey, ++ 'auth_data': None, ++ 'ap_options': ap_options, ++ } ++ ++ if send_seq_number: ++ seq_number = random.randint(0, 0xfffffffe) ++ else: ++ seq_number = None ++ ++ ap_req = self.generate_ap_req(kdc_exchange_dict, ++ None, ++ req_body=None, ++ armor=False, ++ usage=KU_AP_REQ_AUTH, ++ seq_number=seq_number) ++ ++ self.connect(self.host, port=464) ++ self.assertIsNotNone(self.s) ++ ++ family = self.s.family ++ ++ if family == socket.AF_INET: ++ addr_type = 2 # IPv4 ++ elif family == socket.AF_INET6: ++ addr_type = 24 # IPv6 ++ else: ++ self.fail(f'unknown family {family}') ++ ++ def create_address(ip): ++ return { ++ 'addr-type': addr_type, ++ 'address': socket.inet_pton(family, ip), ++ } ++ ++ local_ip = self.s.getsockname()[0] ++ local_address = create_address(local_ip) ++ ++ # remote_ip = self.s.getpeername()[0] ++ # remote_address = create_address(remote_ip) ++ ++ # TODO: due to a bug (?), MIT Kerberos will not accept the request ++ # unless r-address is set to our _local_ address. Heimdal, on the other ++ # hand, requires the r-address is set to the remote address (as ++ # expected). To avoid problems, avoid sending r-address for now. ++ remote_address = None ++ ++ msg = self.kpasswd_create(subkey, ++ user_data, ++ version, ++ seq_number, ++ ap_req, ++ local_address, ++ remote_address) ++ ++ self.send_msg(msg) ++ rep_pdu = self.recv_pdu_raw() ++ ++ self._disconnect('transaction done') ++ ++ self.assertIsNotNone(rep_pdu) ++ ++ header = rep_pdu[:6] ++ reply = rep_pdu[6:] ++ ++ reply_len = (header[0] << 8) | header[1] ++ reply_version = (header[2] << 8) | header[3] ++ ap_rep_len = (header[4] << 8) | header[5] ++ ++ self.assertEqual(reply_len, len(rep_pdu)) ++ self.assertEqual(1, reply_version) # KRB5_KPASSWD_VERS_CHANGEPW ++ self.assertLess(ap_rep_len, reply_len) ++ ++ self.assertNotEqual(0x7e, rep_pdu[1]) ++ self.assertNotEqual(0x5e, rep_pdu[1]) ++ ++ if ap_rep_len: ++ # We received an AP-REQ and KRB-PRIV as a response. This may or may ++ # not indicate an error, depending on the status code. ++ ap_rep = reply[:ap_rep_len] ++ krb_priv = reply[ap_rep_len:] ++ ++ key = ticket.session_key ++ ++ ap_rep = self.der_decode(ap_rep, asn1Spec=krb5_asn1.AP_REP()) ++ self.assertElementEqual(ap_rep, 'msg-type', KRB_AP_REP) ++ enc_part = self.get_enc_part(ap_rep, key, KU_AP_REQ_ENC_PART) ++ enc_part = self.der_decode( ++ enc_part, asn1Spec=krb5_asn1.EncAPRepPart()) ++ ++ self.assertElementPresent(enc_part, 'ctime') ++ self.assertElementPresent(enc_part, 'cusec') ++ # self.assertElementMissing(enc_part, 'subkey') # TODO ++ # self.assertElementPresent(enc_part, 'seq-number') # TODO ++ ++ try: ++ krb_priv = self.der_decode(krb_priv, asn1Spec=krb5_asn1.KRB_PRIV()) ++ except PyAsn1Error: ++ self.fail() ++ ++ self.assertElementEqual(krb_priv, 'msg-type', KRB_PRIV) ++ priv_enc_part = self.get_enc_part(krb_priv, subkey, KU_KRB_PRIV) ++ priv_enc_part = self.der_decode( ++ priv_enc_part, asn1Spec=krb5_asn1.EncKrbPrivPart()) ++ ++ self.assertElementMissing(priv_enc_part, 'timestamp') ++ self.assertElementMissing(priv_enc_part, 'usec') ++ # self.assertElementPresent(priv_enc_part, 'seq-number') # TODO ++ # self.assertElementEqual(priv_enc_part, 's-address', remote_address) # TODO ++ # self.assertElementMissing(priv_enc_part, 'r-address') # TODO ++ ++ result_data = priv_enc_part['user-data'] ++ else: ++ # We received a KRB-ERROR as a response, indicating an error. ++ krb_error = self.der_decode(reply, asn1Spec=krb5_asn1.KRB_ERROR()) ++ ++ sname = self.PrincipalName_create( ++ name_type=NT_PRINCIPAL, ++ names=['kadmin', 'changepw']) ++ realm = self.get_krbtgt_creds().get_realm().upper() ++ ++ self.assertElementEqual(krb_error, 'pvno', 5) ++ self.assertElementEqual(krb_error, 'msg-type', KRB_ERROR) ++ self.assertElementMissing(krb_error, 'ctime') ++ self.assertElementMissing(krb_error, 'usec') ++ self.assertElementPresent(krb_error, 'stime') ++ self.assertElementPresent(krb_error, 'susec') ++ ++ error_code = krb_error['error-code'] ++ if isinstance(expected_code, int): ++ self.assertEqual(error_code, expected_code) ++ else: ++ self.assertIn(error_code, expected_code) ++ ++ self.assertElementMissing(krb_error, 'crealm') ++ self.assertElementMissing(krb_error, 'cname') ++ self.assertElementEqual(krb_error, 'realm', realm.encode('utf-8')) ++ self.assertElementEqualPrincipal(krb_error, 'sname', sname) ++ self.assertElementMissing(krb_error, 'e-text') ++ ++ result_data = krb_error['e-data'] ++ ++ status = result_data[:2] ++ message = result_data[2:] ++ ++ status_code = (status[0] << 8) | status[1] ++ if isinstance(expected_code, int): ++ self.assertEqual(status_code, expected_code) ++ else: ++ self.assertIn(status_code, expected_code) ++ ++ if not message: ++ self.assertEqual(0, status_code, ++ 'got an error result, but no message') ++ return ++ ++ # Check the first character of the message. ++ if message[0]: ++ if isinstance(expected_msg, bytes): ++ self.assertEqual(message, expected_msg) ++ else: ++ self.assertIn(message, expected_msg) ++ else: ++ # We got AD password policy information. ++ self.assertEqual(30, len(message)) ++ ++ (empty_bytes, ++ min_length, ++ history_length, ++ properties, ++ expire_time, ++ min_age) = struct.unpack('>HIIIQQ', message) ++ + def _generic_kdc_exchange(self, + kdc_exchange_dict, # required + cname=None, # optional +@@ -1996,7 +2225,7 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertIsNotNone(generate_fast_fn) + fast_ap_req = generate_fast_armor_fn(kdc_exchange_dict, + callback_dict, +- req_body, ++ None, + armor=True) + + fast_armor_type = kdc_exchange_dict['fast_armor_type'] +@@ -3211,31 +3440,39 @@ class RawKerberosTest(TestCaseInTempDir): + kdc_exchange_dict, + _callback_dict, + req_body, +- armor): ++ armor, ++ usage=None, ++ seq_number=None): ++ req_body_checksum = None ++ + if armor: ++ self.assertIsNone(req_body) ++ + tgt = kdc_exchange_dict['armor_tgt'] + authenticator_subkey = kdc_exchange_dict['armor_subkey'] +- +- req_body_checksum = None + else: + tgt = kdc_exchange_dict['tgt'] + authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] +- body_checksum_type = kdc_exchange_dict['body_checksum_type'] + +- req_body_blob = self.der_encode(req_body, +- asn1Spec=krb5_asn1.KDC_REQ_BODY()) ++ if req_body is not None: ++ body_checksum_type = kdc_exchange_dict['body_checksum_type'] ++ ++ req_body_blob = self.der_encode( ++ req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY()) + +- req_body_checksum = self.Checksum_create(tgt.session_key, +- KU_TGS_REQ_AUTH_CKSUM, +- req_body_blob, +- ctype=body_checksum_type) ++ req_body_checksum = self.Checksum_create( ++ tgt.session_key, ++ KU_TGS_REQ_AUTH_CKSUM, ++ req_body_blob, ++ ctype=body_checksum_type) + + auth_data = kdc_exchange_dict['auth_data'] + + subkey_obj = None + if authenticator_subkey is not None: + subkey_obj = authenticator_subkey.export_obj() +- seq_number = random.randint(0, 0xfffffffe) ++ if seq_number is None: ++ seq_number = random.randint(0, 0xfffffffe) + (ctime, cusec) = self.get_KerberosTimeWithUsec() + authenticator_obj = self.Authenticator_create( + crealm=tgt.crealm, +@@ -3250,7 +3487,8 @@ class RawKerberosTest(TestCaseInTempDir): + authenticator_obj, + asn1Spec=krb5_asn1.Authenticator()) + +- usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH ++ if usage is None: ++ usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH + authenticator = self.EncryptedData_create(tgt.session_key, + usage, + authenticator_blob) +-- +2.25.1 + + +From 450ff39d1c9f538bd828b7b2bee75c88d3dc1ee2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:59:16 +1200 +Subject: [PATCH 71/99] CVE-2022-2031 tests/krb5: Add tests for kpasswd service + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts in usage.py and knownfails; removed + MIT KDC 1.20-specific knownfails as it's not supported] + +[jsutton@samba.org Fixed conflicts in usage.py, knownfails, and + tests.py] +--- + python/samba/tests/krb5/kdc_base_test.py | 4 +- + python/samba/tests/krb5/kpasswd_tests.py | 1021 ++++++++++++++++++++++ + python/samba/tests/krb5/raw_testcase.py | 8 + + python/samba/tests/usage.py | 1 + + selftest/knownfail_heimdal_kdc | 26 + + selftest/knownfail_mit_kdc | 26 + + source4/selftest/tests.py | 4 + + 7 files changed, 1089 insertions(+), 1 deletion(-) + create mode 100755 python/samba/tests/krb5/kpasswd_tests.py + +diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py +index c0ca881985a..f0306dde110 100644 +--- python/samba/tests/krb5/kdc_base_test.py ++++ python/samba/tests/krb5/kdc_base_test.py +@@ -1586,7 +1586,9 @@ class KDCBaseTest(RawKerberosTest): + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + + if expect_error: +- expected_error_mode = KDC_ERR_TGT_REVOKED ++ expected_error_mode = expect_error ++ if expected_error_mode is True: ++ expected_error_mode = KDC_ERR_TGT_REVOKED + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: +diff --git python/samba/tests/krb5/kpasswd_tests.py python/samba/tests/krb5/kpasswd_tests.py +new file mode 100755 +index 00000000000..3a6c7d818dc +--- /dev/null ++++ python/samba/tests/krb5/kpasswd_tests.py +@@ -0,0 +1,1021 @@ ++#!/usr/bin/env python3 ++# Unix SMB/CIFS implementation. ++# Copyright (C) Stefan Metzmacher 2020 ++# Copyright (C) Catalyst.Net Ltd ++# ++# 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 . ++# ++ ++import os ++import sys ++ ++from functools import partial ++ ++from samba import generate_random_password, unix2nttime ++from samba.dcerpc import krb5pac, security ++from samba.sd_utils import SDUtils ++ ++from samba.tests.krb5.kdc_base_test import KDCBaseTest ++from samba.tests.krb5.rfc4120_constants import ( ++ KDC_ERR_TGT_REVOKED, ++ KDC_ERR_TKT_EXPIRED, ++ KPASSWD_ACCESSDENIED, ++ KPASSWD_HARDERROR, ++ KPASSWD_INITIAL_FLAG_NEEDED, ++ KPASSWD_MALFORMED, ++ KPASSWD_SOFTERROR, ++ KPASSWD_SUCCESS, ++ NT_PRINCIPAL, ++ NT_SRV_INST, ++) ++ ++sys.path.insert(0, 'bin/python') ++os.environ['PYTHONUNBUFFERED'] = '1' ++ ++global_asn1_print = False ++global_hexdump = False ++ ++ ++# Note: these tests do not pass on Windows, which returns different error codes ++# to the ones we have chosen, and does not always return additional error data. ++class KpasswdTests(KDCBaseTest): ++ ++ def setUp(self): ++ super().setUp() ++ self.do_asn1_print = global_asn1_print ++ self.do_hexdump = global_hexdump ++ ++ samdb = self.get_samdb() ++ ++ # Get the old 'dSHeuristics' if it was set ++ dsheuristics = samdb.get_dsheuristics() ++ ++ # Reset the 'dSHeuristics' as they were before ++ self.addCleanup(samdb.set_dsheuristics, dsheuristics) ++ ++ # Set the 'dSHeuristics' to activate the correct 'userPassword' ++ # behaviour ++ samdb.set_dsheuristics('000000001') ++ ++ # Get the old 'minPwdAge' ++ minPwdAge = samdb.get_minPwdAge() ++ ++ # Reset the 'minPwdAge' as it was before ++ self.addCleanup(samdb.set_minPwdAge, minPwdAge) ++ ++ # Set it temporarily to '0' ++ samdb.set_minPwdAge('0') ++ ++ def _get_creds(self, expired=False): ++ opts = { ++ 'expired_password': expired ++ } ++ ++ # Create the account. ++ creds = self.get_cached_creds(account_type=self.AccountType.USER, ++ opts=opts, ++ use_cache=False) ++ ++ return creds ++ ++ def issued_by_rodc(self, ticket): ++ krbtgt_creds = self.get_mock_rodc_krbtgt_creds() ++ ++ krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, ++ } ++ ++ return self.modified_ticket( ++ ticket, ++ new_ticket_key=krbtgt_key, ++ checksum_keys=checksum_keys) ++ ++ def get_kpasswd_sname(self): ++ return self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=['kadmin', 'changepw']) ++ ++ def get_ticket_lifetime(self, ticket): ++ enc_part = ticket.ticket_private ++ ++ authtime = enc_part['authtime'] ++ starttime = enc_part.get('starttime', authtime) ++ endtime = enc_part['endtime'] ++ ++ starttime = self.get_EpochFromKerberosTime(starttime) ++ endtime = self.get_EpochFromKerberosTime(endtime) ++ ++ return endtime - starttime ++ ++ def add_requester_sid(self, pac, sid): ++ pac_buffers = pac.buffers ++ ++ buffer_types = [pac_buffer.type for pac_buffer in pac_buffers] ++ self.assertNotIn(krb5pac.PAC_TYPE_REQUESTER_SID, buffer_types) ++ ++ requester_sid = krb5pac.PAC_REQUESTER_SID() ++ requester_sid.sid = security.dom_sid(sid) ++ ++ requester_sid_buffer = krb5pac.PAC_BUFFER() ++ requester_sid_buffer.type = krb5pac.PAC_TYPE_REQUESTER_SID ++ requester_sid_buffer.info = requester_sid ++ ++ pac_buffers.append(requester_sid_buffer) ++ ++ pac.buffers = pac_buffers ++ pac.num_buffers += 1 ++ ++ return pac ++ ++ # Test setting a password with kpasswd. ++ def test_kpasswd_set(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Test the newly set password. ++ creds.update_password(new_password) ++ self.get_tgt(creds, fresh=True) ++ ++ # Test changing a password with kpasswd. ++ def test_kpasswd_change(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test the newly set password. ++ creds.update_password(new_password) ++ self.get_tgt(creds, fresh=True) ++ ++ # Test kpasswd without setting the canonicalize option. ++ def test_kpasswd_no_canonicalize(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option reset and a non-canonical ++ # (by conversion to title case) realm. ++ def test_kpasswd_no_canonicalize_realm_case(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ realm = creds.get_realm().capitalize() # We use a title-cased realm. ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='0') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option set. ++ def test_kpasswd_canonicalize(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='canonicalize') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='canonicalize') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option set and a non-canonical (by ++ # conversion to title case) realm. ++ def test_kpasswd_canonicalize_realm_case(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ realm = creds.get_realm().capitalize() # We use a title-cased realm. ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='canonicalize') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='canonicalize') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects a password that does not meet complexity ++ # requirements. ++ def test_kpasswd_too_weak(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SOFTERROR ++ expected_msg = b'Password does not meet complexity requirements' ++ ++ # Set the password. ++ new_password = 'password' ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects an empty new password. ++ def test_kpasswd_empty(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SOFTERROR, KPASSWD_HARDERROR ++ expected_msg = (b'Password too short, password must be at least 7 ' ++ b'characters long.', ++ b'String conversion failed!') ++ ++ # Set the password. ++ new_password = '' ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'String conversion failed!' ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects a request that does not include a random sequence ++ # number. ++ def test_kpasswd_no_seq_number(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_unwrap failed - NT_STATUS_ACCESS_DENIED\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ send_seq_number=False) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE, ++ send_seq_number=False) ++ ++ # Test kpasswd rejects a ticket issued by an RODC. ++ def test_kpasswd_from_rodc(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Have the ticket be issued by the RODC. ++ ticket = self.issued_by_rodc(ticket) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test setting a password, specifying the principal of the target user. ++ def test_kpasswd_set_target_princ_only(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_MALFORMED ++ expected_msg = (b'Realm and principal must be both present, or ' ++ b'neither present', ++ b'Failed to decode packet') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname) ++ ++ # Test that kpasswd rejects a password set specifying only the realm of the ++ # target user. ++ def test_kpasswd_set_target_realm_only(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_MALFORMED, KPASSWD_ACCESSDENIED ++ expected_msg = (b'Realm and principal must be both present, or ' ++ b'neither present', ++ b'Failed to decode packet', ++ b'No such user when changing password') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_realm=creds.get_realm()) ++ ++ # Show that a user cannot set a password, specifying both principal and ++ # realm of the target user, without having control access. ++ def test_kpasswd_set_target_princ_and_realm_no_access(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_ACCESSDENIED ++ expected_msg = b'Not permitted to change password' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname, ++ target_realm=creds.get_realm()) ++ ++ # Test setting a password, specifying both principal and realm of the ++ # target user, whem the user has control access on their account. ++ def test_kpasswd_set_target_princ_and_realm_access(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ tgt = self.get_tgt(creds) ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ samdb = self.get_samdb() ++ sd_utils = SDUtils(samdb) ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Give the user control access on their account. ++ ace = f'(A;;CR;;;{user_sid})' ++ sd_utils.dacl_add_ace(user_dn, ace) ++ ++ # Get a non-initial ticket to kpasswd. Since we have the right to ++ # change the account's password, we don't need an initial ticket. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname, ++ target_realm=creds.get_realm()) ++ ++ # Test setting a password when the existing password has expired. ++ def test_kpasswd_set_expired_password(self): ++ # Create an account for testing, with an expired password. ++ creds = self._get_creds(expired=True) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Test changing a password when the existing password has expired. ++ def test_kpasswd_change_expired_password(self): ++ # Create an account for testing, with an expired password. ++ creds = self._get_creds(expired=True) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Check the lifetime of a kpasswd ticket is not more than two minutes. ++ def test_kpasswd_ticket_lifetime(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Check the lifetime of the ticket is equal to two minutes. ++ lifetime = self.get_ticket_lifetime(ticket) ++ self.assertEqual(2 * 60, lifetime) ++ ++ # Ensure we cannot perform a TGS-REQ with a kpasswd ticket. ++ def test_kpasswd_ticket_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This fails due to missing REQUESTER_SID buffer. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_TKT_EXPIRED)) ++ ++ def modify_requester_sid_time(self, ticket, sid, lifetime): ++ # Get the krbtgt key. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, ++ } ++ ++ # Set authtime and starttime to an hour in the past, to show that they ++ # do not affect ticket rejection. ++ start_time = self.get_KerberosTime(offset=-60 * 60) ++ ++ # Set the endtime of the ticket relative to our current time, so that ++ # the ticket has 'lifetime' seconds remaining to live. ++ end_time = self.get_KerberosTime(offset=lifetime) ++ ++ # Modify the times in the ticket. ++ def modify_ticket_times(enc_part): ++ enc_part['authtime'] = start_time ++ if 'starttime' in enc_part: ++ enc_part['starttime'] = start_time ++ ++ enc_part['endtime'] = end_time ++ ++ return enc_part ++ ++ # We have to set the times in both the ticket and the PAC, otherwise ++ # Heimdal will complain. ++ def modify_pac_time(pac): ++ pac_buffers = pac.buffers ++ ++ for pac_buffer in pac_buffers: ++ if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME: ++ logon_time = self.get_EpochFromKerberosTime(start_time) ++ pac_buffer.info.logon_time = unix2nttime(logon_time) ++ break ++ else: ++ self.fail('failed to find LOGON_NAME PAC buffer') ++ ++ pac.buffers = pac_buffers ++ ++ return pac ++ ++ # Add a requester SID to show that the KDC will then accept this ++ # kpasswd ticket as if it were a TGT. ++ def modify_pac_fn(pac): ++ pac = self.add_requester_sid(pac, sid=sid) ++ pac = modify_pac_time(pac) ++ return pac ++ ++ # Do the actual modification. ++ return self.modified_ticket(ticket, ++ new_ticket_key=krbtgt_key, ++ modify_fn=modify_ticket_times, ++ modify_pac_fn=modify_pac_fn, ++ checksum_keys=checksum_keys) ++ ++ # Ensure we cannot perform a TGS-REQ with a kpasswd ticket containing a ++ # requester SID and having a remaining lifetime of two minutes. ++ def test_kpasswd_ticket_requester_sid_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Get the user's SID. ++ samdb = self.get_samdb() ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Modify the ticket to add a requester SID and give it two minutes to ++ # live. ++ ticket = self.modify_requester_sid_time(ticket, ++ sid=user_sid, ++ lifetime=2 * 60) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This fails due to the lifetime being too short. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=KDC_ERR_TKT_EXPIRED) ++ ++ # Show we can perform a TGS-REQ with a kpasswd ticket containing a ++ # requester SID if the remaining lifetime exceeds two minutes. ++ def test_kpasswd_ticket_requester_sid_lifetime_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Get the user's SID. ++ samdb = self.get_samdb() ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Modify the ticket to add a requester SID and give it two minutes and ++ # ten seconds to live. ++ ticket = self.modify_requester_sid_time(ticket, ++ sid=user_sid, ++ lifetime=2 * 60 + 10) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This succeeds. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=False) ++ ++ # Test that kpasswd rejects requests with a service ticket. ++ def test_kpasswd_non_initial(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds) ++ ++ # Get a non-initial ticket to kpasswd. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0') ++ ++ expected_code = KPASSWD_INITIAL_FLAG_NEEDED ++ expected_msg = b'Expected an initial ticket' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Show that kpasswd accepts requests with a service ticket modified to set ++ # the 'initial' flag. ++ def test_kpasswd_initial(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ # Get a service ticket, and modify it to set the 'initial' flag. ++ def get_ticket(): ++ tgt = self.get_tgt(creds, fresh=True) ++ ++ # Get a non-initial ticket to kpasswd. ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0', ++ fresh=True) ++ ++ set_initial_flag = partial(self.modify_ticket_flag, flag='initial', ++ value=True) ++ ++ checksum_keys = self.get_krbtgt_checksum_key() ++ return self.modified_ticket(ticket, ++ modify_fn=set_initial_flag, ++ checksum_keys=checksum_keys) ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ ticket = get_ticket() ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ticket = get_ticket() ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test that kpasswd rejects requests where the ticket is encrypted with a ++ # key other than the krbtgt's. ++ def test_kpasswd_wrong_key(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to the Administrator account. ++ admin_creds = self.get_admin_creds() ++ admin_key = self.TicketDecryptionKey_from_creds(admin_creds) ++ self.assertIsNotNone(admin_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: admin_key, ++ } ++ ++ # Re-encrypt the ticket using the Administrator's key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=admin_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of the Administrator account. ++ admin_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=['Administrator']) ++ ticket.set_sname(admin_sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ def test_kpasswd_wrong_key_service(self): ++ # Create an account for testing. ++ creds = self.get_cached_creds(account_type=self.AccountType.COMPUTER, ++ use_cache=False) ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to our account. ++ our_key = self.TicketDecryptionKey_from_creds(creds) ++ self.assertIsNotNone(our_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: our_key, ++ } ++ ++ # Re-encrypt the ticket using our key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=our_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of our account. ++ username = creds.get_username() ++ sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ticket.set_sname(sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test that kpasswd rejects requests where the ticket is encrypted with a ++ # key belonging to a server account other than the krbtgt. ++ def test_kpasswd_wrong_key_server(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to the DC's account. ++ dc_creds = self.get_dc_creds() ++ dc_key = self.TicketDecryptionKey_from_creds(dc_creds) ++ self.assertIsNotNone(dc_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: dc_key, ++ } ++ ++ # Re-encrypt the ticket using the DC's key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=dc_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of the DC's account. ++ dc_username = dc_creds.get_username() ++ dc_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=dc_username.split('/')) ++ ticket.set_sname(dc_sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ ++if __name__ == '__main__': ++ global_asn1_print = False ++ global_hexdump = False ++ import unittest ++ unittest.main() +diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py +index 57010ae73bd..4a78a8eadf3 100644 +--- python/samba/tests/krb5/raw_testcase.py ++++ python/samba/tests/krb5/raw_testcase.py +@@ -500,6 +500,10 @@ class KerberosCredentials(Credentials): + def get_upn(self): + return self.upn + ++ def update_password(self, password): ++ self.set_password(password) ++ self.set_kvno(self.get_kvno() + 1) ++ + + class KerberosTicketCreds: + def __init__(self, ticket, session_key, +@@ -518,6 +522,10 @@ class KerberosTicketCreds: + self.ticket_private = ticket_private + self.encpart_private = encpart_private + ++ def set_sname(self, sname): ++ self.ticket['sname'] = sname ++ self.sname = sname ++ + + class RawKerberosTest(TestCaseInTempDir): + """A raw Kerberos Test case.""" +diff --git python/samba/tests/usage.py python/samba/tests/usage.py +index 6bbd96e7a08..a1210ada579 100644 +--- python/samba/tests/usage.py ++++ python/samba/tests/usage.py +@@ -109,6 +109,7 @@ EXCLUDE_USAGE = { + 'python/samba/tests/krb5/alias_tests.py', + 'python/samba/tests/krb5/test_min_domain_uid.py', + 'python/samba/tests/krb5/test_idmap_nss.py', ++ 'python/samba/tests/krb5/kpasswd_tests.py', + } + + EXCLUDE_HELP = { +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 424a8b81c38..54e69a48bc1 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -271,3 +271,29 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 108c6055d0c..53638afc17a 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -575,3 +575,29 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-- +2.25.1 + + +From 29ec8b2369b5f5e2a660a3165d2528982514a0f2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:21:06 +1200 +Subject: [PATCH 72/99] CVE-2022-2031 s4:kpasswd: Correctly generate error + strings + +The error_data we create already has an explicit length, and should not +be zero-terminated, so we omit the trailing null byte. Previously, +Heimdal builds would leave a superfluous trailing null byte on error +strings, while MIT builds would omit the final character. + +The two bytes added to the string's length are for the prepended error +code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_heimdal_kdc | 12 ------------ + selftest/knownfail_mit_kdc | 15 --------------- + source4/kdc/kpasswd-helper.c | 13 ++++++------- + 3 files changed, 6 insertions(+), 34 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 54e69a48bc1..40e24f3155b 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -276,24 +276,12 @@ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 53638afc17a..a914c4d3492 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -578,26 +578,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # Kpasswd tests + # +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/kdc/kpasswd-helper.c source4/kdc/kpasswd-helper.c +index 995f54825b5..55a2f5b3bf6 100644 +--- source4/kdc/kpasswd-helper.c ++++ source4/kdc/kpasswd-helper.c +@@ -48,17 +48,16 @@ bool kpasswd_make_error_reply(TALLOC_CTX *mem_ctx, + } + + /* +- * The string 's' has two terminating nul-bytes which are also +- * reflected by 'slen'. Normally Kerberos doesn't expect that strings +- * are nul-terminated, but Heimdal does! ++ * The string 's' has one terminating nul-byte which is also ++ * reflected by 'slen'. We subtract it from the length. + */ +-#ifndef SAMBA4_USES_HEIMDAL +- if (slen < 2) { ++ if (slen < 1) { + talloc_free(s); + return false; + } +- slen -= 2; +-#endif ++ slen--; ++ ++ /* Two bytes are added to the length to account for the error code. */ + if (2 + slen < slen) { + talloc_free(s); + return false; +-- +2.25.1 + + +From 3a8da51396f3bf9d4caf8dbd4e75a0314aa47046 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:48:59 +1200 +Subject: [PATCH 73/99] CVE-2022-2031 s4:kpasswd: Don't return AP-REP on + failure + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_mit_kdc | 1 - + source4/kdc/kpasswd-service.c | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index a914c4d3492..f64291e776d 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -579,7 +579,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc +diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c +index 8f1679e4a28..a3c57a67dd1 100644 +--- source4/kdc/kpasswd-service.c ++++ source4/kdc/kpasswd-service.c +@@ -253,6 +253,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &error_string); + if (code != 0) { ++ ap_rep_blob = data_blob_null; + error_code = code; + goto reply; + } +@@ -262,6 +263,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &enc_data_blob); + if (!NT_STATUS_IS_OK(status)) { ++ ap_rep_blob = data_blob_null; + error_code = KRB5_KPASSWD_HARDERROR; + error_string = talloc_asprintf(tmp_ctx, + "gensec_wrap failed - %s\n", +-- +2.25.1 + + +From cf9e37604409ba0c3c5904af40beb2975c309ad4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:29:34 +1200 +Subject: [PATCH 74/99] CVE-2022-2031 lib:krb5_wrap: Generate valid error codes + in smb_krb5_mk_error() + +The error code passed in will be an offset from ERROR_TABLE_BASE_krb5, +so we need to subtract that before creating the error. Heimdal does this +internally, so it isn't needed there. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + lib/krb5_wrap/krb5_samba.c | 2 +- + selftest/knownfail_mit_kdc | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git lib/krb5_wrap/krb5_samba.c lib/krb5_wrap/krb5_samba.c +index 76c2dcd2126..610efcc9b87 100644 +--- lib/krb5_wrap/krb5_samba.c ++++ lib/krb5_wrap/krb5_samba.c +@@ -237,7 +237,7 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, + return code; + } + +- errpkt.error = error_code; ++ errpkt.error = error_code - ERROR_TABLE_BASE_krb5; + + errpkt.text.length = 0; + if (e_text != NULL) { +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index f64291e776d..633bf79e8e0 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -579,9 +579,13 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-- +2.25.1 + + +From cf749fac346ef59c91a9ea87f5e7ddec2e5649c7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:49:43 +1200 +Subject: [PATCH 75/99] CVE-2022-2031 s4:kpasswd: Return a kpasswd error code + in KRB-ERROR + +If we attempt to return an error code outside of Heimdal's allowed range +[KRB5KDC_ERR_NONE, KRB5_ERR_RCSID), it will be replaced with a GENERIC +error, and the error text will be set to the meaningless result of +krb5_get_error_message(). Avoid this by ensuring the error code is in +the correct range. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + selftest/knownfail_heimdal_kdc | 2 -- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/kpasswd-service.c | 2 +- + 3 files changed, 1 insertion(+), 7 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 40e24f3155b..3b494baa658 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -276,9 +276,7 @@ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 633bf79e8e0..f64291e776d 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -579,13 +579,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c +index a3c57a67dd1..b4706de1ad7 100644 +--- source4/kdc/kpasswd-service.c ++++ source4/kdc/kpasswd-service.c +@@ -312,7 +312,7 @@ reply: + } + + code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context, +- error_code, ++ KRB5KDC_ERR_NONE + error_code, + NULL, /* e_text */ + &k_dec_data, + NULL, /* client */ +-- +2.25.1 + + +From 198256e2184897300e1cea4343437c3b7b6f74ad Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:06:31 +1200 +Subject: [PATCH 76/99] CVE-2022-2031 gensec_krb5: Add helper function to check + if client sent an initial ticket + +This will be used in the kpasswd service to ensure that the client has +an initial ticket to kadmin/changepw, and not a service ticket. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/gensec/gensec_krb5.c | 20 +----- + source4/auth/gensec/gensec_krb5_helpers.c | 72 ++++++++++++++++++++++ + source4/auth/gensec/gensec_krb5_helpers.h | 32 ++++++++++ + source4/auth/gensec/gensec_krb5_internal.h | 47 ++++++++++++++ + source4/auth/gensec/wscript_build | 4 ++ + 5 files changed, 157 insertions(+), 18 deletions(-) + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.c + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.h + create mode 100644 source4/auth/gensec/gensec_krb5_internal.h + +diff --git source4/auth/gensec/gensec_krb5.c source4/auth/gensec/gensec_krb5.c +index 7d87b3ac6b9..104e4639c44 100644 +--- source4/auth/gensec/gensec_krb5.c ++++ source4/auth/gensec/gensec_krb5.c +@@ -44,27 +44,11 @@ + #include "../lib/util/asn1.h" + #include "auth/kerberos/pac_utils.h" + #include "gensec_krb5.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" + + _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *); + +-enum GENSEC_KRB5_STATE { +- GENSEC_KRB5_SERVER_START, +- GENSEC_KRB5_CLIENT_START, +- GENSEC_KRB5_CLIENT_MUTUAL_AUTH, +- GENSEC_KRB5_DONE +-}; +- +-struct gensec_krb5_state { +- enum GENSEC_KRB5_STATE state_position; +- struct smb_krb5_context *smb_krb5_context; +- krb5_auth_context auth_context; +- krb5_data enc_ticket; +- krb5_keyblock *keyblock; +- krb5_ticket *ticket; +- bool gssapi; +- krb5_flags ap_req_options; +-}; +- + static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state) + { + if (!gensec_krb5_state->smb_krb5_context) { +diff --git source4/auth/gensec/gensec_krb5_helpers.c source4/auth/gensec/gensec_krb5_helpers.c +new file mode 100644 +index 00000000000..21f2f1e884e +--- /dev/null ++++ source4/auth/gensec/gensec_krb5_helpers.c +@@ -0,0 +1,72 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-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 . ++*/ ++ ++#include "includes.h" ++#include "auth/auth.h" ++#include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++static struct gensec_krb5_state *get_private_state(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ if (strcmp(gensec_security->ops->name, "krb5") != 0) { ++ /* We require that the krb5 mechanism is being used. */ ++ return NULL; ++ } ++ ++ gensec_krb5_state = talloc_get_type(gensec_security->private_data, ++ struct gensec_krb5_state); ++ return gensec_krb5_state; ++} ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ gensec_krb5_state = get_private_state(gensec_security); ++ if (gensec_krb5_state == NULL) { ++ return -1; ++ } ++ ++ if (gensec_krb5_state->ticket == NULL) { ++ /* We don't have a ticket */ ++ return -1; ++ } ++ ++#ifdef SAMBA4_USES_HEIMDAL ++ return gensec_krb5_state->ticket->ticket.flags.initial; ++#else /* MIT KERBEROS */ ++ return (gensec_krb5_state->ticket->enc_part2->flags & TKT_FLG_INITIAL) ? 1 : 0; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} +diff --git source4/auth/gensec/gensec_krb5_helpers.h source4/auth/gensec/gensec_krb5_helpers.h +new file mode 100644 +index 00000000000..d7b694dad0c +--- /dev/null ++++ source4/auth/gensec/gensec_krb5_helpers.h +@@ -0,0 +1,32 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-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 . ++*/ ++ ++struct gensec_security; ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security); +diff --git source4/auth/gensec/gensec_krb5_internal.h source4/auth/gensec/gensec_krb5_internal.h +new file mode 100644 +index 00000000000..0bb796f1b2a +--- /dev/null ++++ source4/auth/gensec/gensec_krb5_internal.h +@@ -0,0 +1,47 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-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 . ++*/ ++ ++#include "includes.h" ++#include "auth/gensec/gensec.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++enum GENSEC_KRB5_STATE { ++ GENSEC_KRB5_SERVER_START, ++ GENSEC_KRB5_CLIENT_START, ++ GENSEC_KRB5_CLIENT_MUTUAL_AUTH, ++ GENSEC_KRB5_DONE ++}; ++ ++struct gensec_krb5_state { ++ enum GENSEC_KRB5_STATE state_position; ++ struct smb_krb5_context *smb_krb5_context; ++ krb5_auth_context auth_context; ++ krb5_data enc_ticket; ++ krb5_keyblock *keyblock; ++ krb5_ticket *ticket; ++ bool gssapi; ++ krb5_flags ap_req_options; ++}; +diff --git source4/auth/gensec/wscript_build source4/auth/gensec/wscript_build +index d14a50ff273..20271f1665b 100644 +--- source4/auth/gensec/wscript_build ++++ source4/auth/gensec/wscript_build +@@ -18,6 +18,10 @@ bld.SAMBA_MODULE('gensec_krb5', + enabled=bld.AD_DC_BUILD_IS_ENABLED() + ) + ++bld.SAMBA_SUBSYSTEM('gensec_krb5_helpers', ++ source='gensec_krb5_helpers.c', ++ deps='gensec_krb5', ++ enabled=bld.AD_DC_BUILD_IS_ENABLED()) + + bld.SAMBA_MODULE('gensec_gssapi', + source='gensec_gssapi.c', +-- +2.25.1 + + +From 6c4fd575d706b2695090941ad7947b30abdb9071 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:52:41 +1200 +Subject: [PATCH 77/99] CVE-2022-2031 s4:kpasswd: Require an initial ticket + +Ensure that for password changes the client uses an AS-REQ to get the +ticket to kpasswd, and not a TGS-REQ. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_heimdal_kdc | 1 - + selftest/knownfail_mit_kdc | 1 - + source4/kdc/kpasswd-service-heimdal.c | 17 +++++++++++++++++ + source4/kdc/kpasswd-service-mit.c | 17 +++++++++++++++++ + source4/kdc/wscript_build | 1 + + 5 files changed, 35 insertions(+), 2 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 3b494baa658..5cd8615f6a9 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -277,7 +277,6 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index f64291e776d..46b0f1fa9ed 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -580,7 +580,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c +index c804852c3a7..1a6c2b60d03 100644 +--- source4/kdc/kpasswd-service-heimdal.c ++++ source4/kdc/kpasswd-service-heimdal.c +@@ -24,6 +24,7 @@ + #include "param/param.h" + #include "auth/auth.h" + #include "auth/gensec/gensec.h" ++#include "gensec_krb5_helpers.h" + #include "kdc/kdc-server.h" + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" +@@ -31,6 +32,7 @@ + + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *password, + DATA_BLOB *kpasswd_reply, +@@ -42,6 +44,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + const char *reject_string = NULL; + struct samr_DomInfo1 *dominfo; + bool ok; ++ int ret; ++ ++ /* ++ * We're doing a password change (rather than a password set), so check ++ * that we were given an initial ticket. ++ */ ++ ret = gensec_krb5_initial_ticket(gensec_security); ++ if (ret != 1) { ++ *error_string = "Expected an initial ticket"; ++ return KRB5_KPASSWD_INITIAL_FLAG_NEEDED; ++ } + + status = samdb_kpasswd_change_password(mem_ctx, + kdc->task->lp_ctx, +@@ -81,6 +94,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + + static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *decoded_data, + DATA_BLOB *kpasswd_reply, +@@ -173,6 +187,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + free_ChangePasswdDataMS(&chpw); + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -272,6 +287,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -280,6 +296,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + case KRB5_KPASSWD_VERS_SETPW: { + return kpasswd_set_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + decoded_data, + kpasswd_reply, +diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c +index 9c4d2801669..de4c6f3f622 100644 +--- source4/kdc/kpasswd-service-mit.c ++++ source4/kdc/kpasswd-service-mit.c +@@ -24,6 +24,7 @@ + #include "param/param.h" + #include "auth/auth.h" + #include "auth/gensec/gensec.h" ++#include "gensec_krb5_helpers.h" + #include "kdc/kdc-server.h" + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" +@@ -84,6 +85,7 @@ out: + + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *password, + DATA_BLOB *kpasswd_reply, +@@ -95,6 +97,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + const char *reject_string = NULL; + struct samr_DomInfo1 *dominfo; + bool ok; ++ int ret; ++ ++ /* ++ * We're doing a password change (rather than a password set), so check ++ * that we were given an initial ticket. ++ */ ++ ret = gensec_krb5_initial_ticket(gensec_security); ++ if (ret != 1) { ++ *error_string = "Expected an initial ticket"; ++ return KRB5_KPASSWD_INITIAL_FLAG_NEEDED; ++ } + + status = samdb_kpasswd_change_password(mem_ctx, + kdc->task->lp_ctx, +@@ -134,6 +147,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + + static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *decoded_data, + DATA_BLOB *kpasswd_reply, +@@ -250,6 +264,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -350,6 +365,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -358,6 +374,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + case RFC3244_VERSION: { + return kpasswd_set_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + decoded_data, + kpasswd_reply, +diff --git source4/kdc/wscript_build source4/kdc/wscript_build +index 0edca94e75f..13ba3947cf6 100644 +--- source4/kdc/wscript_build ++++ source4/kdc/wscript_build +@@ -88,6 +88,7 @@ bld.SAMBA_SUBSYSTEM('KPASSWD-SERVICE', + krb5samba + samba_server_gensec + KPASSWD_GLUE ++ gensec_krb5_helpers + ''') + + bld.SAMBA_SUBSYSTEM('KDC-GLUE', +-- +2.25.1 + + +From 69e742e6208bd471eb509795bd753a0c98392bf6 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 17:11:49 +1200 +Subject: [PATCH 78/99] s4:kpasswd: Restructure code for clarity + +View with 'git show -b'. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-heimdal.c | 46 +++++++++++++-------------- + 1 file changed, 22 insertions(+), 24 deletions(-) + +diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c +index 1a6c2b60d03..a0352d1ad35 100644 +--- source4/kdc/kpasswd-service-heimdal.c ++++ source4/kdc/kpasswd-service-heimdal.c +@@ -160,30 +160,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return 0; + } + +- if (chpw.targname != NULL && chpw.targrealm != NULL) { +- code = krb5_build_principal_ext(context, +- &target_principal, +- strlen(*chpw.targrealm), +- *chpw.targrealm, +- 0); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- code = copy_PrincipalName(chpw.targname, +- &target_principal->name); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- krb5_free_principal(context, target_principal); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- } else { ++ if (chpw.targname == NULL || chpw.targrealm == NULL) { + free_ChangePasswdDataMS(&chpw); + return kpasswd_change_password(kdc, + mem_ctx, +@@ -193,7 +170,28 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + kpasswd_reply, + error_string); + } ++ code = krb5_build_principal_ext(context, ++ &target_principal, ++ strlen(*chpw.targrealm), ++ *chpw.targrealm, ++ 0); ++ if (code != 0) { ++ free_ChangePasswdDataMS(&chpw); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } ++ code = copy_PrincipalName(chpw.targname, ++ &target_principal->name); + free_ChangePasswdDataMS(&chpw); ++ if (code != 0) { ++ krb5_free_principal(context, target_principal); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } + + if (target_principal->name.name_string.len >= 2) { + is_service_principal = true; +-- +2.25.1 + + +From b5adf7cc6d740c8f4f7b5888f106de24a1181da7 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 10:17:00 +0200 +Subject: [PATCH 79/99] CVE-2022-2031 testprogs: Fix auth with smbclient and + krb5 ccache + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton + +[jsutton@samba.org Fixed conflict and renamed --use-krb5-ccache to + --krb5-ccache] +--- + testprogs/blackbox/test_kpasswd_heimdal.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git testprogs/blackbox/test_kpasswd_heimdal.sh testprogs/blackbox/test_kpasswd_heimdal.sh +index 7351ce022d1..1e895daa162 100755 +--- testprogs/blackbox/test_kpasswd_heimdal.sh ++++ testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -72,7 +72,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + testit "change user password with 'samba-tool user password' (unforced)" \ + $VALGRIND $PYTHON $samba_tool user password -W$DOMAIN -U$TEST_USERNAME%$TEST_PASSWORD -k no --newpassword=$TEST_PASSWORD_NEW || failed=`expr $failed + 1` +@@ -85,7 +85,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + ########################################################### + ### check that a short password is rejected +-- +2.25.1 + + +From 91a1b0955a053f73e6d531f0f12eaa604aca79d7 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 19 May 2022 16:35:28 +0200 +Subject: [PATCH 80/99] CVE-2022-2031 testprogs: Add kadmin/changepw + canonicalization test with MIT kpasswd + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton +--- + selftest/knownfail.d/kadmin_changepw | 1 + + testprogs/blackbox/test_kpasswd_heimdal.sh | 35 +++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + create mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git selftest/knownfail.d/kadmin_changepw selftest/knownfail.d/kadmin_changepw +new file mode 100644 +index 00000000000..97c14793ea5 +--- /dev/null ++++ selftest/knownfail.d/kadmin_changepw +@@ -0,0 +1 @@ ++^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git testprogs/blackbox/test_kpasswd_heimdal.sh testprogs/blackbox/test_kpasswd_heimdal.sh +index 1e895daa162..059b7a8e4d1 100755 +--- testprogs/blackbox/test_kpasswd_heimdal.sh ++++ testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -7,7 +7,7 @@ + + if [ $# -lt 6 ]; then + cat < "${PREFIX}/tmpkpasswdscript" < "${KRB5_CONFIG}" ++ testit "MIT kpasswd change user password" \ ++ "${texpect}" "${PREFIX}/tmpkpasswdscript" "${mit_kpasswd}" \ ++ "${TEST_PRINCIPAL}" || ++ failed=$((failed + 1)) ++ KRB5_CONFIG="${SAVE_KRB5_CONFIG}" ++ export KRB5_CONFIG ++fi ++ ++TEST_PASSWORD="${TEST_PASSWORD_NEW}" ++TEST_PASSWORD_NEW="testPaSS@03force%" ++ + ########################################################### + ### Force password change at login + ########################################################### +-- +2.25.1 + + +From 36d94ffb9c99f3e515024424020e3e03e98f34f5 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 09:54:18 +0200 +Subject: [PATCH 81/99] CVE-2022-2031 s4:kdc: Implement is_kadmin_changepw() + helper function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton + +[jsutton@samba.org Adapted entry to entry_ex->entry] +--- + source4/kdc/db-glue.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index 5752ffb821c..45159e6e64d 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -816,6 +816,14 @@ static int principal_comp_strcmp(krb5_context context, + component, string, false); + } + ++static bool is_kadmin_changepw(krb5_context context, ++ krb5_const_principal principal) ++{ ++ return krb5_princ_size(context, principal) == 2 && ++ (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) && ++ (principal_comp_strcmp(context, principal, 1, "changepw") == 0); ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -1110,11 +1118,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + * 'change password', as otherwise we could get into + * trouble, and not enforce the password expirty. + * Instead, only do it when request is for the kpasswd service */ +- if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER +- && krb5_princ_size(context, principal) == 2 +- && (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) +- && (principal_comp_strcmp(context, principal, 1, "changepw") == 0) +- && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && ++ is_kadmin_changepw(context, principal) && ++ lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { + entry_ex->entry.flags.change_pw = 1; + } + +-- +2.25.1 + + +From f68877af829bf73da8e965c9458a9846d1757038 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 82/99] CVE-2022-2031 s4:kdc: Split out a + samba_kdc_get_entry_principal() function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry] + +[jsutton@samba.org Fixed conflicts caused by superfluous whitespace] +--- + source4/kdc/db-glue.c | 192 +++++++++++++++++++++++------------------- + 1 file changed, 107 insertions(+), 85 deletions(-) + +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index 45159e6e64d..ac0c206b5c1 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -824,6 +824,101 @@ static bool is_kadmin_changepw(krb5_context context, + (principal_comp_strcmp(context, principal, 1, "changepw") == 0); + } + ++static krb5_error_code samba_kdc_get_entry_principal( ++ krb5_context context, ++ struct samba_kdc_db_context *kdc_db_ctx, ++ const char *samAccountName, ++ enum samba_kdc_ent_type ent_type, ++ unsigned flags, ++ krb5_const_principal in_princ, ++ krb5_principal *out_princ) ++{ ++ struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; ++ krb5_error_code ret = 0; ++ ++ /* ++ * If we are set to canonicalize, we get back the fixed UPPER ++ * case realm, and the real username (ie matching LDAP ++ * samAccountName) ++ * ++ * Otherwise, if we are set to enterprise, we ++ * get back the whole principal as-sent ++ * ++ * Finally, if we are not set to canonicalize, we get back the ++ * fixed UPPER case realm, but the as-sent username ++ */ ++ ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, ++ lpcfg_realm(lp_ctx), "krbtgt", ++ lpcfg_realm(lp_ctx), NULL); ++ if (ret) { ++ return ret; ++ } ++ smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ /* ++ * this appears to be required regardless of ++ * the canonicalize flag from the client ++ */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -913,93 +1008,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + userAccountControl |= msDS_User_Account_Control_Computed; + } + +- /* +- * If we are set to canonicalize, we get back the fixed UPPER +- * case realm, and the real username (ie matching LDAP +- * samAccountName) +- * +- * Otherwise, if we are set to enterprise, we +- * get back the whole principal as-sent +- * +- * Finally, if we are not set to canonicalize, we get back the +- * fixed UPPER case realm, but the as-sent username +- */ +- + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; +- +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- smb_krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } +- +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } + } + + /* First try and figure out the flags based on the userAccountControl */ +@@ -1185,6 +1195,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + } + } + ++ ret = samba_kdc_get_entry_principal(context, ++ kdc_db_ctx, ++ samAccountName, ++ ent_type, ++ flags, ++ principal, ++ &entry_ex->entry.principal); ++ if (ret != 0) { ++ krb5_clear_error_message(context); ++ goto out; ++ } ++ + entry_ex->entry.valid_start = NULL; + + entry_ex->entry.max_life = malloc(sizeof(*entry_ex->entry.max_life)); +-- +2.25.1 + + +From fa4742e1b9dea0b9c379f00666478bd41c021634 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 17:19:58 +1200 +Subject: [PATCH 83/99] CVE-2022-2031 s4:kdc: Refactor + samba_kdc_get_entry_principal() + +This eliminates some duplicate branches. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider +--- + source4/kdc/db-glue.c | 116 ++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 61 deletions(-) + +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index ac0c206b5c1..385c118a073 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -834,7 +834,8 @@ static krb5_error_code samba_kdc_get_entry_principal( + krb5_principal *out_princ) + { + struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; +- krb5_error_code ret = 0; ++ krb5_error_code code = 0; ++ bool canon = flags & (SDB_F_CANON|SDB_F_FORCE_CANON); + + /* + * If we are set to canonicalize, we get back the fixed UPPER +@@ -848,75 +849,68 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, out_princ, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- return ret; +- } +- smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } +- } ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ return 0; ++ } ++ ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. + * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. + */ +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } ++ /* ++ * For a krbtgt entry, this appears to be required regardless of the ++ * canonicalize flag from the client. ++ */ ++ code = krb5_copy_principal(context, in_princ, out_princ); ++ if (code != 0) { ++ return code; + } + +- return 0; ++ /* ++ * While we have copied the client principal, tests show that Win2k3 ++ * returns the 'corrected' realm, not the client-specified realm. This ++ * code attempts to replace the client principal's realm with the one ++ * we determine from our records ++ */ ++ code = smb_krb5_principal_set_realm(context, ++ *out_princ, ++ lpcfg_realm(lp_ctx)); ++ ++ return code; + } + + /* +-- +2.25.1 + + +From 3cab62893668742781551dae6505558e47cf08b5 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 84/99] CVE-2022-2031 s4:kdc: Fix canonicalisation of + kadmin/changepw principal + +Since this principal goes through the samba_kdc_fetch_server() path, +setting the canonicalisation flag would cause the principal to be +replaced with the sAMAccountName; this meant requests to +kadmin/changepw@REALM would result in a ticket to krbtgt@REALM. Now we +properly handle canonicalisation for the kadmin/changepw principal. + +View with 'git show -b'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Andreas Schneider +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; removed MIT KDC + 1.20-specific knownfails] +--- + selftest/knownfail.d/kadmin_changepw | 1 - + selftest/knownfail_heimdal_kdc | 2 - + source4/kdc/db-glue.c | 84 +++++++++++++++------------- + 3 files changed, 46 insertions(+), 41 deletions(-) + delete mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git selftest/knownfail.d/kadmin_changepw selftest/knownfail.d/kadmin_changepw +deleted file mode 100644 +index 97c14793ea5..00000000000 +--- selftest/knownfail.d/kadmin_changepw ++++ /dev/null +@@ -1 +0,0 @@ +-^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 5cd8615f6a9..49ab29f115d 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -274,8 +274,6 @@ + # + # Kpasswd tests + # +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index 385c118a073..d2d7136608e 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -830,6 +830,7 @@ static krb5_error_code samba_kdc_get_entry_principal( + const char *samAccountName, + enum samba_kdc_ent_type ent_type, + unsigned flags, ++ bool is_kadmin_changepw, + krb5_const_principal in_princ, + krb5_principal *out_princ) + { +@@ -849,46 +850,52 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- "krbtgt", +- lpcfg_realm(lp_ctx), +- NULL); +- if (code != 0) { +- return code; +- } +- smb_krb5_principal_set_type(context, +- *out_princ, +- KRB5_NT_SRV_INST); ++ /* ++ * We need to ensure that the kadmin/changepw principal isn't able to ++ * issue krbtgt tickets, even if canonicalization is turned on. ++ */ ++ if (!is_kadmin_changepw) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- return 0; +- } ++ return 0; ++ } + +- if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || +- (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the +- * AS-REQ case. +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that +- * wants the canonical name in all lookups, and takes +- * care to canonicalize only when appropriate. +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- samAccountName, +- NULL); +- return code; ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + } + + /* +@@ -1194,6 +1201,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + samAccountName, + ent_type, + flags, ++ entry_ex->entry.flags.change_pw, + principal, + &entry_ex->entry.principal); + if (ret != 0) { +-- +2.25.1 + + +From 531e7b596d35785bee61f3b4289e38ece1530f94 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 17:53:49 +1200 +Subject: [PATCH 85/99] CVE-2022-2031 s4:kdc: Limit kpasswd ticket lifetime to + two minutes or less + +This matches the behaviour of Windows. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; included + samba_kdc.h header file] + +[jsutton@samba.org Fixed conflicts] +--- + selftest/knownfail_heimdal_kdc | 1 - + selftest/knownfail_mit_kdc | 1 - + source4/kdc/db-glue.c | 5 +++++ + source4/kdc/mit-kdb/kdb_samba_principals.c | 2 +- + source4/kdc/samba_kdc.h | 2 ++ + 5 files changed, 8 insertions(+), 3 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 49ab29f115d..387ccea3ba7 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -275,7 +275,6 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 46b0f1fa9ed..c2a31b4a140 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -580,7 +580,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index d2d7136608e..073ec83c8cf 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -1226,6 +1226,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + kdc_db_ctx->policy.usr_tkt_lifetime); + } + ++ if (entry_ex->entry.flags.change_pw) { ++ /* Limit lifetime of kpasswd tickets to two minutes or less. */ ++ *entry_ex->entry.max_life = MIN(*entry_ex->entry.max_life, CHANGEPW_LIFETIME); ++ } ++ + entry_ex->entry.max_renew = malloc(sizeof(*entry_ex->entry.max_life)); + if (entry_ex->entry.max_renew == NULL) { + ret = ENOMEM; +diff --git source4/kdc/mit-kdb/kdb_samba_principals.c source4/kdc/mit-kdb/kdb_samba_principals.c +index cc67c2392be..2059ffa855e 100644 +--- source4/kdc/mit-kdb/kdb_samba_principals.c ++++ source4/kdc/mit-kdb/kdb_samba_principals.c +@@ -27,11 +27,11 @@ + #include + #include + ++#include "kdc/samba_kdc.h" + #include "kdc/mit_samba.h" + #include "kdb_samba.h" + + #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ +-#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ + + krb5_error_code ks_get_principal(krb5_context context, + krb5_const_principal principal, +diff --git source4/kdc/samba_kdc.h source4/kdc/samba_kdc.h +index e228a82ce6a..8010d7c35ed 100644 +--- source4/kdc/samba_kdc.h ++++ source4/kdc/samba_kdc.h +@@ -62,4 +62,6 @@ struct samba_kdc_entry { + + extern struct hdb_method hdb_samba4_interface; + ++#define CHANGEPW_LIFETIME 60*2 /* 2 minutes */ ++ + #endif /* _SAMBA_KDC_H_ */ +-- +2.25.1 + + +From abdac4241dd08dd90a08db877edd799f3833c2b4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:18:17 +1200 +Subject: [PATCH 86/99] CVE-2022-2031 s4:kdc: Reject tickets during the last + two minutes of their life + +For Heimdal, this now matches the behaviour of Windows. The object of +this requirement is to ensure we don't allow kpasswd tickets, not having +a lifetime of more than two minutes, to be passed off as TGTs. + +An existing requirement for TGTs to contain a REQUESTER_SID PAC buffer +suffices to prevent kpasswd ticket misuse, so this is just an additional +precaution on top. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org As we don't have access to the ticket or the request + in the plugin, rewrote check directly in Heimdal KDC] +--- + selftest/knownfail_heimdal_kdc | 1 - + source4/heimdal/kdc/krb5tgs.c | 19 ++++++++++++++++++- + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 387ccea3ba7..afb9bcf1209 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -275,7 +275,6 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c +index 38dba8493ae..15be136496f 100644 +--- source4/heimdal/kdc/krb5tgs.c ++++ source4/heimdal/kdc/krb5tgs.c +@@ -33,6 +33,9 @@ + + #include "kdc_locl.h" + ++/* Awful hack to get access to 'struct samba_kdc_entry'. */ ++#include "../../kdc/samba_kdc.h" ++ + /* + * return the realm of a krbtgt-ticket or NULL + */ +@@ -130,6 +133,7 @@ check_PAC(krb5_context context, + static krb5_error_code + check_tgs_flags(krb5_context context, + krb5_kdc_configuration *config, ++ const hdb_entry_ex *krbtgt_in, + KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et) + { + KDCOptions f = b->kdc_options; +@@ -244,6 +248,17 @@ check_tgs_flags(krb5_context context, + et->endtime = min(*et->renew_till, et->endtime); + } + ++ if (tgt->endtime - kdc_time <= CHANGEPW_LIFETIME) { ++ /* Check that the ticket has not arrived across a trust. */ ++ const struct samba_kdc_entry *skdc_entry = krbtgt_in->ctx; ++ if (!skdc_entry->is_trust) { ++ /* This may be a kpasswd ticket rather than a TGT, so don't accept it. */ ++ kdc_log(context, config, 0, ++ "Ticket is not a ticket-granting ticket"); ++ return KRB5KRB_AP_ERR_TKT_EXPIRED; ++ } ++ } ++ + #if 0 + /* checks for excess flags */ + if(f.request_anonymous && !config->allow_anonymous){ +@@ -510,6 +525,7 @@ tgs_make_reply(krb5_context context, + hdb_entry_ex *client, + krb5_principal client_principal, + const char *tgt_realm, ++ const hdb_entry_ex *krbtgt_in, + hdb_entry_ex *krbtgt, + krb5_pac mspac, + uint16_t rodc_id, +@@ -538,7 +554,7 @@ tgs_make_reply(krb5_context context, + ALLOC(et.starttime); + *et.starttime = kdc_time; + +- ret = check_tgs_flags(context, config, b, tgt, &et); ++ ret = check_tgs_flags(context, config, krbtgt_in, b, tgt, &et); + if(ret) + goto out; + +@@ -2129,6 +2145,7 @@ server_lookup: + client, + cp, + tgt_realm, ++ krbtgt, + krbtgt_out, + mspac, + rodc_id, +-- +2.25.1 + + +From 389851bcf399f9511e2cb797350c37ce91aa5849 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 15:23:55 +1200 +Subject: [PATCH 87/99] CVE-2022-2031 tests/krb5: Test truncated forms of + server principals + +We should not be able to use krb@REALM instead of krbtgt@REALM. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to having older version of + _run_as_req_enc_timestamp()] +--- + python/samba/tests/krb5/as_req_tests.py | 40 ++++++++++++++++++++++--- + selftest/knownfail_heimdal_kdc | 4 +++ + selftest/knownfail_mit_kdc | 4 +++ + 3 files changed, 44 insertions(+), 4 deletions(-) + +diff --git python/samba/tests/krb5/as_req_tests.py python/samba/tests/krb5/as_req_tests.py +index 315720f85d6..054a49b64aa 100755 +--- python/samba/tests/krb5/as_req_tests.py ++++ python/samba/tests/krb5/as_req_tests.py +@@ -27,6 +27,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest + import samba.tests.krb5.kcrypto as kcrypto + import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + from samba.tests.krb5.rfc4120_constants import ( ++ KDC_ERR_S_PRINCIPAL_UNKNOWN, + KDC_ERR_ETYPE_NOSUPP, + KDC_ERR_PREAUTH_REQUIRED, + KU_PA_ENC_TIMESTAMP, +@@ -40,7 +41,8 @@ global_hexdump = False + + + class AsReqBaseTest(KDCBaseTest): +- def _run_as_req_enc_timestamp(self, client_creds): ++ def _run_as_req_enc_timestamp(self, client_creds, sname=None, ++ expected_error=None): + client_account = client_creds.get_username() + client_as_etypes = self.get_default_enctypes() + client_kvno = client_creds.get_kvno() +@@ -50,8 +52,9 @@ class AsReqBaseTest(KDCBaseTest): + + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_account]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=[krbtgt_account, realm]) ++ if sname is None: ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) + + expected_crealm = realm + expected_cname = cname +@@ -63,7 +66,10 @@ class AsReqBaseTest(KDCBaseTest): + + initial_etypes = client_as_etypes + initial_kdc_options = krb5_asn1.KDCOptions('forwardable') +- initial_error_mode = KDC_ERR_PREAUTH_REQUIRED ++ if expected_error is not None: ++ initial_error_mode = expected_error ++ else: ++ initial_error_mode = KDC_ERR_PREAUTH_REQUIRED + + rep, kdc_exchange_dict = self._test_as_exchange(cname, + realm, +@@ -80,6 +86,10 @@ class AsReqBaseTest(KDCBaseTest): + None, + initial_kdc_options, + pac_request=True) ++ ++ if expected_error is not None: ++ return None ++ + etype_info2 = kdc_exchange_dict['preauth_etype_info2'] + self.assertIsNotNone(etype_info2) + +@@ -209,6 +219,28 @@ class AsReqKerberosTests(AsReqBaseTest): + client_creds = self.get_mach_creds() + self._run_as_req_enc_timestamp(client_creds) + ++ # Ensure we can't use truncated well-known principals such as krb@REALM ++ # instead of krbtgt@REALM. ++ def test_krbtgt_wrong_principal(self): ++ client_creds = self.get_client_creds() ++ ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ krbtgt_account = krbtgt_creds.get_username() ++ realm = krbtgt_creds.get_realm() ++ ++ # Truncate the name of the krbtgt principal. ++ krbtgt_account = krbtgt_account[:3] ++ ++ wrong_krbtgt_princ = self.PrincipalName_create( ++ name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) ++ ++ self._run_as_req_enc_timestamp( ++ client_creds, ++ sname=wrong_krbtgt_princ, ++ expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN) ++ + + if __name__ == "__main__": + global_asn1_print = False +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index afb9bcf1209..dbfff5784e6 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -278,3 +278,7 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc ++# ++# AS-REQ tests ++# ++^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index c2a31b4a140..0f90ea10299 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -583,3 +583,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc ++# ++# AS-REQ tests ++# ++^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +-- +2.25.1 + + +From d40593be83144713cfc43e4eb1c7bc2d925a0da0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 20:00:55 +1200 +Subject: [PATCH 88/99] CVE-2022-2031 s4:kdc: Don't use strncmp to compare + principal components + +We would only compare the first 'n' characters, where 'n' is the length +of the principal component string, so 'k@REALM' would erroneously be +considered equal to 'krbtgt@REALM'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/db-glue.c | 27 ++++++++++++++++++++++----- + 3 files changed, 22 insertions(+), 13 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index dbfff5784e6..afb9bcf1209 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -278,7 +278,3 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-# +-# AS-REQ tests +-# +-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 0f90ea10299..c2a31b4a140 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -583,7 +583,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-# +-# AS-REQ tests +-# +-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c +index 073ec83c8cf..cfa2097acbd 100644 +--- source4/kdc/db-glue.c ++++ source4/kdc/db-glue.c +@@ -769,15 +769,19 @@ static int principal_comp_strcmp_int(krb5_context context, + bool do_strcasecmp) + { + const char *p; +- size_t len; + + #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) + p = krb5_principal_get_comp_string(context, principal, component); + if (p == NULL) { + return -1; + } +- len = strlen(p); ++ if (do_strcasecmp) { ++ return strcasecmp(p, string); ++ } else { ++ return strcmp(p, string); ++ } + #else ++ size_t len; + krb5_data *d; + if (component >= krb5_princ_size(context, principal)) { + return -1; +@@ -789,13 +793,26 @@ static int principal_comp_strcmp_int(krb5_context context, + } + + p = d->data; +- len = d->length; +-#endif ++ ++ len = strlen(string); ++ ++ /* ++ * We explicitly return -1 or 1. Subtracting of the two lengths might ++ * give the wrong result if the result overflows or loses data when ++ * narrowed to int. ++ */ ++ if (d->length < len) { ++ return -1; ++ } else if (d->length > len) { ++ return 1; ++ } ++ + if (do_strcasecmp) { + return strncasecmp(p, string, len); + } else { +- return strncmp(p, string, len); ++ return memcmp(p, string, len); + } ++#endif + } + + static int principal_comp_strcasecmp(krb5_context context, +-- +2.25.1 + + +From 42ba919c06c24c42ef123304de0c2ca8c689591a Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:36:30 +1200 +Subject: [PATCH 89/99] CVE-2022-32744 s4:kdc: Rename keytab_name -> + kpasswd_keytab_name + +This makes explicitly clear the purpose of this keytab. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to lacking HDBGET support] +--- + source4/kdc/kdc-heimdal.c | 4 ++-- + source4/kdc/kdc-server.h | 2 +- + source4/kdc/kdc-service-mit.c | 4 ++-- + source4/kdc/kpasswd-service.c | 2 +- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git source4/kdc/kdc-heimdal.c source4/kdc/kdc-heimdal.c +index ba74df4f2ec..a4c845b62f8 100644 +--- source4/kdc/kdc-heimdal.c ++++ source4/kdc/kdc-heimdal.c +@@ -444,8 +444,8 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) + return; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "kdc: Failed to set keytab name", + true); +diff --git source4/kdc/kdc-server.h source4/kdc/kdc-server.h +index fd883c2e4b4..89b30f122f5 100644 +--- source4/kdc/kdc-server.h ++++ source4/kdc/kdc-server.h +@@ -40,7 +40,7 @@ struct kdc_server { + struct ldb_context *samdb; + bool am_rodc; + uint32_t proxy_timeout; +- const char *keytab_name; ++ const char *kpasswd_keytab_name; + void *private_data; + }; + +diff --git source4/kdc/kdc-service-mit.c source4/kdc/kdc-service-mit.c +index 5d4180aa7cc..22663b6ecc8 100644 +--- source4/kdc/kdc-service-mit.c ++++ source4/kdc/kdc-service-mit.c +@@ -291,8 +291,8 @@ NTSTATUS mitkdc_task_init(struct task_server *task) + return NT_STATUS_INTERNAL_ERROR; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "KDB:"); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "KDB:"); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "KDC: Out of memory", + true); +diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c +index b4706de1ad7..0d2acd8d9e8 100644 +--- source4/kdc/kpasswd-service.c ++++ source4/kdc/kpasswd-service.c +@@ -167,7 +167,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, +- kdc->keytab_name, ++ kdc->kpasswd_keytab_name, + CRED_SPECIFIED); + if (rv != 0) { + DBG_ERR("Failed to set credentials keytab name\n"); +-- +2.25.1 + + +From 997f50c66471071efb8e02d8efbe4bf5d932e7ee Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 8 Jun 2022 13:53:29 +1200 +Subject: [PATCH 90/99] s4:kdc: Remove kadmin mode from HDB plugin + +It appears we no longer require it. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/hdb-samba4-plugin.c | 35 +++++++-------------------------- + 1 file changed, 7 insertions(+), 28 deletions(-) + +diff --git source4/kdc/hdb-samba4-plugin.c source4/kdc/hdb-samba4-plugin.c +index 6f76124995d..4b90a766f76 100644 +--- source4/kdc/hdb-samba4-plugin.c ++++ source4/kdc/hdb-samba4-plugin.c +@@ -21,40 +21,20 @@ + + #include "includes.h" + #include "kdc/kdc-glue.h" +-#include "kdc/db-glue.h" +-#include "lib/util/samba_util.h" + #include "lib/param/param.h" +-#include "source4/lib/events/events.h" + + static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, const char *arg) + { + NTSTATUS nt_status; +- void *ptr; +- struct samba_kdc_base_context *base_ctx; +- +- if (sscanf(arg, "&%p", &ptr) == 1) { +- base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); +- } else if (arg[0] == '\0' || file_exist(arg)) { +- /* This mode for use in kadmin, rather than in Samba */ +- +- setup_logging("hdb_samba4", DEBUG_DEFAULT_STDERR); +- +- base_ctx = talloc_zero(NULL, struct samba_kdc_base_context); +- if (!base_ctx) { +- return ENOMEM; +- } +- +- base_ctx->ev_ctx = s4_event_context_init(base_ctx); +- base_ctx->lp_ctx = loadparm_init_global(false); +- if (arg[0]) { +- lpcfg_load(base_ctx->lp_ctx, arg); +- } else { +- lpcfg_load_default(base_ctx->lp_ctx); +- } +- } else { ++ void *ptr = NULL; ++ struct samba_kdc_base_context *base_ctx = NULL; ++ ++ if (sscanf(arg, "&%p", &ptr) != 1) { + return EINVAL; + } + ++ base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); ++ + /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ + nt_status = hdb_samba4_create_kdc(base_ctx, context, db); + +@@ -90,8 +70,7 @@ static void hdb_samba4_fini(void *ctx) + + /* Only used in the hdb-backed keytab code + * for a keytab of 'samba4&
' or samba4, to find +- * kpasswd's key in the main DB, and to +- * copy all the keys into a file (libnet_keytab_export) ++ * kpasswd's key in the main DB + * + * The
is the string form of a pointer to a talloced struct hdb_samba_context + */ +-- +2.25.1 + + +From c0c4b7a4bd229bd36d586faec6249baaba8e7adc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:39:20 +1200 +Subject: [PATCH 91/99] CVE-2022-32744 s4:kdc: Modify HDB plugin to only look + up kpasswd principal + +This plugin is now only used by the kpasswd service. Thus, ensuring we +only look up the kadmin/changepw principal means we can't be fooled into +accepting tickets for other service principals. We make sure not to +specify a specific kvno, to ensure that we do not accept RODC-issued +tickets. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Renamed entry to entry_ex; fixed knownfail conflicts; + retained knownfail for test_kpasswd_from_rodc which now causes the KDC + to panic] +--- + selftest/knownfail_heimdal_kdc | 3 -- + source4/kdc/hdb-samba4-plugin.c | 2 +- + source4/kdc/hdb-samba4.c | 66 +++++++++++++++++++++++++++++++++ + source4/kdc/kdc-glue.h | 3 ++ + 4 files changed, 70 insertions(+), 4 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index afb9bcf1209..0d93253f999 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -275,6 +275,3 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/kdc/hdb-samba4-plugin.c source4/kdc/hdb-samba4-plugin.c +index 4b90a766f76..dba25e825de 100644 +--- source4/kdc/hdb-samba4-plugin.c ++++ source4/kdc/hdb-samba4-plugin.c +@@ -36,7 +36,7 @@ static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, + base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); + + /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ +- nt_status = hdb_samba4_create_kdc(base_ctx, context, db); ++ nt_status = hdb_samba4_kpasswd_create_kdc(base_ctx, context, db); + + if (NT_STATUS_IS_OK(nt_status)) { + return 0; +diff --git source4/kdc/hdb-samba4.c source4/kdc/hdb-samba4.c +index 43e836f8360..a8aae50b5b0 100644 +--- source4/kdc/hdb-samba4.c ++++ source4/kdc/hdb-samba4.c +@@ -136,6 +136,47 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, + return code; + } + ++static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db, ++ krb5_const_principal _principal, ++ unsigned flags, ++ krb5_kvno _kvno, ++ hdb_entry_ex *entry_ex) ++{ ++ struct samba_kdc_db_context *kdc_db_ctx = NULL; ++ krb5_error_code ret; ++ krb5_principal kpasswd_principal = NULL; ++ ++ kdc_db_ctx = talloc_get_type_abort(db->hdb_db, ++ struct samba_kdc_db_context); ++ ++ ret = smb_krb5_make_principal(context, &kpasswd_principal, ++ lpcfg_realm(kdc_db_ctx->lp_ctx), ++ "kadmin", "changepw", ++ NULL); ++ if (ret) { ++ return ret; ++ } ++ smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST); ++ ++ /* ++ * For the kpasswd service, always ensure we get the latest kvno. This ++ * also means we (correctly) refuse RODC-issued tickets. ++ */ ++ flags &= ~HDB_F_KVNO_SPECIFIED; ++ ++ /* Don't bother looking up a client or krbtgt. */ ++ flags &= ~(SDB_F_GET_CLIENT|SDB_F_GET_KRBTGT); ++ ++ ret = hdb_samba4_fetch_kvno(context, db, ++ kpasswd_principal, ++ flags, ++ 0, ++ entry_ex); ++ ++ krb5_free_principal(context, kpasswd_principal); ++ return ret; ++} ++ + static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags, + hdb_entry_ex *entry) + { +@@ -194,6 +235,14 @@ static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigne + return ret; + } + ++static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db, ++ unsigned flags, ++ hdb_entry_ex *entry) ++{ ++ DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n"); ++ smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab"); ++} ++ + static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db) + { + talloc_free(db); +@@ -522,3 +571,20 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, + + return NT_STATUS_OK; + } ++ ++NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, ++ krb5_context context, struct HDB **db) ++{ ++ NTSTATUS nt_status; ++ ++ nt_status = hdb_samba4_create_kdc(base_ctx, context, db); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ return nt_status; ++ } ++ ++ (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno; ++ (*db)->hdb_firstkey = hdb_samba4_nextkey_panic; ++ (*db)->hdb_nextkey = hdb_samba4_nextkey_panic; ++ ++ return NT_STATUS_OK; ++} +diff --git source4/kdc/kdc-glue.h source4/kdc/kdc-glue.h +index c083b8c6429..ff8684e1666 100644 +--- source4/kdc/kdc-glue.h ++++ source4/kdc/kdc-glue.h +@@ -45,6 +45,9 @@ kdc_code kpasswdd_process(struct kdc_server *kdc, + NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, + krb5_context context, struct HDB **db); + ++NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, ++ krb5_context context, struct HDB **db); ++ + /* from kdc-glue.c */ + int kdc_check_pac(krb5_context krb5_context, + DATA_BLOB server_sig, +-- +2.25.1 + + +From 340181bc1100fa31c63af88214a3d8328b944fe9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:16:02 +1200 +Subject: [PATCH 92/99] CVE-2022-32744 s4:kpasswd: Ensure we pass the kpasswd + server principal into krb5_rd_req_ctx() + +To ensure that, when decrypting the kpasswd ticket, we look up the +correct principal and don't trust the sname from the ticket, we should +pass the principal name of the kpasswd service into krb5_rd_req_ctx(). +However, gensec_krb5_update_internal() will pass in NULL unless the +principal in our credentials is CRED_SPECIFIED. + +At present, our principal will be considered obtained as CRED_SMB_CONF +(from the cli_credentials_set_conf() a few lines up), so we explicitly +set the realm again, but this time as CRED_SPECIFIED. Now the value of +server_in_keytab that we provide to smb_krb5_rd_req_decoded() will not +be NULL. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed knownfail as KDC no longer panics] +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 2 -- + source4/kdc/kpasswd-service.c | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 30 insertions(+), 6 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 0d93253f999..424a8b81c38 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -271,7 +271,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-# +-# Kpasswd tests +-# +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index c2a31b4a140..0d2f5bab6d2 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -581,5 +581,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c +index 0d2acd8d9e8..b6400be0c49 100644 +--- source4/kdc/kpasswd-service.c ++++ source4/kdc/kpasswd-service.c +@@ -29,6 +29,7 @@ + #include "kdc/kdc-server.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "param/param.h" + + #define HEADER_LEN 6 + #ifndef RFC3244_VERSION +@@ -158,6 +159,20 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + + cli_credentials_set_conf(server_credentials, kdc->task->lp_ctx); + ++ /* ++ * After calling cli_credentials_set_conf(), explicitly set the realm ++ * with CRED_SPECIFIED. We need to do this so the result of ++ * principal_from_credentials() called from the gensec layer is ++ * CRED_SPECIFIED rather than CRED_SMB_CONF, avoiding a fallback to ++ * match-by-key (very undesirable in this case). ++ */ ++ ok = cli_credentials_set_realm(server_credentials, ++ lpcfg_realm(kdc->task->lp_ctx), ++ CRED_SPECIFIED); ++ if (!ok) { ++ goto done; ++ } ++ + ok = cli_credentials_set_username(server_credentials, + "kadmin/changepw", + CRED_SPECIFIED); +@@ -165,6 +180,21 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + goto done; + } + ++ /* Check that the server principal is indeed CRED_SPECIFIED. */ ++ { ++ char *principal = NULL; ++ enum credentials_obtained obtained; ++ ++ principal = cli_credentials_get_principal_and_obtained(server_credentials, ++ tmp_ctx, ++ &obtained); ++ if (obtained < CRED_SPECIFIED) { ++ goto done; ++ } ++ ++ TALLOC_FREE(principal); ++ } ++ + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, + kdc->kpasswd_keytab_name, +-- +2.25.1 + + +From 95afbc2da9b541fb8f2eebdcd411f5873d1675ac Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:17:11 +1200 +Subject: [PATCH 93/99] CVE-2022-2031 tests/krb5: Add test that we cannot + provide a TGT to kpasswd + +The kpasswd service should require a kpasswd service ticket, and +disallow TGTs. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Fixed knownfail conflicts] +--- + python/samba/tests/krb5/kpasswd_tests.py | 28 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 4 ++++ + selftest/knownfail_mit_kdc | 4 ++++ + 3 files changed, 36 insertions(+) + +diff --git python/samba/tests/krb5/kpasswd_tests.py python/samba/tests/krb5/kpasswd_tests.py +index 3a6c7d818dc..0db857f7bbd 100755 +--- python/samba/tests/krb5/kpasswd_tests.py ++++ python/samba/tests/krb5/kpasswd_tests.py +@@ -31,6 +31,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_TGT_REVOKED, + KDC_ERR_TKT_EXPIRED, + KPASSWD_ACCESSDENIED, ++ KPASSWD_AUTHERROR, + KPASSWD_HARDERROR, + KPASSWD_INITIAL_FLAG_NEEDED, + KPASSWD_MALFORMED, +@@ -779,6 +780,33 @@ class KpasswdTests(KDCBaseTest): + self._make_tgs_request(creds, service_creds, ticket, + expect_error=False) + ++ # Show that we cannot provide a TGT to kpasswd to change the password. ++ def test_kpasswd_tgt(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds) ++ ++ # Change the sname of the ticket to match that of kadmin/changepw. ++ tgt.set_sname(self.get_kpasswd_sname()) ++ ++ expected_code = KPASSWD_AUTHERROR ++ expected_msg = b'A TGT may not be used as a ticket to kpasswd' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(tgt, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(tgt, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ + # Test that kpasswd rejects requests with a service ticket. + def test_kpasswd_non_initial(self): + # Create an account for testing, and get a TGT. +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 424a8b81c38..42beccaed58 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -271,3 +271,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 0d2f5bab6d2..9fc34e5d8db 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -581,3 +581,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++# ++# Kpasswd tests ++# ++samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +-- +2.25.1 + + +From 4b61092459b403b2945daa9082052366f3508b69 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:07 +1200 +Subject: [PATCH 94/99] CVE-2022-2031 auth: Add ticket type field to + auth_user_info_dc and auth_session_info + +This field may be used to convey whether we were provided with a TGT or +a non-TGT. We ensure both structures are zeroed out to avoid incorrect +results being produced by an uninitialised field. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + auth/auth_sam_reply.c | 2 +- + auth/auth_util.c | 2 +- + librpc/idl/auth.idl | 23 +++++++++++++++++++++++ + source4/auth/ntlm/auth_developer.c | 2 +- + source4/auth/sam.c | 2 +- + source4/auth/session.c | 2 ++ + source4/auth/system_session.c | 6 +++--- + 7 files changed, 32 insertions(+), 7 deletions(-) + +diff --git auth/auth_sam_reply.c auth/auth_sam_reply.c +index b5b6362dc93..2e27e5715d1 100644 +--- auth/auth_sam_reply.c ++++ auth/auth_sam_reply.c +@@ -416,7 +416,7 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx, + return NT_STATUS_INVALID_LEVEL; + } + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* +diff --git auth/auth_util.c auth/auth_util.c +index fe01babd107..ec9094d0f15 100644 +--- auth/auth_util.c ++++ auth/auth_util.c +@@ -44,7 +44,7 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + return NULL; + } + +- dst = talloc(mem_ctx, struct auth_session_info); ++ dst = talloc_zero(mem_ctx, struct auth_session_info); + if (dst == NULL) { + DBG_ERR("talloc failed\n"); + TALLOC_FREE(frame); +diff --git librpc/idl/auth.idl librpc/idl/auth.idl +index 1092935b971..f7658cdde28 100644 +--- librpc/idl/auth.idl ++++ librpc/idl/auth.idl +@@ -75,6 +75,26 @@ interface auth + [unique,charset(UTF8),string] char *sanitized_username; + } auth_user_info_unix; + ++ /* ++ * If the user was authenticated with a Kerberos ticket, this indicates ++ * the type of the ticket; TGT, or non-TGT (i.e. service ticket). If ++ * unset, the type is unknown. This indicator is useful for the KDC and ++ * the kpasswd service, which share the same account and keys. By ++ * ensuring it is provided with the appopriate ticket type, each service ++ * avoids accepting a ticket meant for the other. ++ * ++ * The heuristic used to determine the type is the presence or absence ++ * of a REQUESTER_SID buffer in the PAC; we use its presence to assume ++ * we have a TGT. This heuristic will fail for older Samba versions and ++ * Windows prior to Nov. 2021 updates, which lack support for this ++ * buffer. ++ */ ++ typedef enum { ++ TICKET_TYPE_UNKNOWN = 0, ++ TICKET_TYPE_TGT = 1, ++ TICKET_TYPE_NON_TGT = 2 ++ } ticket_type; ++ + /* This is the interim product of the auth subsystem, before + * privileges and local groups are handled */ + typedef [public] struct { +@@ -83,6 +103,7 @@ interface auth + auth_user_info *info; + [noprint] DATA_BLOB user_session_key; + [noprint] DATA_BLOB lm_session_key; ++ ticket_type ticket_type; + } auth_user_info_dc; + + typedef [public] struct { +@@ -112,6 +133,8 @@ interface auth + * We generate this in auth_generate_session_info() + */ + GUID unique_session_token; ++ ++ ticket_type ticket_type; + } auth_session_info; + + typedef [public] struct { +diff --git source4/auth/ntlm/auth_developer.c source4/auth/ntlm/auth_developer.c +index 1823989c68d..6e92252d5c5 100644 +--- source4/auth/ntlm/auth_developer.c ++++ source4/auth/ntlm/auth_developer.c +@@ -76,7 +76,7 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, + } + NT_STATUS_NOT_OK_RETURN(nt_status); + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +diff --git source4/auth/sam.c source4/auth/sam.c +index 8b233bab3ad..7c609655fcb 100644 +--- source4/auth/sam.c ++++ source4/auth/sam.c +@@ -363,7 +363,7 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx, + TALLOC_CTX *tmp_ctx; + struct ldb_message_element *el; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + tmp_ctx = talloc_new(user_info_dc); +diff --git source4/auth/session.c source4/auth/session.c +index 8e44dcd24f1..d6e936dd1f1 100644 +--- source4/auth/session.c ++++ source4/auth/session.c +@@ -222,6 +222,8 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, + + session_info->credentials = NULL; + ++ session_info->ticket_type = user_info_dc->ticket_type; ++ + talloc_steal(mem_ctx, session_info); + *_session_info = session_info; + talloc_free(tmp_ctx); +diff --git source4/auth/system_session.c source4/auth/system_session.c +index 85b8f1c4edb..2518d654e8b 100644 +--- source4/auth/system_session.c ++++ source4/auth/system_session.c +@@ -115,7 +115,7 @@ NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +@@ -191,7 +191,7 @@ static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + user_info_dc->num_sids = 7; +@@ -356,7 +356,7 @@ _PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx, + { + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +-- +2.25.1 + + +From 89c6e36938c27b572573b06d1b35db210bfda99b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:35 +1200 +Subject: [PATCH 95/99] CVE-2022-2031 s4:auth: Use PAC to determine whether + ticket is a TGT + +We use the presence or absence of a REQUESTER_SID PAC buffer to +determine whether the ticket is a TGT. We will later use this to reject +TGTs where a service ticket is expected. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/kerberos/kerberos_pac.c | 44 ++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git source4/auth/kerberos/kerberos_pac.c source4/auth/kerberos/kerberos_pac.c +index 54ef4d61b02..bd0ae20e007 100644 +--- source4/auth/kerberos/kerberos_pac.c ++++ source4/auth/kerberos/kerberos_pac.c +@@ -282,6 +282,28 @@ + return ret; + } + ++static krb5_error_code kerberos_pac_buffer_present(krb5_context context, ++ const krb5_pac pac, ++ uint32_t type) ++{ ++#ifdef SAMBA4_USES_HEIMDAL ++ return krb5_pac_get_buffer(context, pac, type, NULL); ++#else /* MIT */ ++ krb5_error_code ret; ++ krb5_data data; ++ ++ /* ++ * MIT won't let us pass NULL for the data parameter, so we are forced ++ * to allocate a new buffer and then immediately free it. ++ */ ++ ret = krb5_pac_get_buffer(context, pac, type, &data); ++ if (ret == 0) { ++ krb5_free_data_contents(context, &data); ++ } ++ return ret; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} ++ + krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + krb5_pac pac, + krb5_context context, +@@ -414,6 +436,28 @@ krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + return EINVAL; + } + } ++ ++ /* ++ * Based on the presence of a REQUESTER_SID PAC buffer, ascertain ++ * whether the ticket is a TGT. This helps the KDC and kpasswd service ++ * ensure they do not accept tickets meant for the other. ++ * ++ * This heuristic will fail for older Samba versions and Windows prior ++ * to Nov. 2021 updates, which lack support for the REQUESTER_SID PAC ++ * buffer. ++ */ ++ ret = kerberos_pac_buffer_present(context, pac, PAC_TYPE_REQUESTER_SID); ++ if (ret == ENOENT) { ++ /* This probably isn't a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_NON_TGT; ++ } else if (ret != 0) { ++ talloc_free(tmp_ctx); ++ return ret; ++ } else { ++ /* This probably is a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_TGT; ++ } ++ + *user_info_dc = user_info_dc_out; + + return 0; +-- +2.25.1 + + +From d5af460403d3949ba266f5c74f051247cd7ce752 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:53 +1200 +Subject: [PATCH 96/99] CVE-2022-2031 s4:kpasswd: Do not accept TGTs as kpasswd + tickets + +If TGTs can be used as kpasswd tickets, the two-minute lifetime of a +authentic kpasswd ticket may be bypassed. Furthermore, kpasswd tickets +are not supposed to be cached, but using this flaw, a stolen credentials +cache containing a TGT may be used to change that account's password, +and thus is made more valuable to an attacker. + +Since all TGTs should be issued with a REQUESTER_SID PAC buffer, and +service tickets without it, we assert the absence of this buffer to +ensure we're not accepting a TGT. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Fixed knownfail conflicts] +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/kpasswd-helper.c | 20 ++++++++++++++++++++ + source4/kdc/kpasswd-helper.h | 2 ++ + source4/kdc/kpasswd-service-heimdal.c | 13 +++++++++++++ + source4/kdc/kpasswd-service-mit.c | 13 +++++++++++++ + 6 files changed, 48 insertions(+), 8 deletions(-) + +diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc +index 42beccaed58..424a8b81c38 100644 +--- selftest/knownfail_heimdal_kdc ++++ selftest/knownfail_heimdal_kdc +@@ -271,7 +271,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-# +-# Kpasswd tests +-# +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc +index 9fc34e5d8db..0d2f5bab6d2 100644 +--- selftest/knownfail_mit_kdc ++++ selftest/knownfail_mit_kdc +@@ -581,7 +581,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-# +-# Kpasswd tests +-# +-samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git source4/kdc/kpasswd-helper.c source4/kdc/kpasswd-helper.c +index 55a2f5b3bf6..2ffdb79aea5 100644 +--- source4/kdc/kpasswd-helper.c ++++ source4/kdc/kpasswd-helper.c +@@ -241,3 +241,23 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + + return status; + } ++ ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string) ++{ ++ switch(session_info->ticket_type) { ++ case TICKET_TYPE_TGT: ++ /* TGTs are disallowed here. */ ++ *error_string = "A TGT may not be used as a ticket to kpasswd"; ++ return KRB5_KPASSWD_AUTHERROR; ++ case TICKET_TYPE_NON_TGT: ++ /* Non-TGTs are permitted, and expected. */ ++ break; ++ default: ++ /* In case we forgot to set the type. */ ++ *error_string = "Failed to ascertain that ticket to kpasswd is not a TGT"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ ++ return 0; ++} +diff --git source4/kdc/kpasswd-helper.h source4/kdc/kpasswd-helper.h +index 8fad81e0a5d..94a6e2acfdd 100644 +--- source4/kdc/kpasswd-helper.h ++++ source4/kdc/kpasswd-helper.h +@@ -43,4 +43,6 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + enum samPwdChangeReason *reject_reason, + struct samr_DomInfo1 **dominfo); + ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string); + #endif /* _KPASSWD_HELPER_H */ +diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c +index a0352d1ad35..4d009b9eb24 100644 +--- source4/kdc/kpasswd-service-heimdal.c ++++ source4/kdc/kpasswd-service-heimdal.c +@@ -253,6 +253,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -264,6 +265,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case KRB5_KPASSWD_VERS_CHANGEPW: { + DATA_BLOB password = data_blob_null; +diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c +index de4c6f3f622..6b051567b6e 100644 +--- source4/kdc/kpasswd-service-mit.c ++++ source4/kdc/kpasswd-service-mit.c +@@ -332,6 +332,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -344,6 +345,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case 1: { + DATA_BLOB password; +-- +2.25.1 + + +From a6231af1f1c03cd81614332f867916e1748e03a8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 23 Jun 2022 13:59:11 +1200 +Subject: [PATCH 97/99] CVE-2022-2031 testprogs: Add test for short-lived + ticket across an incoming trust + +We ensure that the KDC does not reject a TGS-REQ with our short-lived +TGT over an incoming trust. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton + +[jsutton@samba.org Changed --use-krb5-ccache to -k yes to match + surrounding usage] +--- + testprogs/blackbox/test_kinit_trusts_heimdal.sh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git testprogs/blackbox/test_kinit_trusts_heimdal.sh testprogs/blackbox/test_kinit_trusts_heimdal.sh +index bf0b81a0473..621434eac35 100755 +--- testprogs/blackbox/test_kinit_trusts_heimdal.sh ++++ testprogs/blackbox/test_kinit_trusts_heimdal.sh +@@ -54,6 +54,10 @@ testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppa + test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" -k yes || failed=`expr $failed + 1` + rm -rf $KRB5CCNAME_PATH + ++testit "kinit with password and two minute lifetime" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac --server=krbtgt/$REALM@$TRUST_REALM --lifetime=2m $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` ++test_smbclient "Test login with user kerberos ccache and two minute lifetime" 'ls' "$unc" -k yes || failed=`expr $failed + 1` ++rm -rf $KRB5CCNAME_PATH ++ + # Test with smbclient4 + smbclient="$samba4bindir/smbclient4" + testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` +@@ -94,5 +98,5 @@ testit "wbinfo check outgoing trust pw" $VALGRIND $wbinfo --check-secret --domai + + test_smbclient "Test user login with the changed outgoing secret" 'ls' "$unc" -k yes -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1` + +-rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache ++rm -f $PREFIX/tmpccache $PREFIX/tmppassfile + exit $failed +-- +2.25.1 + + +From f6e1750c4fc966c29c2e0663d3c04e87057fa0c3 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Tue, 7 Jun 2022 09:40:45 -0700 +Subject: [PATCH 98/99] CVE-2022-32742: s4: torture: Add raw.write.bad-write + test. + +Reproduces the test code in: + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Add knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 + + source4/torture/raw/write.c | 89 ++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + create mode 100644 selftest/knownfail.d/bad-write + +diff --git selftest/knownfail.d/bad-write selftest/knownfail.d/bad-write +new file mode 100644 +index 00000000000..5fc16606a13 +--- /dev/null ++++ selftest/knownfail.d/bad-write +@@ -0,0 +1,2 @@ ++^samba3.raw.write.bad-write\(nt4_dc_smb1\) ++^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git source4/torture/raw/write.c source4/torture/raw/write.c +index 0a2f50f425b..661485bb548 100644 +--- source4/torture/raw/write.c ++++ source4/torture/raw/write.c +@@ -25,6 +25,7 @@ + #include "libcli/libcli.h" + #include "torture/util.h" + #include "torture/raw/proto.h" ++#include "libcli/raw/raw_proto.h" + + #define CHECK_STATUS(status, correct) do { \ + if (!NT_STATUS_EQUAL(status, correct)) { \ +@@ -694,6 +695,93 @@ done: + return ret; + } + ++/* ++ test a deliberately bad SMB1 write. ++*/ ++static bool test_bad_write(struct torture_context *tctx, ++ struct smbcli_state *cli) ++{ ++ bool ret = false; ++ int fnum = -1; ++ struct smbcli_request *req = NULL; ++ const char *fname = BASEDIR "\\badwrite.txt"; ++ bool ok = false; ++ ++ if (!torture_setup_dir(cli, BASEDIR)) { ++ torture_fail(tctx, "failed to setup basedir"); ++ } ++ ++ torture_comment(tctx, "Testing RAW_BAD_WRITE\n"); ++ ++ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); ++ if (fnum == -1) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Failed to create %s - %s\n", ++ fname, ++ smbcli_errstr(cli->tree))); ++ } ++ ++ req = smbcli_request_setup(cli->tree, ++ SMBwrite, ++ 5, ++ 0); ++ if (req == NULL) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "talloc fail\n")); ++ } ++ ++ SSVAL(req->out.vwv, VWV(0), fnum); ++ SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */ ++ SIVAL(req->out.vwv, VWV(2), 0); /* offset */ ++ SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */ ++ ++ if (!smbcli_request_send(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Send failed\n")); ++ } ++ ++ if (!smbcli_request_receive(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Reveive failed\n")); ++ } ++ ++ /* ++ * Check for expected error codes. ++ * ntvfs returns NT_STATUS_UNSUCCESSFUL. ++ */ ++ ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) || ++ NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL)); ++ ++ if (!ok) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Should have returned " ++ "NT_STATUS_INVALID_PARAMETER or " ++ "NT_STATUS_UNSUCCESSFUL " ++ "got %s\n", ++ nt_errstr(req->status))); ++ } ++ ++ ret = true; ++ ++done: ++ if (req != NULL) { ++ smbcli_request_destroy(req); ++ } ++ if (fnum != -1) { ++ smbcli_close(cli->tree, fnum); ++ } ++ smb_raw_exit(cli->session); ++ smbcli_deltree(cli->tree, BASEDIR); ++ return ret; ++} ++ + /* + basic testing of write calls + */ +@@ -705,6 +793,7 @@ struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx) + torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock); + torture_suite_add_1smb_test(suite, "write close", test_writeclose); + torture_suite_add_1smb_test(suite, "writex", test_writex); ++ torture_suite_add_1smb_test(suite, "bad-write", test_bad_write); + + return suite; + } +-- +2.25.1 + + +From 7720e0acfd7ea6a2339f3e389aa8dcedd6174095 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 8 Jun 2022 13:50:51 -0700 +Subject: [PATCH 99/99] CVE-2022-32742: s3: smbd: Harden the smbreq_bufrem() + macro. + +Fixes the raw.write.bad-write test. + +NB. We need the two (==0) changes in source3/smbd/reply.c +as the gcc optimizer now knows that the return from +smbreq_bufrem() can never be less than zero. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Remove knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 -- + source3/include/smb_macros.h | 2 +- + source3/smbd/reply.c | 4 ++-- + 3 files changed, 3 insertions(+), 5 deletions(-) + delete mode 100644 selftest/knownfail.d/bad-write + +diff --git selftest/knownfail.d/bad-write selftest/knownfail.d/bad-write +deleted file mode 100644 +index 5fc16606a13..00000000000 +--- selftest/knownfail.d/bad-write ++++ /dev/null +@@ -1,2 +0,0 @@ +-^samba3.raw.write.bad-write\(nt4_dc_smb1\) +-^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git source3/include/smb_macros.h source3/include/smb_macros.h +index def122727f0..de1322a503b 100644 +--- source3/include/smb_macros.h ++++ source3/include/smb_macros.h +@@ -152,7 +152,7 @@ + + /* the remaining number of bytes in smb buffer 'buf' from pointer 'p'. */ + #define smb_bufrem(buf, p) (smb_buflen(buf)-PTR_DIFF(p, smb_buf(buf))) +-#define smbreq_bufrem(req, p) (req->buflen - PTR_DIFF(p, req->buf)) ++#define smbreq_bufrem(req, p) ((req)->buflen < PTR_DIFF((p), (req)->buf) ? 0 : (req)->buflen - PTR_DIFF((p), (req)->buf)) + + + /* Note that chain_size must be available as an extern int to this macro. */ +diff --git source3/smbd/reply.c source3/smbd/reply.c +index f33326564f7..b5abe588910 100644 +--- source3/smbd/reply.c ++++ source3/smbd/reply.c +@@ -342,7 +342,7 @@ size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + *err = NT_STATUS_INVALID_PARAMETER; + return 0; + } +@@ -380,7 +380,7 @@ size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + return 0; + } + +-- +2.25.1 + diff --git a/net/samba413/files/patch-waf-2.0.20 b/net/samba413/files/patch-waf-2.0.20 new file mode 100644 index 000000000000..3c40ea15f0ed --- /dev/null +++ b/net/samba413/files/patch-waf-2.0.20 @@ -0,0 +1,1663 @@ +From 5fc3a71d0f54b176d3cb2e399718d0468507e797 Mon Sep 17 00:00:00 2001 +From: David Mulder +Date: Mon, 24 Aug 2020 13:12:46 -0600 +Subject: [PATCH] waf: upgrade to 2.0.20 + +This contain an important change: +"Fix gccdeps.scan() returning nodes that no longer exist on disk." +https://gitlab.com/ita1024/waf/-/merge_requests/2293 + +Signed-off-by: David Mulder +Reviewed-by: Stefan Metzmacher +--- + buildtools/bin/waf | 2 +- + buildtools/wafsamba/samba_utils.py | 2 +- + buildtools/wafsamba/samba_waf18.py | 3 +- + buildtools/wafsamba/wafsamba.py | 2 +- + third_party/waf/waflib/Configure.py | 25 +- + third_party/waf/waflib/Context.py | 18 +- + third_party/waf/waflib/Options.py | 31 +- + third_party/waf/waflib/Scripting.py | 6 +- + third_party/waf/waflib/Tools/c_aliases.py | 4 +- + third_party/waf/waflib/Tools/c_config.py | 22 +- + third_party/waf/waflib/Tools/c_tests.py | 15 +- + third_party/waf/waflib/Tools/compiler_c.py | 2 +- + third_party/waf/waflib/Tools/compiler_cxx.py | 2 +- + third_party/waf/waflib/Tools/fc.py | 4 +- + third_party/waf/waflib/Tools/irixcc.py | 14 +- + third_party/waf/waflib/Tools/javaw.py | 2 +- + third_party/waf/waflib/Tools/python.py | 2 +- + third_party/waf/waflib/Tools/qt5.py | 6 +- + third_party/waf/waflib/Utils.py | 2 +- + .../extras/clang_compilation_database.py | 172 ++++-- + third_party/waf/waflib/extras/doxygen.py | 1 + + third_party/waf/waflib/extras/gccdeps.py | 15 +- + third_party/waf/waflib/extras/javatest.py | 135 ++++- + third_party/waf/waflib/extras/msvc_pdb.py | 46 ++ + third_party/waf/waflib/extras/pytest.py | 17 +- + third_party/waf/waflib/extras/wafcache.py | 524 ++++++++++++++++++ + 26 files changed, 942 insertions(+), 132 deletions(-) + create mode 100644 third_party/waf/waflib/extras/msvc_pdb.py + create mode 100644 third_party/waf/waflib/extras/wafcache.py + +diff --git buildtools/bin/waf buildtools/bin/waf +index 11ce8e7480a..feabe25d131 100755 +--- buildtools/bin/waf ++++ buildtools/bin/waf +@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. + + import os, sys, inspect + +-VERSION="2.0.18" ++VERSION="2.0.20" + REVISION="x" + GIT="x" + INSTALL="x" +diff --git buildtools/wafsamba/samba_utils.py buildtools/wafsamba/samba_utils.py +index 4afee249d33..0587f525aff 100644 +--- buildtools/wafsamba/samba_utils.py ++++ buildtools/wafsamba/samba_utils.py +@@ -459,7 +459,7 @@ def RECURSE(ctx, directory): + return + visited_dirs.add(key) + relpath = os.path.relpath(abspath, ctx.path.abspath()) +- if ctxclass in ['tmp', 'OptionsContext', 'ConfigurationContext', 'BuildContext']: ++ if ctxclass in ['tmp', 'OptionsContext', 'ConfigurationContext', 'BuildContext', 'ClangDbContext']: + return ctx.recurse(relpath) + if 'waflib.extras.compat15' in sys.modules: + return ctx.recurse(relpath) +diff --git buildtools/wafsamba/samba_waf18.py buildtools/wafsamba/samba_waf18.py +index c0bb6bfcf55..ecf3891f175 100644 +--- buildtools/wafsamba/samba_waf18.py ++++ buildtools/wafsamba/samba_waf18.py +@@ -5,6 +5,7 @@ from waflib import Build, Configure, Node, Utils, Options, Logs, TaskGen + from waflib import ConfigSet + from waflib.TaskGen import feature, after + from waflib.Configure import conf, ConfigurationContext ++from waflib.extras import clang_compilation_database + + from waflib.Tools.flex import decide_ext + +@@ -37,7 +38,7 @@ TaskGen.declare_chain( + ) + + +-for y in (Build.BuildContext, Build.CleanContext, Build.InstallContext, Build.UninstallContext, Build.ListContext): ++for y in (Build.BuildContext, Build.CleanContext, Build.InstallContext, Build.UninstallContext, Build.ListContext, clang_compilation_database.ClangDbContext): + class tmp(y): + variant = 'default' + +diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py +index 7827d374654..9f6ee4f5c7f 100644 +--- buildtools/wafsamba/wafsamba.py ++++ buildtools/wafsamba/wafsamba.py +@@ -38,7 +38,7 @@ LIB_PATH="shared" + + os.environ['PYTHONUNBUFFERED'] = '1' + +-if Context.HEXVERSION not in (0x2001200,): ++if Context.HEXVERSION not in (0x2001400,): + Logs.error(''' + Please use the version of waf that comes with Samba, not + a system installed version. See http://wiki.samba.org/index.php/Waf +diff --git third_party/waf/waflib/Configure.py third_party/waf/waflib/Configure.py +index 5762eb66954..e7333948489 100644 +--- third_party/waf/waflib/Configure.py ++++ third_party/waf/waflib/Configure.py +@@ -508,23 +508,27 @@ def find_binary(self, filenames, exts, paths): + @conf + def run_build(self, *k, **kw): + """ +- Create a temporary build context to execute a build. A reference to that build +- context is kept on self.test_bld for debugging purposes, and you should not rely +- on it too much (read the note on the cache below). +- The parameters given in the arguments to this function are passed as arguments for +- a single task generator created in the build. Only three parameters are obligatory: ++ Create a temporary build context to execute a build. A temporary reference to that build ++ context is kept on self.test_bld for debugging purposes. ++ The arguments to this function are passed to a single task generator for that build. ++ Only three parameters are mandatory: + + :param features: features to pass to a task generator created in the build + :type features: list of string + :param compile_filename: file to create for the compilation (default: *test.c*) + :type compile_filename: string +- :param code: code to write in the filename to compile ++ :param code: input file contents + :type code: string + +- Though this function returns *0* by default, the build may set an attribute named *retval* on the ++ Though this function returns *0* by default, the build may bind attribute named *retval* on the + build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. + +- This function also features a cache which can be enabled by the following option:: ++ The temporary builds creates a temporary folder; the name of that folder is calculated ++ by hashing input arguments to this function, with the exception of :py:class:`waflib.ConfigSet.ConfigSet` ++ objects which are used for both reading and writing values. ++ ++ This function also features a cache which is disabled by default; that cache relies ++ on the hash value calculated as indicated above:: + + def options(opt): + opt.add_option('--confcache', dest='confcache', default=0, +@@ -538,7 +542,10 @@ def run_build(self, *k, **kw): + buf = [] + for key in sorted(kw.keys()): + v = kw[key] +- if hasattr(v, '__call__'): ++ if isinstance(v, ConfigSet.ConfigSet): ++ # values are being written to, so they are excluded from contributing to the hash ++ continue ++ elif hasattr(v, '__call__'): + buf.append(Utils.h_fun(v)) + else: + buf.append(str(v)) +diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py +index e3305fa3341..3f1b4fa48ab 100644 +--- third_party/waf/waflib/Context.py ++++ third_party/waf/waflib/Context.py +@@ -6,20 +6,30 @@ + Classes and functions enabling the command system + """ + +-import os, re, imp, sys ++import os, re, sys + from waflib import Utils, Errors, Logs + import waflib.Node + ++if sys.hexversion > 0x3040000: ++ import types ++ class imp(object): ++ new_module = lambda x: types.ModuleType(x) ++else: ++ import imp ++ + # the following 3 constants are updated on each new release (do not touch) +-HEXVERSION=0x2001200 ++HEXVERSION=0x2001400 + """Constant updated on new releases""" + +-WAFVERSION="2.0.18" ++WAFVERSION="2.0.20" + """Constant updated on new releases""" + +-WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" ++WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4" + """Git revision when the waf version is updated""" + ++WAFNAME="waf" ++"""Application name displayed on --help""" ++ + ABI = 20 + """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" + +diff --git third_party/waf/waflib/Options.py third_party/waf/waflib/Options.py +index ad802d4b905..d4104917c82 100644 +--- third_party/waf/waflib/Options.py ++++ third_party/waf/waflib/Options.py +@@ -44,7 +44,7 @@ class opt_parser(optparse.OptionParser): + """ + def __init__(self, ctx, allow_unknown=False): + optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False, +- version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION)) ++ version='%s %s (%s)' % (Context.WAFNAME, Context.WAFVERSION, Context.WAFREVISION)) + self.formatter.width = Logs.get_term_cols() + self.ctx = ctx + self.allow_unknown = allow_unknown +@@ -62,6 +62,21 @@ class opt_parser(optparse.OptionParser): + else: + self.error(str(e)) + ++ def _process_long_opt(self, rargs, values): ++ # --custom-option=-ftxyz is interpreted as -f -t... see #2280 ++ if self.allow_unknown: ++ back = [] + rargs ++ try: ++ optparse.OptionParser._process_long_opt(self, rargs, values) ++ except optparse.BadOptionError: ++ while rargs: ++ rargs.pop() ++ rargs.extend(back) ++ rargs.pop(0) ++ raise ++ else: ++ optparse.OptionParser._process_long_opt(self, rargs, values) ++ + def print_usage(self, file=None): + return self.print_help(file) + +@@ -96,11 +111,11 @@ class opt_parser(optparse.OptionParser): + lst.sort() + ret = '\n'.join(lst) + +- return '''waf [commands] [options] ++ return '''%s [commands] [options] + +-Main commands (example: ./waf build -j4) ++Main commands (example: ./%s build -j4) + %s +-''' % ret ++''' % (Context.WAFNAME, Context.WAFNAME, ret) + + + class OptionsContext(Context.Context): +@@ -141,9 +156,9 @@ class OptionsContext(Context.Context): + gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') + gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') + +- gr.add_option('--no-lock-in-run', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') +- gr.add_option('--no-lock-in-out', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') +- gr.add_option('--no-lock-in-top', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') ++ gr.add_option('--no-lock-in-run', action='store_true', default=os.environ.get('NO_LOCK_IN_RUN', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') ++ gr.add_option('--no-lock-in-out', action='store_true', default=os.environ.get('NO_LOCK_IN_OUT', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') ++ gr.add_option('--no-lock-in-top', action='store_true', default=os.environ.get('NO_LOCK_IN_TOP', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') + + default_prefix = getattr(Context.g_module, 'default_prefix', os.environ.get('PREFIX')) + if not default_prefix: +@@ -282,6 +297,8 @@ class OptionsContext(Context.Context): + elif arg != 'options': + commands.append(arg) + ++ if options.jobs < 1: ++ options.jobs = 1 + for name in 'top out destdir prefix bindir libdir'.split(): + # those paths are usually expanded from Context.launch_dir + if getattr(options, name, None): +diff --git third_party/waf/waflib/Scripting.py third_party/waf/waflib/Scripting.py +index 68dccf29ce0..da83a2166a1 100644 +--- third_party/waf/waflib/Scripting.py ++++ third_party/waf/waflib/Scripting.py +@@ -306,7 +306,7 @@ def distclean(ctx): + + # remove a build folder, if any + cur = '.' +- if ctx.options.no_lock_in_top: ++ if os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top: + cur = ctx.options.out + + try: +@@ -333,9 +333,9 @@ def distclean(ctx): + remove_and_log(env.out_dir, shutil.rmtree) + + env_dirs = [env.out_dir] +- if not ctx.options.no_lock_in_top: ++ if not (os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top): + env_dirs.append(env.top_dir) +- if not ctx.options.no_lock_in_run: ++ if not (os.environ.get('NO_LOCK_IN_RUN') or ctx.options.no_lock_in_run): + env_dirs.append(env.run_dir) + for k in env_dirs: + p = os.path.join(k, Options.lockfile) +diff --git third_party/waf/waflib/Tools/c_aliases.py third_party/waf/waflib/Tools/c_aliases.py +index 985e048bdb7..928cfe29caa 100644 +--- third_party/waf/waflib/Tools/c_aliases.py ++++ third_party/waf/waflib/Tools/c_aliases.py +@@ -38,7 +38,7 @@ def sniff_features(**kw): + :return: the list of features for a task generator processing the source files + :rtype: list of string + """ +- exts = get_extensions(kw['source']) ++ exts = get_extensions(kw.get('source', [])) + typ = kw['typ'] + feats = [] + +@@ -72,7 +72,7 @@ def sniff_features(**kw): + feats.append(x + typ) + will_link = True + if not will_link and not kw.get('features', []): +- raise Errors.WafError('Cannot link from %r, try passing eg: features="c cprogram"?' % kw) ++ raise Errors.WafError('Unable to determine how to link %r, try adding eg: features="c cshlib"?' % kw) + return feats + + def set_features(kw, typ): +diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py +index 80580cc9fcb..98187fac2e2 100644 +--- third_party/waf/waflib/Tools/c_config.py ++++ third_party/waf/waflib/Tools/c_config.py +@@ -86,6 +86,10 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No + :type uselib_store: string + :param env: config set or conf.env by default + :type env: :py:class:`waflib.ConfigSet.ConfigSet` ++ :param force_static: force usage of static libraries ++ :type force_static: bool default False ++ :param posix: usage of POSIX mode for shlex lexical analiysis library ++ :type posix: bool default True + """ + + assert(isinstance(line, str)) +@@ -103,6 +107,8 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No + lex.commenters = '' + lst = list(lex) + ++ so_re = re.compile(r"\.so(?:\.[0-9]+)*$") ++ + # append_unique is not always possible + # for example, apple flags may require both -arch i386 and -arch ppc + uselib = uselib_store +@@ -144,7 +150,7 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No + elif x.startswith('-std='): + prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS' + app(prefix, x) +- elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'): ++ elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie', '-flto', '-fno-lto'): + app('CFLAGS', x) + app('CXXFLAGS', x) + app('LINKFLAGS', x) +@@ -180,7 +186,7 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No + app('CFLAGS', tmp) + app('CXXFLAGS', tmp) + app('LINKFLAGS', tmp) +- elif x.endswith(('.a', '.so', '.dylib', '.lib')): ++ elif x.endswith(('.a', '.dylib', '.lib')) or so_re.search(x): + appu('LINKFLAGS', x) # not cool, #762 + else: + self.to_log('Unhandled flag %r' % x) +@@ -246,6 +252,8 @@ def exec_cfg(self, kw): + * if modversion is given, then return the module version + * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable + ++ :param path: the **-config program to use** ++ :type path: list of string + :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) + :type atleast_pkgconfig_version: string + :param package: package name, for example *gtk+-2.0* +@@ -260,6 +268,12 @@ def exec_cfg(self, kw): + :type variables: list of string + :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) + :type define_variable: dict(string: string) ++ :param pkg_config_path: paths where pkg-config should search for .pc config files (overrides env.PKG_CONFIG_PATH if exists) ++ :type pkg_config_path: string, list of directories separated by colon ++ :param force_static: force usage of static libraries ++ :type force_static: bool default False ++ :param posix: usage of POSIX mode for shlex lexical analiysis library ++ :type posix: bool default True + """ + + path = Utils.to_list(kw['path']) +@@ -334,6 +348,7 @@ def check_cfg(self, *k, **kw): + """ + Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). + This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` ++ so check exec_cfg parameters descriptions for more details on kw passed + + A few examples:: + +@@ -1267,10 +1282,11 @@ def multicheck(self, *k, **kw): + tasks = [] + + id_to_task = {} +- for dct in k: ++ for counter, dct in enumerate(k): + x = Task.classes['cfgtask'](bld=bld, env=None) + tasks.append(x) + x.args = dct ++ x.args['multicheck_counter'] = counter + x.bld = bld + x.conf = self + x.args = dct +diff --git third_party/waf/waflib/Tools/c_tests.py third_party/waf/waflib/Tools/c_tests.py +index 7a4094f2450..bdd186c6bc4 100644 +--- third_party/waf/waflib/Tools/c_tests.py ++++ third_party/waf/waflib/Tools/c_tests.py +@@ -180,9 +180,15 @@ def check_large_file(self, **kw): + ######################################################################################## + + ENDIAN_FRAGMENT = ''' ++#ifdef _MSC_VER ++#define testshlib_EXPORT __declspec(dllexport) ++#else ++#define testshlib_EXPORT ++#endif ++ + short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +-int use_ascii (int i) { ++int testshlib_EXPORT use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +@@ -208,12 +214,12 @@ class grep_for_endianness(Task.Task): + return -1 + + @feature('grep_for_endianness') +-@after_method('process_source') ++@after_method('apply_link') + def grep_for_endianness_fun(self): + """ + Used by the endianness configuration test + """ +- self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) ++ self.create_task('grep_for_endianness', self.link_task.outputs[0]) + + @conf + def check_endianness(self): +@@ -223,7 +229,8 @@ def check_endianness(self): + tmp = [] + def check_msg(self): + return tmp[0] +- self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', ++ ++ self.check(fragment=ENDIAN_FRAGMENT, features='c cshlib grep_for_endianness', + msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, + okmsg=check_msg, confcache=None) + return tmp[0] +diff --git third_party/waf/waflib/Tools/compiler_c.py third_party/waf/waflib/Tools/compiler_c.py +index 2dba3f82704..931dc57efec 100644 +--- third_party/waf/waflib/Tools/compiler_c.py ++++ third_party/waf/waflib/Tools/compiler_c.py +@@ -37,7 +37,7 @@ from waflib.Logs import debug + + c_compiler = { + 'win32': ['msvc', 'gcc', 'clang'], +-'cygwin': ['gcc'], ++'cygwin': ['gcc', 'clang'], + 'darwin': ['clang', 'gcc'], + 'aix': ['xlc', 'gcc', 'clang'], + 'linux': ['gcc', 'clang', 'icc'], +diff --git third_party/waf/waflib/Tools/compiler_cxx.py third_party/waf/waflib/Tools/compiler_cxx.py +index 1af65a226dc..09fca7e4dc6 100644 +--- third_party/waf/waflib/Tools/compiler_cxx.py ++++ third_party/waf/waflib/Tools/compiler_cxx.py +@@ -38,7 +38,7 @@ from waflib.Logs import debug + + cxx_compiler = { + 'win32': ['msvc', 'g++', 'clang++'], +-'cygwin': ['g++'], ++'cygwin': ['g++', 'clang++'], + 'darwin': ['clang++', 'g++'], + 'aix': ['xlc++', 'g++', 'clang++'], + 'linux': ['g++', 'clang++', 'icpc'], +diff --git third_party/waf/waflib/Tools/fc.py third_party/waf/waflib/Tools/fc.py +index fd4d39c90ae..7fbd76d3650 100644 +--- third_party/waf/waflib/Tools/fc.py ++++ third_party/waf/waflib/Tools/fc.py +@@ -13,8 +13,8 @@ from waflib.TaskGen import extension + from waflib.Configure import conf + + ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES', 'FCPPFLAGS']) +-ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +-ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) ++ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS']) ++ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS']) + ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) + + @extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08') +diff --git third_party/waf/waflib/Tools/irixcc.py third_party/waf/waflib/Tools/irixcc.py +index c3ae1ac915c..0335c13cb61 100644 +--- third_party/waf/waflib/Tools/irixcc.py ++++ third_party/waf/waflib/Tools/irixcc.py +@@ -13,22 +13,11 @@ from waflib.Configure import conf + @conf + def find_irixcc(conf): + v = conf.env +- cc = None +- if v.CC: +- cc = v.CC +- elif 'CC' in conf.environ: +- cc = conf.environ['CC'] +- if not cc: +- cc = conf.find_program('cc', var='CC') +- if not cc: +- conf.fatal('irixcc was not found') +- ++ cc = conf.find_program('cc', var='CC') + try: + conf.cmd_and_log(cc + ['-version']) + except Errors.WafError: + conf.fatal('%r -version could not be executed' % cc) +- +- v.CC = cc + v.CC_NAME = 'irix' + + @conf +@@ -57,7 +46,6 @@ def irixcc_common_flags(conf): + + def configure(conf): + conf.find_irixcc() +- conf.find_cpp() + conf.find_ar() + conf.irixcc_common_flags() + conf.cc_load_tools() +diff --git third_party/waf/waflib/Tools/javaw.py third_party/waf/waflib/Tools/javaw.py +index ceb08c28c87..b7f5dd1f87f 100644 +--- third_party/waf/waflib/Tools/javaw.py ++++ third_party/waf/waflib/Tools/javaw.py +@@ -251,7 +251,7 @@ def use_javac_files(self): + base_node = tg.path.get_bld() + + self.use_lst.append(base_node.abspath()) +- self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) ++ self.javac_task.dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) + + for tsk in tg.tasks: + self.javac_task.set_run_after(tsk) +diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py +index 7c45a76ffd2..b1c8dd01285 100644 +--- third_party/waf/waflib/Tools/python.py ++++ third_party/waf/waflib/Tools/python.py +@@ -620,7 +620,7 @@ def configure(conf): + v.PYO = getattr(Options.options, 'pyo', 1) + + try: +- v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip() ++ v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import sys\ntry:\n print(sys.implementation.cache_tag)\nexcept AttributeError:\n import imp\n print(imp.get_tag())\n"]).strip() + except Errors.WafError: + pass + +diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py +index 287c25374a4..99e021bae61 100644 +--- third_party/waf/waflib/Tools/qt5.py ++++ third_party/waf/waflib/Tools/qt5.py +@@ -482,8 +482,8 @@ def configure(self): + self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') + + # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? +- frag = '#include \nint main(int argc, char **argv) {return 0;}\n' +- uses = 'QT5CORE QT5WIDGETS QT5GUI' ++ frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' ++ uses = 'QT5CORE' + for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]: + msg = 'See if Qt files compile ' + if flag: +@@ -499,7 +499,7 @@ def configure(self): + + # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ + if Utils.unversioned_sys_platform() == 'freebsd': +- frag = '#include \nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n' ++ frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' + try: + self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?') + except self.errors.ConfigurationError: +diff --git third_party/waf/waflib/Utils.py third_party/waf/waflib/Utils.py +index 7472226da58..fc64fa05154 100644 +--- third_party/waf/waflib/Utils.py ++++ third_party/waf/waflib/Utils.py +@@ -891,7 +891,7 @@ def run_prefork_process(cmd, kwargs, cargs): + """ + Delegates process execution to a pre-forked process instance. + """ +- if not 'env' in kwargs: ++ if not kwargs.get('env'): + kwargs['env'] = dict(os.environ) + try: + obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs])) +diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py +index 4d9b5e275ae..ff71f22ecfd 100644 +--- third_party/waf/waflib/extras/clang_compilation_database.py ++++ third_party/waf/waflib/extras/clang_compilation_database.py +@@ -1,6 +1,7 @@ + #!/usr/bin/env python + # encoding: utf-8 + # Christoph Koke, 2013 ++# Alibek Omarov, 2019 + + """ + Writes the c and cpp compile commands into build/compile_commands.json +@@ -8,14 +9,23 @@ see http://clang.llvm.org/docs/JSONCompilationDatabase.html + + Usage: + +- def configure(conf): +- conf.load('compiler_cxx') +- ... +- conf.load('clang_compilation_database') ++ Load this tool in `options` to be able to generate database ++ by request in command-line and before build: ++ ++ $ waf clangdb ++ ++ def options(opt): ++ opt.load('clang_compilation_database') ++ ++ Otherwise, load only in `configure` to generate it always before build. ++ ++ def configure(conf): ++ conf.load('compiler_cxx') ++ ... ++ conf.load('clang_compilation_database') + """ + +-import sys, os, json, shlex, pipes +-from waflib import Logs, TaskGen, Task ++from waflib import Logs, TaskGen, Task, Build, Scripting + + Task.Task.keep_last_cmd = True + +@@ -23,63 +33,103 @@ Task.Task.keep_last_cmd = True + @TaskGen.after_method('process_use') + def collect_compilation_db_tasks(self): + "Add a compilation database entry for compiled tasks" +- try: +- clang_db = self.bld.clang_compilation_database_tasks +- except AttributeError: +- clang_db = self.bld.clang_compilation_database_tasks = [] +- self.bld.add_post_fun(write_compilation_database) ++ if not isinstance(self.bld, ClangDbContext): ++ return + + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) + for task in getattr(self, 'compiled_tasks', []): + if isinstance(task, tup): +- clang_db.append(task) +- +-def write_compilation_database(ctx): +- "Write the clang compilation database as JSON" +- database_file = ctx.bldnode.make_node('compile_commands.json') +- Logs.info('Build commands will be stored in %s', database_file.path_from(ctx.path)) +- try: +- root = json.load(database_file) +- except IOError: +- root = [] +- clang_db = dict((x['file'], x) for x in root) +- for task in getattr(ctx, 'clang_compilation_database_tasks', []): ++ self.bld.clang_compilation_database_tasks.append(task) ++ ++class ClangDbContext(Build.BuildContext): ++ '''generates compile_commands.json by request''' ++ cmd = 'clangdb' ++ clang_compilation_database_tasks = [] ++ ++ def write_compilation_database(self): ++ """ ++ Write the clang compilation database as JSON ++ """ ++ database_file = self.bldnode.make_node('compile_commands.json') ++ Logs.info('Build commands will be stored in %s', database_file.path_from(self.path)) + try: +- cmd = task.last_cmd +- except AttributeError: +- continue +- directory = getattr(task, 'cwd', ctx.variant_dir) +- f_node = task.inputs[0] +- filename = os.path.relpath(f_node.abspath(), directory) +- entry = { +- "directory": directory, +- "arguments": cmd, +- "file": filename, +- } +- clang_db[filename] = entry +- root = list(clang_db.values()) +- database_file.write(json.dumps(root, indent=2)) +- +-# Override the runnable_status function to do a dummy/dry run when the file doesn't need to be compiled. +-# This will make sure compile_commands.json is always fully up to date. +-# Previously you could end up with a partial compile_commands.json if the build failed. +-for x in ('c', 'cxx'): +- if x not in Task.classes: +- continue +- +- t = Task.classes[x] +- +- def runnable_status(self): +- def exec_command(cmd, **kw): +- pass +- +- run_status = self.old_runnable_status() +- if run_status == Task.SKIP_ME: +- setattr(self, 'old_exec_command', getattr(self, 'exec_command', None)) +- setattr(self, 'exec_command', exec_command) +- self.run() +- setattr(self, 'exec_command', getattr(self, 'old_exec_command', None)) +- return run_status +- +- setattr(t, 'old_runnable_status', getattr(t, 'runnable_status', None)) +- setattr(t, 'runnable_status', runnable_status) ++ root = database_file.read_json() ++ except IOError: ++ root = [] ++ clang_db = dict((x['file'], x) for x in root) ++ for task in self.clang_compilation_database_tasks: ++ try: ++ cmd = task.last_cmd ++ except AttributeError: ++ continue ++ f_node = task.inputs[0] ++ filename = f_node.path_from(task.get_cwd()) ++ entry = { ++ "directory": task.get_cwd().abspath(), ++ "arguments": cmd, ++ "file": filename, ++ } ++ clang_db[filename] = entry ++ root = list(clang_db.values()) ++ database_file.write_json(root) ++ ++ def execute(self): ++ """ ++ Build dry run ++ """ ++ self.restore() ++ ++ if not self.all_envs: ++ self.load_envs() ++ ++ self.recurse([self.run_dir]) ++ self.pre_build() ++ ++ # we need only to generate last_cmd, so override ++ # exec_command temporarily ++ def exec_command(self, *k, **kw): ++ return 0 ++ ++ for g in self.groups: ++ for tg in g: ++ try: ++ f = tg.post ++ except AttributeError: ++ pass ++ else: ++ f() ++ ++ if isinstance(tg, Task.Task): ++ lst = [tg] ++ else: lst = tg.tasks ++ for tsk in lst: ++ tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) ++ if isinstance(tsk, tup): ++ old_exec = tsk.exec_command ++ tsk.exec_command = exec_command ++ tsk.run() ++ tsk.exec_command = old_exec ++ ++ self.write_compilation_database() ++ ++EXECUTE_PATCHED = False ++def patch_execute(): ++ global EXECUTE_PATCHED ++ ++ if EXECUTE_PATCHED: ++ return ++ ++ def new_execute_build(self): ++ """ ++ Invoke clangdb command before build ++ """ ++ if self.cmd.startswith('build'): ++ Scripting.run_command('clangdb') ++ ++ old_execute_build(self) ++ ++ old_execute_build = getattr(Build.BuildContext, 'execute_build', None) ++ setattr(Build.BuildContext, 'execute_build', new_execute_build) ++ EXECUTE_PATCHED = True ++ ++patch_execute() +diff --git third_party/waf/waflib/extras/doxygen.py third_party/waf/waflib/extras/doxygen.py +index 20cd9e1a852..de75bc2738a 100644 +--- third_party/waf/waflib/extras/doxygen.py ++++ third_party/waf/waflib/extras/doxygen.py +@@ -69,6 +69,7 @@ def parse_doxy(txt): + class doxygen(Task.Task): + vars = ['DOXYGEN', 'DOXYFLAGS'] + color = 'BLUE' ++ ext_in = [ '.py', '.c', '.h', '.java', '.pb.cc' ] + + def runnable_status(self): + ''' +diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py +index bfabe72e6fd..c3a809e252a 100644 +--- third_party/waf/waflib/extras/gccdeps.py ++++ third_party/waf/waflib/extras/gccdeps.py +@@ -27,7 +27,7 @@ if not c_preproc.go_absolute: + gccdeps_flags = ['-MMD'] + + # Third-party tools are allowed to add extra names in here with append() +-supported_compilers = ['gcc', 'icc', 'clang'] ++supported_compilers = ['gas', 'gcc', 'icc', 'clang'] + + def scan(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: +@@ -175,14 +175,14 @@ def wrap_compiled_task(classname): + derived_class.scan = scan + derived_class.sig_implicit_deps = sig_implicit_deps + +-for k in ('c', 'cxx'): ++for k in ('asm', 'c', 'cxx'): + if k in Task.classes: + wrap_compiled_task(k) + + @before_method('process_source') + @feature('force_gccdeps') + def force_gccdeps(self): +- self.env.ENABLE_GCCDEPS = ['c', 'cxx'] ++ self.env.ENABLE_GCCDEPS = ['asm', 'c', 'cxx'] + + def configure(conf): + # in case someone provides a --enable-gccdeps command-line option +@@ -191,6 +191,15 @@ def configure(conf): + + global gccdeps_flags + flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags ++ if conf.env.ASM_NAME in supported_compilers: ++ try: ++ conf.check(fragment='', features='asm force_gccdeps', asflags=flags, compile_filename='test.S', msg='Checking for asm flags %r' % ''.join(flags)) ++ except Errors.ConfigurationError: ++ pass ++ else: ++ conf.env.append_value('ASFLAGS', flags) ++ conf.env.append_unique('ENABLE_GCCDEPS', 'asm') ++ + if conf.env.CC_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags)) +diff --git third_party/waf/waflib/extras/javatest.py third_party/waf/waflib/extras/javatest.py +index 979b8d8242d..76d40edf250 100755 +--- third_party/waf/waflib/extras/javatest.py ++++ third_party/waf/waflib/extras/javatest.py +@@ -1,6 +1,6 @@ + #! /usr/bin/env python + # encoding: utf-8 +-# Federico Pellegrin, 2017 (fedepell) ++# Federico Pellegrin, 2019 (fedepell) + + """ + Provides Java Unit test support using :py:class:`waflib.Tools.waf_unit_test.utest` +@@ -11,6 +11,10 @@ standard waf unit test environment. It has been tested with TestNG and JUnit + but should be easily expandable to other frameworks given the flexibility of + ut_str provided by the standard waf unit test environment. + ++The extra takes care also of managing non-java dependencies (ie. C/C++ libraries ++using JNI or Python modules via JEP) and setting up the environment needed to run ++them. ++ + Example usage: + + def options(opt): +@@ -20,15 +24,15 @@ def configure(conf): + conf.load('java javatest') + + def build(bld): +- ++ + [ ... mainprog is built here ... ] + + bld(features = 'javac javatest', +- srcdir = 'test/', +- outdir = 'test', ++ srcdir = 'test/', ++ outdir = 'test', + sourcepath = ['test'], +- classpath = [ 'src' ], +- basedir = 'test', ++ classpath = [ 'src' ], ++ basedir = 'test', + use = ['JAVATEST', 'mainprog'], # mainprog is the program being tested in src/ + ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}', + jtest_source = bld.path.ant_glob('test/*.xml'), +@@ -53,10 +57,107 @@ The runner class presence on the system is checked for at configuration stage. + """ + + import os +-from waflib import Task, TaskGen, Options ++from waflib import Task, TaskGen, Options, Errors, Utils, Logs ++from waflib.Tools import ccroot ++ ++JAR_RE = '**/*' ++ ++def _process_use_rec(self, name): ++ """ ++ Recursively process ``use`` for task generator with name ``name``.. ++ Used by javatest_process_use. ++ """ ++ if name in self.javatest_use_not or name in self.javatest_use_seen: ++ return ++ try: ++ tg = self.bld.get_tgen_by_name(name) ++ except Errors.WafError: ++ self.javatest_use_not.add(name) ++ return ++ ++ self.javatest_use_seen.append(name) ++ tg.post() ++ ++ for n in self.to_list(getattr(tg, 'use', [])): ++ _process_use_rec(self, n) ++ ++@TaskGen.feature('javatest') ++@TaskGen.after_method('process_source', 'apply_link', 'use_javac_files') ++def javatest_process_use(self): ++ """ ++ Process the ``use`` attribute which contains a list of task generator names and store ++ paths that later is used to populate the unit test runtime environment. ++ """ ++ self.javatest_use_not = set() ++ self.javatest_use_seen = [] ++ self.javatest_libpaths = [] # strings or Nodes ++ self.javatest_pypaths = [] # strings or Nodes ++ self.javatest_dep_nodes = [] ++ ++ names = self.to_list(getattr(self, 'use', [])) ++ for name in names: ++ _process_use_rec(self, name) ++ ++ def extend_unique(lst, varlst): ++ ext = [] ++ for x in varlst: ++ if x not in lst: ++ ext.append(x) ++ lst.extend(ext) ++ ++ # Collect type specific info needed to construct a valid runtime environment ++ # for the test. ++ for name in self.javatest_use_seen: ++ tg = self.bld.get_tgen_by_name(name) ++ ++ # Python-Java embedding crosstools such as JEP ++ if 'py' in tg.features: ++ # Python dependencies are added to PYTHONPATH ++ pypath = getattr(tg, 'install_from', tg.path) ++ ++ if 'buildcopy' in tg.features: ++ # Since buildcopy is used we assume that PYTHONPATH in build should be used, ++ # not source ++ extend_unique(self.javatest_pypaths, [pypath.get_bld().abspath()]) ++ ++ # Add buildcopy output nodes to dependencies ++ extend_unique(self.javatest_dep_nodes, [o for task in getattr(tg, 'tasks', []) for o in getattr(task, 'outputs', [])]) ++ else: ++ # If buildcopy is not used, depend on sources instead ++ extend_unique(self.javatest_dep_nodes, tg.source) ++ extend_unique(self.javatest_pypaths, [pypath.abspath()]) ++ ++ ++ if getattr(tg, 'link_task', None): ++ # For tasks with a link_task (C, C++, D et.c.) include their library paths: ++ if not isinstance(tg.link_task, ccroot.stlink_task): ++ extend_unique(self.javatest_dep_nodes, tg.link_task.outputs) ++ extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH) ++ ++ if 'pyext' in tg.features: ++ # If the taskgen is extending Python we also want to add the interpreter libpath. ++ extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH_PYEXT) ++ else: ++ # Only add to libpath if the link task is not a Python extension ++ extend_unique(self.javatest_libpaths, [tg.link_task.outputs[0].parent.abspath()]) ++ ++ if 'javac' in tg.features or 'jar' in tg.features: ++ if hasattr(tg, 'jar_task'): ++ # For Java JAR tasks depend on generated JAR ++ extend_unique(self.javatest_dep_nodes, tg.jar_task.outputs) ++ else: ++ # For Java non-JAR ones we need to glob generated files (Java output files are not predictable) ++ if hasattr(tg, 'outdir'): ++ base_node = tg.outdir ++ else: ++ base_node = tg.path.get_bld() ++ ++ self.javatest_dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) ++ ++ + + @TaskGen.feature('javatest') +-@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath') ++@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath', 'javatest_process_use') + def make_javatest(self): + """ + Creates a ``utest`` task with a populated environment for Java Unit test execution +@@ -65,6 +166,9 @@ def make_javatest(self): + tsk = self.create_task('utest') + tsk.set_run_after(self.javac_task) + ++ # Dependencies from recursive use analysis ++ tsk.dep_nodes.extend(self.javatest_dep_nodes) ++ + # Put test input files as waf_unit_test relies on that for some prints and log generation + # If jtest_source is there, this is specially useful for passing XML for TestNG + # that contain test specification, use that as inputs, otherwise test sources +@@ -97,6 +201,21 @@ def make_javatest(self): + + if not hasattr(self, 'ut_env'): + self.ut_env = dict(os.environ) ++ def add_paths(var, lst): ++ # Add list of paths to a variable, lst can contain strings or nodes ++ lst = [ str(n) for n in lst ] ++ Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst) ++ self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '') ++ ++ add_paths('PYTHONPATH', self.javatest_pypaths) ++ ++ if Utils.is_win32: ++ add_paths('PATH', self.javatest_libpaths) ++ elif Utils.unversioned_sys_platform() == 'darwin': ++ add_paths('DYLD_LIBRARY_PATH', self.javatest_libpaths) ++ add_paths('LD_LIBRARY_PATH', self.javatest_libpaths) ++ else: ++ add_paths('LD_LIBRARY_PATH', self.javatest_libpaths) + + def configure(ctx): + cp = ctx.env.CLASSPATH or '.' +diff --git third_party/waf/waflib/extras/msvc_pdb.py third_party/waf/waflib/extras/msvc_pdb.py +new file mode 100644 +index 00000000000..077656b4f7e +--- /dev/null ++++ third_party/waf/waflib/extras/msvc_pdb.py +@@ -0,0 +1,46 @@ ++#!/usr/bin/env python ++# encoding: utf-8 ++# Rafaël Kooi 2019 ++ ++from waflib import TaskGen ++ ++@TaskGen.feature('c', 'cxx', 'fc') ++@TaskGen.after_method('propagate_uselib_vars') ++def add_pdb_per_object(self): ++ """For msvc/fortran, specify a unique compile pdb per object, to work ++ around LNK4099. Flags are updated with a unique /Fd flag based on the ++ task output name. This is separate from the link pdb. ++ """ ++ if not hasattr(self, 'compiled_tasks'): ++ return ++ ++ link_task = getattr(self, 'link_task', None) ++ ++ for task in self.compiled_tasks: ++ if task.inputs and task.inputs[0].name.lower().endswith('.rc'): ++ continue ++ ++ add_pdb = False ++ for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): ++ # several languages may be used at once ++ for flag in task.env[flagname]: ++ if flag[1:].lower() == 'zi': ++ add_pdb = True ++ break ++ ++ if add_pdb: ++ node = task.outputs[0].change_ext('.pdb') ++ pdb_flag = '/Fd:' + node.abspath() ++ ++ for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): ++ buf = [pdb_flag] ++ for flag in task.env[flagname]: ++ if flag[1:3] == 'Fd' or flag[1:].lower() == 'fs' or flag[1:].lower() == 'mp': ++ continue ++ buf.append(flag) ++ task.env[flagname] = buf ++ ++ if link_task and not node in link_task.dep_nodes: ++ link_task.dep_nodes.append(node) ++ if not node in task.outputs: ++ task.outputs.append(node) +diff --git third_party/waf/waflib/extras/pytest.py third_party/waf/waflib/extras/pytest.py +index 7dd5a1a087a..fc9ad1c23e4 100644 +--- third_party/waf/waflib/extras/pytest.py ++++ third_party/waf/waflib/extras/pytest.py +@@ -40,6 +40,8 @@ the following environment variables for the `pytest` test runner: + + - `pytest_libpath` attribute is used to manually specify additional linker paths. + ++3. Java class search path (CLASSPATH) of any Java/Javalike dependency ++ + Note: `pytest` cannot automatically determine the correct `PYTHONPATH` for `pyext` taskgens + because the extension might be part of a Python package or used standalone: + +@@ -119,6 +121,7 @@ def pytest_process_use(self): + self.pytest_use_seen = [] + self.pytest_paths = [] # strings or Nodes + self.pytest_libpaths = [] # strings or Nodes ++ self.pytest_javapaths = [] # strings or Nodes + self.pytest_dep_nodes = [] + + names = self.to_list(getattr(self, 'use', [])) +@@ -157,6 +160,17 @@ def pytest_process_use(self): + extend_unique(self.pytest_dep_nodes, tg.source) + extend_unique(self.pytest_paths, [pypath.abspath()]) + ++ if 'javac' in tg.features: ++ # If a JAR is generated point to that, otherwise to directory ++ if getattr(tg, 'jar_task', None): ++ extend_unique(self.pytest_javapaths, [tg.jar_task.outputs[0].abspath()]) ++ else: ++ extend_unique(self.pytest_javapaths, [tg.path.get_bld()]) ++ ++ # And add respective dependencies if present ++ if tg.use_lst: ++ extend_unique(self.pytest_javapaths, tg.use_lst) ++ + if getattr(tg, 'link_task', None): + # For tasks with a link_task (C, C++, D et.c.) include their library paths: + if not isinstance(tg.link_task, ccroot.stlink_task): +@@ -212,8 +226,9 @@ def make_pytest(self): + Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst) + self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '') + +- # Prepend dependency paths to PYTHONPATH and LD_LIBRARY_PATH ++ # Prepend dependency paths to PYTHONPATH, CLASSPATH and LD_LIBRARY_PATH + add_paths('PYTHONPATH', self.pytest_paths) ++ add_paths('CLASSPATH', self.pytest_javapaths) + + if Utils.is_win32: + add_paths('PATH', self.pytest_libpaths) +diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py +new file mode 100644 +index 00000000000..8b9567faf14 +--- /dev/null ++++ third_party/waf/waflib/extras/wafcache.py +@@ -0,0 +1,524 @@ ++#! /usr/bin/env python ++# encoding: utf-8 ++# Thomas Nagy, 2019 (ita) ++ ++""" ++Filesystem-based cache system to share and re-use build artifacts ++ ++Cache access operations (copy to and from) are delegated to ++independent pre-forked worker subprocesses. ++ ++The following environment variables may be set: ++* WAFCACHE: several possibilities: ++ - File cache: ++ absolute path of the waf cache (~/.cache/wafcache_user, ++ where `user` represents the currently logged-in user) ++ - URL to a cache server, for example: ++ export WAFCACHE=http://localhost:8080/files/ ++ in that case, GET/POST requests are made to urls of the form ++ http://localhost:8080/files/000000000/0 (cache management is then up to the server) ++ - GCS or S3 bucket ++ gs://my-bucket/ ++ s3://my-bucket/ ++* WAFCACHE_NO_PUSH: if set, disables pushing to the cache ++* WAFCACHE_VERBOSITY: if set, displays more detailed cache operations ++ ++File cache specific options: ++ Files are copied using hard links by default; if the cache is located ++ onto another partition, the system switches to file copies instead. ++* WAFCACHE_TRIM_MAX_FOLDER: maximum amount of tasks to cache (1M) ++* WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) ++* WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try ++ and trim the cache (3 minutess) ++Usage:: ++ ++ def build(bld): ++ bld.load('wafcache') ++ ... ++ ++To troubleshoot:: ++ ++ waf clean build --zones=wafcache ++""" ++ ++import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3 ++try: ++ import subprocess32 as subprocess ++except ImportError: ++ import subprocess ++ ++base_cache = os.path.expanduser('~/.cache/') ++if not os.path.isdir(base_cache): ++ base_cache = '/tmp/' ++default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser()) ++ ++CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir) ++TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) ++EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) ++EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) ++WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 ++WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 ++OK = "ok" ++ ++try: ++ import cPickle ++except ImportError: ++ import pickle as cPickle ++ ++if __name__ != '__main__': ++ from waflib import Task, Logs, Utils, Build ++ ++def can_retrieve_cache(self): ++ """ ++ New method for waf Task classes ++ """ ++ if not self.outputs: ++ return False ++ ++ self.cached = False ++ ++ sig = self.signature() ++ ssig = Utils.to_hex(self.uid() + sig) ++ ++ files_to = [node.abspath() for node in self.outputs] ++ err = cache_command(ssig, [], files_to) ++ if err.startswith(OK): ++ if WAFCACHE_VERBOSITY: ++ Logs.pprint('CYAN', ' Fetched %r from cache' % files_to) ++ else: ++ Logs.debug('wafcache: fetched %r from cache', files_to) ++ else: ++ if WAFCACHE_VERBOSITY: ++ Logs.pprint('YELLOW', ' No cache entry %s' % files_to) ++ else: ++ Logs.debug('wafcache: No cache entry %s: %s', files_to, err) ++ return False ++ ++ self.cached = True ++ return True ++ ++def put_files_cache(self): ++ """ ++ New method for waf Task classes ++ """ ++ if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs: ++ return ++ ++ bld = self.generator.bld ++ sig = self.signature() ++ ssig = Utils.to_hex(self.uid() + sig) ++ ++ files_from = [node.abspath() for node in self.outputs] ++ err = cache_command(ssig, files_from, []) ++ ++ if err.startswith(OK): ++ if WAFCACHE_VERBOSITY: ++ Logs.pprint('CYAN', ' Successfully uploaded %s to cache' % files_from) ++ else: ++ Logs.debug('wafcache: Successfully uploaded %r to cache', files_from) ++ else: ++ if WAFCACHE_VERBOSITY: ++ Logs.pprint('RED', ' Error caching step results %s: %s' % (files_from, err)) ++ else: ++ Logs.debug('wafcache: Error caching results %s: %s', files_from, err) ++ ++ bld.task_sigs[self.uid()] = self.cache_sig ++ ++def hash_env_vars(self, env, vars_lst): ++ """ ++ Reimplement BuildContext.hash_env_vars so that the resulting hash does not depend on local paths ++ """ ++ if not env.table: ++ env = env.parent ++ if not env: ++ return Utils.SIG_NIL ++ ++ idx = str(id(env)) + str(vars_lst) ++ try: ++ cache = self.cache_env ++ except AttributeError: ++ cache = self.cache_env = {} ++ else: ++ try: ++ return self.cache_env[idx] ++ except KeyError: ++ pass ++ ++ v = str([env[a] for a in vars_lst]) ++ v = v.replace(self.srcnode.abspath().__repr__()[:-1], '') ++ m = Utils.md5() ++ m.update(v.encode()) ++ ret = m.digest() ++ ++ Logs.debug('envhash: %r %r', ret, v) ++ ++ cache[idx] = ret ++ ++ return ret ++ ++def uid(self): ++ """ ++ Reimplement Task.uid() so that the signature does not depend on local paths ++ """ ++ try: ++ return self.uid_ ++ except AttributeError: ++ m = Utils.md5() ++ src = self.generator.bld.srcnode ++ up = m.update ++ up(self.__class__.__name__.encode()) ++ for x in self.inputs + self.outputs: ++ up(x.path_from(src).encode()) ++ self.uid_ = m.digest() ++ return self.uid_ ++ ++ ++def make_cached(cls): ++ """ ++ Enable the waf cache for a given task class ++ """ ++ if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False): ++ return ++ ++ m1 = getattr(cls, 'run', None) ++ def run(self): ++ if getattr(self, 'nocache', False): ++ return m1(self) ++ if self.can_retrieve_cache(): ++ return 0 ++ return m1(self) ++ cls.run = run ++ ++ m2 = getattr(cls, 'post_run', None) ++ def post_run(self): ++ if getattr(self, 'nocache', False): ++ return m2(self) ++ ret = m2(self) ++ self.put_files_cache() ++ if hasattr(self, 'chmod'): ++ for node in self.outputs: ++ os.chmod(node.abspath(), self.chmod) ++ return ret ++ cls.post_run = post_run ++ cls.has_cache = True ++ ++process_pool = [] ++def get_process(): ++ """ ++ Returns a worker process that can process waf cache commands ++ The worker process is assumed to be returned to the process pool when unused ++ """ ++ try: ++ return process_pool.pop() ++ except IndexError: ++ filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'wafcache.py' ++ cmd = [sys.executable, '-c', Utils.readf(filepath)] ++ return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0) ++ ++def atexit_pool(): ++ for k in process_pool: ++ try: ++ os.kill(k.pid, 9) ++ except OSError: ++ pass ++ else: ++ k.wait() ++atexit.register(atexit_pool) ++ ++def build(bld): ++ """ ++ Called during the build process to enable file caching ++ """ ++ if process_pool: ++ # already called once ++ return ++ ++ for x in range(bld.jobs): ++ process_pool.append(get_process()) ++ ++ Task.Task.can_retrieve_cache = can_retrieve_cache ++ Task.Task.put_files_cache = put_files_cache ++ Task.Task.uid = uid ++ Build.BuildContext.hash_env_vars = hash_env_vars ++ for x in reversed(list(Task.classes.values())): ++ make_cached(x) ++ ++def cache_command(sig, files_from, files_to): ++ """ ++ Create a command for cache worker processes, returns a pickled ++ base64-encoded tuple containing the task signature, a list of files to ++ cache and a list of files files to get from cache (one of the lists ++ is assumed to be empty) ++ """ ++ proc = get_process() ++ ++ obj = base64.b64encode(cPickle.dumps([sig, files_from, files_to])) ++ proc.stdin.write(obj) ++ proc.stdin.write('\n'.encode()) ++ proc.stdin.flush() ++ obj = proc.stdout.readline() ++ if not obj: ++ raise OSError('Preforked sub-process %r died' % proc.pid) ++ process_pool.append(proc) ++ return cPickle.loads(base64.b64decode(obj)) ++ ++try: ++ copyfun = os.link ++except NameError: ++ copyfun = shutil.copy2 ++ ++def atomic_copy(orig, dest): ++ """ ++ Copy files to the cache, the operation is atomic for a given file ++ """ ++ global copyfun ++ tmp = dest + '.tmp' ++ up = os.path.dirname(dest) ++ try: ++ os.makedirs(up) ++ except OSError: ++ pass ++ ++ try: ++ copyfun(orig, tmp) ++ except OSError as e: ++ if e.errno == errno.EXDEV: ++ copyfun = shutil.copy2 ++ copyfun(orig, tmp) ++ else: ++ raise ++ os.rename(tmp, dest) ++ ++def lru_trim(): ++ """ ++ the cache folders take the form: ++ `CACHE_DIR/0b/0b180f82246d726ece37c8ccd0fb1cde2650d7bfcf122ec1f169079a3bfc0ab9` ++ they are listed in order of last access, and then removed ++ until the amount of folders is within TRIM_MAX_FOLDERS and the total space ++ taken by files is less than EVICT_MAX_BYTES ++ """ ++ lst = [] ++ for up in os.listdir(CACHE_DIR): ++ if len(up) == 2: ++ sub = os.path.join(CACHE_DIR, up) ++ for hval in os.listdir(sub): ++ path = os.path.join(sub, hval) ++ ++ size = 0 ++ for fname in os.listdir(path): ++ size += os.lstat(os.path.join(path, fname)).st_size ++ lst.append((os.stat(path).st_mtime, size, path)) ++ ++ lst.sort(key=lambda x: x[0]) ++ lst.reverse() ++ ++ tot = sum(x[1] for x in lst) ++ while tot > EVICT_MAX_BYTES or len(lst) > TRIM_MAX_FOLDERS: ++ _, tmp_size, path = lst.pop() ++ tot -= tmp_size ++ ++ tmp = path + '.tmp' ++ try: ++ shutil.rmtree(tmp) ++ except OSError: ++ pass ++ try: ++ os.rename(path, tmp) ++ except OSError: ++ sys.stderr.write('Could not rename %r to %r' % (path, tmp)) ++ else: ++ try: ++ shutil.rmtree(tmp) ++ except OSError: ++ sys.stderr.write('Could not remove %r' % tmp) ++ sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst))) ++ ++ ++def lru_evict(): ++ """ ++ Reduce the cache size ++ """ ++ lockfile = os.path.join(CACHE_DIR, 'all.lock') ++ try: ++ st = os.stat(lockfile) ++ except EnvironmentError as e: ++ if e.errno == errno.ENOENT: ++ with open(lockfile, 'w') as f: ++ f.write('') ++ return ++ else: ++ raise ++ ++ if st.st_mtime < time.time() - EVICT_INTERVAL_MINUTES * 60: ++ # check every EVICT_INTERVAL_MINUTES minutes if the cache is too big ++ # OCLOEXEC is unnecessary because no processes are spawned ++ fd = os.open(lockfile, os.O_RDWR | os.O_CREAT, 0o755) ++ try: ++ try: ++ fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) ++ except EnvironmentError: ++ sys.stderr.write('another process is running!\n') ++ pass ++ else: ++ # now dow the actual cleanup ++ lru_trim() ++ os.utime(lockfile, None) ++ finally: ++ os.close(fd) ++ ++class netcache(object): ++ def __init__(self): ++ self.http = urllib3.PoolManager() ++ ++ def url_of(self, sig, i): ++ return "%s/%s/%s" % (CACHE_DIR, sig, i) ++ ++ def upload(self, file_path, sig, i): ++ url = self.url_of(sig, i) ++ with open(file_path, 'rb') as f: ++ file_data = f.read() ++ r = self.http.request('POST', url, timeout=60, ++ fields={ 'file': ('%s/%s' % (sig, i), file_data), }) ++ if r.status >= 400: ++ raise OSError("Invalid status %r %r" % (url, r.status)) ++ ++ def download(self, file_path, sig, i): ++ url = self.url_of(sig, i) ++ with self.http.request('GET', url, preload_content=False, timeout=60) as inf: ++ if inf.status >= 400: ++ raise OSError("Invalid status %r %r" % (url, inf.status)) ++ with open(file_path, 'wb') as out: ++ shutil.copyfileobj(inf, out) ++ ++ def copy_to_cache(self, sig, files_from, files_to): ++ try: ++ for i, x in enumerate(files_from): ++ if not os.path.islink(x): ++ self.upload(x, sig, i) ++ except Exception: ++ return traceback.format_exc() ++ return OK ++ ++ def copy_from_cache(self, sig, files_from, files_to): ++ try: ++ for i, x in enumerate(files_to): ++ self.download(x, sig, i) ++ except Exception: ++ return traceback.format_exc() ++ return OK ++ ++class fcache(object): ++ def __init__(self): ++ if not os.path.exists(CACHE_DIR): ++ os.makedirs(CACHE_DIR) ++ if not os.path.exists(CACHE_DIR): ++ raise ValueError('Could not initialize the cache directory') ++ ++ def copy_to_cache(self, sig, files_from, files_to): ++ """ ++ Copy files to the cache, existing files are overwritten, ++ and the copy is atomic only for a given file, not for all files ++ that belong to a given task object ++ """ ++ try: ++ for i, x in enumerate(files_from): ++ dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) ++ atomic_copy(x, dest) ++ except Exception: ++ return traceback.format_exc() ++ else: ++ # attempt trimming if caching was successful: ++ # we may have things to trim! ++ lru_evict() ++ return OK ++ ++ def copy_from_cache(self, sig, files_from, files_to): ++ """ ++ Copy files from the cache ++ """ ++ try: ++ for i, x in enumerate(files_to): ++ orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) ++ atomic_copy(orig, x) ++ ++ # success! update the cache time ++ os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None) ++ except Exception: ++ return traceback.format_exc() ++ return OK ++ ++class bucket_cache(object): ++ def bucket_copy(self, source, target): ++ if CACHE_DIR.startswith('s3://'): ++ cmd = ['aws', 's3', 'cp', source, target] ++ else: ++ cmd = ['gsutil', 'cp', source, target] ++ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ out, err = proc.communicate() ++ if proc.returncode: ++ raise OSError('Error copy %r to %r using: %r (exit %r):\n out:%s\n err:%s' % ( ++ source, target, cmd, proc.returncode, out.decode(), err.decode())) ++ ++ def copy_to_cache(self, sig, files_from, files_to): ++ try: ++ for i, x in enumerate(files_from): ++ dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) ++ self.bucket_copy(x, dest) ++ except Exception: ++ return traceback.format_exc() ++ return OK ++ ++ def copy_from_cache(self, sig, files_from, files_to): ++ try: ++ for i, x in enumerate(files_to): ++ orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) ++ self.bucket_copy(orig, x) ++ except EnvironmentError: ++ return traceback.format_exc() ++ return OK ++ ++def loop(service): ++ """ ++ This function is run when this file is run as a standalone python script, ++ it assumes a parent process that will communicate the commands to it ++ as pickled-encoded tuples (one line per command) ++ ++ The commands are to copy files to the cache or copy files from the ++ cache to a target destination ++ """ ++ # one operation is performed at a single time by a single process ++ # therefore stdin never has more than one line ++ txt = sys.stdin.readline().strip() ++ if not txt: ++ # parent process probably ended ++ sys.exit(1) ++ ret = OK ++ ++ [sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt)) ++ if files_from: ++ # TODO return early when pushing files upstream ++ ret = service.copy_to_cache(sig, files_from, files_to) ++ elif files_to: ++ # the build process waits for workers to (possibly) obtain files from the cache ++ ret = service.copy_from_cache(sig, files_from, files_to) ++ else: ++ ret = "Invalid command" ++ ++ obj = base64.b64encode(cPickle.dumps(ret)) ++ sys.stdout.write(obj.decode()) ++ sys.stdout.write('\n') ++ sys.stdout.flush() ++ ++if __name__ == '__main__': ++ if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'): ++ service = bucket_cache() ++ elif CACHE_DIR.startswith('http'): ++ service = netcache() ++ else: ++ service = fcache() ++ while 1: ++ try: ++ loop(service) ++ except KeyboardInterrupt: ++ break ++ +-- +2.37.3 + diff --git a/net/samba413/files/patch-waf-2.0.21 b/net/samba413/files/patch-waf-2.0.21 new file mode 100644 index 000000000000..01b2d6e6cafe --- /dev/null +++ b/net/samba413/files/patch-waf-2.0.21 @@ -0,0 +1,703 @@ +From 6718b5e6d059e5668fc538be802ebd9fbe5ce9af Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 25 Nov 2020 16:29:06 +0100 +Subject: [PATCH] waf: upgrade to 2.0.21 + +This commit message was wrong: + + commit 5fc3a71d0f54b176d3cb2e399718d0468507e797 + Author: David Mulder + Date: Mon Aug 24 13:12:46 2020 -0600 + + waf: upgrade to 2.0.20 + + This contain an important change: + "Fix gccdeps.scan() returning nodes that no longer exist on disk." + https://gitlab.com/ita1024/waf/-/merge_requests/2293 + + Signed-off-by: David Mulder + Reviewed-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +The fix was in in waf master, but not included in 2.0.20, +but it's now included in 2.0.21. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + buildtools/bin/waf | 2 +- + buildtools/wafsamba/wafsamba.py | 2 +- + third_party/waf/waflib/Build.py | 6 ++- + third_party/waf/waflib/Context.py | 8 ++-- + third_party/waf/waflib/Tools/asm.py | 5 +- + third_party/waf/waflib/Tools/c_config.py | 1 + + third_party/waf/waflib/Tools/msvc.py | 8 +++- + third_party/waf/waflib/Tools/qt5.py | 26 +++++++++-- + third_party/waf/waflib/Tools/waf_unit_test.py | 10 +++- + third_party/waf/waflib/extras/boost.py | 5 +- + .../waf/waflib/extras/c_dumbpreproc.py | 2 +- + third_party/waf/waflib/extras/doxygen.py | 4 +- + .../waf/waflib/extras/file_to_object.py | 9 +++- + third_party/waf/waflib/extras/gccdeps.py | 21 +++++++-- + third_party/waf/waflib/extras/msvcdeps.py | 27 +++++++++-- + third_party/waf/waflib/extras/pch.py | 4 +- + third_party/waf/waflib/extras/sphinx.py | 40 ++++++++++++---- + third_party/waf/waflib/extras/wafcache.py | 46 +++++++++++++++---- + third_party/waf/waflib/extras/xcode6.py | 18 ++++---- + 19 files changed, 181 insertions(+), 63 deletions(-) + +diff --git buildtools/bin/waf buildtools/bin/waf +index feabe25d131..041450fc131 100755 +--- buildtools/bin/waf ++++ buildtools/bin/waf +@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. + + import os, sys, inspect + +-VERSION="2.0.20" ++VERSION="2.0.21" + REVISION="x" + GIT="x" + INSTALL="x" +diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py +index 9dd6d05b91b..d1baa3b4940 100644 +--- buildtools/wafsamba/wafsamba.py ++++ buildtools/wafsamba/wafsamba.py +@@ -38,7 +38,7 @@ LIB_PATH="shared" + + os.environ['PYTHONUNBUFFERED'] = '1' + +-if Context.HEXVERSION not in (0x2001400,): ++if Context.HEXVERSION not in (0x2001500,): + Logs.error(''' + Please use the version of waf that comes with Samba, not + a system installed version. See http://wiki.samba.org/index.php/Waf +diff --git third_party/waf/waflib/Build.py third_party/waf/waflib/Build.py +index 39f0991918b..52837618577 100644 +--- third_party/waf/waflib/Build.py ++++ third_party/waf/waflib/Build.py +@@ -753,10 +753,12 @@ class BuildContext(Context.Context): + else: + ln = self.launch_node() + if ln.is_child_of(self.bldnode): +- Logs.warn('Building from the build directory, forcing --targets=*') ++ if Logs.verbose > 1: ++ Logs.warn('Building from the build directory, forcing --targets=*') + ln = self.srcnode + elif not ln.is_child_of(self.srcnode): +- Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) ++ if Logs.verbose > 1: ++ Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) + ln = self.srcnode + + def is_post(tg, ln): +diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py +index 3f1b4fa48ab..0ce9df6e91f 100644 +--- third_party/waf/waflib/Context.py ++++ third_party/waf/waflib/Context.py +@@ -18,13 +18,13 @@ else: + import imp + + # the following 3 constants are updated on each new release (do not touch) +-HEXVERSION=0x2001400 ++HEXVERSION=0x2001500 + """Constant updated on new releases""" + +-WAFVERSION="2.0.20" ++WAFVERSION="2.0.21" + """Constant updated on new releases""" + +-WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4" ++WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4" + """Git revision when the waf version is updated""" + + WAFNAME="waf" +@@ -530,7 +530,7 @@ class Context(ctx): + """ + Prints a configuration message of the form ``msg: result``. + The second part of the message will be in colors. The output +- can be disabled easly by setting ``in_msg`` to a positive value:: ++ can be disabled easily by setting ``in_msg`` to a positive value:: + + def configure(conf): + self.in_msg = 1 +diff --git third_party/waf/waflib/Tools/asm.py third_party/waf/waflib/Tools/asm.py +index a57e83bb5ec..1d34ddaca7f 100644 +--- third_party/waf/waflib/Tools/asm.py ++++ third_party/waf/waflib/Tools/asm.py +@@ -56,13 +56,11 @@ class asm(Task.Task): + Compiles asm files by gas/nasm/yasm/... + """ + color = 'BLUE' +- run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' ++ run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${ASMDEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' + + def scan(self): + if self.env.ASM_NAME == 'gas': + return c_preproc.scan(self) +- Logs.warn('There is no dependency scanner for Nasm!') +- return [[], []] + elif self.env.ASM_NAME == 'nasm': + Logs.warn('The Nasm dependency scanner is incomplete!') + +@@ -106,3 +104,4 @@ class asmstlib(stlink_task): + + def configure(conf): + conf.env.ASMPATH_ST = '-I%s' ++ conf.env.ASMDEFINES_ST = '-D%s' +diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py +index 98187fac2e2..03b6bf61bc0 100644 +--- third_party/waf/waflib/Tools/c_config.py ++++ third_party/waf/waflib/Tools/c_config.py +@@ -68,6 +68,7 @@ MACRO_TO_DEST_CPU = { + '__s390__' : 's390', + '__sh__' : 'sh', + '__xtensa__' : 'xtensa', ++'__e2k__' : 'e2k', + } + + @conf +diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py +index f169c7f441b..37233be8242 100644 +--- third_party/waf/waflib/Tools/msvc.py ++++ third_party/waf/waflib/Tools/msvc.py +@@ -99,7 +99,13 @@ all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), + """List of icl platforms""" + + def options(opt): +- opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') ++ default_ver = '' ++ vsver = os.getenv('VSCMD_VER') ++ if vsver: ++ m = re.match(r'(^\d+\.\d+).*', vsver) ++ if m: ++ default_ver = 'msvc %s' % m.group(1) ++ opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default=default_ver) + opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') + opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') + +diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py +index 99e021bae61..cff2028174f 100644 +--- third_party/waf/waflib/Tools/qt5.py ++++ third_party/waf/waflib/Tools/qt5.py +@@ -57,7 +57,23 @@ A few options (--qt{dir,bin,...}) and environment variables + (QT5_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, + tool path selection, etc; please read the source for more info. + +-The detection uses pkg-config on Linux by default. To force static library detection use: ++The detection uses pkg-config on Linux by default. The list of ++libraries to be requested to pkg-config is formulated by scanning ++in the QTLIBS directory (that can be passed via --qtlibs or by ++setting the environment variable QT5_LIBDIR otherwise is derived ++by querying qmake for QT_INSTALL_LIBS directory) for shared/static ++libraries present. ++Alternatively the list of libraries to be requested via pkg-config ++can be set using the qt5_vars attribute, ie: ++ ++ conf.qt5_vars = ['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'Qt5Test']; ++ ++This can speed up configuration phase if needed libraries are ++known beforehand, can improve detection on systems with a ++sparse QT5 libraries installation (ie. NIX) and can improve ++detection of some header-only Qt modules (ie. Qt5UiPlugin). ++ ++To force static library detection use: + QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure + """ + +@@ -466,6 +482,9 @@ def configure(self): + + The detection uses the program ``pkg-config`` through :py:func:`waflib.Tools.config_c.check_cfg` + """ ++ if 'COMPILER_CXX' not in self.env: ++ self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') ++ + self.find_qt5_binaries() + self.set_qt5_libs_dir() + self.set_qt5_libs_to_check() +@@ -478,9 +497,6 @@ def configure(self): + if not has_xml: + Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') + +- if 'COMPILER_CXX' not in self.env: +- self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') +- + # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? + frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' + uses = 'QT5CORE' +@@ -637,7 +653,7 @@ def set_qt5_libs_dir(self): + except Errors.WafError: + qtdir = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() + qtlibs = os.path.join(qtdir, 'lib') +- self.msg('Found the Qt5 libraries in', qtlibs) ++ self.msg('Found the Qt5 library path', qtlibs) + env.QTLIBS = qtlibs + + @conf +diff --git third_party/waf/waflib/Tools/waf_unit_test.py third_party/waf/waflib/Tools/waf_unit_test.py +index 6ff6f72739f..dc66fe9c184 100644 +--- third_party/waf/waflib/Tools/waf_unit_test.py ++++ third_party/waf/waflib/Tools/waf_unit_test.py +@@ -97,6 +97,7 @@ def make_interpreted_test(self): + if isinstance(v, str): + v = v.split(os.pathsep) + self.ut_env[k] = os.pathsep.join(p + v) ++ self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env]) + + @feature('test') + @after_method('apply_link', 'process_use') +@@ -108,7 +109,8 @@ def make_test(self): + tsk = self.create_task('utest', self.link_task.outputs) + if getattr(self, 'ut_str', None): + self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) +- tsk.vars = lst + tsk.vars ++ tsk.vars = tsk.vars + lst ++ self.env.append_value('UT_DEPS', self.ut_str) + + self.handle_ut_cwd('ut_cwd') + +@@ -139,6 +141,10 @@ def make_test(self): + if not hasattr(self, 'ut_cmd'): + self.ut_cmd = getattr(Options.options, 'testcmd', False) + ++ self.env.append_value('UT_DEPS', str(self.ut_cmd)) ++ self.env.append_value('UT_DEPS', self.ut_paths) ++ self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env]) ++ + @taskgen_method + def add_test_results(self, tup): + """Override and return tup[1] to interrupt the build immediately if a test does not run""" +@@ -159,7 +165,7 @@ class utest(Task.Task): + """ + color = 'PINK' + after = ['vnum', 'inst'] +- vars = [] ++ vars = ['UT_DEPS'] + + def runnable_status(self): + """ +diff --git third_party/waf/waflib/extras/boost.py third_party/waf/waflib/extras/boost.py +index c2aaaa938a2..93b312a1e6e 100644 +--- third_party/waf/waflib/extras/boost.py ++++ third_party/waf/waflib/extras/boost.py +@@ -270,10 +270,12 @@ def boost_get_libs(self, *k, **kw): + return file + return None + ++ # extensions from Tools.ccroot.lib_patterns ++ wo_ext = re.compile(r"\.(a|so|lib|dll|dylib)(\.[0-9\.]+)?$") + def format_lib_name(name): + if name.startswith('lib') and self.env.CC_NAME != 'msvc': + name = name[3:] +- return name[:name.rfind('.')] ++ return wo_ext.sub("", name) + + def match_libs(lib_names, is_static): + libs = [] +@@ -522,4 +524,3 @@ def install_boost(self): + except: + continue + install_boost.done = False +- +diff --git third_party/waf/waflib/extras/c_dumbpreproc.py third_party/waf/waflib/extras/c_dumbpreproc.py +index ce9e1a400b9..1fdd5c364ae 100644 +--- third_party/waf/waflib/extras/c_dumbpreproc.py ++++ third_party/waf/waflib/extras/c_dumbpreproc.py +@@ -66,7 +66,7 @@ class dumb_parser(parser): + if x == c_preproc.POPFILE: + self.currentnode_stack.pop() + continue +- self.tryfind(y) ++ self.tryfind(y, env=env) + + c_preproc.c_parser = dumb_parser + +diff --git third_party/waf/waflib/extras/doxygen.py third_party/waf/waflib/extras/doxygen.py +index de75bc2738a..0fda70361f3 100644 +--- third_party/waf/waflib/extras/doxygen.py ++++ third_party/waf/waflib/extras/doxygen.py +@@ -208,10 +208,10 @@ def process_doxy(self): + self.bld.fatal('doxygen file %s not found' % self.doxyfile) + + # the task instance +- dsk = self.create_task('doxygen', node) ++ dsk = self.create_task('doxygen', node, always_run=getattr(self, 'always', False)) + + if getattr(self, 'doxy_tar', None): +- tsk = self.create_task('tar') ++ tsk = self.create_task('tar', always_run=getattr(self, 'always', False)) + tsk.input_tasks = [dsk] + tsk.set_outputs(self.path.find_or_declare(self.doxy_tar)) + if self.doxy_tar.endswith('bz2'): +diff --git third_party/waf/waflib/extras/file_to_object.py third_party/waf/waflib/extras/file_to_object.py +index 1393b511d63..13d2aef37df 100644 +--- third_party/waf/waflib/extras/file_to_object.py ++++ third_party/waf/waflib/extras/file_to_object.py +@@ -31,7 +31,7 @@ Known issues: + + """ + +-import os ++import os, sys + from waflib import Task, TaskGen, Errors + + def filename_c_escape(x): +@@ -95,12 +95,17 @@ class file_to_object_c(Task.Task): + + name = "_binary_" + "".join(name) + ++ def char_to_num(ch): ++ if sys.version_info[0] < 3: ++ return ord(ch) ++ return ch ++ + data = self.inputs[0].read('rb') + lines, line = [], [] + for idx_byte, byte in enumerate(data): + line.append(byte) + if len(line) > 15 or idx_byte == size-1: +- lines.append(", ".join(("0x%02x" % ord(x)) for x in line)) ++ lines.append(", ".join(("0x%02x" % char_to_num(x)) for x in line)) + line = [] + data = ",\n ".join(lines) + +diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py +index c3a809e252a..1fc9373489a 100644 +--- third_party/waf/waflib/extras/gccdeps.py ++++ third_party/waf/waflib/extras/gccdeps.py +@@ -163,10 +163,25 @@ def post_run(self): + def sig_implicit_deps(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).sig_implicit_deps() ++ bld = self.generator.bld ++ + try: +- return Task.Task.sig_implicit_deps(self) +- except Errors.WafError: +- return Utils.SIG_NIL ++ return self.compute_sig_implicit_deps() ++ except Errors.TaskNotReady: ++ raise ValueError("Please specify the build order precisely with gccdeps (asm/c/c++ tasks)") ++ except EnvironmentError: ++ # If a file is renamed, assume the dependencies are stale and must be recalculated ++ for x in bld.node_deps.get(self.uid(), []): ++ if not x.is_bld() and not x.exists(): ++ try: ++ del x.parent.children[x.name] ++ except KeyError: ++ pass ++ ++ key = self.uid() ++ bld.node_deps[key] = [] ++ bld.raw_deps[key] = [] ++ return Utils.SIG_NIL + + def wrap_compiled_task(classname): + derived_class = type(classname, (Task.classes[classname],), {}) +diff --git third_party/waf/waflib/extras/msvcdeps.py third_party/waf/waflib/extras/msvcdeps.py +index 873a4193150..52985dce058 100644 +--- third_party/waf/waflib/extras/msvcdeps.py ++++ third_party/waf/waflib/extras/msvcdeps.py +@@ -150,11 +150,25 @@ def scan(self): + def sig_implicit_deps(self): + if self.env.CC_NAME not in supported_compilers: + return super(self.derived_msvcdeps, self).sig_implicit_deps() ++ bld = self.generator.bld + + try: +- return Task.Task.sig_implicit_deps(self) +- except Errors.WafError: +- return Utils.SIG_NIL ++ return self.compute_sig_implicit_deps() ++ except Errors.TaskNotReady: ++ raise ValueError("Please specify the build order precisely with msvcdeps (c/c++ tasks)") ++ except EnvironmentError: ++ # If a file is renamed, assume the dependencies are stale and must be recalculated ++ for x in bld.node_deps.get(self.uid(), []): ++ if not x.is_bld() and not x.exists(): ++ try: ++ del x.parent.children[x.name] ++ except KeyError: ++ pass ++ ++ key = self.uid() ++ bld.node_deps[key] = [] ++ bld.raw_deps[key] = [] ++ return Utils.SIG_NIL + + def exec_command(self, cmd, **kw): + if self.env.CC_NAME not in supported_compilers: +@@ -211,11 +225,14 @@ def exec_command(self, cmd, **kw): + # get one from the exception object + ret = getattr(e, 'returncode', 1) + ++ Logs.debug('msvcdeps: Running for: %s' % self.inputs[0]) + for line in raw_out.splitlines(): + if line.startswith(INCLUDE_PATTERN): +- inc_path = line[len(INCLUDE_PATTERN):].strip() ++ # Only strip whitespace after log to preserve ++ # dependency structure in debug output ++ inc_path = line[len(INCLUDE_PATTERN):] + Logs.debug('msvcdeps: Regex matched %s', inc_path) +- self.msvcdeps_paths.append(inc_path) ++ self.msvcdeps_paths.append(inc_path.strip()) + else: + out.append(line) + +diff --git third_party/waf/waflib/extras/pch.py third_party/waf/waflib/extras/pch.py +index 103e752838c..b44c7a2e8fd 100644 +--- third_party/waf/waflib/extras/pch.py ++++ third_party/waf/waflib/extras/pch.py +@@ -90,7 +90,7 @@ def apply_pch(self): + + if getattr(self, 'name', None): + try: +- task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] ++ task = self.bld.pch_tasks[self.name] + self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx)) + except KeyError: + pass +@@ -104,7 +104,7 @@ def apply_pch(self): + + self.pch_task = task + if getattr(self, 'name', None): +- self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task ++ self.bld.pch_tasks[self.name] = task + + @TaskGen.feature('cxx') + @TaskGen.after_method('process_source', 'propagate_uselib_vars') +diff --git third_party/waf/waflib/extras/sphinx.py third_party/waf/waflib/extras/sphinx.py +index ce11110e634..71d1028393b 100644 +--- third_party/waf/waflib/extras/sphinx.py ++++ third_party/waf/waflib/extras/sphinx.py +@@ -20,7 +20,7 @@ def build(bld): + + from waflib.Node import Node + from waflib import Utils +-from waflib.Task import Task ++from waflib import Task + from waflib.TaskGen import feature, after_method + + +@@ -55,13 +55,9 @@ def build_sphinx(self): + sphinx_build_task.set_outputs(self.path.get_bld()) + + # the sphinx-build results are in directory +- sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) +- sphinx_output_directory.mkdir() ++ self.sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) ++ self.sphinx_output_directory.mkdir() + Utils.def_attrs(self, install_path=get_install_path(self)) +- self.add_install_files(install_to=self.install_path, +- install_from=sphinx_output_directory.ant_glob('**/*'), +- cwd=sphinx_output_directory, +- relative_trick=True) + + + def get_install_path(tg): +@@ -73,9 +69,37 @@ def get_install_path(tg): + return tg.env.DOCDIR + + +-class SphinxBuildingTask(Task): ++class SphinxBuildingTask(Task.Task): + color = 'BOLD' + run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}' + + def keyword(self): + return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT ++ ++ def runnable_status(self): ++ ++ for x in self.run_after: ++ if not x.hasrun: ++ return Task.ASK_LATER ++ ++ self.signature() ++ ret = Task.Task.runnable_status(self) ++ if ret == Task.SKIP_ME: ++ # in case the files were removed ++ self.add_install() ++ return ret ++ ++ ++ def post_run(self): ++ self.add_install() ++ return Task.Task.post_run(self) ++ ++ ++ def add_install(self): ++ nodes = self.generator.sphinx_output_directory.ant_glob('**/*', quiet=True) ++ self.outputs += nodes ++ self.generator.add_install_files(install_to=self.generator.install_path, ++ install_from=nodes, ++ postpone=False, ++ cwd=self.generator.sphinx_output_directory, ++ relative_trick=True) +diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py +index 8b9567faf14..088fd0d098d 100644 +--- third_party/waf/waflib/extras/wafcache.py ++++ third_party/waf/waflib/extras/wafcache.py +@@ -16,10 +16,19 @@ The following environment variables may be set: + - URL to a cache server, for example: + export WAFCACHE=http://localhost:8080/files/ + in that case, GET/POST requests are made to urls of the form +- http://localhost:8080/files/000000000/0 (cache management is then up to the server) +- - GCS or S3 bucket +- gs://my-bucket/ +- s3://my-bucket/ ++ http://localhost:8080/files/000000000/0 (cache management is delegated to the server) ++ - GCS, S3 or MINIO bucket ++ gs://my-bucket/ (uses gsutil command line tool or WAFCACHE_CMD) ++ s3://my-bucket/ (uses aws command line tool or WAFCACHE_CMD) ++ minio://my-bucket/ (uses mc command line tool or WAFCACHE_CMD) ++* WAFCACHE_CMD: bucket upload/download command, for example: ++ WAFCACHE_CMD="gsutil cp %{SRC} %{TGT}" ++ Note that the WAFCACHE bucket value is used for the source or destination ++ depending on the operation (upload or download). For example, with: ++ WAFCACHE="gs://mybucket/" ++ the following commands may be run: ++ gsutil cp build/myprogram gs://mybucket/aa/aaaaa/1 ++ gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile + * WAFCACHE_NO_PUSH: if set, disables pushing to the cache + * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations + +@@ -30,6 +39,7 @@ File cache specific options: + * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) + * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try + and trim the cache (3 minutess) ++ + Usage:: + + def build(bld): +@@ -41,7 +51,7 @@ To troubleshoot:: + waf clean build --zones=wafcache + """ + +-import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3 ++import atexit, base64, errno, fcntl, getpass, os, re, shutil, sys, time, traceback, urllib3, shlex + try: + import subprocess32 as subprocess + except ImportError: +@@ -53,6 +63,7 @@ if not os.path.isdir(base_cache): + default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser()) + + CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir) ++WAFCACHE_CMD = os.environ.get('WAFCACHE_CMD') + TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) + EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) + EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) +@@ -60,6 +71,8 @@ WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 + WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 + OK = "ok" + ++re_waf_cmd = re.compile('(?P%{SRC})|(?P%{TGT})') ++ + try: + import cPickle + except ImportError: +@@ -233,8 +246,9 @@ def build(bld): + # already called once + return + +- for x in range(bld.jobs): +- process_pool.append(get_process()) ++ # pre-allocation ++ processes = [get_process() for x in range(bld.jobs)] ++ process_pool.extend(processes) + + Task.Task.can_retrieve_cache = can_retrieve_cache + Task.Task.put_files_cache = put_files_cache +@@ -449,10 +463,20 @@ class fcache(object): + + class bucket_cache(object): + def bucket_copy(self, source, target): +- if CACHE_DIR.startswith('s3://'): ++ if WAFCACHE_CMD: ++ def replacer(match): ++ if match.group('src'): ++ return source ++ elif match.group('tgt'): ++ return target ++ cmd = [re_waf_cmd.sub(replacer, x) for x in shlex.split(WAFCACHE_CMD)] ++ elif CACHE_DIR.startswith('s3://'): + cmd = ['aws', 's3', 'cp', source, target] +- else: ++ elif CACHE_DIR.startswith('gs://'): + cmd = ['gsutil', 'cp', source, target] ++ else: ++ cmd = ['mc', 'cp', source, target] ++ + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + if proc.returncode: +@@ -510,7 +534,9 @@ def loop(service): + sys.stdout.flush() + + if __name__ == '__main__': +- if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'): ++ if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://') or CACHE_DIR.startswith('minio://'): ++ if CACHE_DIR.startswith('minio://'): ++ CACHE_DIR = CACHE_DIR[8:] # minio doesn't need the protocol part, uses config aliases + service = bucket_cache() + elif CACHE_DIR.startswith('http'): + service = netcache() +diff --git third_party/waf/waflib/extras/xcode6.py third_party/waf/waflib/extras/xcode6.py +index 91bbff181ec..c5b309120c9 100644 +--- third_party/waf/waflib/extras/xcode6.py ++++ third_party/waf/waflib/extras/xcode6.py +@@ -99,7 +99,7 @@ env.PROJ_CONFIGURATION = { + ... + } + 'Release': { +- 'ARCHS' x86_64' ++ 'ARCHS': x86_64' + ... + } + } +@@ -163,12 +163,12 @@ class XCodeNode(object): + result = result + "\t\t}" + return result + elif isinstance(value, str): +- return "\"%s\"" % value ++ return '"%s"' % value.replace('"', '\\\\\\"') + elif isinstance(value, list): + result = "(\n" + for i in value: +- result = result + "\t\t\t%s,\n" % self.tostring(i) +- result = result + "\t\t)" ++ result = result + "\t\t\t\t%s,\n" % self.tostring(i) ++ result = result + "\t\t\t)" + return result + elif isinstance(value, XCodeNode): + return value._id +@@ -565,13 +565,13 @@ def process_xcode(self): + # Override target specific build settings + bldsettings = { + 'HEADER_SEARCH_PATHS': ['$(inherited)'] + self.env['INCPATHS'], +- 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR) , ++ 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR), + 'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.FRAMEWORKPATH), +- 'OTHER_LDFLAGS': libs + ' ' + frameworks, +- 'OTHER_LIBTOOLFLAGS': bld.env['LINKFLAGS'], ++ 'OTHER_LDFLAGS': libs + ' ' + frameworks + ' ' + ' '.join(bld.env['LINKFLAGS']), + 'OTHER_CPLUSPLUSFLAGS': Utils.to_list(self.env['CXXFLAGS']), + 'OTHER_CFLAGS': Utils.to_list(self.env['CFLAGS']), +- 'INSTALL_PATH': [] ++ 'INSTALL_PATH': [], ++ 'GCC_PREPROCESSOR_DEFINITIONS': self.env['DEFINES'] + } + + # Install path +@@ -591,7 +591,7 @@ def process_xcode(self): + + # The keys represents different build configuration, e.g. Debug, Release and so on.. + # Insert our generated build settings to all configuration names +- keys = set(settings.keys() + bld.env.PROJ_CONFIGURATION.keys()) ++ keys = set(settings.keys()) | set(bld.env.PROJ_CONFIGURATION.keys()) + for k in keys: + if k in settings: + settings[k].update(bldsettings) +-- +2.37.3 + diff --git a/net/samba413/files/patch-waf-2.0.22 b/net/samba413/files/patch-waf-2.0.22 new file mode 100644 index 000000000000..db3c8edff8d3 --- /dev/null +++ b/net/samba413/files/patch-waf-2.0.22 @@ -0,0 +1,596 @@ +From 59ed09928541d40df72592419247add608a54aca Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Wed, 25 Aug 2021 15:34:58 +0200 +Subject: [PATCH] third_party: Update waf to version 2.0.22 + +New in waf 2.0.22 + +* Fix stdin propagation with faulty vcvarsall scripts #2315 +* Enable mixing Unix-style paths with destdir on Windows platforms #2337 +* Fix shell escaping unit test parameters #2314 +* Improve extras/clang_compilation_database and extras/swig compatibility #2336 +* Propagate C++ flags to the Cuda compiler in extras/cuda #2311 +* Fix detection of Qt 5.0.0 (preparation for Qt6) #2331 +* Enable Haxe processing #2308 +* Fix regression in MACOSX_DEPLOYMENT_TARGET caused by distutils #2330 +* Fix extras/wafcache concurrent trimming issues #2312 +* Fix extras/wafcache symlink handling #2327 + +The import was done like this: + +./third_party/waf/update.sh + +Then changing buildtools/bin/waf and buildtools/wafsamba/wafsamba.py +by hand. + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Andreas Schneider +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Thu Sep 2 21:22:17 UTC 2021 on sn-devel-184 +--- + buildtools/bin/waf | 2 +- + buildtools/wafsamba/wafsamba.py | 2 +- + third_party/waf/waflib/Build.py | 4 +- + third_party/waf/waflib/Context.py | 6 +- + third_party/waf/waflib/Tools/msvc.py | 2 +- + third_party/waf/waflib/Tools/python.py | 2 +- + third_party/waf/waflib/Tools/qt5.py | 6 +- + third_party/waf/waflib/Tools/waf_unit_test.py | 2 +- + third_party/waf/waflib/Utils.py | 15 +- + .../extras/clang_compilation_database.py | 28 ++-- + third_party/waf/waflib/extras/haxe.py | 131 ++++++++++++++++++ + third_party/waf/waflib/extras/wafcache.py | 59 ++++++-- + 12 files changed, 215 insertions(+), 44 deletions(-) + create mode 100644 third_party/waf/waflib/extras/haxe.py + +diff --git buildtools/bin/waf buildtools/bin/waf +index 041450fc131..b0ccb09a877 100755 +--- buildtools/bin/waf ++++ buildtools/bin/waf +@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. + + import os, sys, inspect + +-VERSION="2.0.21" ++VERSION="2.0.22" + REVISION="x" + GIT="x" + INSTALL="x" +diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py +index 4fe9daf160e..dee007bf84e 100644 +--- buildtools/wafsamba/wafsamba.py ++++ buildtools/wafsamba/wafsamba.py +@@ -38,7 +38,7 @@ LIB_PATH="shared" + + os.environ['PYTHONUNBUFFERED'] = '1' + +-if Context.HEXVERSION not in (0x2001500,): ++if Context.HEXVERSION not in (0x2001600,): + Logs.error(''' + Please use the version of waf that comes with Samba, not + a system installed version. See http://wiki.samba.org/index.php/Waf +diff --git third_party/waf/waflib/Build.py third_party/waf/waflib/Build.py +index 52837618577..b49dd8302b1 100644 +--- third_party/waf/waflib/Build.py ++++ third_party/waf/waflib/Build.py +@@ -1066,9 +1066,9 @@ class inst(Task.Task): + else: + dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env)) + if not os.path.isabs(dest): +- dest = os.path.join(self.env.PREFIX, dest) ++ dest = os.path.join(self.env.PREFIX, dest) + if destdir and Options.options.destdir: +- dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) ++ dest = Options.options.destdir.rstrip(os.sep) + os.sep + os.path.splitdrive(dest)[1].lstrip(os.sep) + return dest + + def copy_fun(self, src, tgt): +diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py +index 0ce9df6e91f..07ee1201f03 100644 +--- third_party/waf/waflib/Context.py ++++ third_party/waf/waflib/Context.py +@@ -18,13 +18,13 @@ else: + import imp + + # the following 3 constants are updated on each new release (do not touch) +-HEXVERSION=0x2001500 ++HEXVERSION=0x2001600 + """Constant updated on new releases""" + +-WAFVERSION="2.0.21" ++WAFVERSION="2.0.22" + """Constant updated on new releases""" + +-WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4" ++WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c" + """Git revision when the waf version is updated""" + + WAFNAME="waf" +diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py +index 37233be8242..0c4703aaee9 100644 +--- third_party/waf/waflib/Tools/msvc.py ++++ third_party/waf/waflib/Tools/msvc.py +@@ -193,7 +193,7 @@ echo PATH=%%PATH%% + echo INCLUDE=%%INCLUDE%% + echo LIB=%%LIB%%;%%LIBPATH%% + """ % (vcvars,target)) +- sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) ++ sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()], stdin=getattr(Utils.subprocess, 'DEVNULL', None)) + lines = sout.splitlines() + + if not lines[0]: +diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py +index b1c8dd01285..07442561dff 100644 +--- third_party/waf/waflib/Tools/python.py ++++ third_party/waf/waflib/Tools/python.py +@@ -327,7 +327,7 @@ def check_python_headers(conf, features='pyembed pyext'): + dct = dict(zip(v, lst)) + x = 'MACOSX_DEPLOYMENT_TARGET' + if dct[x]: +- env[x] = conf.environ[x] = dct[x] ++ env[x] = conf.environ[x] = str(dct[x]) + env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake + + +diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py +index cff2028174f..82c83e18c8a 100644 +--- third_party/waf/waflib/Tools/qt5.py ++++ third_party/waf/waflib/Tools/qt5.py +@@ -566,7 +566,7 @@ def find_qt5_binaries(self): + # at the end, try to find qmake in the paths given + # keep the one with the highest version + cand = None +- prev_ver = ['5', '0', '0'] ++ prev_ver = ['0', '0', '0'] + for qmk in ('qmake-qt5', 'qmake5', 'qmake'): + try: + qmake = self.find_program(qmk, path_list=paths) +@@ -580,7 +580,7 @@ def find_qt5_binaries(self): + else: + if version: + new_ver = version.split('.') +- if new_ver > prev_ver: ++ if new_ver[0] == '5' and new_ver > prev_ver: + cand = qmake + prev_ver = new_ver + +@@ -783,7 +783,7 @@ def set_qt5_libs_to_check(self): + pat = self.env.cxxstlib_PATTERN + if Utils.unversioned_sys_platform() == 'darwin': + pat = r"%s\.framework" +- re_qt = re.compile(pat%'Qt5?(?P.*)'+'$') ++ re_qt = re.compile(pat % 'Qt5?(?P\\D+)' + '$') + for x in dirlst: + m = re_qt.match(x) + if m: +diff --git third_party/waf/waflib/Tools/waf_unit_test.py third_party/waf/waflib/Tools/waf_unit_test.py +index dc66fe9c184..8cff89bdeb9 100644 +--- third_party/waf/waflib/Tools/waf_unit_test.py ++++ third_party/waf/waflib/Tools/waf_unit_test.py +@@ -206,7 +206,7 @@ class utest(Task.Task): + self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()]) + ut_cmd = getattr(self.generator, 'ut_cmd', False) + if ut_cmd: +- self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec)) ++ self.ut_exec = shlex.split(ut_cmd % Utils.shell_escape(self.ut_exec)) + + return self.exec_command(self.ut_exec) + +diff --git third_party/waf/waflib/Utils.py third_party/waf/waflib/Utils.py +index fc64fa05154..669490ca908 100644 +--- third_party/waf/waflib/Utils.py ++++ third_party/waf/waflib/Utils.py +@@ -11,7 +11,7 @@ through Python versions 2.5 to 3.X and across different platforms (win32, linux, + + from __future__ import with_statement + +-import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time ++import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time, shlex + + try: + import cPickle +@@ -577,10 +577,13 @@ def quote_define_name(s): + fu = fu.upper() + return fu + +-re_sh = re.compile('\\s|\'|"') +-""" +-Regexp used for shell_escape below +-""" ++# shlex.quote didn't exist until python 3.3. Prior to that it was a non-documented ++# function in pipes. ++try: ++ shell_quote = shlex.quote ++except AttributeError: ++ import pipes ++ shell_quote = pipes.quote + + def shell_escape(cmd): + """ +@@ -589,7 +592,7 @@ def shell_escape(cmd): + """ + if isinstance(cmd, str): + return cmd +- return ' '.join(repr(x) if re_sh.search(x) else x for x in cmd) ++ return ' '.join(shell_quote(x) for x in cmd) + + def h_list(lst): + """ +diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py +index ff71f22ecfd..17f66949376 100644 +--- third_party/waf/waflib/extras/clang_compilation_database.py ++++ third_party/waf/waflib/extras/clang_compilation_database.py +@@ -29,22 +29,9 @@ from waflib import Logs, TaskGen, Task, Build, Scripting + + Task.Task.keep_last_cmd = True + +-@TaskGen.feature('c', 'cxx') +-@TaskGen.after_method('process_use') +-def collect_compilation_db_tasks(self): +- "Add a compilation database entry for compiled tasks" +- if not isinstance(self.bld, ClangDbContext): +- return +- +- tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) +- for task in getattr(self, 'compiled_tasks', []): +- if isinstance(task, tup): +- self.bld.clang_compilation_database_tasks.append(task) +- + class ClangDbContext(Build.BuildContext): + '''generates compile_commands.json by request''' + cmd = 'clangdb' +- clang_compilation_database_tasks = [] + + def write_compilation_database(self): + """ +@@ -78,6 +65,8 @@ class ClangDbContext(Build.BuildContext): + Build dry run + """ + self.restore() ++ self.cur_tasks = [] ++ self.clang_compilation_database_tasks = [] + + if not self.all_envs: + self.load_envs() +@@ -103,8 +92,21 @@ class ClangDbContext(Build.BuildContext): + lst = [tg] + else: lst = tg.tasks + for tsk in lst: ++ if tsk.__class__.__name__ == "swig": ++ tsk.runnable_status() ++ if hasattr(tsk, 'more_tasks'): ++ lst.extend(tsk.more_tasks) ++ # Not all dynamic tasks can be processed, in some cases ++ # one may have to call the method "run()" like this: ++ #elif tsk.__class__.__name__ == 'src2c': ++ # tsk.run() ++ # if hasattr(tsk, 'more_tasks'): ++ # lst.extend(tsk.more_tasks) ++ + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) + if isinstance(tsk, tup): ++ self.clang_compilation_database_tasks.append(tsk) ++ tsk.nocache = True + old_exec = tsk.exec_command + tsk.exec_command = exec_command + tsk.run() +diff --git third_party/waf/waflib/extras/haxe.py third_party/waf/waflib/extras/haxe.py +new file mode 100644 +index 00000000000..cb3ba6a949c +--- /dev/null ++++ third_party/waf/waflib/extras/haxe.py +@@ -0,0 +1,131 @@ ++import os, re ++from waflib import Utils, Task, Errors ++from waflib.TaskGen import extension, taskgen_method, feature ++from waflib.Configure import conf ++ ++@conf ++def libname_haxe(self, libname): ++ return libname ++ ++@conf ++def check_lib_haxe(self, libname, uselib_store=None): ++ haxe_libs = [node.name for node in self.root.find_node('haxe_libraries').ant_glob()] ++ changed = False ++ self.start_msg('Checking for library %s' % libname) ++ if libname + '.hxml' in haxe_libs: ++ self.end_msg('yes') ++ else: ++ changed = True ++ try: ++ cmd = self.env.LIX + ['+lib', libname] ++ res = self.cmd_and_log(cmd) ++ if (res): ++ raise Errors.WafError(res) ++ else: ++ self.end_msg('downloaded', color = 'YELLOW') ++ except Errors.WafError as e: ++ self.end_msg('no', color = 'RED') ++ self.fatal('Getting %s has failed' % libname) ++ ++ postfix = uselib_store if uselib_store else libname.upper() ++ self.env['LIB_' + postfix] += [self.libname_haxe(libname)] ++ return changed ++ ++@conf ++def check_libs_haxe(self, libnames, uselib_store=None): ++ changed = False ++ for libname in Utils.to_list(libnames): ++ if self.check_lib_haxe(libname, uselib_store): ++ changed = True ++ return changed ++ ++@conf ++def ensure_lix_pkg(self, *k, **kw): ++ if kw.get('compiler') == 'hx': ++ if isinstance(kw.get('libs'), list) and len(kw.get('libs')): ++ changed = self.check_libs_haxe(kw.get('libs'), kw.get('uselib_store')) ++ if changed: ++ try: ++ cmd = self.env.LIX + ['download'] ++ res = self.cmd_and_log(cmd) ++ if (res): ++ raise Errors.WafError(res) ++ except Errors.WafError as e: ++ self.fatal('lix download has failed') ++ else: ++ self.check_lib_haxe(kw.get('lib'), kw.get('uselib_store')) ++ ++@conf ++def haxe(bld, *k, **kw): ++ task_gen = bld(*k, **kw) ++ ++class haxe(Task.Task): ++ vars = ['HAXE', 'HAXE_VERSION', 'HAXEFLAGS'] ++ ext_out = ['.hl', '.c', '.h'] ++ ++ def run(self): ++ cmd = self.env.HAXE + self.env.HAXEFLAGS ++ return self.exec_command(cmd, stdout = open(os.devnull, 'w')) ++ ++@taskgen_method ++def init_haxe_task(self, node): ++ def addflags(flags): ++ self.env.append_value('HAXEFLAGS', flags) ++ ++ if node.suffix() == '.hxml': ++ addflags(self.path.abspath() + '/' + node.name) ++ else: ++ addflags(['-main', node.name]) ++ addflags(['-hl', self.path.get_bld().make_node(self.target).abspath()]) ++ addflags(['-cp', self.path.abspath()]) ++ addflags(['-D', 'resourcesPath=%s' % getattr(self, 'res', '')]) ++ if hasattr(self, 'use'): ++ for dep in self.use: ++ if self.env['LIB_' + dep]: ++ for lib in self.env['LIB_' + dep]: addflags(['-lib', lib]) ++ ++@extension('.hx', '.hxml') ++def haxe_file(self, node): ++ if len(self.source) > 1: ++ self.bld.fatal('Use separate task generators for multiple files') ++ ++ try: ++ haxetask = self.haxetask ++ except AttributeError: ++ haxetask = self.haxetask = self.create_task('haxe') ++ self.init_haxe_task(node) ++ ++ haxetask.inputs.append(node) ++ haxetask.outputs.append(self.path.get_bld().make_node(self.target)) ++ ++@conf ++def find_haxe(self, min_version): ++ npx = self.env.NPX = self.find_program('npx') ++ self.env.LIX = npx + ['lix'] ++ npx_haxe = self.env.HAXE = npx + ['haxe'] ++ try: ++ output = self.cmd_and_log(npx_haxe + ['-version']) ++ except Errors.WafError: ++ haxe_version = None ++ else: ++ ver = re.search(r'\d+.\d+.\d+', output).group().split('.') ++ haxe_version = tuple([int(x) for x in ver]) ++ ++ self.msg('Checking for haxe version', ++ haxe_version, haxe_version and haxe_version >= min_version) ++ if npx_haxe and haxe_version < min_version: ++ self.fatal('haxe version %r is too old, need >= %r' % (haxe_version, min_version)) ++ ++ self.env.HAXE_VERSION = haxe_version ++ return npx_haxe ++ ++@conf ++def check_haxe(self, min_version=(4,1,4)): ++ if self.env.HAXE_MINVER: ++ min_version = self.env.HAXE_MINVER ++ find_haxe(self, min_version) ++ ++def configure(self): ++ self.env.HAXEFLAGS = [] ++ self.check_haxe() ++ self.add_os_flags('HAXEFLAGS', dup = False) +diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py +index 088fd0d098d..cc23fcd6673 100644 +--- third_party/waf/waflib/extras/wafcache.py ++++ third_party/waf/waflib/extras/wafcache.py +@@ -31,6 +31,7 @@ The following environment variables may be set: + gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile + * WAFCACHE_NO_PUSH: if set, disables pushing to the cache + * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations ++* WAFCACHE_STATS: if set, displays cache usage statistics on exit + + File cache specific options: + Files are copied using hard links by default; if the cache is located +@@ -69,6 +70,7 @@ EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3 + EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) + WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 + WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 ++WAFCACHE_STATS = 1 if os.environ.get('WAFCACHE_STATS') else 0 + OK = "ok" + + re_waf_cmd = re.compile('(?P%{SRC})|(?P%{TGT})') +@@ -93,6 +95,9 @@ def can_retrieve_cache(self): + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + ++ if WAFCACHE_STATS: ++ self.generator.bld.cache_reqs += 1 ++ + files_to = [node.abspath() for node in self.outputs] + err = cache_command(ssig, [], files_to) + if err.startswith(OK): +@@ -100,6 +105,8 @@ def can_retrieve_cache(self): + Logs.pprint('CYAN', ' Fetched %r from cache' % files_to) + else: + Logs.debug('wafcache: fetched %r from cache', files_to) ++ if WAFCACHE_STATS: ++ self.generator.bld.cache_hits += 1 + else: + if WAFCACHE_VERBOSITY: + Logs.pprint('YELLOW', ' No cache entry %s' % files_to) +@@ -117,11 +124,17 @@ def put_files_cache(self): + if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs: + return + ++ files_from = [] ++ for node in self.outputs: ++ path = node.abspath() ++ if not os.path.isfile(path): ++ return ++ files_from.append(path) ++ + bld = self.generator.bld + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + +- files_from = [node.abspath() for node in self.outputs] + err = cache_command(ssig, files_from, []) + + if err.startswith(OK): +@@ -129,6 +142,8 @@ def put_files_cache(self): + Logs.pprint('CYAN', ' Successfully uploaded %s to cache' % files_from) + else: + Logs.debug('wafcache: Successfully uploaded %r to cache', files_from) ++ if WAFCACHE_STATS: ++ self.generator.bld.cache_puts += 1 + else: + if WAFCACHE_VERBOSITY: + Logs.pprint('RED', ' Error caching step results %s: %s' % (files_from, err)) +@@ -193,6 +208,10 @@ def make_cached(cls): + if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False): + return + ++ full_name = "%s.%s" % (cls.__module__, cls.__name__) ++ if full_name in ('waflib.Tools.ccroot.vnum', 'waflib.Build.inst'): ++ return ++ + m1 = getattr(cls, 'run', None) + def run(self): + if getattr(self, 'nocache', False): +@@ -208,9 +227,6 @@ def make_cached(cls): + return m2(self) + ret = m2(self) + self.put_files_cache() +- if hasattr(self, 'chmod'): +- for node in self.outputs: +- os.chmod(node.abspath(), self.chmod) + return ret + cls.post_run = post_run + cls.has_cache = True +@@ -257,6 +273,19 @@ def build(bld): + for x in reversed(list(Task.classes.values())): + make_cached(x) + ++ if WAFCACHE_STATS: ++ # Init counter for statistics and hook to print results at the end ++ bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 ++ ++ def printstats(bld): ++ hit_ratio = 0 ++ if bld.cache_reqs > 0: ++ hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 ++ Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % ++ (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) ++ ++ bld.add_post_fun(printstats) ++ + def cache_command(sig, files_from, files_to): + """ + Create a command for cache worker processes, returns a pickled +@@ -320,7 +349,10 @@ def lru_trim(): + + size = 0 + for fname in os.listdir(path): +- size += os.lstat(os.path.join(path, fname)).st_size ++ try: ++ size += os.lstat(os.path.join(path, fname)).st_size ++ except OSError: ++ pass + lst.append((os.stat(path).st_mtime, size, path)) + + lst.sort(key=lambda x: x[0]) +@@ -331,7 +363,7 @@ def lru_trim(): + _, tmp_size, path = lst.pop() + tot -= tmp_size + +- tmp = path + '.tmp' ++ tmp = path + '.remove' + try: + shutil.rmtree(tmp) + except OSError: +@@ -339,12 +371,12 @@ def lru_trim(): + try: + os.rename(path, tmp) + except OSError: +- sys.stderr.write('Could not rename %r to %r' % (path, tmp)) ++ sys.stderr.write('Could not rename %r to %r\n' % (path, tmp)) + else: + try: + shutil.rmtree(tmp) + except OSError: +- sys.stderr.write('Could not remove %r' % tmp) ++ sys.stderr.write('Could not remove %r\n' % tmp) + sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst))) + + +@@ -371,8 +403,8 @@ def lru_evict(): + try: + fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + except EnvironmentError: +- sys.stderr.write('another process is running!\n') +- pass ++ if WAFCACHE_VERBOSITY: ++ sys.stderr.write('wafcache: another cleaning process is running\n') + else: + # now dow the actual cleanup + lru_trim() +@@ -443,7 +475,10 @@ class fcache(object): + else: + # attempt trimming if caching was successful: + # we may have things to trim! +- lru_evict() ++ try: ++ lru_evict() ++ except Exception: ++ return traceback.format_exc() + return OK + + def copy_from_cache(self, sig, files_from, files_to): +@@ -481,7 +516,7 @@ class bucket_cache(object): + out, err = proc.communicate() + if proc.returncode: + raise OSError('Error copy %r to %r using: %r (exit %r):\n out:%s\n err:%s' % ( +- source, target, cmd, proc.returncode, out.decode(), err.decode())) ++ source, target, cmd, proc.returncode, out.decode(errors='replace'), err.decode(errors='replace'))) + + def copy_to_cache(self, sig, files_from, files_to): + try: +-- +2.37.3 + diff --git a/net/samba413/files/patch-waf-2.0.23 b/net/samba413/files/patch-waf-2.0.23 new file mode 100644 index 000000000000..36a70e32e8c3 --- /dev/null +++ b/net/samba413/files/patch-waf-2.0.23 @@ -0,0 +1,877 @@ +From fb175576b698f43224dab815fd6c0763a12db2b2 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 17 Feb 2022 15:40:20 +0100 +Subject: [PATCH] third_party: Update waf to verison 2.0.23 + +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon Feb 21 10:06:27 UTC 2022 on sn-devel-184 +--- + buildtools/bin/waf | 3 +- + buildtools/wafsamba/wafsamba.py | 2 +- + third_party/waf/waflib/Context.py | 6 +- + third_party/waf/waflib/Runner.py | 4 +- + third_party/waf/waflib/TaskGen.py | 8 +- + third_party/waf/waflib/Tools/c_config.py | 1 + + third_party/waf/waflib/Tools/compiler_c.py | 25 +++--- + third_party/waf/waflib/Tools/compiler_cxx.py | 25 +++--- + third_party/waf/waflib/Tools/python.py | 7 +- + third_party/waf/waflib/Tools/qt5.py | 4 +- + third_party/waf/waflib/Tools/winres.py | 35 ++++++++ + .../extras/clang_compilation_database.py | 2 +- + .../waf/waflib/extras/classic_runner.py | 68 +++++++++++++++ + third_party/waf/waflib/extras/color_gcc.py | 2 +- + third_party/waf/waflib/extras/eclipse.py | 74 ++++++++++++++++- + third_party/waf/waflib/extras/gccdeps.py | 82 ++++++++++--------- + third_party/waf/waflib/extras/msvcdeps.py | 54 ++++++++---- + third_party/waf/waflib/extras/msvs.py | 6 +- + third_party/waf/waflib/extras/swig.py | 2 +- + third_party/waf/waflib/extras/wafcache.py | 26 +++--- + third_party/waf/waflib/fixpy2.py | 2 +- + 21 files changed, 325 insertions(+), 113 deletions(-) + create mode 100644 third_party/waf/waflib/extras/classic_runner.py + +diff --git buildtools/bin/waf buildtools/bin/waf +index b0ccb09a877..2001ccdbd8a 100755 +--- buildtools/bin/waf ++++ buildtools/bin/waf +@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. + + import os, sys, inspect + +-VERSION="2.0.22" ++VERSION="2.0.23" + REVISION="x" + GIT="x" + INSTALL="x" +@@ -164,4 +164,3 @@ if __name__ == '__main__': + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir[0]) +- +diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py +index 185ef3b73a2..710b82af663 100644 +--- buildtools/wafsamba/wafsamba.py ++++ buildtools/wafsamba/wafsamba.py +@@ -38,7 +38,7 @@ LIB_PATH="shared" + + os.environ['PYTHONUNBUFFERED'] = '1' + +-if Context.HEXVERSION not in (0x2001600,): ++if Context.HEXVERSION not in (0x2001700,): + Logs.error(''' + Please use the version of waf that comes with Samba, not + a system installed version. See http://wiki.samba.org/index.php/Waf +diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py +index 07ee1201f03..36d1ca74fef 100644 +--- third_party/waf/waflib/Context.py ++++ third_party/waf/waflib/Context.py +@@ -18,13 +18,13 @@ else: + import imp + + # the following 3 constants are updated on each new release (do not touch) +-HEXVERSION=0x2001600 ++HEXVERSION=0x2001700 + """Constant updated on new releases""" + +-WAFVERSION="2.0.22" ++WAFVERSION="2.0.23" + """Constant updated on new releases""" + +-WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c" ++WAFREVISION="cc6b34cf555d354c34f554c41206134072588de7" + """Git revision when the waf version is updated""" + + WAFNAME="waf" +diff --git third_party/waf/waflib/Runner.py third_party/waf/waflib/Runner.py +index 91d55479e20..350c86a22c0 100644 +--- third_party/waf/waflib/Runner.py ++++ third_party/waf/waflib/Runner.py +@@ -71,7 +71,7 @@ class Consumer(Utils.threading.Thread): + """Task to execute""" + self.spawner = spawner + """Coordinator object""" +- self.setDaemon(1) ++ self.daemon = True + self.start() + def run(self): + """ +@@ -98,7 +98,7 @@ class Spawner(Utils.threading.Thread): + """:py:class:`waflib.Runner.Parallel` producer instance""" + self.sem = Utils.threading.Semaphore(master.numjobs) + """Bounded semaphore that prevents spawning more than *n* concurrent consumers""" +- self.setDaemon(1) ++ self.daemon = True + self.start() + def run(self): + """ +diff --git third_party/waf/waflib/TaskGen.py third_party/waf/waflib/TaskGen.py +index f8f92bd57c1..89f63169910 100644 +--- third_party/waf/waflib/TaskGen.py ++++ third_party/waf/waflib/TaskGen.py +@@ -631,12 +631,8 @@ def process_rule(self): + cls.scan = self.scan + elif has_deps: + def scan(self): +- nodes = [] +- for x in self.generator.to_list(getattr(self.generator, 'deps', None)): +- node = self.generator.path.find_resource(x) +- if not node: +- self.generator.bld.fatal('Could not find %r (was it declared?)' % x) +- nodes.append(node) ++ deps = getattr(self.generator, 'deps', None) ++ nodes = self.generator.to_nodes(deps) + return [nodes, []] + cls.scan = scan + +diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py +index 03b6bf61bc0..f5ab19bf6ce 100644 +--- third_party/waf/waflib/Tools/c_config.py ++++ third_party/waf/waflib/Tools/c_config.py +@@ -69,6 +69,7 @@ MACRO_TO_DEST_CPU = { + '__sh__' : 'sh', + '__xtensa__' : 'xtensa', + '__e2k__' : 'e2k', ++'__riscv' : 'riscv', + } + + @conf +diff --git third_party/waf/waflib/Tools/compiler_c.py third_party/waf/waflib/Tools/compiler_c.py +index 931dc57efec..e033ce6c5c3 100644 +--- third_party/waf/waflib/Tools/compiler_c.py ++++ third_party/waf/waflib/Tools/compiler_c.py +@@ -36,18 +36,19 @@ from waflib import Utils + from waflib.Logs import debug + + c_compiler = { +-'win32': ['msvc', 'gcc', 'clang'], +-'cygwin': ['gcc', 'clang'], +-'darwin': ['clang', 'gcc'], +-'aix': ['xlc', 'gcc', 'clang'], +-'linux': ['gcc', 'clang', 'icc'], +-'sunos': ['suncc', 'gcc'], +-'irix': ['gcc', 'irixcc'], +-'hpux': ['gcc'], +-'osf1V': ['gcc'], +-'gnu': ['gcc', 'clang'], +-'java': ['gcc', 'msvc', 'clang', 'icc'], +-'default':['clang', 'gcc'], ++'win32': ['msvc', 'gcc', 'clang'], ++'cygwin': ['gcc', 'clang'], ++'darwin': ['clang', 'gcc'], ++'aix': ['xlc', 'gcc', 'clang'], ++'linux': ['gcc', 'clang', 'icc'], ++'sunos': ['suncc', 'gcc'], ++'irix': ['gcc', 'irixcc'], ++'hpux': ['gcc'], ++'osf1V': ['gcc'], ++'gnu': ['gcc', 'clang'], ++'java': ['gcc', 'msvc', 'clang', 'icc'], ++'gnukfreebsd': ['gcc', 'clang'], ++'default': ['clang', 'gcc'], + } + """ + Dict mapping platform names to Waf tools finding specific C compilers:: +diff --git third_party/waf/waflib/Tools/compiler_cxx.py third_party/waf/waflib/Tools/compiler_cxx.py +index 09fca7e4dc6..42658c5847e 100644 +--- third_party/waf/waflib/Tools/compiler_cxx.py ++++ third_party/waf/waflib/Tools/compiler_cxx.py +@@ -37,18 +37,19 @@ from waflib import Utils + from waflib.Logs import debug + + cxx_compiler = { +-'win32': ['msvc', 'g++', 'clang++'], +-'cygwin': ['g++', 'clang++'], +-'darwin': ['clang++', 'g++'], +-'aix': ['xlc++', 'g++', 'clang++'], +-'linux': ['g++', 'clang++', 'icpc'], +-'sunos': ['sunc++', 'g++'], +-'irix': ['g++'], +-'hpux': ['g++'], +-'osf1V': ['g++'], +-'gnu': ['g++', 'clang++'], +-'java': ['g++', 'msvc', 'clang++', 'icpc'], +-'default': ['clang++', 'g++'] ++'win32': ['msvc', 'g++', 'clang++'], ++'cygwin': ['g++', 'clang++'], ++'darwin': ['clang++', 'g++'], ++'aix': ['xlc++', 'g++', 'clang++'], ++'linux': ['g++', 'clang++', 'icpc'], ++'sunos': ['sunc++', 'g++'], ++'irix': ['g++'], ++'hpux': ['g++'], ++'osf1V': ['g++'], ++'gnu': ['g++', 'clang++'], ++'java': ['g++', 'msvc', 'clang++', 'icpc'], ++'gnukfreebsd': ['g++', 'clang++'], ++'default': ['clang++', 'g++'] + } + """ + Dict mapping the platform names to Waf tools finding specific C++ compilers:: +diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py +index 07442561dff..fb641e5e20d 100644 +--- third_party/waf/waflib/Tools/python.py ++++ third_party/waf/waflib/Tools/python.py +@@ -416,9 +416,14 @@ def check_python_headers(conf, features='pyembed pyext'): + + if not result: + path = [os.path.join(dct['prefix'], "libs")] +- conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") ++ conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY rather than pythonX.Y (win32)\n") + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) + ++ if not result: ++ path = [os.path.normpath(os.path.join(dct['INCLUDEPY'], '..', 'libs'))] ++ conf.to_log("\n\n# try again with -L$INCLUDEPY/../libs, and pythonXY rather than pythonX.Y (win32)\n") ++ result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $INCLUDEPY/../libs' % name) ++ + if result: + break # do not forget to set LIBPATH_PYEMBED + +diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py +index 82c83e18c8a..b3e61325e50 100644 +--- third_party/waf/waflib/Tools/qt5.py ++++ third_party/waf/waflib/Tools/qt5.py +@@ -783,8 +783,8 @@ def set_qt5_libs_to_check(self): + pat = self.env.cxxstlib_PATTERN + if Utils.unversioned_sys_platform() == 'darwin': + pat = r"%s\.framework" +- re_qt = re.compile(pat % 'Qt5?(?P\\D+)' + '$') +- for x in dirlst: ++ re_qt = re.compile(pat % 'Qt5?(?P\\w+)' + '$') ++ for x in sorted(dirlst): + m = re_qt.match(x) + if m: + self.qt5_vars.append("Qt5%s" % m.group('name')) +diff --git third_party/waf/waflib/Tools/winres.py third_party/waf/waflib/Tools/winres.py +index 9be1ed66009..73c0e95315b 100644 +--- third_party/waf/waflib/Tools/winres.py ++++ third_party/waf/waflib/Tools/winres.py +@@ -4,10 +4,12 @@ + + "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" + ++import os + import re + from waflib import Task + from waflib.TaskGen import extension + from waflib.Tools import c_preproc ++from waflib import Utils + + @extension('.rc') + def rc_file(self, node): +@@ -61,6 +63,39 @@ class winrc(Task.Task): + tmp.start(self.inputs[0], self.env) + return (tmp.nodes, tmp.names) + ++ def exec_command(self, cmd, **kw): ++ if self.env.WINRC_TGT_F == '/fo': ++ # Since winres include paths may contain spaces, they do not fit in ++ # response files and are best passed as environment variables ++ replace_cmd = [] ++ incpaths = [] ++ while cmd: ++ # filter include path flags ++ flag = cmd.pop(0) ++ if flag.upper().startswith('/I'): ++ if len(flag) == 2: ++ incpaths.append(cmd.pop(0)) ++ else: ++ incpaths.append(flag[2:]) ++ else: ++ replace_cmd.append(flag) ++ cmd = replace_cmd ++ if incpaths: ++ # append to existing environment variables in INCLUDE ++ env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ) ++ pre_includes = env.get('INCLUDE', '') ++ env['INCLUDE'] = pre_includes + os.pathsep + os.pathsep.join(incpaths) ++ ++ return super(winrc, self).exec_command(cmd, **kw) ++ ++ def quote_flag(self, flag): ++ if self.env.WINRC_TGT_F == '/fo': ++ # winres does not support quotes around flags in response files ++ return flag ++ ++ return super(winrc, self).quote_flag(flag) ++ ++ + def configure(conf): + """ + Detects the programs RC or windres, depending on the C/C++ compiler in use +diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py +index 17f66949376..bd29db93fd5 100644 +--- third_party/waf/waflib/extras/clang_compilation_database.py ++++ third_party/waf/waflib/extras/clang_compilation_database.py +@@ -126,7 +126,7 @@ def patch_execute(): + Invoke clangdb command before build + """ + if self.cmd.startswith('build'): +- Scripting.run_command('clangdb') ++ Scripting.run_command(self.cmd.replace('build','clangdb')) + + old_execute_build(self) + +diff --git third_party/waf/waflib/extras/classic_runner.py third_party/waf/waflib/extras/classic_runner.py +new file mode 100644 +index 00000000000..b08c794e880 +--- /dev/null ++++ third_party/waf/waflib/extras/classic_runner.py +@@ -0,0 +1,68 @@ ++#!/usr/bin/env python ++# encoding: utf-8 ++# Thomas Nagy, 2021 (ita) ++ ++from waflib import Utils, Runner ++ ++""" ++Re-enable the classic threading system from waf 1.x ++ ++def configure(conf): ++ conf.load('classic_runner') ++""" ++ ++class TaskConsumer(Utils.threading.Thread): ++ """ ++ Task consumers belong to a pool of workers ++ ++ They wait for tasks in the queue and then use ``task.process(...)`` ++ """ ++ def __init__(self, spawner): ++ Utils.threading.Thread.__init__(self) ++ """ ++ Obtain :py:class:`waflib.Task.TaskBase` instances from this queue. ++ """ ++ self.spawner = spawner ++ self.daemon = True ++ self.start() ++ ++ def run(self): ++ """ ++ Loop over the tasks to execute ++ """ ++ try: ++ self.loop() ++ except Exception: ++ pass ++ ++ def loop(self): ++ """ ++ Obtain tasks from :py:attr:`waflib.Runner.TaskConsumer.ready` and call ++ :py:meth:`waflib.Task.TaskBase.process`. If the object is a function, execute it. ++ """ ++ master = self.spawner.master ++ while 1: ++ if not master.stop: ++ try: ++ tsk = master.ready.get() ++ if tsk: ++ tsk.log_display(tsk.generator.bld) ++ master.process_task(tsk) ++ else: ++ break ++ finally: ++ master.out.put(tsk) ++ ++class Spawner(object): ++ """ ++ Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and ++ spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each ++ :py:class:`waflib.Task.Task` instance. ++ """ ++ def __init__(self, master): ++ self.master = master ++ """:py:class:`waflib.Runner.Parallel` producer instance""" ++ ++ self.pool = [TaskConsumer(self) for i in range(master.numjobs)] ++ ++Runner.Spawner = Spawner +diff --git third_party/waf/waflib/extras/color_gcc.py third_party/waf/waflib/extras/color_gcc.py +index b68c5ebf2df..09729035fec 100644 +--- third_party/waf/waflib/extras/color_gcc.py ++++ third_party/waf/waflib/extras/color_gcc.py +@@ -19,7 +19,7 @@ class ColorGCCFormatter(Logs.formatter): + func = frame.f_code.co_name + if func == 'exec_command': + cmd = frame.f_locals.get('cmd') +- if isinstance(cmd, list) and ('gcc' in cmd[0] or 'g++' in cmd[0]): ++ if isinstance(cmd, list) and (len(cmd) > 0) and ('gcc' in cmd[0] or 'g++' in cmd[0]): + lines = [] + for line in rec.msg.splitlines(): + if 'warning: ' in line: +diff --git third_party/waf/waflib/extras/eclipse.py third_party/waf/waflib/extras/eclipse.py +index bb787416e9f..49ca9686b7b 100644 +--- third_party/waf/waflib/extras/eclipse.py ++++ third_party/waf/waflib/extras/eclipse.py +@@ -10,6 +10,9 @@ Usage: + def options(opt): + opt.load('eclipse') + ++To add additional targets beside standard ones (configure, dist, install, check) ++the environment ECLIPSE_EXTRA_TARGETS can be set (ie. to ['test', 'lint', 'docs']) ++ + $ waf configure eclipse + """ + +@@ -25,6 +28,8 @@ cdt_core = oe_cdt + '.core' + cdt_bld = oe_cdt + '.build.core' + extbuilder_dir = '.externalToolBuilders' + extbuilder_name = 'Waf_Builder.launch' ++settings_dir = '.settings' ++settings_name = 'language.settings.xml' + + class eclipse(Build.BuildContext): + cmd = 'eclipse' +@@ -131,9 +136,11 @@ class eclipse(Build.BuildContext): + path = p.path_from(self.srcnode) + + if (path.startswith("/")): +- cpppath.append(path) ++ if path not in cpppath: ++ cpppath.append(path) + else: +- workspace_includes.append(path) ++ if path not in workspace_includes: ++ workspace_includes.append(path) + + if is_cc and path not in source_dirs: + source_dirs.append(path) +@@ -156,6 +163,61 @@ class eclipse(Build.BuildContext): + project = self.impl_create_javaproject(javasrcpath, javalibpath) + self.write_conf_to_xml('.classpath', project) + ++ # Create editor language settings to have correct standards applied in IDE, as per project configuration ++ try: ++ os.mkdir(settings_dir) ++ except OSError: ++ pass # Ignore if dir already exists ++ ++ lang_settings = Document() ++ project = lang_settings.createElement('project') ++ ++ # Language configurations for C and C++ via cdt ++ if hasc: ++ configuration = self.add(lang_settings, project, 'configuration', ++ {'id' : 'org.eclipse.cdt.core.default.config.1', 'name': 'Default'}) ++ ++ extension = self.add(lang_settings, configuration, 'extension', {'point': 'org.eclipse.cdt.core.LanguageSettingsProvider'}) ++ ++ provider = self.add(lang_settings, extension, 'provider', ++ { 'copy-of': 'extension', ++ 'id': 'org.eclipse.cdt.ui.UserLanguageSettingsProvider'}) ++ ++ provider = self.add(lang_settings, extension, 'provider-reference', ++ { 'id': 'org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider', ++ 'ref': 'shared-provider'}) ++ ++ provider = self.add(lang_settings, extension, 'provider-reference', ++ { 'id': 'org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider', ++ 'ref': 'shared-provider'}) ++ ++ # C and C++ are kept as separated providers so appropriate flags are used also in mixed projects ++ if self.env.CC: ++ provider = self.add(lang_settings, extension, 'provider', ++ { 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector', ++ 'console': 'false', ++ 'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.1', ++ 'keep-relative-paths' : 'false', ++ 'name': 'CDT GCC Built-in Compiler Settings', ++ 'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CC[0],' '.join(self.env['CFLAGS'])), ++ 'prefer-non-shared': 'true' }) ++ ++ self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.gcc'}) ++ ++ if self.env.CXX: ++ provider = self.add(lang_settings, extension, 'provider', ++ { 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector', ++ 'console': 'false', ++ 'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.2', ++ 'keep-relative-paths' : 'false', ++ 'name': 'CDT GCC Built-in Compiler Settings', ++ 'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CXX[0],' '.join(self.env['CXXFLAGS'])), ++ 'prefer-non-shared': 'true' }) ++ self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.g++'}) ++ ++ lang_settings.appendChild(project) ++ self.write_conf_to_xml('%s%s%s'%(settings_dir, os.path.sep, settings_name), lang_settings) ++ + def impl_create_project(self, executable, appname, hasc, hasjava, haspython, waf_executable): + doc = Document() + projectDescription = doc.createElement('projectDescription') +@@ -341,6 +403,8 @@ class eclipse(Build.BuildContext): + addTargetWrap('dist', False) + addTargetWrap('install', False) + addTargetWrap('check', False) ++ for addTgt in self.env.ECLIPSE_EXTRA_TARGETS or []: ++ addTargetWrap(addTgt, False) + + storageModule = self.add(doc, cproject, 'storageModule', + {'moduleId': 'cdtBuildSystem', +@@ -348,6 +412,12 @@ class eclipse(Build.BuildContext): + + self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname}) + ++ storageModule = self.add(doc, cproject, 'storageModule', ++ {'moduleId': 'org.eclipse.cdt.core.LanguageSettingsProviders'}) ++ ++ storageModule = self.add(doc, cproject, 'storageModule', ++ {'moduleId': 'scannerConfiguration'}) ++ + doc.appendChild(cproject) + return doc + +diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py +index 1fc9373489a..9e9952f2f7d 100644 +--- third_party/waf/waflib/extras/gccdeps.py ++++ third_party/waf/waflib/extras/gccdeps.py +@@ -29,13 +29,6 @@ if not c_preproc.go_absolute: + # Third-party tools are allowed to add extra names in here with append() + supported_compilers = ['gas', 'gcc', 'icc', 'clang'] + +-def scan(self): +- if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: +- return super(self.derived_gccdeps, self).scan() +- nodes = self.generator.bld.node_deps.get(self.uid(), []) +- names = [] +- return (nodes, names) +- + re_o = re.compile(r"\.o$") + re_splitter = re.compile(r'(? Node lookup + + PREPROCESSOR_FLAG = '/showIncludes' + INCLUDE_PATTERN = 'Note: including file:' +@@ -50,23 +49,47 @@ def apply_msvcdeps_flags(taskgen): + if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0: + taskgen.env.append_value(flag, PREPROCESSOR_FLAG) + ++ ++def get_correct_path_case(base_path, path): ++ ''' ++ Return a case-corrected version of ``path`` by searching the filesystem for ++ ``path``, relative to ``base_path``, using the case returned by the filesystem. ++ ''' ++ components = Utils.split_path(path) ++ ++ corrected_path = '' ++ if os.path.isabs(path): ++ corrected_path = components.pop(0).upper() + os.sep ++ ++ for part in components: ++ part = part.lower() ++ search_path = os.path.join(base_path, corrected_path) ++ if part == '..': ++ corrected_path = os.path.join(corrected_path, part) ++ search_path = os.path.normpath(search_path) ++ continue ++ ++ for item in sorted(os.listdir(search_path)): ++ if item.lower() == part: ++ corrected_path = os.path.join(corrected_path, item) ++ break ++ else: ++ raise ValueError("Can't find %r in %r" % (part, search_path)) ++ ++ return corrected_path ++ ++ + def path_to_node(base_node, path, cached_nodes): + ''' + Take the base node and the path and return a node + Results are cached because searching the node tree is expensive + The following code is executed by threads, it is not safe, so a lock is needed... + ''' +- # normalize the path because ant_glob() does not understand +- # parent path components (..) ++ # normalize the path to remove parent path components (..) + path = os.path.normpath(path) + + # normalize the path case to increase likelihood of a cache hit +- path = os.path.normcase(path) +- +- # ant_glob interprets [] and () characters, so those must be replaced +- path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]') +- +- node_lookup_key = (base_node, path) ++ node_lookup_key = (base_node, os.path.normcase(path)) + + try: + node = cached_nodes[node_lookup_key] +@@ -76,8 +99,8 @@ def path_to_node(base_node, path, cached_nodes): + try: + node = cached_nodes[node_lookup_key] + except KeyError: +- node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False) +- node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None ++ path = get_correct_path_case(base_node.abspath(), path) ++ node = cached_nodes[node_lookup_key] = base_node.find_node(path) + + return node + +@@ -89,9 +112,9 @@ def post_run(self): + if getattr(self, 'cached', None): + return Task.Task.post_run(self) + +- bld = self.generator.bld +- unresolved_names = [] + resolved_nodes = [] ++ unresolved_names = [] ++ bld = self.generator.bld + + # Dynamically bind to the cache + try: +@@ -124,11 +147,14 @@ def post_run(self): + continue + + if id(node) == id(self.inputs[0]): +- # Self-dependency ++ # ignore the source file, it is already in the dependencies ++ # this way, successful config tests may be retrieved from the cache + continue + + resolved_nodes.append(node) + ++ Logs.debug('deps: msvcdeps for %s returned %s', self, resolved_nodes) ++ + bld.node_deps[self.uid()] = resolved_nodes + bld.raw_deps[self.uid()] = unresolved_names + +diff --git third_party/waf/waflib/extras/msvs.py third_party/waf/waflib/extras/msvs.py +index 8aa2db0b751..03b739f849c 100644 +--- third_party/waf/waflib/extras/msvs.py ++++ third_party/waf/waflib/extras/msvs.py +@@ -787,8 +787,12 @@ class msvs_generator(BuildContext): + self.collect_dirs() + default_project = getattr(self, 'default_project', None) + def sortfun(x): +- if x.name == default_project: ++ # folders should sort to the top ++ if getattr(x, 'VS_GUID_SOLUTIONFOLDER', None): + return '' ++ # followed by the default project ++ elif x.name == default_project: ++ return ' ' + return getattr(x, 'path', None) and x.path.win32path() or x.name + self.all_projects.sort(key=sortfun) + +diff --git third_party/waf/waflib/extras/swig.py third_party/waf/waflib/extras/swig.py +index 740ab46d963..967caeb5a82 100644 +--- third_party/waf/waflib/extras/swig.py ++++ third_party/waf/waflib/extras/swig.py +@@ -17,7 +17,7 @@ tasks have to be added dynamically: + + SWIG_EXTS = ['.swig', '.i'] + +-re_module = re.compile(r'%module(?:\s*\(.*\))?\s+(.+)', re.M) ++re_module = re.compile(r'%module(?:\s*\(.*\))?\s+([^\r\n]+)', re.M) + + re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) + re_2 = re.compile(r'[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) +diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py +index cc23fcd6673..2cef46c0e1c 100644 +--- third_party/waf/waflib/extras/wafcache.py ++++ third_party/waf/waflib/extras/wafcache.py +@@ -258,6 +258,19 @@ def build(bld): + """ + Called during the build process to enable file caching + """ ++ if WAFCACHE_STATS: ++ # Init counter for statistics and hook to print results at the end ++ bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 ++ ++ def printstats(bld): ++ hit_ratio = 0 ++ if bld.cache_reqs > 0: ++ hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 ++ Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % ++ (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) ++ ++ bld.add_post_fun(printstats) ++ + if process_pool: + # already called once + return +@@ -273,19 +286,6 @@ def build(bld): + for x in reversed(list(Task.classes.values())): + make_cached(x) + +- if WAFCACHE_STATS: +- # Init counter for statistics and hook to print results at the end +- bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 +- +- def printstats(bld): +- hit_ratio = 0 +- if bld.cache_reqs > 0: +- hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 +- Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % +- (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) +- +- bld.add_post_fun(printstats) +- + def cache_command(sig, files_from, files_to): + """ + Create a command for cache worker processes, returns a pickled +diff --git third_party/waf/waflib/fixpy2.py third_party/waf/waflib/fixpy2.py +index 24176e06645..c99bff4b9ae 100644 +--- third_party/waf/waflib/fixpy2.py ++++ third_party/waf/waflib/fixpy2.py +@@ -56,7 +56,7 @@ def r1(code): + @subst('Runner.py') + def r4(code): + "generator syntax" +- return code.replace('next(self.biter)', 'self.biter.next()') ++ return code.replace('next(self.biter)', 'self.biter.next()').replace('self.daemon = True', 'self.setDaemon(1)') + + @subst('Context.py') + def r5(code): +-- +2.37.3 + diff --git a/net/samba413/files/patch-waf-2.0.24 b/net/samba413/files/patch-waf-2.0.24 new file mode 100644 index 000000000000..2c5c76e6ca3b --- /dev/null +++ b/net/samba413/files/patch-waf-2.0.24 @@ -0,0 +1,164 @@ +From d19dfe1efb2f6cb0dcf0a63b957df584d8ed5945 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 23 May 2022 07:54:06 +0200 +Subject: [PATCH] third_party: Update waf to version 2.0.24 + +This fixes building of python libraries with Python 3.11! + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15071 + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon May 23 09:34:51 UTC 2022 on sn-devel-184 +--- + buildtools/bin/waf | 2 +- + buildtools/wafsamba/wafsamba.py | 2 +- + third_party/waf/waflib/Context.py | 8 ++++---- + third_party/waf/waflib/Tools/ccroot.py | 1 + + third_party/waf/waflib/Tools/msvc.py | 17 ++++++++++++++++- + third_party/waf/waflib/Tools/python.py | 4 ++-- + third_party/waf/waflib/Tools/tex.py | 1 + + 7 files changed, 26 insertions(+), 9 deletions(-) + +diff --git buildtools/bin/waf buildtools/bin/waf +index 2001ccdbd8a..d9cba343623 100755 +--- buildtools/bin/waf ++++ buildtools/bin/waf +@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. + + import os, sys, inspect + +-VERSION="2.0.23" ++VERSION="2.0.24" + REVISION="x" + GIT="x" + INSTALL="x" +diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py +index 4bd4e9f7fe3..79fe8b5e575 100644 +--- buildtools/wafsamba/wafsamba.py ++++ buildtools/wafsamba/wafsamba.py +@@ -38,7 +38,7 @@ LIB_PATH="shared" + + os.environ['PYTHONUNBUFFERED'] = '1' + +-if Context.HEXVERSION not in (0x2001700,): ++if Context.HEXVERSION not in (0x2001800,): + Logs.error(''' + Please use the version of waf that comes with Samba, not + a system installed version. See http://wiki.samba.org/index.php/Waf +diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py +index 36d1ca74fef..4a0130b24a0 100644 +--- third_party/waf/waflib/Context.py ++++ third_party/waf/waflib/Context.py +@@ -18,13 +18,13 @@ else: + import imp + + # the following 3 constants are updated on each new release (do not touch) +-HEXVERSION=0x2001700 ++HEXVERSION=0x2001800 + """Constant updated on new releases""" + +-WAFVERSION="2.0.23" ++WAFVERSION="2.0.24" + """Constant updated on new releases""" + +-WAFREVISION="cc6b34cf555d354c34f554c41206134072588de7" ++WAFREVISION="1af97c71f5a6756abf36d0f78ed8fd551596d7cb" + """Git revision when the waf version is updated""" + + WAFNAME="waf" +@@ -144,7 +144,7 @@ class Context(ctx): + :type fun: string + + .. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext +- ++ :top-classes: waflib.Context.Context + """ + + errors = Errors +diff --git third_party/waf/waflib/Tools/ccroot.py third_party/waf/waflib/Tools/ccroot.py +index 579d5b2b72b..76deff54dcb 100644 +--- third_party/waf/waflib/Tools/ccroot.py ++++ third_party/waf/waflib/Tools/ccroot.py +@@ -128,6 +128,7 @@ class link_task(Task.Task): + Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. + + .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib ++ :top-classes: waflib.Tools.ccroot.link_task + """ + color = 'YELLOW' + +diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py +index 0c4703aaee9..026a4c7fc48 100644 +--- third_party/waf/waflib/Tools/msvc.py ++++ third_party/waf/waflib/Tools/msvc.py +@@ -109,6 +109,21 @@ def options(opt): + opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') + opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') + ++class MSVCVersion(object): ++ def __init__(self, ver): ++ m = re.search('^(.*)\s+(\d+[.]\d+)', ver) ++ if m: ++ self.name = m.group(1) ++ self.number = float(m.group(2)) ++ else: ++ self.name = ver ++ self.number = 0. ++ ++ def __lt__(self, other): ++ if self.number == other.number: ++ return self.name < other.name ++ return self.number < other.number ++ + @conf + def setup_msvc(conf, versiondict): + """ +@@ -125,7 +140,7 @@ def setup_msvc(conf, versiondict): + platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] + desired_versions = getattr(Options.options, 'msvc_version', '').split(',') + if desired_versions == ['']: +- desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) ++ desired_versions = conf.env.MSVC_VERSIONS or list(sorted(versiondict.keys(), key=MSVCVersion, reverse=True)) + + # Override lazy detection by evaluating after the fact. + lazy_detect = getattr(Options.options, 'msvc_lazy', True) +diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py +index fb641e5e20d..a23bd019335 100644 +--- third_party/waf/waflib/Tools/python.py ++++ third_party/waf/waflib/Tools/python.py +@@ -315,7 +315,7 @@ def check_python_headers(conf, features='pyembed pyext'): + conf.fatal('Could not find the python executable') + + # so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below +- v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() ++ v = 'prefix SO EXT_SUFFIX LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() + try: + lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) + except RuntimeError: +@@ -328,7 +328,7 @@ def check_python_headers(conf, features='pyembed pyext'): + x = 'MACOSX_DEPLOYMENT_TARGET' + if dct[x]: + env[x] = conf.environ[x] = str(dct[x]) +- env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake ++ env.pyext_PATTERN = '%s' + (dct['EXT_SUFFIX'] or dct['SO']) # SO is deprecated in 3.5 and removed in 3.11 + + + # Try to get pythonX.Y-config +diff --git third_party/waf/waflib/Tools/tex.py third_party/waf/waflib/Tools/tex.py +index eaf9fdb5802..b4792c3fe87 100644 +--- third_party/waf/waflib/Tools/tex.py ++++ third_party/waf/waflib/Tools/tex.py +@@ -90,6 +90,7 @@ class tex(Task.Task): + Compiles a tex/latex file. + + .. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex ++ :top-classes: waflib.Tools.tex.tex + """ + + bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) +-- +2.37.3 + diff --git a/net/samba413/pkg-plist.ad_dc b/net/samba413/pkg-plist.ad_dc index 13dbcc536782..b7c8a91fbba4 100644 --- a/net/samba413/pkg-plist.ad_dc +++ b/net/samba413/pkg-plist.ad_dc @@ -1,175 +1,173 @@ bin/samba-tool sbin/samba_downgrade_db sbin/samba sbin/samba_dnsupdate sbin/samba_kcc sbin/samba_spnupdate sbin/samba_upgradedns -sbin/samba-gpupdate include/samba4/dcerpc_server.h lib/samba4/libdcerpc-server.so lib/samba4/libdcerpc-server.so.0 lib/samba4/private/libdlz-bind9-for-torture-samba4.so lib/samba4/private/libprocess-model-samba4.so lib/samba4/private/libservice-samba4.so %%GSSAPI_BUILTIN%%lib/samba4/private/libHDB-SAMBA4-samba4.so lib/samba4/private/libdb-glue-samba4.so lib/samba4/private/libdfs-server-ad-samba4.so lib/samba4/private/libdnsserver-common-samba4.so lib/samba4/private/libdsdb-garbage-collect-tombstones-samba4.so lib/samba4/private/libpac-samba4.so lib/samba4/private/libscavenge-dns-records-samba4.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_9.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_10.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_11.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_12.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_14.so %%SAMBA4_MODULEDIR%%/bind9/dlz_bind9_16.so %%SAMBA4_MODULEDIR%%/gensec/krb5.so %%SAMBA4_MODULEDIR%%/ldb/acl.so %%SAMBA4_MODULEDIR%%/ldb/aclread.so %%SAMBA4_MODULEDIR%%/ldb/anr.so %%SAMBA4_MODULEDIR%%/ldb/audit_log.so %%SAMBA4_MODULEDIR%%/ldb/descriptor.so %%SAMBA4_MODULEDIR%%/ldb/dirsync.so %%SAMBA4_MODULEDIR%%/ldb/dns_notify.so %%SAMBA4_MODULEDIR%%/ldb/dsdb_notification.so %%SAMBA4_MODULEDIR%%/ldb/encrypted_secrets.so %%SAMBA4_MODULEDIR%%/ldb/extended_dn_in.so %%SAMBA4_MODULEDIR%%/ldb/extended_dn_out.so %%SAMBA4_MODULEDIR%%/ldb/extended_dn_store.so %%SAMBA4_MODULEDIR%%/ldb/group_audit_log.so %%SAMBA4_MODULEDIR%%/ldb/instancetype.so %%SAMBA4_MODULEDIR%%/ldb/lazy_commit.so %%SAMBA4_MODULEDIR%%/ldb/linked_attributes.so %%SAMBA4_MODULEDIR%%/ldb/new_partition.so %%SAMBA4_MODULEDIR%%/ldb/objectclass_attrs.so %%SAMBA4_MODULEDIR%%/ldb/objectclass.so %%SAMBA4_MODULEDIR%%/ldb/objectguid.so %%SAMBA4_MODULEDIR%%/ldb/operational.so %%SAMBA4_MODULEDIR%%/ldb/paged_results.so %%SAMBA4_MODULEDIR%%/ldb/partition.so %%SAMBA4_MODULEDIR%%/ldb/password_hash.so %%SAMBA4_MODULEDIR%%/ldb/ranged_results.so %%SAMBA4_MODULEDIR%%/ldb/repl_meta_data.so %%SAMBA4_MODULEDIR%%/ldb/resolve_oids.so %%SAMBA4_MODULEDIR%%/ldb/rootdse.so %%SAMBA4_MODULEDIR%%/ldb/samba_dsdb.so %%SAMBA4_MODULEDIR%%/ldb/samba_secrets.so %%SAMBA4_MODULEDIR%%/ldb/samba3sam.so %%SAMBA4_MODULEDIR%%/ldb/samba3sid.so %%SAMBA4_MODULEDIR%%/ldb/samldb.so %%SAMBA4_MODULEDIR%%/ldb/schema_data.so %%SAMBA4_MODULEDIR%%/ldb/schema_load.so %%SAMBA4_MODULEDIR%%/ldb/secrets_tdb_sync.so %%SAMBA4_MODULEDIR%%/ldb/show_deleted.so %%SAMBA4_MODULEDIR%%/ldb/subtree_delete.so %%SAMBA4_MODULEDIR%%/ldb/subtree_rename.so %%SAMBA4_MODULEDIR%%/ldb/tombstone_reanimate.so %%SAMBA4_MODULEDIR%%/ldb/unique_object_sids.so %%SAMBA4_MODULEDIR%%/ldb/update_keytab.so %%SAMBA4_MODULEDIR%%/ldb/vlv.so %%SAMBA4_MODULEDIR%%/ldb/wins_ldb.so %%SAMBA4_MODULEDIR%%/process_model/prefork.so %%SAMBA4_MODULEDIR%%/process_model/standard.so %%SAMBA4_MODULEDIR%%/service/cldap.so %%SAMBA4_MODULEDIR%%/service/dcerpc.so %%SAMBA4_MODULEDIR%%/service/dns_update.so %%SAMBA4_MODULEDIR%%/service/dns.so %%SAMBA4_MODULEDIR%%/service/drepl.so %%SAMBA4_MODULEDIR%%/service/kcc.so %%SAMBA4_MODULEDIR%%/service/kdc.so %%SAMBA4_MODULEDIR%%/service/ldap.so %%SAMBA4_MODULEDIR%%/service/nbtd.so %%SAMBA4_MODULEDIR%%/service/ntp_signd.so %%SAMBA4_MODULEDIR%%/service/s3fs.so %%SAMBA4_MODULEDIR%%/service/winbindd.so %%SAMBA4_MODULEDIR%%/service/wrepl.so %%SAMBA4_MODULEDIR%%/vfs/posix_eadb.so %%PKGCONFIGDIR%%/dcerpc_server.pc %%DATADIR%%/samba/admx/en-US/samba.adml %%DATADIR%%/samba/admx/samba.admx %%DATADIR%%/setup/ad-schema/AD_DS_Attributes__Windows_Server_2012_R2.ldf %%DATADIR%%/setup/ad-schema/AD_DS_Attributes__Windows_Server_2016.ldf %%DATADIR%%/setup/ad-schema/AD_DS_Classes__Windows_Server_2012_R2.ldf %%DATADIR%%/setup/ad-schema/AD_DS_Classes__Windows_Server_2016.ldf %%DATADIR%%/setup/ad-schema/Attributes_for_AD_DS__Windows_Server_2008_R2.ldf %%DATADIR%%/setup/ad-schema/Attributes_for_AD_DS__Windows_Server_2012.ldf %%DATADIR%%/setup/ad-schema/Classes_for_AD_DS__Windows_Server_2008_R2.ldf %%DATADIR%%/setup/ad-schema/Classes_for_AD_DS__Windows_Server_2012.ldf %%DATADIR%%/setup/ad-schema/licence.txt %%DATADIR%%/setup/ad-schema/MS-AD_Schema_2K8_Attributes.txt %%DATADIR%%/setup/ad-schema/MS-AD_Schema_2K8_Classes.txt %%DATADIR%%/setup/ad-schema/MS-AD_Schema_2K8_R2_Attributes.txt %%DATADIR%%/setup/ad-schema/MS-AD_Schema_2K8_R2_Classes.txt %%DATADIR%%/setup/adprep/fix-forest-rev.ldf %%DATADIR%%/setup/adprep/WindowsServerDocs/Forest-Wide-Updates.md %%DATADIR%%/setup/adprep/WindowsServerDocs/Sch49.ldf.diff %%DATADIR%%/setup/adprep/WindowsServerDocs/Sch50.ldf.diff %%DATADIR%%/setup/adprep/WindowsServerDocs/Sch51.ldf.diff %%DATADIR%%/setup/adprep/WindowsServerDocs/Sch57.ldf.diff %%DATADIR%%/setup/adprep/WindowsServerDocs/Sch59.ldf.diff %%DATADIR%%/setup/adprep/WindowsServerDocs/Schema-Updates.md %%DATADIR%%/setup/aggregate_schema.ldif %%DATADIR%%/setup/display-specifiers/DisplaySpecifiers-Win2k0.txt %%DATADIR%%/setup/display-specifiers/DisplaySpecifiers-Win2k3.txt %%DATADIR%%/setup/display-specifiers/DisplaySpecifiers-Win2k3R2.txt %%DATADIR%%/setup/display-specifiers/DisplaySpecifiers-Win2k8.txt %%DATADIR%%/setup/display-specifiers/DisplaySpecifiers-Win2k8R2.txt %%DATADIR%%/setup/dns_update_list %%DATADIR%%/setup/extended-rights.ldif %%DATADIR%%/setup/idmap_init.ldif %%DATADIR%%/setup/krb5.conf %%DATADIR%%/setup/named.conf %%DATADIR%%/setup/named.conf.dlz %%DATADIR%%/setup/named.conf.update %%DATADIR%%/setup/named.txt %%DATADIR%%/setup/prefixMap.txt %%DATADIR%%/setup/provision_basedn_modify.ldif %%DATADIR%%/setup/provision_basedn_options.ldif %%DATADIR%%/setup/provision_basedn_references.ldif %%DATADIR%%/setup/provision_basedn.ldif %%DATADIR%%/setup/provision_computers_add.ldif %%DATADIR%%/setup/provision_computers_modify.ldif %%DATADIR%%/setup/provision_configuration_basedn.ldif %%DATADIR%%/setup/provision_configuration_modify.ldif %%DATADIR%%/setup/provision_configuration_references.ldif %%DATADIR%%/setup/provision_configuration.ldif %%DATADIR%%/setup/provision_dns_accounts_add.ldif %%DATADIR%%/setup/provision_dns_add_samba.ldif %%DATADIR%%/setup/provision_dnszones_add.ldif %%DATADIR%%/setup/provision_dnszones_modify.ldif %%DATADIR%%/setup/provision_dnszones_partitions.ldif %%DATADIR%%/setup/provision_group_policy.ldif %%DATADIR%%/setup/provision_init.ldif %%DATADIR%%/setup/provision_partitions.ldif %%DATADIR%%/setup/provision_privilege.ldif %%DATADIR%%/setup/provision_rootdse_add.ldif %%DATADIR%%/setup/provision_rootdse_modify.ldif %%DATADIR%%/setup/provision_schema_basedn_modify.ldif %%DATADIR%%/setup/provision_schema_basedn.ldif %%DATADIR%%/setup/provision_self_join_config.ldif %%DATADIR%%/setup/provision_self_join_modify_config.ldif %%DATADIR%%/setup/provision_self_join_modify_schema.ldif %%DATADIR%%/setup/provision_self_join_modify.ldif %%DATADIR%%/setup/provision_self_join.ldif %%DATADIR%%/setup/provision_users_add.ldif %%DATADIR%%/setup/provision_users_modify.ldif %%DATADIR%%/setup/provision_users.ldif %%DATADIR%%/setup/provision_well_known_sec_princ.ldif %%DATADIR%%/setup/provision.ldif %%DATADIR%%/setup/provision.reg %%DATADIR%%/setup/provision.zone %%DATADIR%%/setup/schema_samba4.ldif %%DATADIR%%/setup/secrets_dns.ldif %%DATADIR%%/setup/secrets_init.ldif %%DATADIR%%/setup/secrets.ldif %%DATADIR%%/setup/share.ldif %%DATADIR%%/setup/spn_update_list %%DATADIR%%/setup/ypServ30.ldif @dir %%DATADIR%%/setup/display-specifiers @dir %%DATADIR%%/setup/ad-schema @dir %%DATADIR%%/setup @dir %%DATADIR%% -man/man8/samba-gpupdate.8.gz diff --git a/net/samba413/pkg-plist.python b/net/samba413/pkg-plist.python index c931ab22f63e..6de93c2891d0 100644 --- a/net/samba413/pkg-plist.python +++ b/net/samba413/pkg-plist.python @@ -1,386 +1,389 @@ bin/smbtorture +sbin/samba-gpupdate man/man1/smbtorture.1.gz +man/man8/samba-gpupdate.8.gz include/samba4/policy.h lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so.0 lib/samba4/private/libsamba-net%%PYTHON_EXT_SUFFIX%%-samba4.so lib/samba4/private/libsamba-python%%PYTHON_EXT_SUFFIX%%-samba4.so %%PKGCONFIGDIR%%/samba-policy%%PYTHON_EXT_SUFFIX%%.pc @comment Python block %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/dckeytab%%PYTHON_EXT_SUFFIX%%.so %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/posix_eadb%%PYTHON_EXT_SUFFIX%%.so %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/xattr_native%%PYTHON_EXT_SUFFIX%%.so %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/xattr_tdb%%PYTHON_EXT_SUFFIX%%.so %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/dsdb_dns%%PYTHON_EXT_SUFFIX%%.so %%AD_DC%%%%PYTHON_SITELIBDIR%%/samba/dsdb%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/__init__.py %%PYTHON_SITELIBDIR%%/samba/_glue%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/_ldb%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/auth_util.py %%PYTHON_SITELIBDIR%%/samba/auth%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/colour.py %%PYTHON_SITELIBDIR%%/samba/common.py %%PYTHON_SITELIBDIR%%/samba/compat.py %%PYTHON_SITELIBDIR%%/samba/credentials%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/crypto%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dbchecker.py %%PYTHON_SITELIBDIR%%/samba/dcerpc/__init__.py %%PYTHON_SITELIBDIR%%/samba/dcerpc/atsvc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/auth%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/base%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/dcerpc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/dfs%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/dns%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/dnsp%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/dnsserver%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/drsblobs%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/drsuapi%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/echo%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/epmapper%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/idmap%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/initshutdown%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/irpc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/krb5ccache%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/krb5pac%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/lsa%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/mdssvc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/messaging%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/mgmt%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/misc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/nbt%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/netlogon%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/ntlmssp%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/preg%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/samr%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/security%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/server_id%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/smb_acl%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/spoolss%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/srvsvc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/svcctl%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/unixinfo%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/winbind%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/windows_event_ids%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/winreg%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/winspool%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/witness%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/wkssvc%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/dcerpc/xattr%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/descriptor.py %%PYTHON_SITELIBDIR%%/samba/dnsresolver.py %%PYTHON_SITELIBDIR%%/samba/dnsserver.py %%PYTHON_SITELIBDIR%%/samba/domain_update.py %%PYTHON_SITELIBDIR%%/samba/drs_utils.py %%PYTHON_SITELIBDIR%%/samba/emulate/__init__.py %%PYTHON_SITELIBDIR%%/samba/emulate/traffic_packets.py %%PYTHON_SITELIBDIR%%/samba/emulate/traffic.py %%PYTHON_SITELIBDIR%%/samba/forest_update.py %%PYTHON_SITELIBDIR%%/samba/gensec%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/getopt.py %%PYTHON_SITELIBDIR%%/samba/gp_ext_loader.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/__init__.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/gp_aas.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/gp_csv.py %%PYTHON_SITELIBDIR%%/samba/gp_scripts_ext.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/gp_inf.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/gp_ini.py %%PYTHON_SITELIBDIR%%/samba/gp_parse/gp_pol.py %%PYTHON_SITELIBDIR%%/samba/gp_sec_ext.py %%PYTHON_SITELIBDIR%%/samba/gpclass.py %%PYTHON_SITELIBDIR%%/samba/gpo%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/graph.py %%PYTHON_SITELIBDIR%%/samba/hostconfig.py %%PYTHON_SITELIBDIR%%/samba/idmap.py %%PYTHON_SITELIBDIR%%/samba/join.py %%PYTHON_SITELIBDIR%%/samba/kcc/__init__.py %%PYTHON_SITELIBDIR%%/samba/kcc/debug.py %%PYTHON_SITELIBDIR%%/samba/kcc/graph_utils.py %%PYTHON_SITELIBDIR%%/samba/kcc/graph.py %%PYTHON_SITELIBDIR%%/samba/kcc/kcc_utils.py %%PYTHON_SITELIBDIR%%/samba/kcc/ldif_import_export.py %%PYTHON_SITELIBDIR%%/samba/logger.py %%PYTHON_SITELIBDIR%%/samba/mdb_util.py %%PYTHON_SITELIBDIR%%/samba/messaging%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/ms_display_specifiers.py %%PYTHON_SITELIBDIR%%/samba/ms_forest_updates_markdown.py %%PYTHON_SITELIBDIR%%/samba/ms_schema_markdown.py %%PYTHON_SITELIBDIR%%/samba/ms_schema.py %%PYTHON_SITELIBDIR%%/samba/ndr.py %%PYTHON_SITELIBDIR%%/samba/net%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/netbios%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/netcmd/__init__.py %%PYTHON_SITELIBDIR%%/samba/netcmd/common.py %%PYTHON_SITELIBDIR%%/samba/netcmd/computer.py %%PYTHON_SITELIBDIR%%/samba/netcmd/contact.py %%PYTHON_SITELIBDIR%%/samba/netcmd/dbcheck.py %%PYTHON_SITELIBDIR%%/samba/netcmd/delegation.py %%PYTHON_SITELIBDIR%%/samba/netcmd/dns.py %%PYTHON_SITELIBDIR%%/samba/netcmd/domain_backup.py %%PYTHON_SITELIBDIR%%/samba/netcmd/domain.py %%PYTHON_SITELIBDIR%%/samba/netcmd/drs.py %%PYTHON_SITELIBDIR%%/samba/netcmd/dsacl.py %%PYTHON_SITELIBDIR%%/samba/netcmd/forest.py %%PYTHON_SITELIBDIR%%/samba/netcmd/fsmo.py %%PYTHON_SITELIBDIR%%/samba/netcmd/gpo.py %%PYTHON_SITELIBDIR%%/samba/netcmd/group.py %%PYTHON_SITELIBDIR%%/samba/netcmd/ldapcmp.py %%PYTHON_SITELIBDIR%%/samba/netcmd/main.py %%PYTHON_SITELIBDIR%%/samba/netcmd/nettime.py %%PYTHON_SITELIBDIR%%/samba/netcmd/ntacl.py %%PYTHON_SITELIBDIR%%/samba/netcmd/ou.py %%PYTHON_SITELIBDIR%%/samba/netcmd/processes.py %%PYTHON_SITELIBDIR%%/samba/netcmd/pso.py %%PYTHON_SITELIBDIR%%/samba/netcmd/rodc.py %%PYTHON_SITELIBDIR%%/samba/netcmd/schema.py %%PYTHON_SITELIBDIR%%/samba/netcmd/sites.py %%PYTHON_SITELIBDIR%%/samba/netcmd/spn.py %%PYTHON_SITELIBDIR%%/samba/netcmd/testparm.py %%PYTHON_SITELIBDIR%%/samba/netcmd/user.py %%PYTHON_SITELIBDIR%%/samba/netcmd/visualize.py %%PYTHON_SITELIBDIR%%/samba/ntacls.py %%PYTHON_SITELIBDIR%%/samba/ntstatus%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/param%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/policy%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/provision/__init__.py %%PYTHON_SITELIBDIR%%/samba/provision/backend.py %%PYTHON_SITELIBDIR%%/samba/provision/common.py %%PYTHON_SITELIBDIR%%/samba/provision/kerberos_implementation.py %%PYTHON_SITELIBDIR%%/samba/provision/kerberos.py %%PYTHON_SITELIBDIR%%/samba/provision/sambadns.py %%PYTHON_SITELIBDIR%%/samba/registry%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/remove_dc.py %%PYTHON_SITELIBDIR%%/samba/samba3/__init__.py %%PYTHON_SITELIBDIR%%/samba/samba3/libsmb_samba_internal%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/samba3/mdscli%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/samba3/param%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/samba3/passdb%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/samba3/smbd%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/samdb.py %%PYTHON_SITELIBDIR%%/samba/schema.py %%PYTHON_SITELIBDIR%%/samba/sd_utils.py %%PYTHON_SITELIBDIR%%/samba/security%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/sites.py %%PYTHON_SITELIBDIR%%/samba/subnets.py %%PYTHON_SITELIBDIR%%/samba/subunit/__init__.py %%PYTHON_SITELIBDIR%%/samba/subunit/run.py %%PYTHON_SITELIBDIR%%/samba/tdb_util.py %%PYTHON_SITELIBDIR%%/samba/tests/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/audit_log_base.py %%PYTHON_SITELIBDIR%%/samba/tests/audit_log_dsdb.py %%PYTHON_SITELIBDIR%%/samba/tests/audit_log_pass_change.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_base.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_ncalrpc.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_netlogon_bad_creds.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_netlogon.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_pass_change.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_samlogon.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log_winbind.py %%PYTHON_SITELIBDIR%%/samba/tests/auth_log.py %%PYTHON_SITELIBDIR%%/samba/tests/auth.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/bug13653.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/check_output.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/downgradedatabase.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/mdfind.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/ndrdump.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/netads_json.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/samba_dnsupdate.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/smbcacls_basic.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/smbcacls.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/smbcontrol_process.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/smbcontrol.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/traffic_learner.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/traffic_replay.py %%PYTHON_SITELIBDIR%%/samba/tests/blackbox/traffic_summary.py %%PYTHON_SITELIBDIR%%/samba/tests/common.py %%PYTHON_SITELIBDIR%%/samba/tests/complex_expressions.py %%PYTHON_SITELIBDIR%%/samba/tests/core.py %%PYTHON_SITELIBDIR%%/samba/tests/credentials.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/array.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/bare.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/dnsserver.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/integer.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/lsa.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/mdssvc.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/misc.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/raw_protocol.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/raw_testcase.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/registry.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/rpc_talloc.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/rpcecho.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/sam.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/srvsvc.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/string_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/testrpc.py %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc/unix.py %%PYTHON_SITELIBDIR%%/samba/tests/dckeytab.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_base.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_forwarder_helpers/server.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_forwarder.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_invalid.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_packet.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_tkey.py %%PYTHON_SITELIBDIR%%/samba/tests/dns_wildcard.py %%PYTHON_SITELIBDIR%%/samba/tests/dns.py %%PYTHON_SITELIBDIR%%/samba/tests/docs.py %%PYTHON_SITELIBDIR%%/samba/tests/domain_backup_offline.py %%PYTHON_SITELIBDIR%%/samba/tests/domain_backup.py %%PYTHON_SITELIBDIR%%/samba/tests/dsdb_api.py %%PYTHON_SITELIBDIR%%/samba/tests/dsdb_lock.py %%PYTHON_SITELIBDIR%%/samba/tests/dsdb_schema_attributes.py %%PYTHON_SITELIBDIR%%/samba/tests/dsdb.py %%PYTHON_SITELIBDIR%%/samba/tests/emulate/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/emulate/traffic_packet.py %%PYTHON_SITELIBDIR%%/samba/tests/emulate/traffic.py %%PYTHON_SITELIBDIR%%/samba/tests/encrypted_secrets.py %%PYTHON_SITELIBDIR%%/samba/tests/gensec.py %%PYTHON_SITELIBDIR%%/samba/tests/get_opt.py %%PYTHON_SITELIBDIR%%/samba/tests/getdcname.py %%PYTHON_SITELIBDIR%%/samba/tests/glue.py %%PYTHON_SITELIBDIR%%/samba/tests/gpo.py %%PYTHON_SITELIBDIR%%/samba/tests/graph.py %%PYTHON_SITELIBDIR%%/samba/tests/group_audit.py %%PYTHON_SITELIBDIR%%/samba/tests/hostconfig.py %%PYTHON_SITELIBDIR%%/samba/tests/join.py %%PYTHON_SITELIBDIR%%/samba/tests/kcc/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/kcc/graph_utils.py %%PYTHON_SITELIBDIR%%/samba/tests/kcc/graph.py %%PYTHON_SITELIBDIR%%/samba/tests/kcc/kcc_utils.py %%PYTHON_SITELIBDIR%%/samba/tests/kcc/ldif_import_export.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5_credentials.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/alias_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/as_canonicalization_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/as_req_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/compatability_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/fast_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/kcrypto.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_base_test.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tgs_tests.py +%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kpasswd_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/raw_testcase.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/rfc4120_constants.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/rfc4120_pyasn1.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/rodc_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/s4u_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/salt_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/simple_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/spn_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_ccache.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_idmap_nss.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_ldap.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_min_domain_uid.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_rpc.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/test_smb.py %%PYTHON_SITELIBDIR%%/samba/tests/krb5/xrealm_tests.py %%PYTHON_SITELIBDIR%%/samba/tests/ldap_raw.py %%PYTHON_SITELIBDIR%%/samba/tests/ldap_referrals.py %%PYTHON_SITELIBDIR%%/samba/tests/ldap_spn.py %%PYTHON_SITELIBDIR%%/samba/tests/ldap_upn_sam_account.py %%PYTHON_SITELIBDIR%%/samba/tests/libsmb.py %%PYTHON_SITELIBDIR%%/samba/tests/loadparm.py %%PYTHON_SITELIBDIR%%/samba/tests/lsa_string.py %%PYTHON_SITELIBDIR%%/samba/tests/messaging.py %%PYTHON_SITELIBDIR%%/samba/tests/net_join_no_spnego.py %%PYTHON_SITELIBDIR%%/samba/tests/net_join.py %%PYTHON_SITELIBDIR%%/samba/tests/netbios.py %%PYTHON_SITELIBDIR%%/samba/tests/netcmd.py %%PYTHON_SITELIBDIR%%/samba/tests/netlogonsvc.py %%PYTHON_SITELIBDIR%%/samba/tests/ntacls_backup.py %%PYTHON_SITELIBDIR%%/samba/tests/ntacls.py %%PYTHON_SITELIBDIR%%/samba/tests/ntlm_auth_base.py %%PYTHON_SITELIBDIR%%/samba/tests/ntlm_auth_krb5.py %%PYTHON_SITELIBDIR%%/samba/tests/ntlm_auth.py %%PYTHON_SITELIBDIR%%/samba/tests/ntlmdisabled.py %%PYTHON_SITELIBDIR%%/samba/tests/pam_winbind_chauthtok.py %%PYTHON_SITELIBDIR%%/samba/tests/pam_winbind_warn_pwd_expire.py %%PYTHON_SITELIBDIR%%/samba/tests/pam_winbind.py %%PYTHON_SITELIBDIR%%/samba/tests/param.py %%PYTHON_SITELIBDIR%%/samba/tests/password_hash_fl2003.py %%PYTHON_SITELIBDIR%%/samba/tests/password_hash_fl2008.py %%PYTHON_SITELIBDIR%%/samba/tests/password_hash_gpgme.py %%PYTHON_SITELIBDIR%%/samba/tests/password_hash_ldap.py %%PYTHON_SITELIBDIR%%/samba/tests/password_hash.py %%PYTHON_SITELIBDIR%%/samba/tests/password_quality.py %%PYTHON_SITELIBDIR%%/samba/tests/password_test.py %%PYTHON_SITELIBDIR%%/samba/tests/policy.py %%PYTHON_SITELIBDIR%%/samba/tests/posixacl.py %%PYTHON_SITELIBDIR%%/samba/tests/prefork_restart.py %%PYTHON_SITELIBDIR%%/samba/tests/process_limits.py %%PYTHON_SITELIBDIR%%/samba/tests/provision.py %%PYTHON_SITELIBDIR%%/samba/tests/pso.py %%PYTHON_SITELIBDIR%%/samba/tests/py_credentials.py %%PYTHON_SITELIBDIR%%/samba/tests/registry.py %%PYTHON_SITELIBDIR%%/samba/tests/s3idmapdb.py %%PYTHON_SITELIBDIR%%/samba/tests/s3param.py %%PYTHON_SITELIBDIR%%/samba/tests/s3passdb.py %%PYTHON_SITELIBDIR%%/samba/tests/s3registry.py %%PYTHON_SITELIBDIR%%/samba/tests/s3windb.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/__init__.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/base.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/computer.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/contact.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/demote.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/dnscmd.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/drs_clone_dc_data_lmdb_size.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/dsacl.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/forest.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/fsmo.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/gpo.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/group.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/help.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/join_lmdb_size.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/join.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/ntacl.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/ou.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/passwordsettings.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/processes.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/promote_dc_lmdb_size.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/provision_lmdb_size.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/provision_password_check.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/rodc.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/schema.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/sites.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/timecmd.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_check_password_script.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_virtualCryptSHA_base.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_virtualCryptSHA.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user_wdigest.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/user.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/visualize_drs.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool/visualize.py %%PYTHON_SITELIBDIR%%/samba/tests/samba_upgradedns_lmdb.py %%PYTHON_SITELIBDIR%%/samba/tests/samba3sam.py %%PYTHON_SITELIBDIR%%/samba/tests/samdb_api.py %%PYTHON_SITELIBDIR%%/samba/tests/samdb.py %%PYTHON_SITELIBDIR%%/samba/tests/security.py %%PYTHON_SITELIBDIR%%/samba/tests/segfault.py %%PYTHON_SITELIBDIR%%/samba/tests/smb.py %%PYTHON_SITELIBDIR%%/samba/tests/smbd_base.py %%PYTHON_SITELIBDIR%%/samba/tests/smbd_fuzztest.py %%PYTHON_SITELIBDIR%%/samba/tests/source.py %%PYTHON_SITELIBDIR%%/samba/tests/strings.py %%PYTHON_SITELIBDIR%%/samba/tests/subunitrun.py %%PYTHON_SITELIBDIR%%/samba/tests/tdb_util.py %%PYTHON_SITELIBDIR%%/samba/tests/upgrade.py %%PYTHON_SITELIBDIR%%/samba/tests/upgradeprovision.py %%PYTHON_SITELIBDIR%%/samba/tests/upgradeprovisionneeddc.py %%PYTHON_SITELIBDIR%%/samba/tests/usage.py %%PYTHON_SITELIBDIR%%/samba/tests/xattr.py %%PYTHON_SITELIBDIR%%/samba/upgrade.py %%PYTHON_SITELIBDIR%%/samba/upgradehelpers.py %%PYTHON_SITELIBDIR%%/samba/uptodateness.py %%PYTHON_SITELIBDIR%%/samba/werror%%PYTHON_EXT_SUFFIX%%.so %%PYTHON_SITELIBDIR%%/samba/xattr.py @dir %%PYTHON_SITELIBDIR%%/samba/tests/samba_tool @dir %%PYTHON_SITELIBDIR%%/samba/tests/dcerpc @dir %%PYTHON_SITELIBDIR%%/samba/tests/blackbox @dir %%PYTHON_SITELIBDIR%%/samba/tests @dir %%PYTHON_SITELIBDIR%%/samba/samba3 @dir %%PYTHON_SITELIBDIR%%/samba/provision @dir %%PYTHON_SITELIBDIR%%/samba/netcmd @dir %%PYTHON_SITELIBDIR%%/samba/dcerpc @dir %%PYTHON_SITELIBDIR%%/samba