From f462037f85c3f4cd2aaad538c635259c017ed7f9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 27 Oct 2021 14:24:50 +1300 Subject: [PATCH 001/645] Revert "bootstrap: Cope with case changes in CentOS 8 repo names" This reverts commit 9b5dd480590fb4693547e9a1e27452058c0f5da8. [abartlet@samba.org Reverted to allow subsequent patches to apply cleanly] --- .gitlab-ci.yml | 2 +- bootstrap/config.py | 3 +-- bootstrap/generated-dists/centos8/bootstrap.sh | 3 +-- bootstrap/sha1sum.txt | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c706dac66bd..56adf10c7be 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 8bec130a6b741608616302662edee02fd39f3baf + SAMBA_CI_CONTAINER_TAG: 41319f2580c026f66b2750604a0eb15d6b6f7b50 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. diff --git a/bootstrap/config.py b/bootstrap/config.py index 5ead9f74501..bcada1dc628 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -226,8 +226,7 @@ set -xueo pipefail yum update -y yum install -y dnf-plugins-core yum install -y epel-release -yum config-manager --set-enabled PowerTools -y || \ - yum config-manager --set-enabled powertools -y +yum config-manager --set-enabled PowerTools -y yum update -y yum install -y \ diff --git a/bootstrap/generated-dists/centos8/bootstrap.sh b/bootstrap/generated-dists/centos8/bootstrap.sh index e6fab86e446..22484b3f6ad 100755 --- a/bootstrap/generated-dists/centos8/bootstrap.sh +++ b/bootstrap/generated-dists/centos8/bootstrap.sh @@ -10,8 +10,7 @@ set -xueo pipefail yum update -y yum install -y dnf-plugins-core yum install -y epel-release -yum config-manager --set-enabled PowerTools -y || \ - yum config-manager --set-enabled powertools -y +yum config-manager --set-enabled PowerTools -y yum update -y yum install -y \ diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 5328cff1cd3..62c2245564e 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -8bec130a6b741608616302662edee02fd39f3baf +41319f2580c026f66b2750604a0eb15d6b6f7b50 -- 2.25.1 From 7f39b48fb55b62e920b87acaf77e5948c55f0c61 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 4 Mar 2020 13:58:48 +1300 Subject: [PATCH 002/645] bootstrap: Remove long-unsupported OS versions Samba has not built on these versions for quite some time due to the need for Python 3.5 and GnuTLS 3.4.7 These were always marked as broken, but given the requirements these are never likely to come back. Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider (cherry picked from commit d048d7e17d756099e208fa4d6b931a147b0b1489) --- .gitlab-ci.yml | 2 +- bootstrap/.gitlab-ci.yml | 12 -- bootstrap/config.py | 64 ---------- bootstrap/generated-dists/Vagrantfile | 28 ----- bootstrap/generated-dists/centos6/Dockerfile | 27 ----- .../generated-dists/centos6/bootstrap.sh | 109 ------------------ bootstrap/generated-dists/centos6/locale.sh | 55 --------- .../generated-dists/centos6/packages.yml | 89 -------------- bootstrap/generated-dists/debian7/Dockerfile | 27 ----- .../generated-dists/debian7/bootstrap.sh | 101 ---------------- bootstrap/generated-dists/debian7/locale.sh | 55 --------- .../generated-dists/debian7/packages.yml | 86 -------------- bootstrap/generated-dists/debian8/Dockerfile | 27 ----- .../generated-dists/debian8/bootstrap.sh | 105 ----------------- bootstrap/generated-dists/debian8/locale.sh | 55 --------- .../generated-dists/debian8/packages.yml | 90 --------------- .../generated-dists/ubuntu1404/Dockerfile | 27 ----- .../generated-dists/ubuntu1404/bootstrap.sh | 103 ----------------- .../generated-dists/ubuntu1404/locale.sh | 55 --------- .../generated-dists/ubuntu1404/packages.yml | 88 -------------- bootstrap/sha1sum.txt | 2 +- 21 files changed, 2 insertions(+), 1205 deletions(-) delete mode 100644 bootstrap/generated-dists/centos6/Dockerfile delete mode 100755 bootstrap/generated-dists/centos6/bootstrap.sh delete mode 100755 bootstrap/generated-dists/centos6/locale.sh delete mode 100644 bootstrap/generated-dists/centos6/packages.yml delete mode 100644 bootstrap/generated-dists/debian7/Dockerfile delete mode 100755 bootstrap/generated-dists/debian7/bootstrap.sh delete mode 100755 bootstrap/generated-dists/debian7/locale.sh delete mode 100644 bootstrap/generated-dists/debian7/packages.yml delete mode 100644 bootstrap/generated-dists/debian8/Dockerfile delete mode 100755 bootstrap/generated-dists/debian8/bootstrap.sh delete mode 100755 bootstrap/generated-dists/debian8/locale.sh delete mode 100644 bootstrap/generated-dists/debian8/packages.yml delete mode 100644 bootstrap/generated-dists/ubuntu1404/Dockerfile delete mode 100755 bootstrap/generated-dists/ubuntu1404/bootstrap.sh delete mode 100755 bootstrap/generated-dists/ubuntu1404/locale.sh delete mode 100644 bootstrap/generated-dists/ubuntu1404/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 56adf10c7be..00ffff202d9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 41319f2580c026f66b2750604a0eb15d6b6f7b50 + SAMBA_CI_CONTAINER_TAG: cd4cebb9c611fb98f3a21171dd4832df930add28 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index aa0b6448d74..cbf1cb9b58a 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -89,21 +89,12 @@ ubuntu1804: ubuntu1604: extends: .build_image_template -ubuntu1404: - extends: .build_image_template_force_broken - debian10: extends: .build_image_template debian9: extends: .build_image_template -debian8: - extends: .build_image_template_force_broken - -debian7: - extends: .build_image_template_force_broken - fedora31: extends: .build_image_template @@ -124,9 +115,6 @@ centos7: # We install a compat-gnutls34 package for GnuTLS >= 3.4.7 PKG_CONFIG_PATH: /usr/lib64/compat-gnutls34/pkgconfig:/usr/lib64/compat-nettle32/pkgconfig -centos6: - extends: .build_image_template_force_broken - opensuse150: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index bcada1dc628..552524ae759 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -374,30 +374,6 @@ end DEB_DISTS = { - 'debian7': { - 'docker_image': 'debian:7', - 'vagrant_box': 'debian/wheezy64', - 'replace': { - 'libgnutls28-dev': 'libgnutls-dev', - 'libsystemd-dev': '', # not available, remove - 'lmdb-utils': '', # not available, remove - 'liblmdb-dev': '', # not available, remove - 'python-gpg': 'python-gpgme', - 'python3-gpg': '', # no python3 gpg pkg available, remove - 'language-pack-en': '', # included in locales - 'liburing-dev': '', # not available - } - }, - 'debian8': { - 'docker_image': 'debian:8', - 'vagrant_box': 'debian/jessie64', - 'replace': { - 'python-gpg': 'python-gpgme', - 'python3-gpg': 'python3-gpgme', - 'language-pack-en': '', # included in locales - 'liburing-dev': '', # not available - } - }, 'debian9': { 'docker_image': 'debian:9', 'vagrant_box': 'debian/stretch64', @@ -414,22 +390,6 @@ DEB_DISTS = { 'liburing-dev': '', # not available } }, - 'ubuntu1404': { - 'docker_image': 'ubuntu:14.04', - 'vagrant_box': 'ubuntu/trusty64', - 'replace': { - 'libsystemd-dev': '', # remove - 'libgnutls28-dev': 'libgnutls-dev', - 'python-gpg': 'python-gpgme', - 'python3-gpg': 'python3-gpgme', - 'lmdb-utils': 'lmdb-utils/trusty-backports', - 'liblmdb-dev': 'liblmdb-dev/trusty-backports', - 'libunwind-dev': 'libunwind8-dev', - 'glusterfs-common': '', - 'libcephfs-dev': '', - 'liburing-dev': '', # not available - } - }, 'ubuntu1604': { 'docker_image': 'ubuntu:16.04', 'vagrant_box': 'ubuntu/xenial64', @@ -452,30 +412,6 @@ DEB_DISTS = { RPM_DISTS = { - 'centos6': { - 'docker_image': 'centos:6', - 'vagrant_box': 'centos/6', - 'bootstrap': YUM_BOOTSTRAP, - 'replace': { - 'lsb-release': 'redhat-lsb', - 'python3': 'python36', - 'python3-devel': 'python36-devel', - 'python2-gpg': 'pygpgme', - 'python3-gpg': '', # no python3-gpg yet - '@development-tools': '"@Development Tools"', # add quotes - 'glibc-langpack-en': '', # included in glibc-common - 'glibc-locale-source': '', # included in glibc-common - 'procps-ng': 'procps', # centos6 still use old name - # update perl core modules on centos - # fix: Can't locate Archive/Tar.pm in @INC - 'perl': 'perl-core', - 'rpcsvc-proto-devel': '', - 'glusterfs-api-devel': '', - 'glusterfs-devel': '', - 'libcephfs-devel': '', - 'liburing-devel': '', # not available - } - }, 'centos7': { 'docker_image': 'centos:7', 'vagrant_box': 'centos/7', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index b3cb6bea485..983e66aa57f 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -10,13 +10,6 @@ Vagrant.configure("2") do |config| config.ssh.insert_key = false - config.vm.define "centos6" do |v| - v.vm.box = "centos/6" - v.vm.hostname = "centos6" - v.vm.provision :shell, path: "centos6/bootstrap.sh" - v.vm.provision :shell, path: "centos6/locale.sh" - end - config.vm.define "centos7" do |v| v.vm.box = "centos/7" v.vm.hostname = "centos7" @@ -38,20 +31,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "debian10/locale.sh" end - config.vm.define "debian7" do |v| - v.vm.box = "debian/wheezy64" - v.vm.hostname = "debian7" - v.vm.provision :shell, path: "debian7/bootstrap.sh" - v.vm.provision :shell, path: "debian7/locale.sh" - end - - config.vm.define "debian8" do |v| - v.vm.box = "debian/jessie64" - v.vm.hostname = "debian8" - v.vm.provision :shell, path: "debian8/bootstrap.sh" - v.vm.provision :shell, path: "debian8/locale.sh" - end - config.vm.define "debian9" do |v| v.vm.box = "debian/stretch64" v.vm.hostname = "debian9" @@ -94,13 +73,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "opensuse151/locale.sh" end - config.vm.define "ubuntu1404" do |v| - v.vm.box = "ubuntu/trusty64" - v.vm.hostname = "ubuntu1404" - v.vm.provision :shell, path: "ubuntu1404/bootstrap.sh" - v.vm.provision :shell, path: "ubuntu1404/locale.sh" - end - config.vm.define "ubuntu1604" do |v| v.vm.box = "ubuntu/xenial64" v.vm.hostname = "ubuntu1604" diff --git a/bootstrap/generated-dists/centos6/Dockerfile b/bootstrap/generated-dists/centos6/Dockerfile deleted file mode 100644 index 2716eebdd35..00000000000 --- a/bootstrap/generated-dists/centos6/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM centos:6 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/centos6/bootstrap.sh b/bootstrap/generated-dists/centos6/bootstrap.sh deleted file mode 100755 index ee6fcc33799..00000000000 --- a/bootstrap/generated-dists/centos6/bootstrap.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -yum update -y -yum install -y epel-release -yum install -y yum-plugin-copr -yum copr enable -y sergiomb/SambaAD -yum update -y - -yum install -y \ - "@Development Tools" \ - acl \ - attr \ - autoconf \ - avahi-devel \ - bind-utils \ - binutils \ - bison \ - chrpath \ - cups-devel \ - curl \ - dbus-devel \ - docbook-dtds \ - docbook-style-xsl \ - flex \ - gawk \ - gcc \ - gdb \ - git \ - glib2-devel \ - glibc-common \ - gnutls-devel \ - gpgme-devel \ - gzip \ - hostname \ - htop \ - jansson-devel \ - keyutils-libs-devel \ - krb5-devel \ - krb5-server \ - lcov \ - libacl-devel \ - libarchive-devel \ - libattr-devel \ - libblkid-devel \ - libbsd-devel \ - libcap-devel \ - libicu-devel \ - libnsl2-devel \ - libpcap-devel \ - libsemanage-python \ - libtasn1-devel \ - libtasn1-tools \ - libtirpc-devel \ - libunwind-devel \ - libuuid-devel \ - libxslt \ - lmdb \ - lmdb-devel \ - make \ - mingw64-gcc \ - ncurses-devel \ - openldap-devel \ - pam-devel \ - patch \ - perl-Archive-Tar \ - perl-ExtUtils-MakeMaker \ - perl-JSON-Parse \ - perl-Parse-Yapp \ - perl-Test-Base \ - perl-core \ - perl-generators \ - perl-interpreter \ - pkgconfig \ - policycoreutils-python \ - popt-devel \ - procps \ - psmisc \ - python3-dns \ - python3-markdown \ - python36 \ - python36-devel \ - quota-devel \ - readline-devel \ - redhat-lsb \ - rng-tools \ - rpcgen \ - rsync \ - sed \ - sudo \ - systemd-devel \ - tar \ - tree \ - which \ - xfsprogs-devel \ - yum-utils \ - zlib-devel - -yum clean all - -if [ ! -f /usr/bin/python3 ]; then - ln -sf /usr/bin/python3.6 /usr/bin/python3 -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/centos6/locale.sh b/bootstrap/generated-dists/centos6/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/centos6/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/centos6/packages.yml b/bootstrap/generated-dists/centos6/packages.yml deleted file mode 100644 index 1e2b5a98fa6..00000000000 --- a/bootstrap/generated-dists/centos6/packages.yml +++ /dev/null @@ -1,89 +0,0 @@ ---- -packages: - - "@Development Tools" - - acl - - attr - - autoconf - - avahi-devel - - bind-utils - - binutils - - bison - - chrpath - - cups-devel - - curl - - dbus-devel - - docbook-dtds - - docbook-style-xsl - - flex - - gawk - - gcc - - gdb - - git - - glib2-devel - - glibc-common - - gnutls-devel - - gpgme-devel - - gzip - - hostname - - htop - - jansson-devel - - keyutils-libs-devel - - krb5-devel - - krb5-server - - lcov - - libacl-devel - - libarchive-devel - - libattr-devel - - libblkid-devel - - libbsd-devel - - libcap-devel - - libicu-devel - - libnsl2-devel - - libpcap-devel - - libsemanage-python - - libtasn1-devel - - libtasn1-tools - - libtirpc-devel - - libunwind-devel - - libuuid-devel - - libxslt - - lmdb - - lmdb-devel - - make - - mingw64-gcc - - ncurses-devel - - openldap-devel - - pam-devel - - patch - - perl-Archive-Tar - - perl-ExtUtils-MakeMaker - - perl-JSON-Parse - - perl-Parse-Yapp - - perl-Test-Base - - perl-core - - perl-generators - - perl-interpreter - - pkgconfig - - policycoreutils-python - - popt-devel - - procps - - psmisc - - python3-dns - - python3-markdown - - python36 - - python36-devel - - quota-devel - - readline-devel - - redhat-lsb - - rng-tools - - rpcgen - - rsync - - sed - - sudo - - systemd-devel - - tar - - tree - - which - - xfsprogs-devel - - yum-utils - - zlib-devel \ No newline at end of file diff --git a/bootstrap/generated-dists/debian7/Dockerfile b/bootstrap/generated-dists/debian7/Dockerfile deleted file mode 100644 index dfe0e389653..00000000000 --- a/bootstrap/generated-dists/debian7/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM debian:7 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/debian7/bootstrap.sh b/bootstrap/generated-dists/debian7/bootstrap.sh deleted file mode 100755 index daedce84fd9..00000000000 --- a/bootstrap/generated-dists/debian7/bootstrap.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -export DEBIAN_FRONTEND=noninteractive -apt-get -y update - -apt-get -y install \ - acl \ - apt-utils \ - attr \ - autoconf \ - bind9utils \ - binutils \ - bison \ - build-essential \ - chrpath \ - curl \ - debhelper \ - dnsutils \ - docbook-xml \ - docbook-xsl \ - flex \ - gcc \ - gdb \ - git \ - glusterfs-common \ - gzip \ - heimdal-multidev \ - hostname \ - htop \ - krb5-config \ - krb5-kdc \ - krb5-user \ - lcov \ - libacl1-dev \ - libarchive-dev \ - libattr1-dev \ - libavahi-common-dev \ - libblkid-dev \ - libbsd-dev \ - libcap-dev \ - libcephfs-dev \ - libcups2-dev \ - libdbus-1-dev \ - libglib2.0-dev \ - libgnutls-dev \ - libgpgme11-dev \ - libicu-dev \ - libjansson-dev \ - libjs-jquery \ - libjson-perl \ - libkrb5-dev \ - libldap2-dev \ - libncurses5-dev \ - libpam0g-dev \ - libparse-yapp-perl \ - libpcap-dev \ - libpopt-dev \ - libreadline-dev \ - libtasn1-bin \ - libtasn1-dev \ - libunwind-dev \ - locales \ - lsb-release \ - make \ - mawk \ - mingw-w64 \ - patch \ - perl \ - perl-modules \ - pkg-config \ - procps \ - psmisc \ - python3 \ - python3-dbg \ - python3-dev \ - python3-dnspython \ - python3-iso8601 \ - python3-markdown \ - python3-matplotlib \ - python3-pexpect \ - rng-tools \ - rsync \ - sed \ - sudo \ - tar \ - tree \ - uuid-dev \ - xfslibs-dev \ - xsltproc \ - zlib1g-dev - -apt-get -y autoremove -apt-get -y autoclean -apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/debian7/locale.sh b/bootstrap/generated-dists/debian7/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/debian7/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/debian7/packages.yml b/bootstrap/generated-dists/debian7/packages.yml deleted file mode 100644 index 3cac6870b3e..00000000000 --- a/bootstrap/generated-dists/debian7/packages.yml +++ /dev/null @@ -1,86 +0,0 @@ ---- -packages: - - acl - - apt-utils - - attr - - autoconf - - bind9utils - - binutils - - bison - - build-essential - - chrpath - - curl - - debhelper - - dnsutils - - docbook-xml - - docbook-xsl - - flex - - gcc - - gdb - - git - - glusterfs-common - - gzip - - heimdal-multidev - - hostname - - htop - - krb5-config - - krb5-kdc - - krb5-user - - lcov - - libacl1-dev - - libarchive-dev - - libattr1-dev - - libavahi-common-dev - - libblkid-dev - - libbsd-dev - - libcap-dev - - libcephfs-dev - - libcups2-dev - - libdbus-1-dev - - libglib2.0-dev - - libgnutls-dev - - libgpgme11-dev - - libicu-dev - - libjansson-dev - - libjs-jquery - - libjson-perl - - libkrb5-dev - - libldap2-dev - - libncurses5-dev - - libpam0g-dev - - libparse-yapp-perl - - libpcap-dev - - libpopt-dev - - libreadline-dev - - libtasn1-bin - - libtasn1-dev - - libunwind-dev - - locales - - lsb-release - - make - - mawk - - mingw-w64 - - patch - - perl - - perl-modules - - pkg-config - - procps - - psmisc - - python3 - - python3-dbg - - python3-dev - - python3-dnspython - - python3-iso8601 - - python3-markdown - - python3-matplotlib - - python3-pexpect - - rng-tools - - rsync - - sed - - sudo - - tar - - tree - - uuid-dev - - xfslibs-dev - - xsltproc - - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/generated-dists/debian8/Dockerfile b/bootstrap/generated-dists/debian8/Dockerfile deleted file mode 100644 index a5a35654c22..00000000000 --- a/bootstrap/generated-dists/debian8/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM debian:8 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/debian8/bootstrap.sh b/bootstrap/generated-dists/debian8/bootstrap.sh deleted file mode 100755 index 010508360ed..00000000000 --- a/bootstrap/generated-dists/debian8/bootstrap.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -export DEBIAN_FRONTEND=noninteractive -apt-get -y update - -apt-get -y install \ - acl \ - apt-utils \ - attr \ - autoconf \ - bind9utils \ - binutils \ - bison \ - build-essential \ - chrpath \ - curl \ - debhelper \ - dnsutils \ - docbook-xml \ - docbook-xsl \ - flex \ - gcc \ - gdb \ - git \ - glusterfs-common \ - gzip \ - heimdal-multidev \ - hostname \ - htop \ - krb5-config \ - krb5-kdc \ - krb5-user \ - lcov \ - libacl1-dev \ - libarchive-dev \ - libattr1-dev \ - libavahi-common-dev \ - libblkid-dev \ - libbsd-dev \ - libcap-dev \ - libcephfs-dev \ - libcups2-dev \ - libdbus-1-dev \ - libglib2.0-dev \ - libgnutls28-dev \ - libgpgme11-dev \ - libicu-dev \ - libjansson-dev \ - libjs-jquery \ - libjson-perl \ - libkrb5-dev \ - libldap2-dev \ - liblmdb-dev \ - libncurses5-dev \ - libpam0g-dev \ - libparse-yapp-perl \ - libpcap-dev \ - libpopt-dev \ - libreadline-dev \ - libsystemd-dev \ - libtasn1-bin \ - libtasn1-dev \ - libunwind-dev \ - lmdb-utils \ - locales \ - lsb-release \ - make \ - mawk \ - mingw-w64 \ - patch \ - perl \ - perl-modules \ - pkg-config \ - procps \ - psmisc \ - python3 \ - python3-dbg \ - python3-dev \ - python3-dnspython \ - python3-gpgme \ - python3-iso8601 \ - python3-markdown \ - python3-matplotlib \ - python3-pexpect \ - rng-tools \ - rsync \ - sed \ - sudo \ - tar \ - tree \ - uuid-dev \ - xfslibs-dev \ - xsltproc \ - zlib1g-dev - -apt-get -y autoremove -apt-get -y autoclean -apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/debian8/locale.sh b/bootstrap/generated-dists/debian8/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/debian8/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/debian8/packages.yml b/bootstrap/generated-dists/debian8/packages.yml deleted file mode 100644 index 1c9552b85f3..00000000000 --- a/bootstrap/generated-dists/debian8/packages.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -packages: - - acl - - apt-utils - - attr - - autoconf - - bind9utils - - binutils - - bison - - build-essential - - chrpath - - curl - - debhelper - - dnsutils - - docbook-xml - - docbook-xsl - - flex - - gcc - - gdb - - git - - glusterfs-common - - gzip - - heimdal-multidev - - hostname - - htop - - krb5-config - - krb5-kdc - - krb5-user - - lcov - - libacl1-dev - - libarchive-dev - - libattr1-dev - - libavahi-common-dev - - libblkid-dev - - libbsd-dev - - libcap-dev - - libcephfs-dev - - libcups2-dev - - libdbus-1-dev - - libglib2.0-dev - - libgnutls28-dev - - libgpgme11-dev - - libicu-dev - - libjansson-dev - - libjs-jquery - - libjson-perl - - libkrb5-dev - - libldap2-dev - - liblmdb-dev - - libncurses5-dev - - libpam0g-dev - - libparse-yapp-perl - - libpcap-dev - - libpopt-dev - - libreadline-dev - - libsystemd-dev - - libtasn1-bin - - libtasn1-dev - - libunwind-dev - - lmdb-utils - - locales - - lsb-release - - make - - mawk - - mingw-w64 - - patch - - perl - - perl-modules - - pkg-config - - procps - - psmisc - - python3 - - python3-dbg - - python3-dev - - python3-dnspython - - python3-gpgme - - python3-iso8601 - - python3-markdown - - python3-matplotlib - - python3-pexpect - - rng-tools - - rsync - - sed - - sudo - - tar - - tree - - uuid-dev - - xfslibs-dev - - xsltproc - - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1404/Dockerfile b/bootstrap/generated-dists/ubuntu1404/Dockerfile deleted file mode 100644 index 4cbb2d3902c..00000000000 --- a/bootstrap/generated-dists/ubuntu1404/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM ubuntu:14.04 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1404/bootstrap.sh b/bootstrap/generated-dists/ubuntu1404/bootstrap.sh deleted file mode 100755 index 78c8969ac69..00000000000 --- a/bootstrap/generated-dists/ubuntu1404/bootstrap.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -export DEBIAN_FRONTEND=noninteractive -apt-get -y update - -apt-get -y install \ - acl \ - apt-utils \ - attr \ - autoconf \ - bind9utils \ - binutils \ - bison \ - build-essential \ - chrpath \ - curl \ - debhelper \ - dnsutils \ - docbook-xml \ - docbook-xsl \ - flex \ - gcc \ - gdb \ - git \ - gzip \ - heimdal-multidev \ - hostname \ - htop \ - krb5-config \ - krb5-kdc \ - krb5-user \ - language-pack-en \ - lcov \ - libacl1-dev \ - libarchive-dev \ - libattr1-dev \ - libavahi-common-dev \ - libblkid-dev \ - libbsd-dev \ - libcap-dev \ - libcups2-dev \ - libdbus-1-dev \ - libglib2.0-dev \ - libgnutls-dev \ - libgpgme11-dev \ - libicu-dev \ - libjansson-dev \ - libjs-jquery \ - libjson-perl \ - libkrb5-dev \ - libldap2-dev \ - liblmdb-dev/trusty-backports \ - libncurses5-dev \ - libpam0g-dev \ - libparse-yapp-perl \ - libpcap-dev \ - libpopt-dev \ - libreadline-dev \ - libtasn1-bin \ - libtasn1-dev \ - libunwind8-dev \ - lmdb-utils/trusty-backports \ - locales \ - lsb-release \ - make \ - mawk \ - mingw-w64 \ - patch \ - perl \ - perl-modules \ - pkg-config \ - procps \ - psmisc \ - python3 \ - python3-dbg \ - python3-dev \ - python3-dnspython \ - python3-gpgme \ - python3-iso8601 \ - python3-markdown \ - python3-matplotlib \ - python3-pexpect \ - rng-tools \ - rsync \ - sed \ - sudo \ - tar \ - tree \ - uuid-dev \ - xfslibs-dev \ - xsltproc \ - zlib1g-dev - -apt-get -y autoremove -apt-get -y autoclean -apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1404/locale.sh b/bootstrap/generated-dists/ubuntu1404/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/ubuntu1404/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1404/packages.yml b/bootstrap/generated-dists/ubuntu1404/packages.yml deleted file mode 100644 index f6c8a0aaa00..00000000000 --- a/bootstrap/generated-dists/ubuntu1404/packages.yml +++ /dev/null @@ -1,88 +0,0 @@ ---- -packages: - - acl - - apt-utils - - attr - - autoconf - - bind9utils - - binutils - - bison - - build-essential - - chrpath - - curl - - debhelper - - dnsutils - - docbook-xml - - docbook-xsl - - flex - - gcc - - gdb - - git - - gzip - - heimdal-multidev - - hostname - - htop - - krb5-config - - krb5-kdc - - krb5-user - - language-pack-en - - lcov - - libacl1-dev - - libarchive-dev - - libattr1-dev - - libavahi-common-dev - - libblkid-dev - - libbsd-dev - - libcap-dev - - libcups2-dev - - libdbus-1-dev - - libglib2.0-dev - - libgnutls-dev - - libgpgme11-dev - - libicu-dev - - libjansson-dev - - libjs-jquery - - libjson-perl - - libkrb5-dev - - libldap2-dev - - liblmdb-dev/trusty-backports - - libncurses5-dev - - libpam0g-dev - - libparse-yapp-perl - - libpcap-dev - - libpopt-dev - - libreadline-dev - - libtasn1-bin - - libtasn1-dev - - libunwind8-dev - - lmdb-utils/trusty-backports - - locales - - lsb-release - - make - - mawk - - mingw-w64 - - patch - - perl - - perl-modules - - pkg-config - - procps - - psmisc - - python3 - - python3-dbg - - python3-dev - - python3-dnspython - - python3-gpgme - - python3-iso8601 - - python3-markdown - - python3-matplotlib - - python3-pexpect - - rng-tools - - rsync - - sed - - sudo - - tar - - tree - - uuid-dev - - xfslibs-dev - - xsltproc - - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 62c2245564e..2378dd2d94f 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -41319f2580c026f66b2750604a0eb15d6b6f7b50 +cd4cebb9c611fb98f3a21171dd4832df930add28 -- 2.25.1 From bf46319a4cbb0f8fb4231b77d7ca68b475ef0970 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 4 Mar 2020 13:55:27 +1300 Subject: [PATCH 003/645] .gitlab-ci.yml: Do not build Samba for Ubuntu 16.04 or Debian 9 any longer These only have Python 3.5 and we want to increase the minimum to Python 3.6. Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider (cherry picked from commit e9ce0f13e695f1d7e719923628255ea786a90c20) --- .gitlab-ci.yml | 10 +- bootstrap/.gitlab-ci.yml | 6 - bootstrap/config.py | 19 ---- bootstrap/generated-dists/Vagrantfile | 14 --- bootstrap/generated-dists/debian9/Dockerfile | 27 ----- .../generated-dists/debian9/bootstrap.sh | 105 ------------------ bootstrap/generated-dists/debian9/locale.sh | 55 --------- .../generated-dists/debian9/packages.yml | 90 --------------- .../generated-dists/ubuntu1604/Dockerfile | 27 ----- .../generated-dists/ubuntu1604/bootstrap.sh | 104 ----------------- .../generated-dists/ubuntu1604/locale.sh | 55 --------- .../generated-dists/ubuntu1604/packages.yml | 89 --------------- bootstrap/sha1sum.txt | 2 +- 13 files changed, 2 insertions(+), 601 deletions(-) delete mode 100644 bootstrap/generated-dists/debian9/Dockerfile delete mode 100755 bootstrap/generated-dists/debian9/bootstrap.sh delete mode 100755 bootstrap/generated-dists/debian9/locale.sh delete mode 100644 bootstrap/generated-dists/debian9/packages.yml delete mode 100644 bootstrap/generated-dists/ubuntu1604/Dockerfile delete mode 100755 bootstrap/generated-dists/ubuntu1604/bootstrap.sh delete mode 100755 bootstrap/generated-dists/ubuntu1604/locale.sh delete mode 100644 bootstrap/generated-dists/ubuntu1604/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00ffff202d9..9bd5dd04b4f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: cd4cebb9c611fb98f3a21171dd4832df930add28 + SAMBA_CI_CONTAINER_TAG: 2b0275df23424240774afcd61fae8abed8663996 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -277,14 +277,6 @@ ubuntu1804-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu1804 -ubuntu1604-samba-o3: - extends: .samba-o3-template - image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu1604 - -debian9-samba-o3: - extends: .samba-o3-template - image: $SAMBA_CI_CONTAINER_IMAGE_debian9 - debian10-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_debian10 diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index cbf1cb9b58a..4e52da09dcc 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -86,15 +86,9 @@ services: ubuntu1804: extends: .build_image_template -ubuntu1604: - extends: .build_image_template - debian10: extends: .build_image_template -debian9: - extends: .build_image_template - fedora31: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index 552524ae759..19a2cf08b9d 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -374,14 +374,6 @@ end DEB_DISTS = { - 'debian9': { - 'docker_image': 'debian:9', - 'vagrant_box': 'debian/stretch64', - 'replace': { - 'language-pack-en': '', # included in locales - 'liburing-dev': '', # not available - } - }, 'debian10': { 'docker_image': 'debian:10', 'vagrant_box': 'debian/buster64', @@ -390,17 +382,6 @@ DEB_DISTS = { 'liburing-dev': '', # not available } }, - 'ubuntu1604': { - 'docker_image': 'ubuntu:16.04', - 'vagrant_box': 'ubuntu/xenial64', - 'replace': { - 'python-gpg': 'python-gpgme', - 'python3-gpg': 'python3-gpgme', - 'glusterfs-common': '', - 'libcephfs-dev': '', - 'liburing-dev': '', # not available - } - }, 'ubuntu1804': { 'docker_image': 'ubuntu:18.04', 'vagrant_box': 'ubuntu/bionic64', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 983e66aa57f..091c65488cb 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -31,13 +31,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "debian10/locale.sh" end - config.vm.define "debian9" do |v| - v.vm.box = "debian/stretch64" - v.vm.hostname = "debian9" - v.vm.provision :shell, path: "debian9/bootstrap.sh" - v.vm.provision :shell, path: "debian9/locale.sh" - end - config.vm.define "fedora29" do |v| v.vm.box = "fedora/29-cloud-base" v.vm.hostname = "fedora29" @@ -73,13 +66,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "opensuse151/locale.sh" end - config.vm.define "ubuntu1604" do |v| - v.vm.box = "ubuntu/xenial64" - v.vm.hostname = "ubuntu1604" - v.vm.provision :shell, path: "ubuntu1604/bootstrap.sh" - v.vm.provision :shell, path: "ubuntu1604/locale.sh" - end - config.vm.define "ubuntu1804" do |v| v.vm.box = "ubuntu/bionic64" v.vm.hostname = "ubuntu1804" diff --git a/bootstrap/generated-dists/debian9/Dockerfile b/bootstrap/generated-dists/debian9/Dockerfile deleted file mode 100644 index 50195295447..00000000000 --- a/bootstrap/generated-dists/debian9/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM debian:9 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/debian9/bootstrap.sh b/bootstrap/generated-dists/debian9/bootstrap.sh deleted file mode 100755 index f0847eb3c20..00000000000 --- a/bootstrap/generated-dists/debian9/bootstrap.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -export DEBIAN_FRONTEND=noninteractive -apt-get -y update - -apt-get -y install \ - acl \ - apt-utils \ - attr \ - autoconf \ - bind9utils \ - binutils \ - bison \ - build-essential \ - chrpath \ - curl \ - debhelper \ - dnsutils \ - docbook-xml \ - docbook-xsl \ - flex \ - gcc \ - gdb \ - git \ - glusterfs-common \ - gzip \ - heimdal-multidev \ - hostname \ - htop \ - krb5-config \ - krb5-kdc \ - krb5-user \ - lcov \ - libacl1-dev \ - libarchive-dev \ - libattr1-dev \ - libavahi-common-dev \ - libblkid-dev \ - libbsd-dev \ - libcap-dev \ - libcephfs-dev \ - libcups2-dev \ - libdbus-1-dev \ - libglib2.0-dev \ - libgnutls28-dev \ - libgpgme11-dev \ - libicu-dev \ - libjansson-dev \ - libjs-jquery \ - libjson-perl \ - libkrb5-dev \ - libldap2-dev \ - liblmdb-dev \ - libncurses5-dev \ - libpam0g-dev \ - libparse-yapp-perl \ - libpcap-dev \ - libpopt-dev \ - libreadline-dev \ - libsystemd-dev \ - libtasn1-bin \ - libtasn1-dev \ - libunwind-dev \ - lmdb-utils \ - locales \ - lsb-release \ - make \ - mawk \ - mingw-w64 \ - patch \ - perl \ - perl-modules \ - pkg-config \ - procps \ - psmisc \ - python3 \ - python3-dbg \ - python3-dev \ - python3-dnspython \ - python3-gpg \ - python3-iso8601 \ - python3-markdown \ - python3-matplotlib \ - python3-pexpect \ - rng-tools \ - rsync \ - sed \ - sudo \ - tar \ - tree \ - uuid-dev \ - xfslibs-dev \ - xsltproc \ - zlib1g-dev - -apt-get -y autoremove -apt-get -y autoclean -apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/debian9/locale.sh b/bootstrap/generated-dists/debian9/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/debian9/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/debian9/packages.yml b/bootstrap/generated-dists/debian9/packages.yml deleted file mode 100644 index a242cd8b362..00000000000 --- a/bootstrap/generated-dists/debian9/packages.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -packages: - - acl - - apt-utils - - attr - - autoconf - - bind9utils - - binutils - - bison - - build-essential - - chrpath - - curl - - debhelper - - dnsutils - - docbook-xml - - docbook-xsl - - flex - - gcc - - gdb - - git - - glusterfs-common - - gzip - - heimdal-multidev - - hostname - - htop - - krb5-config - - krb5-kdc - - krb5-user - - lcov - - libacl1-dev - - libarchive-dev - - libattr1-dev - - libavahi-common-dev - - libblkid-dev - - libbsd-dev - - libcap-dev - - libcephfs-dev - - libcups2-dev - - libdbus-1-dev - - libglib2.0-dev - - libgnutls28-dev - - libgpgme11-dev - - libicu-dev - - libjansson-dev - - libjs-jquery - - libjson-perl - - libkrb5-dev - - libldap2-dev - - liblmdb-dev - - libncurses5-dev - - libpam0g-dev - - libparse-yapp-perl - - libpcap-dev - - libpopt-dev - - libreadline-dev - - libsystemd-dev - - libtasn1-bin - - libtasn1-dev - - libunwind-dev - - lmdb-utils - - locales - - lsb-release - - make - - mawk - - mingw-w64 - - patch - - perl - - perl-modules - - pkg-config - - procps - - psmisc - - python3 - - python3-dbg - - python3-dev - - python3-dnspython - - python3-gpg - - python3-iso8601 - - python3-markdown - - python3-matplotlib - - python3-pexpect - - rng-tools - - rsync - - sed - - sudo - - tar - - tree - - uuid-dev - - xfslibs-dev - - xsltproc - - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/Dockerfile b/bootstrap/generated-dists/ubuntu1604/Dockerfile deleted file mode 100644 index 93001fcdcca..00000000000 --- a/bootstrap/generated-dists/ubuntu1604/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM ubuntu:16.04 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh deleted file mode 100755 index a8f47762ded..00000000000 --- a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -export DEBIAN_FRONTEND=noninteractive -apt-get -y update - -apt-get -y install \ - acl \ - apt-utils \ - attr \ - autoconf \ - bind9utils \ - binutils \ - bison \ - build-essential \ - chrpath \ - curl \ - debhelper \ - dnsutils \ - docbook-xml \ - docbook-xsl \ - flex \ - gcc \ - gdb \ - git \ - gzip \ - heimdal-multidev \ - hostname \ - htop \ - krb5-config \ - krb5-kdc \ - krb5-user \ - language-pack-en \ - lcov \ - libacl1-dev \ - libarchive-dev \ - libattr1-dev \ - libavahi-common-dev \ - libblkid-dev \ - libbsd-dev \ - libcap-dev \ - libcups2-dev \ - libdbus-1-dev \ - libglib2.0-dev \ - libgnutls28-dev \ - libgpgme11-dev \ - libicu-dev \ - libjansson-dev \ - libjs-jquery \ - libjson-perl \ - libkrb5-dev \ - libldap2-dev \ - liblmdb-dev \ - libncurses5-dev \ - libpam0g-dev \ - libparse-yapp-perl \ - libpcap-dev \ - libpopt-dev \ - libreadline-dev \ - libsystemd-dev \ - libtasn1-bin \ - libtasn1-dev \ - libunwind-dev \ - lmdb-utils \ - locales \ - lsb-release \ - make \ - mawk \ - mingw-w64 \ - patch \ - perl \ - perl-modules \ - pkg-config \ - procps \ - psmisc \ - python3 \ - python3-dbg \ - python3-dev \ - python3-dnspython \ - python3-gpgme \ - python3-iso8601 \ - python3-markdown \ - python3-matplotlib \ - python3-pexpect \ - rng-tools \ - rsync \ - sed \ - sudo \ - tar \ - tree \ - uuid-dev \ - xfslibs-dev \ - xsltproc \ - zlib1g-dev - -apt-get -y autoremove -apt-get -y autoclean -apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/locale.sh b/bootstrap/generated-dists/ubuntu1604/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/ubuntu1604/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/packages.yml b/bootstrap/generated-dists/ubuntu1604/packages.yml deleted file mode 100644 index c3cd9af9c3e..00000000000 --- a/bootstrap/generated-dists/ubuntu1604/packages.yml +++ /dev/null @@ -1,89 +0,0 @@ ---- -packages: - - acl - - apt-utils - - attr - - autoconf - - bind9utils - - binutils - - bison - - build-essential - - chrpath - - curl - - debhelper - - dnsutils - - docbook-xml - - docbook-xsl - - flex - - gcc - - gdb - - git - - gzip - - heimdal-multidev - - hostname - - htop - - krb5-config - - krb5-kdc - - krb5-user - - language-pack-en - - lcov - - libacl1-dev - - libarchive-dev - - libattr1-dev - - libavahi-common-dev - - libblkid-dev - - libbsd-dev - - libcap-dev - - libcups2-dev - - libdbus-1-dev - - libglib2.0-dev - - libgnutls28-dev - - libgpgme11-dev - - libicu-dev - - libjansson-dev - - libjs-jquery - - libjson-perl - - libkrb5-dev - - libldap2-dev - - liblmdb-dev - - libncurses5-dev - - libpam0g-dev - - libparse-yapp-perl - - libpcap-dev - - libpopt-dev - - libreadline-dev - - libsystemd-dev - - libtasn1-bin - - libtasn1-dev - - libunwind-dev - - lmdb-utils - - locales - - lsb-release - - make - - mawk - - mingw-w64 - - patch - - perl - - perl-modules - - pkg-config - - procps - - psmisc - - python3 - - python3-dbg - - python3-dev - - python3-dnspython - - python3-gpgme - - python3-iso8601 - - python3-markdown - - python3-matplotlib - - python3-pexpect - - rng-tools - - rsync - - sed - - sudo - - tar - - tree - - uuid-dev - - xfslibs-dev - - xsltproc - - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 2378dd2d94f..7344075d11d 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -cd4cebb9c611fb98f3a21171dd4832df930add28 +2b0275df23424240774afcd61fae8abed8663996 -- 2.25.1 From 8a9e1d2f57aaac8e8ae2a4ff56f098e5896eedaa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 17 Mar 2020 16:49:02 +1300 Subject: [PATCH 004/645] bootstrap: Bring back a Ubuntu 16.04 build but just for the samba-fuzz task This is needed to restore oss-fuzz support, as this uses the Ubuntu 16.04 package list because all the docker images provided start with a Ubuntu 16.04 base. REF: https://github.com/google/oss-fuzz/issues/3505 REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21189 Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer (cherry picked from commit e10910f8de542b0be9b89942791bd37288b7a32a) --- .gitlab-ci.yml | 3 +- bootstrap/.gitlab-ci.yml | 11 +- bootstrap/config.py | 11 ++ bootstrap/generated-dists/Vagrantfile | 7 ++ .../generated-dists/ubuntu1604/Dockerfile | 27 +++++ .../generated-dists/ubuntu1604/bootstrap.sh | 104 ++++++++++++++++++ .../generated-dists/ubuntu1604/locale.sh | 55 +++++++++ .../generated-dists/ubuntu1604/packages.yml | 89 +++++++++++++++ bootstrap/sha1sum.txt | 2 +- 9 files changed, 305 insertions(+), 4 deletions(-) create mode 100644 bootstrap/generated-dists/ubuntu1604/Dockerfile create mode 100755 bootstrap/generated-dists/ubuntu1604/bootstrap.sh create mode 100755 bootstrap/generated-dists/ubuntu1604/locale.sh create mode 100644 bootstrap/generated-dists/ubuntu1604/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9bd5dd04b4f..8becacb8d4e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 2b0275df23424240774afcd61fae8abed8663996 + SAMBA_CI_CONTAINER_TAG: 6bb2eeaf8203467d9a93a722071b0f081027410e # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -157,6 +157,7 @@ samba-static: samba-fuzz: extends: .shared_template + image: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1604:${SAMBA_CI_CONTAINER_TAG} ctdb: extends: .shared_template diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index 4e52da09dcc..ecd9f4d4223 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -9,6 +9,7 @@ services: - gce variables: SAMBA_CI_IS_BROKEN_IMAGE: "no" + SAMBA_CI_TEST_JOB: "samba-o3" before_script: # Ensure we are generating correct the container - uname -a @@ -40,9 +41,9 @@ services: docker run --volume $(pwd):${samba_repo_root} --workdir ${samba_repo_root} ${ci_image_name} \ bootstrap/template.py --sha1sum > /tmp/sha1sum-template.txt diff -u bootstrap/sha1sum.txt /tmp/sha1sum-template.txt - # run smoke test with samba-o3 + # run smoke test with samba-o3 or samba-fuzz docker run --volume $(pwd):${samba_repo_root} --workdir ${samba_repo_root} ${ci_image_name} \ - /bin/bash -c "sudo chown -R samba:samba ./** && export PKG_CONFIG_PATH=/usr/lib64/compat-gnutls34/pkgconfig:/usr/lib64/compat-nettle32/pkgconfig && script/autobuild.py samba-o3 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase" + /bin/bash -c "sudo chown -R samba:samba ./** && export PKG_CONFIG_PATH=/usr/lib64/compat-gnutls34/pkgconfig:/usr/lib64/compat-nettle32/pkgconfig && script/autobuild.py ${SAMBA_CI_TEST_JOB} --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase" docker tag ${ci_image_name} ${ci_image_path}:${SAMBA_CI_CONTAINER_TAG} docker tag ${ci_image_name} ${ci_image_path}:${timestamp_tag} # We build all images, but only upload is it's not marked as broken @@ -83,6 +84,12 @@ services: # - $SAMBA_CI_REBUILD_BROKEN_IMAGES == "yes" +# This is ONLY for oss-fuzz, so we test a fuzz build not a real one +ubuntu1604: + extends: .build_image_template + variables: + SAMBA_CI_TEST_JOB: "samba-fuzz" + ubuntu1804: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index 19a2cf08b9d..ff9bb150672 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -382,6 +382,17 @@ DEB_DISTS = { 'liburing-dev': '', # not available } }, + 'ubuntu1604': { + 'docker_image': 'ubuntu:16.04', + 'vagrant_box': 'ubuntu/xenial64', + 'replace': { + 'python-gpg': 'python-gpgme', + 'python3-gpg': 'python3-gpgme', + 'glusterfs-common': '', + 'libcephfs-dev': '', + 'liburing-dev': '', # not available + } + }, 'ubuntu1804': { 'docker_image': 'ubuntu:18.04', 'vagrant_box': 'ubuntu/bionic64', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 091c65488cb..47c58d5a87b 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -66,6 +66,13 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "opensuse151/locale.sh" end + config.vm.define "ubuntu1604" do |v| + v.vm.box = "ubuntu/xenial64" + v.vm.hostname = "ubuntu1604" + v.vm.provision :shell, path: "ubuntu1604/bootstrap.sh" + v.vm.provision :shell, path: "ubuntu1604/locale.sh" + end + config.vm.define "ubuntu1804" do |v| v.vm.box = "ubuntu/bionic64" v.vm.hostname = "ubuntu1804" diff --git a/bootstrap/generated-dists/ubuntu1604/Dockerfile b/bootstrap/generated-dists/ubuntu1604/Dockerfile new file mode 100644 index 00000000000..93001fcdcca --- /dev/null +++ b/bootstrap/generated-dists/ubuntu1604/Dockerfile @@ -0,0 +1,27 @@ +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +FROM ubuntu:16.04 + +# pass in with --build-arg while build +ARG SHA1SUM +RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt + +ADD *.sh /tmp/ +# need root permission, do it before USER samba +RUN /tmp/bootstrap.sh && /tmp/locale.sh + +# if ld.gold exists, force link it to ld +RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" + +# make test can not work with root, so we have to create a new user +RUN useradd -m -U -s /bin/bash samba && \ + mkdir -p /etc/sudoers.d && \ + echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba + +USER samba +WORKDIR /home/samba +# samba tests rely on this +ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh new file mode 100755 index 00000000000..a8f47762ded --- /dev/null +++ b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +export DEBIAN_FRONTEND=noninteractive +apt-get -y update + +apt-get -y install \ + acl \ + apt-utils \ + attr \ + autoconf \ + bind9utils \ + binutils \ + bison \ + build-essential \ + chrpath \ + curl \ + debhelper \ + dnsutils \ + docbook-xml \ + docbook-xsl \ + flex \ + gcc \ + gdb \ + git \ + gzip \ + heimdal-multidev \ + hostname \ + htop \ + krb5-config \ + krb5-kdc \ + krb5-user \ + language-pack-en \ + lcov \ + libacl1-dev \ + libarchive-dev \ + libattr1-dev \ + libavahi-common-dev \ + libblkid-dev \ + libbsd-dev \ + libcap-dev \ + libcups2-dev \ + libdbus-1-dev \ + libglib2.0-dev \ + libgnutls28-dev \ + libgpgme11-dev \ + libicu-dev \ + libjansson-dev \ + libjs-jquery \ + libjson-perl \ + libkrb5-dev \ + libldap2-dev \ + liblmdb-dev \ + libncurses5-dev \ + libpam0g-dev \ + libparse-yapp-perl \ + libpcap-dev \ + libpopt-dev \ + libreadline-dev \ + libsystemd-dev \ + libtasn1-bin \ + libtasn1-dev \ + libunwind-dev \ + lmdb-utils \ + locales \ + lsb-release \ + make \ + mawk \ + mingw-w64 \ + patch \ + perl \ + perl-modules \ + pkg-config \ + procps \ + psmisc \ + python3 \ + python3-dbg \ + python3-dev \ + python3-dnspython \ + python3-gpgme \ + python3-iso8601 \ + python3-markdown \ + python3-matplotlib \ + python3-pexpect \ + rng-tools \ + rsync \ + sed \ + sudo \ + tar \ + tree \ + uuid-dev \ + xfslibs-dev \ + xsltproc \ + zlib1g-dev + +apt-get -y autoremove +apt-get -y autoclean +apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/locale.sh b/bootstrap/generated-dists/ubuntu1604/locale.sh new file mode 100755 index 00000000000..cc64e180483 --- /dev/null +++ b/bootstrap/generated-dists/ubuntu1604/locale.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +# refer to /usr/share/i18n/locales +INPUTFILE=en_US +# refer to /usr/share/i18n/charmaps +CHARMAP=UTF-8 +# locale to generate in /usr/lib/locale +# glibc/localedef will normalize UTF-8 to utf8, follow the naming style +LOCALE=$INPUTFILE.utf8 + +# if locale is already correct, exit +( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 + +# if locale not available, generate locale into /usr/lib/locale +if ! ( locale --all-locales | grep -i $LOCALE ) +then + # no-archive means create its own dir + localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE +fi + +# update locale conf and global env file +# set both LC_ALL and LANG for safe + +# update conf for Debian family +FILE=/etc/default/locale +if [ -f $FILE ] +then + echo LC_ALL="$LOCALE" > $FILE + echo LANG="$LOCALE" >> $FILE +fi + +# update conf for RedHat family +FILE=/etc/locale.conf +if [ -f $FILE ] +then + # LC_ALL is not valid in this file, set LANG only + echo LANG="$LOCALE" > $FILE +fi + +# update global env file +FILE=/etc/environment +if [ -f $FILE ] +then + # append LC_ALL if not exist + grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE + # append LANG if not exist + grep LANG $FILE || echo LANG="$LOCALE" >> $FILE +fi \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu1604/packages.yml b/bootstrap/generated-dists/ubuntu1604/packages.yml new file mode 100644 index 00000000000..c3cd9af9c3e --- /dev/null +++ b/bootstrap/generated-dists/ubuntu1604/packages.yml @@ -0,0 +1,89 @@ +--- +packages: + - acl + - apt-utils + - attr + - autoconf + - bind9utils + - binutils + - bison + - build-essential + - chrpath + - curl + - debhelper + - dnsutils + - docbook-xml + - docbook-xsl + - flex + - gcc + - gdb + - git + - gzip + - heimdal-multidev + - hostname + - htop + - krb5-config + - krb5-kdc + - krb5-user + - language-pack-en + - lcov + - libacl1-dev + - libarchive-dev + - libattr1-dev + - libavahi-common-dev + - libblkid-dev + - libbsd-dev + - libcap-dev + - libcups2-dev + - libdbus-1-dev + - libglib2.0-dev + - libgnutls28-dev + - libgpgme11-dev + - libicu-dev + - libjansson-dev + - libjs-jquery + - libjson-perl + - libkrb5-dev + - libldap2-dev + - liblmdb-dev + - libncurses5-dev + - libpam0g-dev + - libparse-yapp-perl + - libpcap-dev + - libpopt-dev + - libreadline-dev + - libsystemd-dev + - libtasn1-bin + - libtasn1-dev + - libunwind-dev + - lmdb-utils + - locales + - lsb-release + - make + - mawk + - mingw-w64 + - patch + - perl + - perl-modules + - pkg-config + - procps + - psmisc + - python3 + - python3-dbg + - python3-dev + - python3-dnspython + - python3-gpgme + - python3-iso8601 + - python3-markdown + - python3-matplotlib + - python3-pexpect + - rng-tools + - rsync + - sed + - sudo + - tar + - tree + - uuid-dev + - xfslibs-dev + - xsltproc + - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 7344075d11d..1c9d01d5e7d 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -2b0275df23424240774afcd61fae8abed8663996 +6bb2eeaf8203467d9a93a722071b0f081027410e -- 2.25.1 From 726fb38c1ce2126886eaf8a8ed050c54e98c5daf Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 17 Mar 2020 17:39:48 +0100 Subject: [PATCH 005/645] bootstrap: Add podman command to readme Reviewed-by: Alexander Bokovoy (cherry picked from commit 272b43d331c7cd0452069128166404af7f088b36) --- bootstrap/READMD.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bootstrap/READMD.md b/bootstrap/READMD.md index b8a30098b67..023686e20c4 100644 --- a/bootstrap/READMD.md +++ b/bootstrap/READMD.md @@ -83,6 +83,10 @@ With Docker: docker pull registry.gitlab.com/samba-team/devel/samba/samba-ci-ubuntu1804:${sha1sum} docker run -it -v $(pwd):/home/samba/samba samba-ci-ubuntu1804:${sha1sum} bash +With podman: + + podman run -ti --cap-add=SYS_PTRACE --security-opt seccomp=unconfined registry.gitlab.com/samba-team/devel/samba/samba-ci-ubuntu1804:${sha1sum} bash + With Vagrant: cd bootstrap/generated-dists/ -- 2.25.1 From 12fe6ac5e72ff4ca10d883ce3ef2098d8e6fd2a0 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 16 Mar 2020 17:00:16 +0100 Subject: [PATCH 006/645] third_party: Update nss_wrapper to version 1.1.10 Signed-off-by: Andreas Schneider Reviewed-by: Alexander Bokovoy Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Fri Mar 20 12:41:36 UTC 2020 on sn-devel-184 (cherry picked from commit 639e64d30d54d600e96ea06c9a2afaa91cb1c9a4) --- buildtools/wafsamba/samba_third_party.py | 2 +- third_party/nss_wrapper/nss_wrapper.c | 550 ++++++++++++++++++++--- third_party/nss_wrapper/wscript | 3 +- 3 files changed, 493 insertions(+), 62 deletions(-) diff --git a/buildtools/wafsamba/samba_third_party.py b/buildtools/wafsamba/samba_third_party.py index 38df19369d7..a7026034984 100644 --- a/buildtools/wafsamba/samba_third_party.py +++ b/buildtools/wafsamba/samba_third_party.py @@ -29,7 +29,7 @@ Build.BuildContext.CHECK_SOCKET_WRAPPER = CHECK_SOCKET_WRAPPER @conf def CHECK_NSS_WRAPPER(conf): - return conf.CHECK_BUNDLED_SYSTEM_PKG('nss_wrapper', minversion='1.1.7') + return conf.CHECK_BUNDLED_SYSTEM_PKG('nss_wrapper', minversion='1.1.10') Build.BuildContext.CHECK_NSS_WRAPPER = CHECK_NSS_WRAPPER @conf diff --git a/third_party/nss_wrapper/nss_wrapper.c b/third_party/nss_wrapper/nss_wrapper.c index 1bcd3b1b72d..d90264c6d24 100644 --- a/third_party/nss_wrapper/nss_wrapper.c +++ b/third_party/nss_wrapper/nss_wrapper.c @@ -351,6 +351,15 @@ struct nwrap_libc_fns { struct hostent *(*_libc_gethostbyname)(const char *name); #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ struct hostent *(*_libc_gethostbyname2)(const char *name, int af); +#endif +#ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ + int (*_libc_gethostbyname2_r)(const char *name, + int af, + struct hostent *ret, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop); #endif struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type); @@ -395,6 +404,14 @@ struct nwrap_module_nss_fns { NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS (*_nss_endgrent)(void); + NSS_STATUS (*_nss_gethostbyaddr_r)(const void *addr, socklen_t addrlen, + int af, struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); + NSS_STATUS (*_nss_gethostbyname2_r)(const char *name, int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); }; struct nwrap_backend { @@ -405,6 +422,8 @@ struct nwrap_backend { struct nwrap_module_nss_fns *fns; }; +struct nwrap_vector; + struct nwrap_ops { struct passwd * (*nw_getpwnam)(struct nwrap_backend *b, const char *name); @@ -440,6 +459,18 @@ struct nwrap_ops { struct group *grdst, char *buf, size_t buflen, struct group **grdstp); void (*nw_endgrent)(struct nwrap_backend *b); + struct hostent *(*nw_gethostbyaddr)(struct nwrap_backend *b, + const void *addr, + socklen_t len, int type); + struct hostent *(*nw_gethostbyname)(struct nwrap_backend *b, + const char *name); + struct hostent *(*nw_gethostbyname2)(struct nwrap_backend *b, + const char *name, int af); + int (*nw_gethostbyname2_r)(struct nwrap_backend *b, + const char *name, int af, + struct hostent *hedst, + char *buf, size_t buflen, + struct hostent **hedstp); }; /* Public prototypes */ @@ -485,6 +516,20 @@ static int nwrap_files_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_files_endgrent(struct nwrap_backend *b); +static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b, + const void *addr, + socklen_t len, int type); +static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b, + const char *name); +#ifdef HAVE_GETHOSTBYNAME2 +static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b, + const char *name, int af); +#endif /* HAVE_GETHOSTBYNAME2 */ +static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, + const char *name, int af, + struct hostent *hedst, + char *buf, size_t buflen, + struct hostent **hedstp); /* prototypes for module backend */ @@ -522,6 +567,18 @@ static void nwrap_module_setgrent(struct nwrap_backend *b); static void nwrap_module_endgrent(struct nwrap_backend *b); static int nwrap_module_initgroups(struct nwrap_backend *b, const char *user, gid_t group); +static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b, + const void *addr, + socklen_t len, int type); +static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b, + const char *name); +static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b, + const char *name, int af); +static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b, + const char *name, int af, + struct hostent *hedst, + char *buf, size_t buflen, + struct hostent **hedstp); struct nwrap_ops nwrap_files_ops = { .nw_getpwnam = nwrap_files_getpwnam, @@ -541,6 +598,12 @@ struct nwrap_ops nwrap_files_ops = { .nw_getgrent = nwrap_files_getgrent, .nw_getgrent_r = nwrap_files_getgrent_r, .nw_endgrent = nwrap_files_endgrent, + .nw_gethostbyaddr = nwrap_files_gethostbyaddr, + .nw_gethostbyname = nwrap_files_gethostbyname, +#ifdef HAVE_GETHOSTBYNAME2 + .nw_gethostbyname2 = nwrap_files_gethostbyname2, +#endif /* HAVE_GETHOSTBYNAME2 */ + .nw_gethostbyname2_r = nwrap_files_gethostbyname2_r, }; struct nwrap_ops nwrap_module_ops = { @@ -561,6 +624,10 @@ struct nwrap_ops nwrap_module_ops = { .nw_getgrent = nwrap_module_getgrent, .nw_getgrent_r = nwrap_module_getgrent_r, .nw_endgrent = nwrap_module_endgrent, + .nw_gethostbyaddr = nwrap_module_gethostbyaddr, + .nw_gethostbyname = nwrap_module_gethostbyname, + .nw_gethostbyname2 = nwrap_module_gethostbyname2, + .nw_gethostbyname2_r = nwrap_module_gethostbyname2_r, }; struct nwrap_libc { @@ -571,7 +638,7 @@ struct nwrap_libc { }; struct nwrap_main { - int num_backends; + size_t num_backends; struct nwrap_backend *backends; struct nwrap_libc *libc; }; @@ -1318,6 +1385,27 @@ static struct hostent *libc_gethostbyname2(const char *name, int af) } #endif +#ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ +static int libc_gethostbyname2_r(const char *name, + int af, + struct hostent *ret, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2_r); + + return nwrap_main_global->libc->fns->_libc_gethostbyname2_r(name, + af, + ret, + buf, + buflen, + result, + h_errnop); +} +#endif + static struct hostent *libc_gethostbyaddr(const void *addr, socklen_t len, int type) @@ -1417,22 +1505,24 @@ static int libc_getnameinfo(const struct sockaddr *sa, static void *nwrap_load_module_fn(struct nwrap_backend *b, const char *fn_name) { - void *res; - char *s; + void *res = NULL; + char *s = NULL; + int rc; - if (!b->so_handle) { + if (b->so_handle == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "No handle"); return NULL; } - if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) { + rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name); + if (rc == -1) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return NULL; } res = dlsym(b->so_handle, s); - if (!res) { - NWRAP_LOG(NWRAP_LOG_ERROR, + if (res == NULL) { + NWRAP_LOG(NWRAP_LOG_WARN, "Cannot find function %s in %s", s, b->so_path); } @@ -1475,6 +1565,10 @@ static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend * nwrap_load_module_fn(b, "getgrent_r"); *(void **)(&fns->_nss_endgrent) = nwrap_load_module_fn(b, "endgrent"); + *(void **)(&fns->_nss_gethostbyaddr_r) = + nwrap_load_module_fn(b, "gethostbyaddr_r"); + *(void **)(&fns->_nss_gethostbyname2_r) = + nwrap_load_module_fn(b, "gethostbyname2_r"); return fns; } @@ -1501,7 +1595,7 @@ static void *nwrap_load_module(const char *so_path) static bool nwrap_module_init(const char *name, struct nwrap_ops *ops, const char *so_path, - int *num_backends, + size_t *num_backends, struct nwrap_backend **backends) { struct nwrap_backend *b; @@ -3513,9 +3607,9 @@ static void nwrap_files_endgrent(struct nwrap_backend *b) } /* hosts functions */ -static int nwrap_files_gethostbyname(const char *name, int af, - struct hostent *result, - struct nwrap_vector *addr_list) +static int nwrap_files_internal_gethostbyname(const char *name, int af, + struct hostent *result, + struct nwrap_vector *addr_list) { struct nwrap_entlist *el; struct hostent *he; @@ -3527,6 +3621,12 @@ static int nwrap_files_gethostbyname(const char *name, int af, bool he_found = false; bool ok; + /* + * We need to make sure we have zeroed return pointer for consumers + * which don't check return values, e.g. OpenLDAP. + */ + ZERO_STRUCTP(result); + ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); @@ -3611,19 +3711,30 @@ no_ent: return -1; } -#ifdef HAVE_GETHOSTBYNAME_R -static int nwrap_gethostbyname_r(const char *name, - struct hostent *ret, - char *buf, size_t buflen, - struct hostent **result, int *h_errnop) +static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, + const char *name, int af, + struct hostent *hedst, + char *buf, size_t buflen, + struct hostent **hedstp) { - struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector)); + struct nwrap_vector *addr_list = NULL; union { char *ptr; char **list; } g; int rc; + (void) b; /* unused */ + (void) af; /* unused */ + + if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) { + errno = EINVAL; + return -1; + } + *hedstp = NULL; + buf[0] = '\0'; + + addr_list = calloc(1, sizeof(struct nwrap_vector)); if (addr_list == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for address list"); @@ -3631,20 +3742,17 @@ static int nwrap_gethostbyname_r(const char *name, return -1; } - ZERO_STRUCTP(addr_list); - - rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list); + rc = nwrap_files_internal_gethostbyname(name, af, hedst, + addr_list); if (rc == -1) { - *h_errnop = h_errno; - if (addr_list->items != NULL) { - free(addr_list->items); - } + SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); errno = ENOENT; return -1; } - if (buflen < (addr_list->count * sizeof(void *))) { + /* +1 i for ending NULL pointer */ + if (buflen < ((addr_list->count + 1) * sizeof(void *))) { SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); return ERANGE; @@ -3655,15 +3763,38 @@ static int nwrap_gethostbyname_r(const char *name, * +1 is for ending NULL pointer. */ memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *)); - free(addr_list->items); - free(addr_list); + SAFE_FREE(addr_list->items); + SAFE_FREE(addr_list); g.ptr = buf; - ret->h_addr_list = g.list; - *result = ret; + hedst->h_addr_list = g.list; + *hedstp = hedst; return 0; } +#ifdef HAVE_GETHOSTBYNAME_R +static int nwrap_gethostbyname_r(const char *name, + struct hostent *ret, + char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + int rc; + size_t i; + + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret, + buf, buflen, result); + if (rc == 0) { + return 0; + } else if (rc == ERANGE) { + return ERANGE; + } + } + *h_errnop = h_errno; + return ENOENT; +} + int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, @@ -3682,6 +3813,44 @@ int gethostbyname_r(const char *name, } #endif +#ifdef HAVE_GETHOSTBYNAME2_R +static int nwrap_gethostbyname2_r(const char *name, int af, + struct hostent *ret, + char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + int rc; + size_t i; + + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + rc = b->ops->nw_gethostbyname2_r(b, name, af, ret, + buf, buflen, result); + if (rc == 0) { + return 0; + } else if (rc == ERANGE) { + return ERANGE; + } + } + *h_errnop = h_errno; + return ENOENT; +} + +int gethostbyname2_r(const char *name, int af, + struct hostent *ret, + char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + if (!nss_wrapper_hosts_enabled()) { + return libc_gethostbyname2_r(name, af, ret, buf, buflen, + result, h_errnop); + } + + return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result, + h_errnop); +} +#endif + static int nwrap_files_getaddrinfo(const char *name, unsigned short port, const struct addrinfo *hints, @@ -3785,7 +3954,8 @@ static int nwrap_files_getaddrinfo(const char *name, return rc; } -static struct hostent *nwrap_files_gethostbyaddr(const void *addr, +static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b, + const void *addr, socklen_t len, int type) { struct hostent *he; @@ -3795,6 +3965,7 @@ static struct hostent *nwrap_files_gethostbyaddr(const void *addr, size_t i; bool ok; + (void) b; /* unused */ (void) len; /* unused */ ok = nwrap_files_cache_reload(nwrap_he_global.cache); @@ -3831,15 +4002,23 @@ static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { - *result = nwrap_files_gethostbyaddr(addr, len, type); + size_t i; + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + *result = b->ops->nw_gethostbyaddr(b, addr, len, type); + if (*result != NULL) { + break; + } + } + if (*result != NULL) { memset(buf, '\0', buflen); *ret = **result; return 0; - } else { - *h_errnop = h_errno; - return -1; } + + *h_errnop = h_errno; + return -1; } int gethostbyaddr_r(const void *addr, socklen_t len, int type, @@ -4336,13 +4515,189 @@ static void nwrap_module_endgrent(struct nwrap_backend *b) b->fns->_nss_endgrent(); } +static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b, + const void *addr, + socklen_t len, int type) +{ + static struct hostent he; + static char *buf = NULL; + static size_t buflen = 1000; + NSS_STATUS status; + + if (b->fns->_nss_gethostbyaddr_r == NULL) { + return NULL; + } + + if (buf == NULL) { + buf = (char *)malloc(buflen); + if (buf == NULL) { + return NULL; + } + } +again: + status = b->fns->_nss_gethostbyaddr_r(addr, len, type, &he, + buf, buflen, &errno, &h_errno); + if (status == NSS_STATUS_TRYAGAIN) { + char *p = NULL; + + buflen *= 2; + p = (char *)realloc(buf, buflen); + if (p == NULL) { + SAFE_FREE(buf); + return NULL; + } + buf = p; + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + SAFE_FREE(buf); + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + SAFE_FREE(buf); + return NULL; + } + + return &he; +} + +static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b, + const char *name, int af, + struct hostent *hedst, + char *buf, size_t buflen, + struct hostent **hedstp) +{ + NSS_STATUS status; + + *hedstp = NULL; + + if (b->fns->_nss_gethostbyname2_r == NULL) { + return ENOENT; + } + + status = b->fns->_nss_gethostbyname2_r(name, af, hedst, + buf, buflen, &errno, &h_errno); + switch (status) { + case NSS_STATUS_SUCCESS: + *hedstp = hedst; + return 0; + case NSS_STATUS_NOTFOUND: + if (errno != 0) { + return errno; + } + return ENOENT; + case NSS_STATUS_TRYAGAIN: + if (errno != 0) { + return errno; + } + return ERANGE; + default: + if (errno != 0) { + return errno; + } + return status; + } +} + +static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b, + const char *name) +{ + static struct hostent he; + static char *buf = NULL; + static size_t buflen = 1000; + NSS_STATUS status; + + if (b->fns->_nss_gethostbyname2_r == NULL) { + return NULL; + } + + if (buf == NULL) { + buf = (char *)malloc(buflen); + if (buf == NULL) { + return NULL; + } + } + +again: + status = b->fns->_nss_gethostbyname2_r(name, AF_UNSPEC, &he, + buf, buflen, &errno, &h_errno); + if (status == NSS_STATUS_TRYAGAIN) { + char *p = NULL; + + buflen *= 2; + p = (char *)realloc(buf, buflen); + if (p == NULL) { + SAFE_FREE(buf); + return NULL; + } + buf = p; + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + SAFE_FREE(buf); + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + SAFE_FREE(buf); + return NULL; + } + + return &he; +} + +static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b, + const char *name, int af) +{ + static struct hostent he; + static char *buf = NULL; + static size_t buflen = 1000; + NSS_STATUS status; + + if (b->fns->_nss_gethostbyname2_r == NULL) { + return NULL; + } + + if (buf == NULL) { + buf = (char *)malloc(buflen); + if (buf == NULL) { + return NULL; + } + } + +again: + status = b->fns->_nss_gethostbyname2_r(name, af, &he, + buf, buflen, &errno, &h_errno); + if (status == NSS_STATUS_TRYAGAIN) { + char *p = NULL; + + buflen *= 2; + p = (char *)realloc(buf, buflen); + if (p == NULL) { + SAFE_FREE(buf); + return NULL; + } + buf = p; + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + SAFE_FREE(buf); + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + SAFE_FREE(buf); + return NULL; + } + + return &he; +} + /**************************************************************************** * GETPWNAM ***************************************************************************/ static struct passwd *nwrap_getpwnam(const char *name) { - int i; + size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4372,7 +4727,8 @@ struct passwd *getpwnam(const char *name) static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { - int i,ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4409,7 +4765,7 @@ int getpwnam_r(const char *name, struct passwd *pwdst, static struct passwd *nwrap_getpwuid(uid_t uid) { - int i; + size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4439,7 +4795,8 @@ struct passwd *getpwuid(uid_t uid) static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { - int i,ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4474,7 +4831,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwdst, static void nwrap_setpwent(void) { - int i; + size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4498,7 +4855,7 @@ void setpwent(void) static struct passwd *nwrap_getpwent(void) { - int i; + size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4529,7 +4886,8 @@ struct passwd *getpwent(void) static int nwrap_getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { - int i,ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4578,7 +4936,7 @@ int getpwent_r(struct passwd *pwdst, char *buf, static void nwrap_endpwent(void) { - int i; + size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4602,7 +4960,7 @@ void endpwent(void) static int nwrap_initgroups(const char *user, gid_t group) { - int i; + size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4633,7 +4991,7 @@ int initgroups(const char *user, gid_t group) static struct group *nwrap_getgrnam(const char *name) { - int i; + size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4663,7 +5021,8 @@ struct group *getgrnam(const char *name) static int nwrap_getgrnam_r(const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { - int i, ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4704,7 +5063,7 @@ int getgrnam_r(const char *name, struct group *grp, static struct group *nwrap_getgrgid(gid_t gid) { - int i; + size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4734,7 +5093,8 @@ struct group *getgrgid(gid_t gid) static int nwrap_getgrgid_r(gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { - int i,ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4771,7 +5131,7 @@ int getgrgid_r(gid_t gid, struct group *grdst, static void nwrap_setgrent(void) { - int i; + size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4806,7 +5166,7 @@ out: static struct group *nwrap_getgrent(void) { - int i; + size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { @@ -4837,7 +5197,8 @@ struct group *getgrent(void) static int nwrap_getgrent_r(struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { - int i,ret; + size_t i; + int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -4887,7 +5248,7 @@ int getgrent_r(struct group *src, char *buf, static void nwrap_endgrent(void) { - int i; + size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -5129,6 +5490,7 @@ void endhostent(void) } #endif /* HAVE_SOLARIS_ENDHOSTENT */ + #ifdef BSD /* BSD implementation stores data in thread local storage but GLIBC does not */ static __thread struct hostent user_he; @@ -5137,12 +5499,37 @@ static __thread struct nwrap_vector user_addrlist; static struct hostent user_he; static struct nwrap_vector user_addrlist; #endif /* BSD */ + +static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b, + const char *name) +{ + int ret; + + (void) b; /* unused */ + + ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he, + &user_addrlist); + if (ret == 0) { + return &user_he; + } + + return NULL; +} + static struct hostent *nwrap_gethostbyname(const char *name) { - if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) { - return NULL; + size_t i; + struct hostent *he = NULL; + + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + he = b->ops->nw_gethostbyname(b, name); + if (he != NULL) { + return he; + } } - return &user_he; + + return NULL; } struct hostent *gethostbyname(const char *name) @@ -5164,12 +5551,37 @@ static __thread struct nwrap_vector user_addrlist2; static struct hostent user_he2; static struct nwrap_vector user_addrlist2; #endif /* BSD */ + +static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b, + const char *name, int af) +{ + int ret; + + (void) b; /* unused */ + + ret = nwrap_files_internal_gethostbyname(name, af, &user_he2, + &user_addrlist2); + if (ret == 0) { + return &user_he2; + } + + return NULL; +} + static struct hostent *nwrap_gethostbyname2(const char *name, int af) { - if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) { - return NULL; + size_t i; + struct hostent *he = NULL; + + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + he = b->ops->nw_gethostbyname2(b, name, af); + if (he != NULL) { + return he; + } } - return &user_he2; + + return NULL; } struct hostent *gethostbyname2(const char *name, int af) @@ -5185,7 +5597,18 @@ struct hostent *gethostbyname2(const char *name, int af) static struct hostent *nwrap_gethostbyaddr(const void *addr, socklen_t len, int type) { - return nwrap_files_gethostbyaddr(addr, len, type); + size_t i; + struct hostent *he = NULL; + + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + he = b->ops->nw_gethostbyaddr(b, addr, len, type); + if (he != NULL) { + return he; + } + } + + return NULL; } struct hostent *gethostbyaddr(const void *addr, @@ -5531,6 +5954,7 @@ static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, socklen_t addrlen; uint16_t port; sa_family_t type; + size_t i; if (sa == NULL || salen < sizeof(sa_family_t)) { return EAI_FAMILY; @@ -5585,7 +6009,13 @@ static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, if (host != NULL) { he = NULL; if ((flags & NI_NUMERICHOST) == 0) { - he = nwrap_files_gethostbyaddr(addr, addrlen, type); + for (i=0; i < nwrap_main_global->num_backends; i++) { + struct nwrap_backend *b = &nwrap_main_global->backends[i]; + he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type); + if (he != NULL) { + break; + } + } if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL)) return EAI_NONAME; } @@ -5698,7 +6128,7 @@ void nwrap_constructor(void) */ void nwrap_destructor(void) { - int i; + size_t i; NWRAP_LOCK_ALL; if (nwrap_main_global != NULL) { diff --git a/third_party/nss_wrapper/wscript b/third_party/nss_wrapper/wscript index dd83083b2e7..1f6e705ee07 100644 --- a/third_party/nss_wrapper/wscript +++ b/third_party/nss_wrapper/wscript @@ -2,7 +2,7 @@ import os -VERSION="1.1.7" +VERSION="1.1.10" def configure(conf): if conf.CHECK_NSS_WRAPPER(): @@ -28,6 +28,7 @@ def configure(conf): msg='Checking for printf format validation support') conf.CHECK_FUNCS('gethostbyaddr_r gethostbyname_r') + conf.CHECK_FUNCS('gethostbyname2 gethostbyname2_r') # Solaris conf.CHECK_FUNCS('__posix_getpwnam_r __posix_getpwuid_r') conf.CHECK_FUNCS('__posix_getgrgid_r __posix_getgrnam_r') -- 2.25.1 From e8fd17d4285019b8fd7ed48c82e52dd49101ce4c Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 19 Mar 2020 10:23:02 +0100 Subject: [PATCH 007/645] gitlab-ci: Remove Fedora 29 which is already EOL Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit 087566641e32821ea3cae0d23bd70a5602581b53) --- .gitlab-ci.yml | 7 +- bootstrap/.gitlab-ci.yml | 3 - bootstrap/config.py | 9 -- bootstrap/generated-dists/Vagrantfile | 7 -- bootstrap/generated-dists/fedora29/Dockerfile | 27 ----- .../generated-dists/fedora29/bootstrap.sh | 108 ------------------ bootstrap/generated-dists/fedora29/locale.sh | 55 --------- .../generated-dists/fedora29/packages.yml | 95 --------------- bootstrap/sha1sum.txt | 2 +- 9 files changed, 2 insertions(+), 311 deletions(-) delete mode 100644 bootstrap/generated-dists/fedora29/Dockerfile delete mode 100755 bootstrap/generated-dists/fedora29/bootstrap.sh delete mode 100755 bootstrap/generated-dists/fedora29/locale.sh delete mode 100644 bootstrap/generated-dists/fedora29/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8becacb8d4e..1d89dda5045 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 6bb2eeaf8203467d9a93a722071b0f081027410e + SAMBA_CI_CONTAINER_TAG: 2366db8ea66e6a07f36b77c0f3152a06e7056adc # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -39,7 +39,6 @@ variables: SAMBA_CI_CONTAINER_IMAGE_debian10: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-debian10:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse150: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse150:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse151: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse151:${SAMBA_CI_CONTAINER_TAG} - SAMBA_CI_CONTAINER_IMAGE_fedora29: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora29:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_fedora30: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora30:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_fedora31: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora31:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_centos7: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos7:${SAMBA_CI_CONTAINER_TAG} @@ -303,10 +302,6 @@ centos8-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_centos8 -fedora29-samba-o3: - extends: .samba-o3-template - image: $SAMBA_CI_CONTAINER_IMAGE_fedora29 - fedora30-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_fedora30 diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index ecd9f4d4223..c4c8599ef3d 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -102,9 +102,6 @@ fedora31: fedora30: extends: .build_image_template -fedora29: - extends: .build_image_template - centos8: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index ff9bb150672..36a19a1e6cf 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -453,15 +453,6 @@ RPM_DISTS = { 'liburing-devel': '', # not available yet, Add me back, once available! } }, - 'fedora29': { - 'docker_image': 'fedora:29', - 'vagrant_box': 'fedora/29-cloud-base', - 'bootstrap': DNF_BOOTSTRAP, - 'replace': { - 'lsb-release': 'redhat-lsb', - 'liburing-devel': '', # not available - } - }, 'fedora30': { 'docker_image': 'fedora:30', 'vagrant_box': 'fedora/30-cloud-base', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 47c58d5a87b..2daf1dde552 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -31,13 +31,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "debian10/locale.sh" end - config.vm.define "fedora29" do |v| - v.vm.box = "fedora/29-cloud-base" - v.vm.hostname = "fedora29" - v.vm.provision :shell, path: "fedora29/bootstrap.sh" - v.vm.provision :shell, path: "fedora29/locale.sh" - end - config.vm.define "fedora30" do |v| v.vm.box = "fedora/30-cloud-base" v.vm.hostname = "fedora30" diff --git a/bootstrap/generated-dists/fedora29/Dockerfile b/bootstrap/generated-dists/fedora29/Dockerfile deleted file mode 100644 index 268c79da161..00000000000 --- a/bootstrap/generated-dists/fedora29/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM fedora:29 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora29/bootstrap.sh b/bootstrap/generated-dists/fedora29/bootstrap.sh deleted file mode 100755 index effe2a9d214..00000000000 --- a/bootstrap/generated-dists/fedora29/bootstrap.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -dnf update -y - -dnf install -y \ - --setopt=install_weak_deps=False \ - @development-tools \ - acl \ - attr \ - autoconf \ - avahi-devel \ - bind-utils \ - binutils \ - bison \ - chrpath \ - cups-devel \ - curl \ - dbus-devel \ - docbook-dtds \ - docbook-style-xsl \ - flex \ - gawk \ - gcc \ - gdb \ - git \ - glib2-devel \ - glibc-common \ - glibc-langpack-en \ - glusterfs-api-devel \ - glusterfs-devel \ - gnutls-devel \ - gpgme-devel \ - gzip \ - hostname \ - htop \ - jansson-devel \ - keyutils-libs-devel \ - krb5-devel \ - krb5-server \ - lcov \ - libacl-devel \ - libarchive-devel \ - libattr-devel \ - libblkid-devel \ - libbsd-devel \ - libcap-devel \ - libcephfs-devel \ - libicu-devel \ - libnsl2-devel \ - libpcap-devel \ - libsemanage-python \ - libtasn1-devel \ - libtasn1-tools \ - libtirpc-devel \ - libunwind-devel \ - libuuid-devel \ - libxslt \ - lmdb \ - lmdb-devel \ - make \ - mingw64-gcc \ - ncurses-devel \ - openldap-devel \ - pam-devel \ - patch \ - perl \ - perl-Archive-Tar \ - perl-ExtUtils-MakeMaker \ - perl-JSON-Parse \ - perl-Parse-Yapp \ - perl-Test-Base \ - perl-generators \ - perl-interpreter \ - pkgconfig \ - policycoreutils-python \ - popt-devel \ - procps-ng \ - psmisc \ - python3 \ - python3-devel \ - python3-dns \ - python3-gpg \ - python3-markdown \ - quota-devel \ - readline-devel \ - redhat-lsb \ - rng-tools \ - rpcgen \ - rpcsvc-proto-devel \ - rsync \ - sed \ - sudo \ - systemd-devel \ - tar \ - tree \ - which \ - xfsprogs-devel \ - yum-utils \ - zlib-devel - -dnf clean all \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora29/locale.sh b/bootstrap/generated-dists/fedora29/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/fedora29/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora29/packages.yml b/bootstrap/generated-dists/fedora29/packages.yml deleted file mode 100644 index 3b767f8ba08..00000000000 --- a/bootstrap/generated-dists/fedora29/packages.yml +++ /dev/null @@ -1,95 +0,0 @@ ---- -packages: - - @development-tools - - acl - - attr - - autoconf - - avahi-devel - - bind-utils - - binutils - - bison - - chrpath - - cups-devel - - curl - - dbus-devel - - docbook-dtds - - docbook-style-xsl - - flex - - gawk - - gcc - - gdb - - git - - glib2-devel - - glibc-common - - glibc-langpack-en - - glusterfs-api-devel - - glusterfs-devel - - gnutls-devel - - gpgme-devel - - gzip - - hostname - - htop - - jansson-devel - - keyutils-libs-devel - - krb5-devel - - krb5-server - - lcov - - libacl-devel - - libarchive-devel - - libattr-devel - - libblkid-devel - - libbsd-devel - - libcap-devel - - libcephfs-devel - - libicu-devel - - libnsl2-devel - - libpcap-devel - - libsemanage-python - - libtasn1-devel - - libtasn1-tools - - libtirpc-devel - - libunwind-devel - - libuuid-devel - - libxslt - - lmdb - - lmdb-devel - - make - - mingw64-gcc - - ncurses-devel - - openldap-devel - - pam-devel - - patch - - perl - - perl-Archive-Tar - - perl-ExtUtils-MakeMaker - - perl-JSON-Parse - - perl-Parse-Yapp - - perl-Test-Base - - perl-generators - - perl-interpreter - - pkgconfig - - policycoreutils-python - - popt-devel - - procps-ng - - psmisc - - python3 - - python3-devel - - python3-dns - - python3-gpg - - python3-markdown - - quota-devel - - readline-devel - - redhat-lsb - - rng-tools - - rpcgen - - rpcsvc-proto-devel - - rsync - - sed - - sudo - - systemd-devel - - tar - - tree - - which - - xfsprogs-devel - - yum-utils - - zlib-devel \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 1c9d01d5e7d..39f2633892e 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -6bb2eeaf8203467d9a93a722071b0f081027410e +2366db8ea66e6a07f36b77c0f3152a06e7056adc -- 2.25.1 From 5ea7f8cc213d10116331189c47e8ade83753d43d Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 19 Mar 2020 10:28:23 +0100 Subject: [PATCH 008/645] gitlab-ci: Remove Fedora 30 It is pretty similar to Fedora 31, so remove it safe some CI resources. We will add Fedora 32 next. Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit ef08b30380093726297529d20b087e64caa58572) --- .gitlab-ci.yml | 7 +- bootstrap/.gitlab-ci.yml | 3 - bootstrap/config.py | 9 -- bootstrap/generated-dists/Vagrantfile | 7 -- bootstrap/generated-dists/fedora30/Dockerfile | 27 ----- .../generated-dists/fedora30/bootstrap.sh | 108 ------------------ bootstrap/generated-dists/fedora30/locale.sh | 55 --------- .../generated-dists/fedora30/packages.yml | 95 --------------- bootstrap/sha1sum.txt | 2 +- 9 files changed, 2 insertions(+), 311 deletions(-) delete mode 100644 bootstrap/generated-dists/fedora30/Dockerfile delete mode 100755 bootstrap/generated-dists/fedora30/bootstrap.sh delete mode 100755 bootstrap/generated-dists/fedora30/locale.sh delete mode 100644 bootstrap/generated-dists/fedora30/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d89dda5045..a8e1099be11 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 2366db8ea66e6a07f36b77c0f3152a06e7056adc + SAMBA_CI_CONTAINER_TAG: 9f95136e88779ec8eed6c18614b1e0779ef2bfec # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -39,7 +39,6 @@ variables: SAMBA_CI_CONTAINER_IMAGE_debian10: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-debian10:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse150: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse150:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse151: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse151:${SAMBA_CI_CONTAINER_TAG} - SAMBA_CI_CONTAINER_IMAGE_fedora30: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora30:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_fedora31: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora31:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_centos7: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos7:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_centos8: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos8:${SAMBA_CI_CONTAINER_TAG} @@ -302,10 +301,6 @@ centos8-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_centos8 -fedora30-samba-o3: - extends: .samba-o3-template - image: $SAMBA_CI_CONTAINER_IMAGE_fedora30 - fedora31-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_fedora31 diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index c4c8599ef3d..89c1453a34c 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -99,9 +99,6 @@ debian10: fedora31: extends: .build_image_template -fedora30: - extends: .build_image_template - centos8: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index 36a19a1e6cf..6d4d662d563 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -453,15 +453,6 @@ RPM_DISTS = { 'liburing-devel': '', # not available yet, Add me back, once available! } }, - 'fedora30': { - 'docker_image': 'fedora:30', - 'vagrant_box': 'fedora/30-cloud-base', - 'bootstrap': DNF_BOOTSTRAP, - 'replace': { - 'lsb-release': 'redhat-lsb', - 'liburing-devel': '', # not available - } - }, 'fedora31': { 'docker_image': 'fedora:31', 'vagrant_box': 'fedora/31-cloud-base', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 2daf1dde552..770e364c70b 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -31,13 +31,6 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "debian10/locale.sh" end - config.vm.define "fedora30" do |v| - v.vm.box = "fedora/30-cloud-base" - v.vm.hostname = "fedora30" - v.vm.provision :shell, path: "fedora30/bootstrap.sh" - v.vm.provision :shell, path: "fedora30/locale.sh" - end - config.vm.define "fedora31" do |v| v.vm.box = "fedora/31-cloud-base" v.vm.hostname = "fedora31" diff --git a/bootstrap/generated-dists/fedora30/Dockerfile b/bootstrap/generated-dists/fedora30/Dockerfile deleted file mode 100644 index f2a2c3546f0..00000000000 --- a/bootstrap/generated-dists/fedora30/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -FROM fedora:30 - -# pass in with --build-arg while build -ARG SHA1SUM -RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt - -ADD *.sh /tmp/ -# need root permission, do it before USER samba -RUN /tmp/bootstrap.sh && /tmp/locale.sh - -# if ld.gold exists, force link it to ld -RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" - -# make test can not work with root, so we have to create a new user -RUN useradd -m -U -s /bin/bash samba && \ - mkdir -p /etc/sudoers.d && \ - echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba - -USER samba -WORKDIR /home/samba -# samba tests rely on this -ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora30/bootstrap.sh b/bootstrap/generated-dists/fedora30/bootstrap.sh deleted file mode 100755 index effe2a9d214..00000000000 --- a/bootstrap/generated-dists/fedora30/bootstrap.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -dnf update -y - -dnf install -y \ - --setopt=install_weak_deps=False \ - @development-tools \ - acl \ - attr \ - autoconf \ - avahi-devel \ - bind-utils \ - binutils \ - bison \ - chrpath \ - cups-devel \ - curl \ - dbus-devel \ - docbook-dtds \ - docbook-style-xsl \ - flex \ - gawk \ - gcc \ - gdb \ - git \ - glib2-devel \ - glibc-common \ - glibc-langpack-en \ - glusterfs-api-devel \ - glusterfs-devel \ - gnutls-devel \ - gpgme-devel \ - gzip \ - hostname \ - htop \ - jansson-devel \ - keyutils-libs-devel \ - krb5-devel \ - krb5-server \ - lcov \ - libacl-devel \ - libarchive-devel \ - libattr-devel \ - libblkid-devel \ - libbsd-devel \ - libcap-devel \ - libcephfs-devel \ - libicu-devel \ - libnsl2-devel \ - libpcap-devel \ - libsemanage-python \ - libtasn1-devel \ - libtasn1-tools \ - libtirpc-devel \ - libunwind-devel \ - libuuid-devel \ - libxslt \ - lmdb \ - lmdb-devel \ - make \ - mingw64-gcc \ - ncurses-devel \ - openldap-devel \ - pam-devel \ - patch \ - perl \ - perl-Archive-Tar \ - perl-ExtUtils-MakeMaker \ - perl-JSON-Parse \ - perl-Parse-Yapp \ - perl-Test-Base \ - perl-generators \ - perl-interpreter \ - pkgconfig \ - policycoreutils-python \ - popt-devel \ - procps-ng \ - psmisc \ - python3 \ - python3-devel \ - python3-dns \ - python3-gpg \ - python3-markdown \ - quota-devel \ - readline-devel \ - redhat-lsb \ - rng-tools \ - rpcgen \ - rpcsvc-proto-devel \ - rsync \ - sed \ - sudo \ - systemd-devel \ - tar \ - tree \ - which \ - xfsprogs-devel \ - yum-utils \ - zlib-devel - -dnf clean all \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora30/locale.sh b/bootstrap/generated-dists/fedora30/locale.sh deleted file mode 100755 index cc64e180483..00000000000 --- a/bootstrap/generated-dists/fedora30/locale.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# -# This file is generated by 'bootstrap/template.py --render' -# See also bootstrap/config.py -# - -set -xueo pipefail - -# refer to /usr/share/i18n/locales -INPUTFILE=en_US -# refer to /usr/share/i18n/charmaps -CHARMAP=UTF-8 -# locale to generate in /usr/lib/locale -# glibc/localedef will normalize UTF-8 to utf8, follow the naming style -LOCALE=$INPUTFILE.utf8 - -# if locale is already correct, exit -( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 - -# if locale not available, generate locale into /usr/lib/locale -if ! ( locale --all-locales | grep -i $LOCALE ) -then - # no-archive means create its own dir - localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE -fi - -# update locale conf and global env file -# set both LC_ALL and LANG for safe - -# update conf for Debian family -FILE=/etc/default/locale -if [ -f $FILE ] -then - echo LC_ALL="$LOCALE" > $FILE - echo LANG="$LOCALE" >> $FILE -fi - -# update conf for RedHat family -FILE=/etc/locale.conf -if [ -f $FILE ] -then - # LC_ALL is not valid in this file, set LANG only - echo LANG="$LOCALE" > $FILE -fi - -# update global env file -FILE=/etc/environment -if [ -f $FILE ] -then - # append LC_ALL if not exist - grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE - # append LANG if not exist - grep LANG $FILE || echo LANG="$LOCALE" >> $FILE -fi \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora30/packages.yml b/bootstrap/generated-dists/fedora30/packages.yml deleted file mode 100644 index 3b767f8ba08..00000000000 --- a/bootstrap/generated-dists/fedora30/packages.yml +++ /dev/null @@ -1,95 +0,0 @@ ---- -packages: - - @development-tools - - acl - - attr - - autoconf - - avahi-devel - - bind-utils - - binutils - - bison - - chrpath - - cups-devel - - curl - - dbus-devel - - docbook-dtds - - docbook-style-xsl - - flex - - gawk - - gcc - - gdb - - git - - glib2-devel - - glibc-common - - glibc-langpack-en - - glusterfs-api-devel - - glusterfs-devel - - gnutls-devel - - gpgme-devel - - gzip - - hostname - - htop - - jansson-devel - - keyutils-libs-devel - - krb5-devel - - krb5-server - - lcov - - libacl-devel - - libarchive-devel - - libattr-devel - - libblkid-devel - - libbsd-devel - - libcap-devel - - libcephfs-devel - - libicu-devel - - libnsl2-devel - - libpcap-devel - - libsemanage-python - - libtasn1-devel - - libtasn1-tools - - libtirpc-devel - - libunwind-devel - - libuuid-devel - - libxslt - - lmdb - - lmdb-devel - - make - - mingw64-gcc - - ncurses-devel - - openldap-devel - - pam-devel - - patch - - perl - - perl-Archive-Tar - - perl-ExtUtils-MakeMaker - - perl-JSON-Parse - - perl-Parse-Yapp - - perl-Test-Base - - perl-generators - - perl-interpreter - - pkgconfig - - policycoreutils-python - - popt-devel - - procps-ng - - psmisc - - python3 - - python3-devel - - python3-dns - - python3-gpg - - python3-markdown - - quota-devel - - readline-devel - - redhat-lsb - - rng-tools - - rpcgen - - rpcsvc-proto-devel - - rsync - - sed - - sudo - - systemd-devel - - tar - - tree - - which - - xfsprogs-devel - - yum-utils - - zlib-devel \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 39f2633892e..ef012315ce1 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -2366db8ea66e6a07f36b77c0f3152a06e7056adc +9f95136e88779ec8eed6c18614b1e0779ef2bfec -- 2.25.1 From 4920e3348df9d2f953289e7e0ddf26d5617fed3b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 19 Mar 2020 10:32:17 +0100 Subject: [PATCH 009/645] gitlab-ci: Add Fedora 32 (Beta) Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Fri Mar 20 15:19:50 UTC 2020 on sn-devel-184 (cherry picked from commit bce99f59332ffd4d817be457ff4b39743e724319) --- .gitlab-ci.yml | 7 +- bootstrap/.gitlab-ci.yml | 3 + bootstrap/config.py | 10 ++ bootstrap/generated-dists/Vagrantfile | 7 ++ bootstrap/generated-dists/fedora32/Dockerfile | 27 +++++ .../generated-dists/fedora32/bootstrap.sh | 109 ++++++++++++++++++ bootstrap/generated-dists/fedora32/locale.sh | 55 +++++++++ .../generated-dists/fedora32/packages.yml | 96 +++++++++++++++ bootstrap/sha1sum.txt | 2 +- 9 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 bootstrap/generated-dists/fedora32/Dockerfile create mode 100755 bootstrap/generated-dists/fedora32/bootstrap.sh create mode 100755 bootstrap/generated-dists/fedora32/locale.sh create mode 100644 bootstrap/generated-dists/fedora32/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a8e1099be11..bf05c3cd792 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 9f95136e88779ec8eed6c18614b1e0779ef2bfec + SAMBA_CI_CONTAINER_TAG: 9061307e79ad13733c69352a965eeb4f44bef4b7 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -40,6 +40,7 @@ variables: SAMBA_CI_CONTAINER_IMAGE_opensuse150: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse150:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse151: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse151:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_fedora31: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora31:${SAMBA_CI_CONTAINER_TAG} + SAMBA_CI_CONTAINER_IMAGE_fedora32: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora32:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_centos7: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos7:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_centos8: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos8:${SAMBA_CI_CONTAINER_TAG} @@ -305,6 +306,10 @@ fedora31-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_fedora31 +fedora32-samba-o3: + extends: .samba-o3-template + image: $SAMBA_CI_CONTAINER_IMAGE_fedora32 + # # Keep the samba-o3 sections at the end ... # diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index 89c1453a34c..8427dbdc314 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -99,6 +99,9 @@ debian10: fedora31: extends: .build_image_template +fedora32: + extends: .build_image_template + centos8: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index 6d4d662d563..093b84676f0 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -463,6 +463,16 @@ RPM_DISTS = { 'policycoreutils-python': 'python3-policycoreutils', } }, + 'fedora32': { + 'docker_image': 'fedora:32', + 'vagrant_box': 'fedora/32-cloud-base', + 'bootstrap': DNF_BOOTSTRAP, + 'replace': { + 'lsb-release': 'redhat-lsb', + 'libsemanage-python': 'python3-libsemanage', + 'policycoreutils-python': 'python3-policycoreutils', + } + }, 'opensuse150': { 'docker_image': 'opensuse/leap:15.0', 'vagrant_box': 'opensuse/openSUSE-15.0-x86_64', diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 770e364c70b..15fc686f584 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -38,6 +38,13 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "fedora31/locale.sh" end + config.vm.define "fedora32" do |v| + v.vm.box = "fedora/32-cloud-base" + v.vm.hostname = "fedora32" + v.vm.provision :shell, path: "fedora32/bootstrap.sh" + v.vm.provision :shell, path: "fedora32/locale.sh" + end + config.vm.define "opensuse150" do |v| v.vm.box = "opensuse/openSUSE-15.0-x86_64" v.vm.hostname = "opensuse150" diff --git a/bootstrap/generated-dists/fedora32/Dockerfile b/bootstrap/generated-dists/fedora32/Dockerfile new file mode 100644 index 00000000000..d8a75cf8445 --- /dev/null +++ b/bootstrap/generated-dists/fedora32/Dockerfile @@ -0,0 +1,27 @@ +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +FROM fedora:32 + +# pass in with --build-arg while build +ARG SHA1SUM +RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt + +ADD *.sh /tmp/ +# need root permission, do it before USER samba +RUN /tmp/bootstrap.sh && /tmp/locale.sh + +# if ld.gold exists, force link it to ld +RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" + +# make test can not work with root, so we have to create a new user +RUN useradd -m -U -s /bin/bash samba && \ + mkdir -p /etc/sudoers.d && \ + echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba + +USER samba +WORKDIR /home/samba +# samba tests rely on this +ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora32/bootstrap.sh b/bootstrap/generated-dists/fedora32/bootstrap.sh new file mode 100755 index 00000000000..18c58092eff --- /dev/null +++ b/bootstrap/generated-dists/fedora32/bootstrap.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +dnf update -y + +dnf install -y \ + --setopt=install_weak_deps=False \ + @development-tools \ + acl \ + attr \ + autoconf \ + avahi-devel \ + bind-utils \ + binutils \ + bison \ + chrpath \ + cups-devel \ + curl \ + dbus-devel \ + docbook-dtds \ + docbook-style-xsl \ + flex \ + gawk \ + gcc \ + gdb \ + git \ + glib2-devel \ + glibc-common \ + glibc-langpack-en \ + glusterfs-api-devel \ + glusterfs-devel \ + gnutls-devel \ + gpgme-devel \ + gzip \ + hostname \ + htop \ + jansson-devel \ + keyutils-libs-devel \ + krb5-devel \ + krb5-server \ + lcov \ + libacl-devel \ + libarchive-devel \ + libattr-devel \ + libblkid-devel \ + libbsd-devel \ + libcap-devel \ + libcephfs-devel \ + libicu-devel \ + libnsl2-devel \ + libpcap-devel \ + libtasn1-devel \ + libtasn1-tools \ + libtirpc-devel \ + libunwind-devel \ + liburing-devel \ + libuuid-devel \ + libxslt \ + lmdb \ + lmdb-devel \ + make \ + mingw64-gcc \ + ncurses-devel \ + openldap-devel \ + pam-devel \ + patch \ + perl \ + perl-Archive-Tar \ + perl-ExtUtils-MakeMaker \ + perl-JSON-Parse \ + perl-Parse-Yapp \ + perl-Test-Base \ + perl-generators \ + perl-interpreter \ + pkgconfig \ + popt-devel \ + procps-ng \ + psmisc \ + python3 \ + python3-devel \ + python3-dns \ + python3-gpg \ + python3-libsemanage \ + python3-markdown \ + python3-policycoreutils \ + quota-devel \ + readline-devel \ + redhat-lsb \ + rng-tools \ + rpcgen \ + rpcsvc-proto-devel \ + rsync \ + sed \ + sudo \ + systemd-devel \ + tar \ + tree \ + which \ + xfsprogs-devel \ + yum-utils \ + zlib-devel + +dnf clean all \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora32/locale.sh b/bootstrap/generated-dists/fedora32/locale.sh new file mode 100755 index 00000000000..cc64e180483 --- /dev/null +++ b/bootstrap/generated-dists/fedora32/locale.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +# refer to /usr/share/i18n/locales +INPUTFILE=en_US +# refer to /usr/share/i18n/charmaps +CHARMAP=UTF-8 +# locale to generate in /usr/lib/locale +# glibc/localedef will normalize UTF-8 to utf8, follow the naming style +LOCALE=$INPUTFILE.utf8 + +# if locale is already correct, exit +( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 + +# if locale not available, generate locale into /usr/lib/locale +if ! ( locale --all-locales | grep -i $LOCALE ) +then + # no-archive means create its own dir + localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE +fi + +# update locale conf and global env file +# set both LC_ALL and LANG for safe + +# update conf for Debian family +FILE=/etc/default/locale +if [ -f $FILE ] +then + echo LC_ALL="$LOCALE" > $FILE + echo LANG="$LOCALE" >> $FILE +fi + +# update conf for RedHat family +FILE=/etc/locale.conf +if [ -f $FILE ] +then + # LC_ALL is not valid in this file, set LANG only + echo LANG="$LOCALE" > $FILE +fi + +# update global env file +FILE=/etc/environment +if [ -f $FILE ] +then + # append LC_ALL if not exist + grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE + # append LANG if not exist + grep LANG $FILE || echo LANG="$LOCALE" >> $FILE +fi \ No newline at end of file diff --git a/bootstrap/generated-dists/fedora32/packages.yml b/bootstrap/generated-dists/fedora32/packages.yml new file mode 100644 index 00000000000..3165af8dd82 --- /dev/null +++ b/bootstrap/generated-dists/fedora32/packages.yml @@ -0,0 +1,96 @@ +--- +packages: + - @development-tools + - acl + - attr + - autoconf + - avahi-devel + - bind-utils + - binutils + - bison + - chrpath + - cups-devel + - curl + - dbus-devel + - docbook-dtds + - docbook-style-xsl + - flex + - gawk + - gcc + - gdb + - git + - glib2-devel + - glibc-common + - glibc-langpack-en + - glusterfs-api-devel + - glusterfs-devel + - gnutls-devel + - gpgme-devel + - gzip + - hostname + - htop + - jansson-devel + - keyutils-libs-devel + - krb5-devel + - krb5-server + - lcov + - libacl-devel + - libarchive-devel + - libattr-devel + - libblkid-devel + - libbsd-devel + - libcap-devel + - libcephfs-devel + - libicu-devel + - libnsl2-devel + - libpcap-devel + - libtasn1-devel + - libtasn1-tools + - libtirpc-devel + - libunwind-devel + - liburing-devel + - libuuid-devel + - libxslt + - lmdb + - lmdb-devel + - make + - mingw64-gcc + - ncurses-devel + - openldap-devel + - pam-devel + - patch + - perl + - perl-Archive-Tar + - perl-ExtUtils-MakeMaker + - perl-JSON-Parse + - perl-Parse-Yapp + - perl-Test-Base + - perl-generators + - perl-interpreter + - pkgconfig + - popt-devel + - procps-ng + - psmisc + - python3 + - python3-devel + - python3-dns + - python3-gpg + - python3-libsemanage + - python3-markdown + - python3-policycoreutils + - quota-devel + - readline-devel + - redhat-lsb + - rng-tools + - rpcgen + - rpcsvc-proto-devel + - rsync + - sed + - sudo + - systemd-devel + - tar + - tree + - which + - xfsprogs-devel + - yum-utils + - zlib-devel \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index ef012315ce1..df1b85b9f21 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -9f95136e88779ec8eed6c18614b1e0779ef2bfec +9061307e79ad13733c69352a965eeb4f44bef4b7 -- 2.25.1 From a7e297dbc631afdfcfe0082d9bb7318dbc0ba212 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 25 Mar 2020 22:17:46 +0100 Subject: [PATCH 010/645] bootstrap: add ubuntu2004 Ubuntu Focal Fossa (development branch) Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 53402b353007893f3851afbf574c2a67f9f6a44b) --- .gitlab-ci.yml | 9 +- bootstrap/.gitlab-ci.yml | 3 + bootstrap/config.py | 7 ++ bootstrap/generated-dists/Vagrantfile | 7 ++ .../generated-dists/ubuntu2004/Dockerfile | 27 +++++ .../generated-dists/ubuntu2004/bootstrap.sh | 106 ++++++++++++++++++ .../generated-dists/ubuntu2004/locale.sh | 55 +++++++++ .../generated-dists/ubuntu2004/packages.yml | 91 +++++++++++++++ bootstrap/sha1sum.txt | 2 +- 9 files changed, 304 insertions(+), 3 deletions(-) create mode 100644 bootstrap/generated-dists/ubuntu2004/Dockerfile create mode 100755 bootstrap/generated-dists/ubuntu2004/bootstrap.sh create mode 100755 bootstrap/generated-dists/ubuntu2004/locale.sh create mode 100644 bootstrap/generated-dists/ubuntu2004/packages.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bf05c3cd792..efb9fe87d17 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 9061307e79ad13733c69352a965eeb4f44bef4b7 + SAMBA_CI_CONTAINER_TAG: f5212e7abcae3208b796c939432ab9bec319264a # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. @@ -33,8 +33,9 @@ variables: # Please see the samba-o3 sections at the end of this file! # We should run that for each available image # - SAMBA_CI_CONTAINER_IMAGE_ubuntu1804: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1804:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_ubuntu1604: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1604:${SAMBA_CI_CONTAINER_TAG} + SAMBA_CI_CONTAINER_IMAGE_ubuntu1804: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1804:${SAMBA_CI_CONTAINER_TAG} + SAMBA_CI_CONTAINER_IMAGE_ubuntu2004: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu2004:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_debian9: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-debian9:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_debian10: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-debian10:${SAMBA_CI_CONTAINER_TAG} SAMBA_CI_CONTAINER_IMAGE_opensuse150: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse150:${SAMBA_CI_CONTAINER_TAG} @@ -277,6 +278,10 @@ ubuntu1804-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu1804 +.ubuntu2004-samba-o3: + extends: .samba-o3-template + image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu2004 + debian10-samba-o3: extends: .samba-o3-template image: $SAMBA_CI_CONTAINER_IMAGE_debian10 diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml index 8427dbdc314..d6cf02109fd 100644 --- a/bootstrap/.gitlab-ci.yml +++ b/bootstrap/.gitlab-ci.yml @@ -93,6 +93,9 @@ ubuntu1604: ubuntu1804: extends: .build_image_template +ubuntu2004: + extends: .build_image_template + debian10: extends: .build_image_template diff --git a/bootstrap/config.py b/bootstrap/config.py index 093b84676f0..b862053b915 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -400,6 +400,13 @@ DEB_DISTS = { 'liburing-dev': '', # not available } }, + 'ubuntu2004': { + 'docker_image': 'ubuntu:20.04', + 'vagrant_box': 'ubuntu/focal64', + 'replace': { + 'liburing-dev': '', # not available + } + }, } diff --git a/bootstrap/generated-dists/Vagrantfile b/bootstrap/generated-dists/Vagrantfile index 15fc686f584..e01c20bc161 100644 --- a/bootstrap/generated-dists/Vagrantfile +++ b/bootstrap/generated-dists/Vagrantfile @@ -73,5 +73,12 @@ Vagrant.configure("2") do |config| v.vm.provision :shell, path: "ubuntu1804/locale.sh" end + config.vm.define "ubuntu2004" do |v| + v.vm.box = "ubuntu/focal64" + v.vm.hostname = "ubuntu2004" + v.vm.provision :shell, path: "ubuntu2004/bootstrap.sh" + v.vm.provision :shell, path: "ubuntu2004/locale.sh" + end + end diff --git a/bootstrap/generated-dists/ubuntu2004/Dockerfile b/bootstrap/generated-dists/ubuntu2004/Dockerfile new file mode 100644 index 00000000000..f94e8801aad --- /dev/null +++ b/bootstrap/generated-dists/ubuntu2004/Dockerfile @@ -0,0 +1,27 @@ +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +FROM ubuntu:20.04 + +# pass in with --build-arg while build +ARG SHA1SUM +RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt + +ADD *.sh /tmp/ +# need root permission, do it before USER samba +RUN /tmp/bootstrap.sh && /tmp/locale.sh + +# if ld.gold exists, force link it to ld +RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD" + +# make test can not work with root, so we have to create a new user +RUN useradd -m -U -s /bin/bash samba && \ + mkdir -p /etc/sudoers.d && \ + echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba + +USER samba +WORKDIR /home/samba +# samba tests rely on this +ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu2004/bootstrap.sh b/bootstrap/generated-dists/ubuntu2004/bootstrap.sh new file mode 100755 index 00000000000..97d32815d72 --- /dev/null +++ b/bootstrap/generated-dists/ubuntu2004/bootstrap.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +export DEBIAN_FRONTEND=noninteractive +apt-get -y update + +apt-get -y install \ + acl \ + apt-utils \ + attr \ + autoconf \ + bind9utils \ + binutils \ + bison \ + build-essential \ + chrpath \ + curl \ + debhelper \ + dnsutils \ + docbook-xml \ + docbook-xsl \ + flex \ + gcc \ + gdb \ + git \ + glusterfs-common \ + gzip \ + heimdal-multidev \ + hostname \ + htop \ + krb5-config \ + krb5-kdc \ + krb5-user \ + language-pack-en \ + lcov \ + libacl1-dev \ + libarchive-dev \ + libattr1-dev \ + libavahi-common-dev \ + libblkid-dev \ + libbsd-dev \ + libcap-dev \ + libcephfs-dev \ + libcups2-dev \ + libdbus-1-dev \ + libglib2.0-dev \ + libgnutls28-dev \ + libgpgme11-dev \ + libicu-dev \ + libjansson-dev \ + libjs-jquery \ + libjson-perl \ + libkrb5-dev \ + libldap2-dev \ + liblmdb-dev \ + libncurses5-dev \ + libpam0g-dev \ + libparse-yapp-perl \ + libpcap-dev \ + libpopt-dev \ + libreadline-dev \ + libsystemd-dev \ + libtasn1-bin \ + libtasn1-dev \ + libunwind-dev \ + lmdb-utils \ + locales \ + lsb-release \ + make \ + mawk \ + mingw-w64 \ + patch \ + perl \ + perl-modules \ + pkg-config \ + procps \ + psmisc \ + python3 \ + python3-dbg \ + python3-dev \ + python3-dnspython \ + python3-gpg \ + python3-iso8601 \ + python3-markdown \ + python3-matplotlib \ + python3-pexpect \ + rng-tools \ + rsync \ + sed \ + sudo \ + tar \ + tree \ + uuid-dev \ + xfslibs-dev \ + xsltproc \ + zlib1g-dev + +apt-get -y autoremove +apt-get -y autoclean +apt-get -y clean \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu2004/locale.sh b/bootstrap/generated-dists/ubuntu2004/locale.sh new file mode 100755 index 00000000000..cc64e180483 --- /dev/null +++ b/bootstrap/generated-dists/ubuntu2004/locale.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# +# This file is generated by 'bootstrap/template.py --render' +# See also bootstrap/config.py +# + +set -xueo pipefail + +# refer to /usr/share/i18n/locales +INPUTFILE=en_US +# refer to /usr/share/i18n/charmaps +CHARMAP=UTF-8 +# locale to generate in /usr/lib/locale +# glibc/localedef will normalize UTF-8 to utf8, follow the naming style +LOCALE=$INPUTFILE.utf8 + +# if locale is already correct, exit +( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0 + +# if locale not available, generate locale into /usr/lib/locale +if ! ( locale --all-locales | grep -i $LOCALE ) +then + # no-archive means create its own dir + localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE +fi + +# update locale conf and global env file +# set both LC_ALL and LANG for safe + +# update conf for Debian family +FILE=/etc/default/locale +if [ -f $FILE ] +then + echo LC_ALL="$LOCALE" > $FILE + echo LANG="$LOCALE" >> $FILE +fi + +# update conf for RedHat family +FILE=/etc/locale.conf +if [ -f $FILE ] +then + # LC_ALL is not valid in this file, set LANG only + echo LANG="$LOCALE" > $FILE +fi + +# update global env file +FILE=/etc/environment +if [ -f $FILE ] +then + # append LC_ALL if not exist + grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE + # append LANG if not exist + grep LANG $FILE || echo LANG="$LOCALE" >> $FILE +fi \ No newline at end of file diff --git a/bootstrap/generated-dists/ubuntu2004/packages.yml b/bootstrap/generated-dists/ubuntu2004/packages.yml new file mode 100644 index 00000000000..f45deb2c808 --- /dev/null +++ b/bootstrap/generated-dists/ubuntu2004/packages.yml @@ -0,0 +1,91 @@ +--- +packages: + - acl + - apt-utils + - attr + - autoconf + - bind9utils + - binutils + - bison + - build-essential + - chrpath + - curl + - debhelper + - dnsutils + - docbook-xml + - docbook-xsl + - flex + - gcc + - gdb + - git + - glusterfs-common + - gzip + - heimdal-multidev + - hostname + - htop + - krb5-config + - krb5-kdc + - krb5-user + - language-pack-en + - lcov + - libacl1-dev + - libarchive-dev + - libattr1-dev + - libavahi-common-dev + - libblkid-dev + - libbsd-dev + - libcap-dev + - libcephfs-dev + - libcups2-dev + - libdbus-1-dev + - libglib2.0-dev + - libgnutls28-dev + - libgpgme11-dev + - libicu-dev + - libjansson-dev + - libjs-jquery + - libjson-perl + - libkrb5-dev + - libldap2-dev + - liblmdb-dev + - libncurses5-dev + - libpam0g-dev + - libparse-yapp-perl + - libpcap-dev + - libpopt-dev + - libreadline-dev + - libsystemd-dev + - libtasn1-bin + - libtasn1-dev + - libunwind-dev + - lmdb-utils + - locales + - lsb-release + - make + - mawk + - mingw-w64 + - patch + - perl + - perl-modules + - pkg-config + - procps + - psmisc + - python3 + - python3-dbg + - python3-dev + - python3-dnspython + - python3-gpg + - python3-iso8601 + - python3-markdown + - python3-matplotlib + - python3-pexpect + - rng-tools + - rsync + - sed + - sudo + - tar + - tree + - uuid-dev + - xfslibs-dev + - xsltproc + - zlib1g-dev \ No newline at end of file diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index df1b85b9f21..c3a72eec5c6 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -9061307e79ad13733c69352a965eeb4f44bef4b7 +f5212e7abcae3208b796c939432ab9bec319264a -- 2.25.1 From 3f40e387bc72c72d5e4a982bb9a114b46dc8cdb1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Mar 2020 15:36:48 +0100 Subject: [PATCH 011/645] bootstrap: add python3-pyasn1/python3-cryptography for kerberos testing Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 99b644248746a8a038d6f4b15aa621a907adc987) --- .gitlab-ci.yml | 2 +- bootstrap/config.py | 8 ++++---- bootstrap/generated-dists/centos7/bootstrap.sh | 2 ++ bootstrap/generated-dists/centos7/packages.yml | 2 ++ bootstrap/generated-dists/centos8/bootstrap.sh | 2 ++ bootstrap/generated-dists/centos8/packages.yml | 2 ++ bootstrap/generated-dists/debian10/bootstrap.sh | 2 ++ bootstrap/generated-dists/debian10/packages.yml | 2 ++ bootstrap/generated-dists/fedora31/bootstrap.sh | 2 ++ bootstrap/generated-dists/fedora31/packages.yml | 2 ++ bootstrap/generated-dists/fedora32/bootstrap.sh | 2 ++ bootstrap/generated-dists/fedora32/packages.yml | 2 ++ bootstrap/generated-dists/opensuse150/bootstrap.sh | 2 ++ bootstrap/generated-dists/opensuse150/packages.yml | 2 ++ bootstrap/generated-dists/opensuse151/bootstrap.sh | 2 ++ bootstrap/generated-dists/opensuse151/packages.yml | 2 ++ bootstrap/generated-dists/ubuntu1604/bootstrap.sh | 2 ++ bootstrap/generated-dists/ubuntu1604/packages.yml | 2 ++ bootstrap/generated-dists/ubuntu1804/bootstrap.sh | 2 ++ bootstrap/generated-dists/ubuntu1804/packages.yml | 2 ++ bootstrap/generated-dists/ubuntu2004/bootstrap.sh | 2 ++ bootstrap/generated-dists/ubuntu2004/packages.yml | 2 ++ bootstrap/sha1sum.txt | 2 +- 23 files changed, 46 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index efb9fe87d17..6a5e8693e80 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: f5212e7abcae3208b796c939432ab9bec319264a + SAMBA_CI_CONTAINER_TAG: 7414ad7ef9108d406b1f6b17ebce19e32aee9f70 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. diff --git a/bootstrap/config.py b/bootstrap/config.py index b862053b915..196f9bdf8eb 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -129,6 +129,7 @@ PKGS = [ ('mawk', 'gawk'), ('python3', 'python3'), + ('python3-cryptography', 'python3-cryptography'), # for krb5 tests ('python3-dev', 'python3-devel'), ('python3-dbg', ''), ('python3-iso8601', ''), @@ -137,6 +138,7 @@ PKGS = [ ('python3-matplotlib', ''), ('python3-dnspython', 'python3-dns'), ('python3-pexpect', ''), # for wintest only + ('python3-pyasn1', 'python3-pyasn1'), # for krb5 tests ('', 'libsemanage-python'), ('', 'policycoreutils-python'), @@ -418,9 +420,10 @@ RPM_DISTS = { 'replace': { 'lsb-release': 'redhat-lsb', 'python3': 'python36', - 'python3-crypto': 'python36-crypto', + 'python3-cryptography': 'python36-cryptography', 'python3-devel': 'python36-devel', 'python3-dns': 'python36-dns', + 'python3-pyasn1': 'python36-pyasn1', 'python3-gpg': 'python36-gpg', 'python3-iso8601' : 'python36-iso8601', 'python3-markdown': 'python36-markdown', @@ -455,7 +458,6 @@ RPM_DISTS = { 'perl-JSON-Parse': '', # does not exist? 'perl-Test-Base': 'perl-Test-Simple', 'policycoreutils-python': 'python3-policycoreutils', - 'python3-crypto': '', 'quota-devel': '', # FIXME: Add me back, once available! 'liburing-devel': '', # not available yet, Add me back, once available! } @@ -503,7 +505,6 @@ RPM_DISTS = { 'perl-interpreter': '', 'procps-ng': 'procps', 'python-dns': 'python2-dnspython', - 'python3-crypto': 'python3-pycrypto', 'python3-dns': 'python3-dnspython', 'python3-markdown': 'python3-Markdown', 'quota-devel': '', @@ -536,7 +537,6 @@ RPM_DISTS = { 'perl-interpreter': '', 'procps-ng': 'procps', 'python-dns': 'python2-dnspython', - 'python3-crypto': 'python3-pycrypto', 'python3-dns': 'python3-dnspython', 'python3-markdown': 'python3-Markdown', 'quota-devel': '', diff --git a/bootstrap/generated-dists/centos7/bootstrap.sh b/bootstrap/generated-dists/centos7/bootstrap.sh index 2f0bb1bcc28..37f5d684663 100755 --- a/bootstrap/generated-dists/centos7/bootstrap.sh +++ b/bootstrap/generated-dists/centos7/bootstrap.sh @@ -83,9 +83,11 @@ yum install -y \ procps-ng \ psmisc \ python36 \ + python36-cryptography \ python36-devel \ python36-dns \ python36-markdown \ + python36-pyasn1 \ quota-devel \ readline-devel \ redhat-lsb \ diff --git a/bootstrap/generated-dists/centos7/packages.yml b/bootstrap/generated-dists/centos7/packages.yml index 475326b6db7..1b80882bd8c 100644 --- a/bootstrap/generated-dists/centos7/packages.yml +++ b/bootstrap/generated-dists/centos7/packages.yml @@ -69,9 +69,11 @@ packages: - procps-ng - psmisc - python36 + - python36-cryptography - python36-devel - python36-dns - python36-markdown + - python36-pyasn1 - quota-devel - readline-devel - redhat-lsb diff --git a/bootstrap/generated-dists/centos8/bootstrap.sh b/bootstrap/generated-dists/centos8/bootstrap.sh index 22484b3f6ad..61debd5e2ee 100755 --- a/bootstrap/generated-dists/centos8/bootstrap.sh +++ b/bootstrap/generated-dists/centos8/bootstrap.sh @@ -84,12 +84,14 @@ yum install -y \ procps-ng \ psmisc \ python3 \ + python3-cryptography \ python3-devel \ python3-dns \ python3-gpg \ python3-libsemanage \ python3-markdown \ python3-policycoreutils \ + python3-pyasn1 \ readline-devel \ redhat-lsb \ rng-tools \ diff --git a/bootstrap/generated-dists/centos8/packages.yml b/bootstrap/generated-dists/centos8/packages.yml index 07be0deeceb..2467b35dafb 100644 --- a/bootstrap/generated-dists/centos8/packages.yml +++ b/bootstrap/generated-dists/centos8/packages.yml @@ -69,12 +69,14 @@ packages: - procps-ng - psmisc - python3 + - python3-cryptography - python3-devel - python3-dns - python3-gpg - python3-libsemanage - python3-markdown - python3-policycoreutils + - python3-pyasn1 - readline-devel - redhat-lsb - rng-tools diff --git a/bootstrap/generated-dists/debian10/bootstrap.sh b/bootstrap/generated-dists/debian10/bootstrap.sh index f0847eb3c20..9391c1ca815 100755 --- a/bootstrap/generated-dists/debian10/bootstrap.sh +++ b/bootstrap/generated-dists/debian10/bootstrap.sh @@ -81,6 +81,7 @@ apt-get -y install \ procps \ psmisc \ python3 \ + python3-cryptography \ python3-dbg \ python3-dev \ python3-dnspython \ @@ -89,6 +90,7 @@ apt-get -y install \ python3-markdown \ python3-matplotlib \ python3-pexpect \ + python3-pyasn1 \ rng-tools \ rsync \ sed \ diff --git a/bootstrap/generated-dists/debian10/packages.yml b/bootstrap/generated-dists/debian10/packages.yml index a242cd8b362..dee4d5cef20 100644 --- a/bootstrap/generated-dists/debian10/packages.yml +++ b/bootstrap/generated-dists/debian10/packages.yml @@ -70,6 +70,7 @@ packages: - procps - psmisc - python3 + - python3-cryptography - python3-dbg - python3-dev - python3-dnspython @@ -78,6 +79,7 @@ packages: - python3-markdown - python3-matplotlib - python3-pexpect + - python3-pyasn1 - rng-tools - rsync - sed diff --git a/bootstrap/generated-dists/fedora31/bootstrap.sh b/bootstrap/generated-dists/fedora31/bootstrap.sh index 18c58092eff..09d36e88058 100755 --- a/bootstrap/generated-dists/fedora31/bootstrap.sh +++ b/bootstrap/generated-dists/fedora31/bootstrap.sh @@ -83,12 +83,14 @@ dnf install -y \ procps-ng \ psmisc \ python3 \ + python3-cryptography \ python3-devel \ python3-dns \ python3-gpg \ python3-libsemanage \ python3-markdown \ python3-policycoreutils \ + python3-pyasn1 \ quota-devel \ readline-devel \ redhat-lsb \ diff --git a/bootstrap/generated-dists/fedora31/packages.yml b/bootstrap/generated-dists/fedora31/packages.yml index 3165af8dd82..a2fbd0eb83b 100644 --- a/bootstrap/generated-dists/fedora31/packages.yml +++ b/bootstrap/generated-dists/fedora31/packages.yml @@ -72,12 +72,14 @@ packages: - procps-ng - psmisc - python3 + - python3-cryptography - python3-devel - python3-dns - python3-gpg - python3-libsemanage - python3-markdown - python3-policycoreutils + - python3-pyasn1 - quota-devel - readline-devel - redhat-lsb diff --git a/bootstrap/generated-dists/fedora32/bootstrap.sh b/bootstrap/generated-dists/fedora32/bootstrap.sh index 18c58092eff..09d36e88058 100755 --- a/bootstrap/generated-dists/fedora32/bootstrap.sh +++ b/bootstrap/generated-dists/fedora32/bootstrap.sh @@ -83,12 +83,14 @@ dnf install -y \ procps-ng \ psmisc \ python3 \ + python3-cryptography \ python3-devel \ python3-dns \ python3-gpg \ python3-libsemanage \ python3-markdown \ python3-policycoreutils \ + python3-pyasn1 \ quota-devel \ readline-devel \ redhat-lsb \ diff --git a/bootstrap/generated-dists/fedora32/packages.yml b/bootstrap/generated-dists/fedora32/packages.yml index 3165af8dd82..a2fbd0eb83b 100644 --- a/bootstrap/generated-dists/fedora32/packages.yml +++ b/bootstrap/generated-dists/fedora32/packages.yml @@ -72,12 +72,14 @@ packages: - procps-ng - psmisc - python3 + - python3-cryptography - python3-devel - python3-dns - python3-gpg - python3-libsemanage - python3-markdown - python3-policycoreutils + - python3-pyasn1 - quota-devel - readline-devel - redhat-lsb diff --git a/bootstrap/generated-dists/opensuse150/bootstrap.sh b/bootstrap/generated-dists/opensuse150/bootstrap.sh index 3fbcaacb24f..341b0ef9d35 100755 --- a/bootstrap/generated-dists/opensuse150/bootstrap.sh +++ b/bootstrap/generated-dists/opensuse150/bootstrap.sh @@ -80,9 +80,11 @@ zypper --non-interactive install \ python2-semanage \ python3 \ python3-Markdown \ + python3-cryptography \ python3-devel \ python3-dnspython \ python3-gpg \ + python3-pyasn1 \ readline-devel \ rng-tools \ rpcgen \ diff --git a/bootstrap/generated-dists/opensuse150/packages.yml b/bootstrap/generated-dists/opensuse150/packages.yml index 0eb19244677..b8c469cadca 100644 --- a/bootstrap/generated-dists/opensuse150/packages.yml +++ b/bootstrap/generated-dists/opensuse150/packages.yml @@ -68,9 +68,11 @@ packages: - python2-semanage - python3 - python3-Markdown + - python3-cryptography - python3-devel - python3-dnspython - python3-gpg + - python3-pyasn1 - readline-devel - rng-tools - rpcgen diff --git a/bootstrap/generated-dists/opensuse151/bootstrap.sh b/bootstrap/generated-dists/opensuse151/bootstrap.sh index 3fbcaacb24f..341b0ef9d35 100755 --- a/bootstrap/generated-dists/opensuse151/bootstrap.sh +++ b/bootstrap/generated-dists/opensuse151/bootstrap.sh @@ -80,9 +80,11 @@ zypper --non-interactive install \ python2-semanage \ python3 \ python3-Markdown \ + python3-cryptography \ python3-devel \ python3-dnspython \ python3-gpg \ + python3-pyasn1 \ readline-devel \ rng-tools \ rpcgen \ diff --git a/bootstrap/generated-dists/opensuse151/packages.yml b/bootstrap/generated-dists/opensuse151/packages.yml index 0eb19244677..b8c469cadca 100644 --- a/bootstrap/generated-dists/opensuse151/packages.yml +++ b/bootstrap/generated-dists/opensuse151/packages.yml @@ -68,9 +68,11 @@ packages: - python2-semanage - python3 - python3-Markdown + - python3-cryptography - python3-devel - python3-dnspython - python3-gpg + - python3-pyasn1 - readline-devel - rng-tools - rpcgen diff --git a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh index a8f47762ded..f5791357d45 100755 --- a/bootstrap/generated-dists/ubuntu1604/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu1604/bootstrap.sh @@ -80,6 +80,7 @@ apt-get -y install \ procps \ psmisc \ python3 \ + python3-cryptography \ python3-dbg \ python3-dev \ python3-dnspython \ @@ -88,6 +89,7 @@ apt-get -y install \ python3-markdown \ python3-matplotlib \ python3-pexpect \ + python3-pyasn1 \ rng-tools \ rsync \ sed \ diff --git a/bootstrap/generated-dists/ubuntu1604/packages.yml b/bootstrap/generated-dists/ubuntu1604/packages.yml index c3cd9af9c3e..932cc162041 100644 --- a/bootstrap/generated-dists/ubuntu1604/packages.yml +++ b/bootstrap/generated-dists/ubuntu1604/packages.yml @@ -69,6 +69,7 @@ packages: - procps - psmisc - python3 + - python3-cryptography - python3-dbg - python3-dev - python3-dnspython @@ -77,6 +78,7 @@ packages: - python3-markdown - python3-matplotlib - python3-pexpect + - python3-pyasn1 - rng-tools - rsync - sed diff --git a/bootstrap/generated-dists/ubuntu1804/bootstrap.sh b/bootstrap/generated-dists/ubuntu1804/bootstrap.sh index 97d32815d72..e668057ea82 100755 --- a/bootstrap/generated-dists/ubuntu1804/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu1804/bootstrap.sh @@ -82,6 +82,7 @@ apt-get -y install \ procps \ psmisc \ python3 \ + python3-cryptography \ python3-dbg \ python3-dev \ python3-dnspython \ @@ -90,6 +91,7 @@ apt-get -y install \ python3-markdown \ python3-matplotlib \ python3-pexpect \ + python3-pyasn1 \ rng-tools \ rsync \ sed \ diff --git a/bootstrap/generated-dists/ubuntu1804/packages.yml b/bootstrap/generated-dists/ubuntu1804/packages.yml index f45deb2c808..edf5720f84c 100644 --- a/bootstrap/generated-dists/ubuntu1804/packages.yml +++ b/bootstrap/generated-dists/ubuntu1804/packages.yml @@ -71,6 +71,7 @@ packages: - procps - psmisc - python3 + - python3-cryptography - python3-dbg - python3-dev - python3-dnspython @@ -79,6 +80,7 @@ packages: - python3-markdown - python3-matplotlib - python3-pexpect + - python3-pyasn1 - rng-tools - rsync - sed diff --git a/bootstrap/generated-dists/ubuntu2004/bootstrap.sh b/bootstrap/generated-dists/ubuntu2004/bootstrap.sh index 97d32815d72..e668057ea82 100755 --- a/bootstrap/generated-dists/ubuntu2004/bootstrap.sh +++ b/bootstrap/generated-dists/ubuntu2004/bootstrap.sh @@ -82,6 +82,7 @@ apt-get -y install \ procps \ psmisc \ python3 \ + python3-cryptography \ python3-dbg \ python3-dev \ python3-dnspython \ @@ -90,6 +91,7 @@ apt-get -y install \ python3-markdown \ python3-matplotlib \ python3-pexpect \ + python3-pyasn1 \ rng-tools \ rsync \ sed \ diff --git a/bootstrap/generated-dists/ubuntu2004/packages.yml b/bootstrap/generated-dists/ubuntu2004/packages.yml index f45deb2c808..edf5720f84c 100644 --- a/bootstrap/generated-dists/ubuntu2004/packages.yml +++ b/bootstrap/generated-dists/ubuntu2004/packages.yml @@ -71,6 +71,7 @@ packages: - procps - psmisc - python3 + - python3-cryptography - python3-dbg - python3-dev - python3-dnspython @@ -79,6 +80,7 @@ packages: - python3-markdown - python3-matplotlib - python3-pexpect + - python3-pyasn1 - rng-tools - rsync - sed diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index c3a72eec5c6..085ef7c5297 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -f5212e7abcae3208b796c939432ab9bec319264a +7414ad7ef9108d406b1f6b17ebce19e32aee9f70 -- 2.25.1 From 223077cce9193ffc82d9acf0469fcc1acaa871d1 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Wed, 9 Dec 2020 00:03:47 +1100 Subject: [PATCH 012/645] bootstrap: Cope with case changes in CentOS 8 repo names RN: Be more flexible with repository names in CentOS 8 test environments BUG: https://bugzilla.samba.org/show_bug.cgi?id=14594 Signed-off-by: Martin Schwenke Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit 1c59f49aaede8ec1662d4e49aef84fcd902a8a76 due to conflicts in sha1sum because changes in-between this and the last backported changes were not included] --- .gitlab-ci.yml | 2 +- bootstrap/config.py | 3 ++- bootstrap/generated-dists/centos8/bootstrap.sh | 3 ++- bootstrap/sha1sum.txt | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6a5e8693e80..7c7597e31b6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ variables: # Set this to the contents of bootstrap/sha1sum.txt # which is generated by bootstrap/template.py --render # - SAMBA_CI_CONTAINER_TAG: 7414ad7ef9108d406b1f6b17ebce19e32aee9f70 + SAMBA_CI_CONTAINER_TAG: 5a03ad6f346def64a757bcd2e71dc9a5c10ceae0 # # We use the ubuntu1804 image as default as # it matches what we have on sn-devel-184. diff --git a/bootstrap/config.py b/bootstrap/config.py index 196f9bdf8eb..93e321a7e81 100644 --- a/bootstrap/config.py +++ b/bootstrap/config.py @@ -228,7 +228,8 @@ set -xueo pipefail yum update -y yum install -y dnf-plugins-core yum install -y epel-release -yum config-manager --set-enabled PowerTools -y +yum config-manager --set-enabled PowerTools -y || \ + yum config-manager --set-enabled powertools -y yum update -y yum install -y \ diff --git a/bootstrap/generated-dists/centos8/bootstrap.sh b/bootstrap/generated-dists/centos8/bootstrap.sh index 61debd5e2ee..2ee15dba86c 100755 --- a/bootstrap/generated-dists/centos8/bootstrap.sh +++ b/bootstrap/generated-dists/centos8/bootstrap.sh @@ -10,7 +10,8 @@ set -xueo pipefail yum update -y yum install -y dnf-plugins-core yum install -y epel-release -yum config-manager --set-enabled PowerTools -y +yum config-manager --set-enabled PowerTools -y || \ + yum config-manager --set-enabled powertools -y yum update -y yum install -y \ diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt index 085ef7c5297..b1e6736def0 100644 --- a/bootstrap/sha1sum.txt +++ b/bootstrap/sha1sum.txt @@ -1 +1 @@ -7414ad7ef9108d406b1f6b17ebce19e32aee9f70 +5a03ad6f346def64a757bcd2e71dc9a5c10ceae0 -- 2.25.1 From 64b62b7c9fea1b288d4eec350dcadaa7e8785e65 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Mar 2020 14:02:58 +0100 Subject: [PATCH 013/645] python/tests: let usage.py be more verbose on errors Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 0f805db40a4948f9902733aa03ed6ae2789dabb3) --- python/samba/tests/usage.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 4b7bccde758..259ec91f66e 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -331,8 +331,9 @@ class HelpTestSuper(TestCase): if self.check_return_code: self.assertEqual(p.returncode, 0, - "%s %s\nreturncode should not be %d" % - (filename, h, p.returncode)) + "%s %s\nreturncode should not be %d\n" + "err:\n%s\nout:\n%s" % + (filename, h, p.returncode, err, out)) if self.check_contains_usage: self.assertIn('usage', outl, 'lacks "Usage:"\n') if self.check_multiline: -- 2.25.1 From c55219d57f55e0bd300a23b505c2d0d1e657fd43 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sat, 15 Feb 2020 18:33:33 +0100 Subject: [PATCH 014/645] python/tests/krb5: add crypto.py from greghudson/pyk5 as kcrypto.py This is crypto.py of commit f0612aa908062fb239d1c3873595e7204ae1691d from https://github.com/greghudson/pyk5.git This will be used in order to do raw protocol testing against [MS-KILE] KDCs. Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Isaac Boukris Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher (cherry picked from commit 679bb52c957dafcec96ff37f87d8c3496996b909) --- python/samba/tests/krb5/kcrypto.py | 713 +++++++++++++++++++++++++++++ python/samba/tests/source.py | 6 + python/samba/tests/usage.py | 4 +- 3 files changed, 722 insertions(+), 1 deletion(-) create mode 100644 python/samba/tests/krb5/kcrypto.py diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py new file mode 100644 index 00000000000..18c0f71c24c --- /dev/null +++ b/python/samba/tests/krb5/kcrypto.py @@ -0,0 +1,713 @@ +# Copyright (C) 2013 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. + +# XXX current status: +# * Done and tested +# - AES encryption, checksum, string2key, prf +# - cf2 (needed for FAST) +# * Still to do: +# - DES enctypes and cksumtypes +# - RC4 exported enctype (if we need it for anything) +# - Unkeyed checksums +# - Special RC4, raw DES/DES3 operations for GSSAPI +# * Difficult or low priority: +# - Camellia not supported by PyCrypto +# - Cipher state only needed for kcmd suite +# - Nonstandard enctypes and cksumtypes like des-hmac-sha1 + +from math import gcd +from functools import reduce +from struct import pack, unpack +from Crypto.Cipher import AES, DES3, ARC4 +from Crypto.Hash import HMAC, MD4, MD5, SHA +from Crypto.Protocol.KDF import PBKDF2 +from Crypto.Random import get_random_bytes + + +class Enctype(object): + DES_CRC = 1 + DES_MD4 = 2 + DES_MD5 = 3 + DES3 = 16 + AES128 = 17 + AES256 = 18 + RC4 = 23 + + +class Cksumtype(object): + CRC32 = 1 + MD4 = 2 + MD4_DES = 3 + MD5 = 7 + MD5_DES = 8 + SHA1 = 9 + SHA1_DES3 = 12 + SHA1_AES128 = 15 + SHA1_AES256 = 16 + HMAC_MD5 = -138 + + +class InvalidChecksum(ValueError): + pass + + +def _zeropad(s, padsize): + # Return s padded with 0 bytes to a multiple of padsize. + padlen = (padsize - (len(s) % padsize)) % padsize + return s + bytes(padlen) + + +def _xorbytes(b1, b2): + # xor two strings together and return the resulting string. + assert len(b1) == len(b2) + return bytes([x ^ y for x, y in zip(b1, b2)]) + + +def _mac_equal(mac1, mac2): + # Constant-time comparison function. (We can't use HMAC.verify + # since we use truncated macs.) + assert len(mac1) == len(mac2) + res = 0 + for x, y in zip(mac1, mac2): + res |= x ^ y + return res == 0 + + +def _nfold(str, nbytes): + # Convert str to a string of length nbytes using the RFC 3961 nfold + # operation. + + # Rotate the bytes in str to the right by nbits bits. + def rotate_right(str, nbits): + nbytes, remain = (nbits//8) % len(str), nbits % 8 + return bytes([(str[i-nbytes] >> remain) | + (str[i-nbytes-1] << (8-remain) & 0xff) + for i in range(len(str))]) + + # Add equal-length strings together with end-around carry. + def add_ones_complement(str1, str2): + n = len(str1) + v = [a + b for a, b in zip(str1, str2)] + # Propagate carry bits to the left until there aren't any left. + while any(x & ~0xff for x in v): + v = [(v[i-n+1]>>8) + (v[i]&0xff) for i in range(n)] + return bytes([x for x in v]) + + # Concatenate copies of str to produce the least common multiple + # of len(str) and nbytes, rotating each copy of str to the right + # by 13 bits times its list position. Decompose the concatenation + # into slices of length nbytes, and add them together as + # big-endian ones' complement integers. + slen = len(str) + lcm = nbytes * slen // gcd(nbytes, slen) + bigstr = b''.join((rotate_right(str, 13 * i) for i in range(lcm // slen))) + slices = (bigstr[p:p+nbytes] for p in range(0, lcm, nbytes)) + return reduce(add_ones_complement, slices) + + +def _is_weak_des_key(keybytes): + return keybytes in (b'\x01\x01\x01\x01\x01\x01\x01\x01', + b'\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE', + b'\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E', + b'\xE0\xE0\xE0\xE0\xF1\xF1\xF1\xF1', + b'\x01\xFE\x01\xFE\x01\xFE\x01\xFE', + b'\xFE\x01\xFE\x01\xFE\x01\xFE\x01', + b'\x1F\xE0\x1F\xE0\x0E\xF1\x0E\xF1', + b'\xE0\x1F\xE0\x1F\xF1\x0E\xF1\x0E', + b'\x01\xE0\x01\xE0\x01\xF1\x01\xF1', + b'\xE0\x01\xE0\x01\xF1\x01\xF1\x01', + b'\x1F\xFE\x1F\xFE\x0E\xFE\x0E\xFE', + b'\xFE\x1F\xFE\x1F\xFE\x0E\xFE\x0E', + b'\x01\x1F\x01\x1F\x01\x0E\x01\x0E', + b'\x1F\x01\x1F\x01\x0E\x01\x0E\x01', + b'\xE0\xFE\xE0\xFE\xF1\xFE\xF1\xFE', + b'\xFE\xE0\xFE\xE0\xFE\xF1\xFE\xF1') + + +class _EnctypeProfile(object): + # Base class for enctype profiles. Usable enctype classes must define: + # * enctype: enctype number + # * keysize: protocol size of key in bytes + # * seedsize: random_to_key input size in bytes + # * random_to_key (if the keyspace is not dense) + # * string_to_key + # * encrypt + # * decrypt + # * prf + + @classmethod + def random_to_key(cls, seed): + if len(seed) != cls.seedsize: + raise ValueError('Wrong seed length') + return Key(cls.enctype, seed) + + +class _SimplifiedEnctype(_EnctypeProfile): + # Base class for enctypes using the RFC 3961 simplified profile. + # Defines the encrypt, decrypt, and prf methods. Subclasses must + # define: + # * blocksize: Underlying cipher block size in bytes + # * padsize: Underlying cipher padding multiple (1 or blocksize) + # * macsize: Size of integrity MAC in bytes + # * hashmod: PyCrypto hash module for underlying hash function + # * basic_encrypt, basic_decrypt: Underlying CBC/CTS cipher + + @classmethod + def derive(cls, key, constant): + # RFC 3961 only says to n-fold the constant only if it is + # shorter than the cipher block size. But all Unix + # implementations n-fold constants if their length is larger + # than the block size as well, and n-folding when the length + # is equal to the block size is a no-op. + plaintext = _nfold(constant, cls.blocksize) + rndseed = b'' + while len(rndseed) < cls.seedsize: + ciphertext = cls.basic_encrypt(key, plaintext) + rndseed += ciphertext + plaintext = ciphertext + return cls.random_to_key(rndseed[0:cls.seedsize]) + + @classmethod + def encrypt(cls, key, keyusage, plaintext, confounder): + ki = cls.derive(key, pack('>iB', keyusage, 0x55)) + ke = cls.derive(key, pack('>iB', keyusage, 0xAA)) + if confounder is None: + confounder = get_random_bytes(cls.blocksize) + basic_plaintext = confounder + _zeropad(plaintext, cls.padsize) + hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest() + return cls.basic_encrypt(ke, basic_plaintext) + hmac[:cls.macsize] + + @classmethod + def decrypt(cls, key, keyusage, ciphertext): + ki = cls.derive(key, pack('>iB', keyusage, 0x55)) + ke = cls.derive(key, pack('>iB', keyusage, 0xAA)) + if len(ciphertext) < cls.blocksize + cls.macsize: + raise ValueError('ciphertext too short') + basic_ctext, mac = ciphertext[:-cls.macsize], ciphertext[-cls.macsize:] + if len(basic_ctext) % cls.padsize != 0: + raise ValueError('ciphertext does not meet padding requirement') + basic_plaintext = cls.basic_decrypt(ke, basic_ctext) + hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest() + expmac = hmac[:cls.macsize] + if not _mac_equal(mac, expmac): + raise InvalidChecksum('ciphertext integrity failure') + # Discard the confounder. + return basic_plaintext[cls.blocksize:] + + @classmethod + def prf(cls, key, string): + # Hash the input. RFC 3961 says to truncate to the padding + # size, but implementations truncate to the block size. + hashval = cls.hashmod.new(string).digest() + truncated = hashval[:-(len(hashval) % cls.blocksize)] + # Encrypt the hash with a derived key. + kp = cls.derive(key, b'prf') + return cls.basic_encrypt(kp, truncated) + + +class _DES3CBC(_SimplifiedEnctype): + enctype = Enctype.DES3 + keysize = 24 + seedsize = 21 + blocksize = 8 + padsize = 8 + macsize = 20 + hashmod = SHA + + @classmethod + def random_to_key(cls, seed): + # XXX Maybe reframe as _DESEnctype.random_to_key and use that + # way from DES3 random-to-key when DES is implemented, since + # MIT does this instead of the RFC 3961 random-to-key. + def expand(seed): + def parity(b): + # Return b with the low-order bit set to yield odd parity. + b &= ~1 + return b if bin(b & ~1).count('1') % 2 else b | 1 + assert len(seed) == 7 + firstbytes = [parity(b & ~1) for b in seed] + lastbyte = parity(sum((seed[i]&1) << i+1 for i in range(7))) + keybytes = bytes([b for b in firstbytes + [lastbyte]]) + if _is_weak_des_key(keybytes): + keybytes[7] = bytes([keybytes[7] ^ 0xF0]) + return keybytes + + if len(seed) != 21: + raise ValueError('Wrong seed length') + k1, k2, k3 = expand(seed[:7]), expand(seed[7:14]), expand(seed[14:]) + return Key(cls.enctype, k1 + k2 + k3) + + @classmethod + def string_to_key(cls, string, salt, params): + if params is not None and params != b'': + raise ValueError('Invalid DES3 string-to-key parameters') + k = cls.random_to_key(_nfold(string + salt, 21)) + return cls.derive(k, b'kerberos') + + @classmethod + def basic_encrypt(cls, key, plaintext): + assert len(plaintext) % 8 == 0 + des3 = DES3.new(key.contents, AES.MODE_CBC, bytes(8)) + return des3.encrypt(plaintext) + + @classmethod + def basic_decrypt(cls, key, ciphertext): + assert len(ciphertext) % 8 == 0 + des3 = DES3.new(key.contents, AES.MODE_CBC, bytes(8)) + return des3.decrypt(ciphertext) + + +class _AESEnctype(_SimplifiedEnctype): + # Base class for aes128-cts and aes256-cts. + blocksize = 16 + padsize = 1 + macsize = 12 + hashmod = SHA + + @classmethod + def string_to_key(cls, string, salt, params): + (iterations,) = unpack('>L', params or b'\x00\x00\x10\x00') + prf = lambda p, s: HMAC.new(p, s, SHA).digest() + seed = PBKDF2(string, salt, cls.seedsize, iterations, prf) + tkey = cls.random_to_key(seed) + return cls.derive(tkey, b'kerberos') + + @classmethod + def basic_encrypt(cls, key, plaintext): + assert len(plaintext) >= 16 + aes = AES.new(key.contents, AES.MODE_CBC, bytes(16)) + ctext = aes.encrypt(_zeropad(plaintext, 16)) + if len(plaintext) > 16: + # Swap the last two ciphertext blocks and truncate the + # final block to match the plaintext length. + lastlen = len(plaintext) % 16 or 16 + ctext = ctext[:-32] + ctext[-16:] + ctext[-32:-16][:lastlen] + return ctext + + @classmethod + def basic_decrypt(cls, key, ciphertext): + assert len(ciphertext) >= 16 + aes = AES.new(key.contents, AES.MODE_ECB) + if len(ciphertext) == 16: + return aes.decrypt(ciphertext) + # Split the ciphertext into blocks. The last block may be partial. + cblocks = [ciphertext[p:p+16] for p in range(0, len(ciphertext), 16)] + lastlen = len(cblocks[-1]) + # CBC-decrypt all but the last two blocks. + prev_cblock = bytes(16) + plaintext = b'' + for b in cblocks[:-2]: + plaintext += _xorbytes(aes.decrypt(b), prev_cblock) + prev_cblock = b + # Decrypt the second-to-last cipher block. The left side of + # the decrypted block will be the final block of plaintext + # xor'd with the final partial cipher block; the right side + # will be the omitted bytes of ciphertext from the final + # block. + b = aes.decrypt(cblocks[-2]) + lastplaintext =_xorbytes(b[:lastlen], cblocks[-1]) + omitted = b[lastlen:] + # Decrypt the final cipher block plus the omitted bytes to get + # the second-to-last plaintext block. + plaintext += _xorbytes(aes.decrypt(cblocks[-1] + omitted), prev_cblock) + return plaintext + lastplaintext + + +class _AES128CTS(_AESEnctype): + enctype = Enctype.AES128 + keysize = 16 + seedsize = 16 + + +class _AES256CTS(_AESEnctype): + enctype = Enctype.AES256 + keysize = 32 + seedsize = 32 + + +class _RC4(_EnctypeProfile): + enctype = Enctype.RC4 + keysize = 16 + seedsize = 16 + + @staticmethod + def usage_str(keyusage): + # Return a four-byte string for an RFC 3961 keyusage, using + # the RFC 4757 rules. Per the errata, do not map 9 to 8. + table = {3: 8, 23: 13} + msusage = table[keyusage] if keyusage in table else keyusage + return pack('iB', keyusage, 0x99)) + hmac = HMAC.new(kc.contents, text, cls.enc.hashmod).digest() + return hmac[:cls.macsize] + + @classmethod + def verify(cls, key, keyusage, text, cksum): + if key.enctype != cls.enc.enctype: + raise ValueError('Wrong key type for checksum') + super(_SimplifiedChecksum, cls).verify(key, keyusage, text, cksum) + + +class _SHA1AES128(_SimplifiedChecksum): + macsize = 12 + enc = _AES128CTS + + +class _SHA1AES256(_SimplifiedChecksum): + macsize = 12 + enc = _AES256CTS + + +class _SHA1DES3(_SimplifiedChecksum): + macsize = 20 + enc = _DES3CBC + + +class _HMACMD5(_ChecksumProfile): + @classmethod + def checksum(cls, key, keyusage, text): + ksign = HMAC.new(key.contents, b'signaturekey\0', MD5).digest() + md5hash = MD5.new(_RC4.usage_str(keyusage) + text).digest() + return HMAC.new(ksign, md5hash, MD5).digest() + + @classmethod + def verify(cls, key, keyusage, text, cksum): + if key.enctype != Enctype.RC4: + raise ValueError('Wrong key type for checksum') + super(_HMACMD5, cls).verify(key, keyusage, text, cksum) + + +_enctype_table = { + Enctype.DES3: _DES3CBC, + Enctype.AES128: _AES128CTS, + Enctype.AES256: _AES256CTS, + Enctype.RC4: _RC4 +} + + +_checksum_table = { + Cksumtype.SHA1_DES3: _SHA1DES3, + Cksumtype.SHA1_AES128: _SHA1AES128, + Cksumtype.SHA1_AES256: _SHA1AES256, + Cksumtype.HMAC_MD5: _HMACMD5 +} + + +def _get_enctype_profile(enctype): + if enctype not in _enctype_table: + raise ValueError('Invalid enctype %d' % enctype) + return _enctype_table[enctype] + + +def _get_checksum_profile(cksumtype): + if cksumtype not in _checksum_table: + raise ValueError('Invalid cksumtype %d' % cksumtype) + return _checksum_table[cksumtype] + + +class Key(object): + def __init__(self, enctype, contents): + e = _get_enctype_profile(enctype) + if len(contents) != e.keysize: + raise ValueError('Wrong key length') + self.enctype = enctype + self.contents = contents + + +def seedsize(enctype): + e = _get_enctype_profile(enctype) + return e.seedsize + + +def random_to_key(enctype, seed): + e = _get_enctype_profile(enctype) + if len(seed) != e.seedsize: + raise ValueError('Wrong crypto seed length') + return e.random_to_key(seed) + + +def string_to_key(enctype, string, salt, params=None): + e = _get_enctype_profile(enctype) + return e.string_to_key(string, salt, params) + + +def encrypt(key, keyusage, plaintext, confounder=None): + e = _get_enctype_profile(key.enctype) + return e.encrypt(key, keyusage, plaintext, confounder) + + +def decrypt(key, keyusage, ciphertext): + # Throw InvalidChecksum on checksum failure. Throw ValueError on + # invalid key enctype or malformed ciphertext. + e = _get_enctype_profile(key.enctype) + return e.decrypt(key, keyusage, ciphertext) + + +def prf(key, string): + e = _get_enctype_profile(key.enctype) + return e.prf(key, string) + + +def make_checksum(cksumtype, key, keyusage, text): + c = _get_checksum_profile(cksumtype) + return c.checksum(key, keyusage, text) + + +def verify_checksum(cksumtype, key, keyusage, text, cksum): + # Throw InvalidChecksum exception on checksum failure. Throw + # ValueError on invalid cksumtype, invalid key enctype, or + # malformed checksum. + c = _get_checksum_profile(cksumtype) + c.verify(key, keyusage, text, cksum) + + +def prfplus(key, pepper, l): + # Produce l bytes of output using the RFC 6113 PRF+ function. + out = b'' + count = 1 + while len(out) < l: + out += prf(key, bytes([count]) + pepper) + count += 1 + return out[:l] + + +def cf2(enctype, key1, key2, pepper1, pepper2): + # Combine two keys and two pepper strings to produce a result key + # of type enctype, using the RFC 6113 KRB-FX-CF2 function. + e = _get_enctype_profile(enctype) + return e.random_to_key(_xorbytes(prfplus(key1, pepper1, e.seedsize), + prfplus(key2, pepper2, e.seedsize))) + + +if __name__ == '__main__': + def h(hexstr): + return bytes.fromhex(hexstr) + + # AES128 encrypt and decrypt + kb = h('9062430C8CDA3388922E6D6A509F5B7A') + conf = h('94B491F481485B9A0678CD3C4EA386AD') + keyusage = 2 + plain = b'9 bytesss' + ctxt = h('68FB9679601F45C78857B2BF820FD6E53ECA8D42FD4B1D7024A09205ABB7CD2E' + 'C26C355D2F') + k = Key(Enctype.AES128, kb) + assert(encrypt(k, keyusage, plain, conf) == ctxt) + assert(decrypt(k, keyusage, ctxt) == plain) + + # AES256 encrypt and decrypt + kb = h('F1C795E9248A09338D82C3F8D5B567040B0110736845041347235B1404231398') + conf = h('E45CA518B42E266AD98E165E706FFB60') + keyusage = 4 + plain = b'30 bytes bytes bytes bytes byt' + ctxt = h('D1137A4D634CFECE924DBC3BF6790648BD5CFF7DE0E7B99460211D0DAEF3D79A' + '295C688858F3B34B9CBD6EEBAE81DAF6B734D4D498B6714F1C1D') + k = Key(Enctype.AES256, kb) + assert(encrypt(k, keyusage, plain, conf) == ctxt) + assert(decrypt(k, keyusage, ctxt) == plain) + + # AES128 checksum + kb = h('9062430C8CDA3388922E6D6A509F5B7A') + keyusage = 3 + plain = b'eight nine ten eleven twelve thirteen' + cksum = h('01A4B088D45628F6946614E3') + k = Key(Enctype.AES128, kb) + verify_checksum(Cksumtype.SHA1_AES128, k, keyusage, plain, cksum) + + # AES256 checksum + kb = h('B1AE4CD8462AFF1677053CC9279AAC30B796FB81CE21474DD3DDBCFEA4EC76D7') + keyusage = 4 + plain = b'fourteen' + cksum = h('E08739E3279E2903EC8E3836') + k = Key(Enctype.AES256, kb) + verify_checksum(Cksumtype.SHA1_AES256, k, keyusage, plain, cksum) + + # AES128 string-to-key + string = b'password' + salt = b'ATHENA.MIT.EDUraeburn' + params = h('00000002') + kb = h('C651BF29E2300AC27FA469D693BDDA13') + k = string_to_key(Enctype.AES128, string, salt, params) + assert(k.contents == kb) + + # AES256 string-to-key + string = b'X' * 64 + salt = b'pass phrase equals block size' + params = h('000004B0') + kb = h('89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56C553BA4B34') + k = string_to_key(Enctype.AES256, string, salt, params) + assert(k.contents == kb) + + # AES128 prf + kb = h('77B39A37A868920F2A51F9DD150C5717') + k = string_to_key(Enctype.AES128, b'key1', b'key1') + assert(prf(k, b'\x01\x61') == kb) + + # AES256 prf + kb = h('0D674DD0F9A6806525A4D92E828BD15A') + k = string_to_key(Enctype.AES256, b'key2', b'key2') + assert(prf(k, b'\x02\x62') == kb) + + # AES128 cf2 + kb = h('97DF97E4B798B29EB31ED7280287A92A') + k1 = string_to_key(Enctype.AES128, b'key1', b'key1') + k2 = string_to_key(Enctype.AES128, b'key2', b'key2') + k = cf2(Enctype.AES128, k1, k2, b'a', b'b') + assert(k.contents == kb) + + # AES256 cf2 + kb = h('4D6CA4E629785C1F01BAF55E2E548566B9617AE3A96868C337CB93B5E72B1C7B') + k1 = string_to_key(Enctype.AES256, b'key1', b'key1') + k2 = string_to_key(Enctype.AES256, b'key2', b'key2') + k = cf2(Enctype.AES256, k1, k2, b'a', b'b') + assert(k.contents == kb) + + # DES3 encrypt and decrypt + kb = h('0DD52094E0F41CECCB5BE510A764B35176E3981332F1E598') + conf = h('94690A17B2DA3C9B') + keyusage = 3 + plain = b'13 bytes byte' + ctxt = h('839A17081ECBAFBCDC91B88C6955DD3C4514023CF177B77BF0D0177A16F705E8' + '49CB7781D76A316B193F8D30') + k = Key(Enctype.DES3, kb) + assert(encrypt(k, keyusage, plain, conf) == ctxt) + assert(decrypt(k, keyusage, ctxt) == _zeropad(plain, 8)) + + # DES3 string-to-key + string = b'password' + salt = b'ATHENA.MIT.EDUraeburn' + kb = h('850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E') + k = string_to_key(Enctype.DES3, string, salt) + assert(k.contents == kb) + + # DES3 checksum + kb = h('7A25DF8992296DCEDA0E135BC4046E2375B3C14C98FBC162') + keyusage = 2 + plain = b'six seven' + cksum = h('0EEFC9C3E049AABC1BA5C401677D9AB699082BB4') + k = Key(Enctype.DES3, kb) + verify_checksum(Cksumtype.SHA1_DES3, k, keyusage, plain, cksum) + + # DES3 cf2 + kb = h('E58F9EB643862C13AD38E529313462A7F73E62834FE54A01') + k1 = string_to_key(Enctype.DES3, b'key1', b'key1') + k2 = string_to_key(Enctype.DES3, b'key2', b'key2') + k = cf2(Enctype.DES3, k1, k2, b'a', b'b') + assert(k.contents == kb) + + # RC4 encrypt and decrypt + kb = h('68F263DB3FCE15D031C9EAB02D67107A') + conf = h('37245E73A45FBF72') + keyusage = 4 + plain = b'30 bytes bytes bytes bytes byt' + ctxt = h('95F9047C3AD75891C2E9B04B16566DC8B6EB9CE4231AFB2542EF87A7B5A0F260' + 'A99F0460508DE0CECC632D07C354124E46C5D2234EB8') + k = Key(Enctype.RC4, kb) + assert(encrypt(k, keyusage, plain, conf) == ctxt) + assert(decrypt(k, keyusage, ctxt) == plain) + + # RC4 string-to-key + string = b'foo' + kb = h('AC8E657F83DF82BEEA5D43BDAF7800CC') + k = string_to_key(Enctype.RC4, string, None) + assert(k.contents == kb) + + # RC4 checksum + kb = h('F7D3A155AF5E238A0B7A871A96BA2AB2') + keyusage = 6 + plain = b'seventeen eighteen nineteen twenty' + cksum = h('EB38CC97E2230F59DA4117DC5859D7EC') + k = Key(Enctype.RC4, kb) + verify_checksum(Cksumtype.HMAC_MD5, k, keyusage, plain, cksum) + + # RC4 cf2 + kb = h('24D7F6B6BAE4E5C00D2082C5EBAB3672') + k1 = string_to_key(Enctype.RC4, b'key1', b'key1') + k2 = string_to_key(Enctype.RC4, b'key2', b'key2') + k = cf2(Enctype.RC4, k1, k2, b'a', b'b') + assert(k.contents == kb) diff --git a/python/samba/tests/source.py b/python/samba/tests/source.py index 4bb652c4204..b7608b1bab3 100644 --- a/python/samba/tests/source.py +++ b/python/samba/tests/source.py @@ -90,6 +90,9 @@ class TestSource(TestCase): if "wafsamba" in fname: # FIXME: No copyright headers in wafsamba continue + if fname.endswith("python/samba/tests/krb5/kcrypto.py"): + # Imported from MIT testing repo + continue match = copyright_re.search(text) if not match: incorrect.append((fname, 'no copyright line found\n')) @@ -132,6 +135,9 @@ class TestSource(TestCase): # Imported from subunit/testtools, which are dual # Apache2/BSD-3. continue + if fname.endswith("python/samba/tests/krb5/kcrypto.py"): + # Imported from MIT testing repo + continue if not gpl_re.search(text): incorrect.append(fname) diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 259ec91f66e..06fdc9afacb 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -84,7 +84,8 @@ EXCLUDE_USAGE = { 'selftest/tests.py', 'python/samba/subunit/run.py', 'bin/python/samba/subunit/run.py', - 'python/samba/tests/dcerpc/raw_protocol.py' + 'python/samba/tests/dcerpc/raw_protocol.py', + 'python/samba/tests/krb5/kcrypto.py', } EXCLUDE_HELP = { @@ -101,6 +102,7 @@ EXCLUDE_DIRS = { 'bin/ab', 'bin/python/samba/tests', 'bin/python/samba/tests/dcerpc', + 'bin/python/samba/tests/krb5', } -- 2.25.1 From c0bc4d8fafb7773ce10462f2234b52de5aaff702 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Mar 2020 12:47:39 +0100 Subject: [PATCH 015/645] python/tests/krb5: convert kcrypto.py to python3-cryptography and a few Samba helpers Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 8bdd37997686d4ca60584bdfda78440be8432405) --- python/samba/tests/krb5/kcrypto.py | 460 +++++++++++++++++------------ 1 file changed, 273 insertions(+), 187 deletions(-) mode change 100644 => 100755 python/samba/tests/krb5/kcrypto.py diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py old mode 100644 new mode 100755 index 18c0f71c24c..0907d881b68 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Copyright (C) 2013 by the Massachusetts Institute of Technology. # All rights reserved. # @@ -40,14 +42,26 @@ # - Cipher state only needed for kcmd suite # - Nonstandard enctypes and cksumtypes like des-hmac-sha1 +import sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + from math import gcd from functools import reduce from struct import pack, unpack -from Crypto.Cipher import AES, DES3, ARC4 -from Crypto.Hash import HMAC, MD4, MD5, SHA -from Crypto.Protocol.KDF import PBKDF2 -from Crypto.Random import get_random_bytes - +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hmac +from cryptography.hazmat.primitives.ciphers import algorithms as ciphers +from cryptography.hazmat.primitives.ciphers import modes +from cryptography.hazmat.primitives.ciphers.base import Cipher +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC +from samba.tests import TestCase +from samba.credentials import Credentials +from samba import generate_random_bytes as get_random_bytes +from samba.compat import get_string, get_bytes class Enctype(object): DES_CRC = 1 @@ -97,6 +111,15 @@ def _mac_equal(mac1, mac2): res |= x ^ y return res == 0 +def SIMPLE_HASH(string, algo_cls): + hash_ctx = hashes.Hash(algo_cls(), default_backend()) + hash_ctx.update(string) + return hash_ctx.finalize() + +def HMAC_HASH(key, string, algo_cls): + hmac_ctx = hmac.HMAC(key, algo_cls(), default_backend()) + hmac_ctx.update(string) + return hmac_ctx.finalize() def _nfold(str, nbytes): # Convert str to a string of length nbytes using the RFC 3961 nfold @@ -199,7 +222,7 @@ class _SimplifiedEnctype(_EnctypeProfile): if confounder is None: confounder = get_random_bytes(cls.blocksize) basic_plaintext = confounder + _zeropad(plaintext, cls.padsize) - hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest() + hmac = HMAC_HASH(ki.contents, basic_plaintext, cls.hashalgo) return cls.basic_encrypt(ke, basic_plaintext) + hmac[:cls.macsize] @classmethod @@ -212,7 +235,7 @@ class _SimplifiedEnctype(_EnctypeProfile): if len(basic_ctext) % cls.padsize != 0: raise ValueError('ciphertext does not meet padding requirement') basic_plaintext = cls.basic_decrypt(ke, basic_ctext) - hmac = HMAC.new(ki.contents, basic_plaintext, cls.hashmod).digest() + hmac = HMAC_HASH(ki.contents, basic_plaintext, cls.hashalgo) expmac = hmac[:cls.macsize] if not _mac_equal(mac, expmac): raise InvalidChecksum('ciphertext integrity failure') @@ -223,7 +246,7 @@ class _SimplifiedEnctype(_EnctypeProfile): def prf(cls, key, string): # Hash the input. RFC 3961 says to truncate to the padding # size, but implementations truncate to the block size. - hashval = cls.hashmod.new(string).digest() + hashval = SIMPLE_HASH(string, cls.hashalgo) truncated = hashval[:-(len(hashval) % cls.blocksize)] # Encrypt the hash with a derived key. kp = cls.derive(key, b'prf') @@ -237,7 +260,7 @@ class _DES3CBC(_SimplifiedEnctype): blocksize = 8 padsize = 8 macsize = 20 - hashmod = SHA + hashalgo = hashes.SHA1 @classmethod def random_to_key(cls, seed): @@ -272,14 +295,20 @@ class _DES3CBC(_SimplifiedEnctype): @classmethod def basic_encrypt(cls, key, plaintext): assert len(plaintext) % 8 == 0 - des3 = DES3.new(key.contents, AES.MODE_CBC, bytes(8)) - return des3.encrypt(plaintext) + algo = ciphers.TripleDES(key.contents) + cbc = modes.CBC(bytes(8)) + encryptor = Cipher(algo, cbc, default_backend()).encryptor() + ciphertext = encryptor.update(plaintext) + return ciphertext @classmethod def basic_decrypt(cls, key, ciphertext): assert len(ciphertext) % 8 == 0 - des3 = DES3.new(key.contents, AES.MODE_CBC, bytes(8)) - return des3.decrypt(ciphertext) + algo = ciphers.TripleDES(key.contents) + cbc = modes.CBC(bytes(8)) + decryptor = Cipher(algo, cbc, default_backend()).decryptor() + plaintext = decryptor.update(ciphertext) + return plaintext class _AESEnctype(_SimplifiedEnctype): @@ -287,21 +316,35 @@ class _AESEnctype(_SimplifiedEnctype): blocksize = 16 padsize = 1 macsize = 12 - hashmod = SHA + hashalgo = hashes.SHA1 @classmethod def string_to_key(cls, string, salt, params): (iterations,) = unpack('>L', params or b'\x00\x00\x10\x00') - prf = lambda p, s: HMAC.new(p, s, SHA).digest() - seed = PBKDF2(string, salt, cls.seedsize, iterations, prf) + pwbytes = get_bytes(string) + kdf = PBKDF2HMAC(algorithm=hashes.SHA1(), + length=cls.seedsize, + salt=salt, + iterations=iterations, + backend=default_backend()) + seed = kdf.derive(pwbytes) tkey = cls.random_to_key(seed) return cls.derive(tkey, b'kerberos') @classmethod def basic_encrypt(cls, key, plaintext): assert len(plaintext) >= 16 - aes = AES.new(key.contents, AES.MODE_CBC, bytes(16)) - ctext = aes.encrypt(_zeropad(plaintext, 16)) + + algo = ciphers.AES(key.contents) + cbc = modes.CBC(bytes(16)) + aes_ctx = Cipher(algo, cbc, default_backend()) + + def aes_encrypt(plaintext): + encryptor = aes_ctx.encryptor() + ciphertext = encryptor.update(plaintext) + return ciphertext + + ctext = aes_encrypt(_zeropad(plaintext, 16)) if len(plaintext) > 16: # Swap the last two ciphertext blocks and truncate the # final block to match the plaintext length. @@ -312,9 +355,18 @@ class _AESEnctype(_SimplifiedEnctype): @classmethod def basic_decrypt(cls, key, ciphertext): assert len(ciphertext) >= 16 - aes = AES.new(key.contents, AES.MODE_ECB) + + algo = ciphers.AES(key.contents) + cbc = modes.CBC(bytes(16)) + aes_ctx = Cipher(algo, cbc, default_backend()) + + def aes_decrypt(ciphertext): + decryptor = aes_ctx.decryptor() + plaintext = decryptor.update(ciphertext) + return plaintext + if len(ciphertext) == 16: - return aes.decrypt(ciphertext) + return aes_decrypt(ciphertext) # Split the ciphertext into blocks. The last block may be partial. cblocks = [ciphertext[p:p+16] for p in range(0, len(ciphertext), 16)] lastlen = len(cblocks[-1]) @@ -322,19 +374,19 @@ class _AESEnctype(_SimplifiedEnctype): prev_cblock = bytes(16) plaintext = b'' for b in cblocks[:-2]: - plaintext += _xorbytes(aes.decrypt(b), prev_cblock) + plaintext += _xorbytes(aes_decrypt(b), prev_cblock) prev_cblock = b # Decrypt the second-to-last cipher block. The left side of # the decrypted block will be the final block of plaintext # xor'd with the final partial cipher block; the right side # will be the omitted bytes of ciphertext from the final # block. - b = aes.decrypt(cblocks[-2]) + b = aes_decrypt(cblocks[-2]) lastplaintext =_xorbytes(b[:lastlen], cblocks[-1]) omitted = b[lastlen:] # Decrypt the final cipher block plus the omitted bytes to get # the second-to-last plaintext block. - plaintext += _xorbytes(aes.decrypt(cblocks[-1] + omitted), prev_cblock) + plaintext += _xorbytes(aes_decrypt(cblocks[-1] + omitted), prev_cblock) return plaintext + lastplaintext @@ -365,32 +417,43 @@ class _RC4(_EnctypeProfile): @classmethod def string_to_key(cls, string, salt, params): - utf16string = string.decode('UTF-8').encode('UTF-16LE') - return Key(cls.enctype, MD4.new(utf16string).digest()) + utf8string = get_string(string) + tmp = Credentials() + tmp.set_anonymous() + tmp.set_password(utf8string) + nthash = tmp.get_nt_hash() + return Key(cls.enctype, nthash) @classmethod def encrypt(cls, key, keyusage, plaintext, confounder): if confounder is None: confounder = get_random_bytes(8) - ki = HMAC.new(key.contents, cls.usage_str(keyusage), MD5).digest() - cksum = HMAC.new(ki, confounder + plaintext, MD5).digest() - ke = HMAC.new(ki, cksum, MD5).digest() - return cksum + ARC4.new(ke).encrypt(confounder + plaintext) + ki = HMAC_HASH(key.contents, cls.usage_str(keyusage), hashes.MD5) + cksum = HMAC_HASH(ki, confounder + plaintext, hashes.MD5) + ke = HMAC_HASH(ki, cksum, hashes.MD5) + + encryptor = Cipher(ciphers.ARC4(ke), None, default_backend()).encryptor() + ctext = encryptor.update(confounder + plaintext) + + return cksum + ctext @classmethod def decrypt(cls, key, keyusage, ciphertext): if len(ciphertext) < 24: raise ValueError('ciphertext too short') cksum, basic_ctext = ciphertext[:16], ciphertext[16:] - ki = HMAC.new(key.contents, cls.usage_str(keyusage), MD5).digest() - ke = HMAC.new(ki, cksum, MD5).digest() - basic_plaintext = ARC4.new(ke).decrypt(basic_ctext) - exp_cksum = HMAC.new(ki, basic_plaintext, MD5).digest() + ki = HMAC_HASH(key.contents, cls.usage_str(keyusage), hashes.MD5) + ke = HMAC_HASH(ki, cksum, hashes.MD5) + + decryptor = Cipher(ciphers.ARC4(ke), None, default_backend()).decryptor() + basic_plaintext = decryptor.update(basic_ctext) + + exp_cksum = HMAC_HASH(ki, basic_plaintext, hashes.MD5) ok = _mac_equal(cksum, exp_cksum) if not ok and keyusage == 9: # Try again with usage 8, due to RFC 4757 errata. - ki = HMAC.new(key.contents, pack('iB', keyusage, 0x99)) - hmac = HMAC.new(kc.contents, text, cls.enc.hashmod).digest() + hmac = HMAC_HASH(kc.contents, text, cls.enc.hashalgo) return hmac[:cls.macsize] @classmethod @@ -452,9 +515,9 @@ class _SHA1DES3(_SimplifiedChecksum): class _HMACMD5(_ChecksumProfile): @classmethod def checksum(cls, key, keyusage, text): - ksign = HMAC.new(key.contents, b'signaturekey\0', MD5).digest() - md5hash = MD5.new(_RC4.usage_str(keyusage) + text).digest() - return HMAC.new(ksign, md5hash, MD5).digest() + ksign = HMAC_HASH(key.contents, b'signaturekey\0', hashes.MD5) + md5hash = SIMPLE_HASH(_RC4.usage_str(keyusage) + text, hashes.MD5) + return HMAC_HASH(ksign, md5hash, hashes.MD5) @classmethod def verify(cls, key, keyusage, text, cksum): @@ -564,150 +627,173 @@ def cf2(enctype, key1, key2, pepper1, pepper2): return e.random_to_key(_xorbytes(prfplus(key1, pepper1, e.seedsize), prfplus(key2, pepper2, e.seedsize))) - -if __name__ == '__main__': - def h(hexstr): - return bytes.fromhex(hexstr) - - # AES128 encrypt and decrypt - kb = h('9062430C8CDA3388922E6D6A509F5B7A') - conf = h('94B491F481485B9A0678CD3C4EA386AD') - keyusage = 2 - plain = b'9 bytesss' - ctxt = h('68FB9679601F45C78857B2BF820FD6E53ECA8D42FD4B1D7024A09205ABB7CD2E' - 'C26C355D2F') - k = Key(Enctype.AES128, kb) - assert(encrypt(k, keyusage, plain, conf) == ctxt) - assert(decrypt(k, keyusage, ctxt) == plain) - - # AES256 encrypt and decrypt - kb = h('F1C795E9248A09338D82C3F8D5B567040B0110736845041347235B1404231398') - conf = h('E45CA518B42E266AD98E165E706FFB60') - keyusage = 4 - plain = b'30 bytes bytes bytes bytes byt' - ctxt = h('D1137A4D634CFECE924DBC3BF6790648BD5CFF7DE0E7B99460211D0DAEF3D79A' - '295C688858F3B34B9CBD6EEBAE81DAF6B734D4D498B6714F1C1D') - k = Key(Enctype.AES256, kb) - assert(encrypt(k, keyusage, plain, conf) == ctxt) - assert(decrypt(k, keyusage, ctxt) == plain) - - # AES128 checksum - kb = h('9062430C8CDA3388922E6D6A509F5B7A') - keyusage = 3 - plain = b'eight nine ten eleven twelve thirteen' - cksum = h('01A4B088D45628F6946614E3') - k = Key(Enctype.AES128, kb) - verify_checksum(Cksumtype.SHA1_AES128, k, keyusage, plain, cksum) - - # AES256 checksum - kb = h('B1AE4CD8462AFF1677053CC9279AAC30B796FB81CE21474DD3DDBCFEA4EC76D7') - keyusage = 4 - plain = b'fourteen' - cksum = h('E08739E3279E2903EC8E3836') - k = Key(Enctype.AES256, kb) - verify_checksum(Cksumtype.SHA1_AES256, k, keyusage, plain, cksum) - - # AES128 string-to-key - string = b'password' - salt = b'ATHENA.MIT.EDUraeburn' - params = h('00000002') - kb = h('C651BF29E2300AC27FA469D693BDDA13') - k = string_to_key(Enctype.AES128, string, salt, params) - assert(k.contents == kb) - - # AES256 string-to-key - string = b'X' * 64 - salt = b'pass phrase equals block size' - params = h('000004B0') - kb = h('89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56C553BA4B34') - k = string_to_key(Enctype.AES256, string, salt, params) - assert(k.contents == kb) - - # AES128 prf - kb = h('77B39A37A868920F2A51F9DD150C5717') - k = string_to_key(Enctype.AES128, b'key1', b'key1') - assert(prf(k, b'\x01\x61') == kb) - - # AES256 prf - kb = h('0D674DD0F9A6806525A4D92E828BD15A') - k = string_to_key(Enctype.AES256, b'key2', b'key2') - assert(prf(k, b'\x02\x62') == kb) - - # AES128 cf2 - kb = h('97DF97E4B798B29EB31ED7280287A92A') - k1 = string_to_key(Enctype.AES128, b'key1', b'key1') - k2 = string_to_key(Enctype.AES128, b'key2', b'key2') - k = cf2(Enctype.AES128, k1, k2, b'a', b'b') - assert(k.contents == kb) - - # AES256 cf2 - kb = h('4D6CA4E629785C1F01BAF55E2E548566B9617AE3A96868C337CB93B5E72B1C7B') - k1 = string_to_key(Enctype.AES256, b'key1', b'key1') - k2 = string_to_key(Enctype.AES256, b'key2', b'key2') - k = cf2(Enctype.AES256, k1, k2, b'a', b'b') - assert(k.contents == kb) - - # DES3 encrypt and decrypt - kb = h('0DD52094E0F41CECCB5BE510A764B35176E3981332F1E598') - conf = h('94690A17B2DA3C9B') - keyusage = 3 - plain = b'13 bytes byte' - ctxt = h('839A17081ECBAFBCDC91B88C6955DD3C4514023CF177B77BF0D0177A16F705E8' - '49CB7781D76A316B193F8D30') - k = Key(Enctype.DES3, kb) - assert(encrypt(k, keyusage, plain, conf) == ctxt) - assert(decrypt(k, keyusage, ctxt) == _zeropad(plain, 8)) - - # DES3 string-to-key - string = b'password' - salt = b'ATHENA.MIT.EDUraeburn' - kb = h('850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E') - k = string_to_key(Enctype.DES3, string, salt) - assert(k.contents == kb) - - # DES3 checksum - kb = h('7A25DF8992296DCEDA0E135BC4046E2375B3C14C98FBC162') - keyusage = 2 - plain = b'six seven' - cksum = h('0EEFC9C3E049AABC1BA5C401677D9AB699082BB4') - k = Key(Enctype.DES3, kb) - verify_checksum(Cksumtype.SHA1_DES3, k, keyusage, plain, cksum) - - # DES3 cf2 - kb = h('E58F9EB643862C13AD38E529313462A7F73E62834FE54A01') - k1 = string_to_key(Enctype.DES3, b'key1', b'key1') - k2 = string_to_key(Enctype.DES3, b'key2', b'key2') - k = cf2(Enctype.DES3, k1, k2, b'a', b'b') - assert(k.contents == kb) - - # RC4 encrypt and decrypt - kb = h('68F263DB3FCE15D031C9EAB02D67107A') - conf = h('37245E73A45FBF72') - keyusage = 4 - plain = b'30 bytes bytes bytes bytes byt' - ctxt = h('95F9047C3AD75891C2E9B04B16566DC8B6EB9CE4231AFB2542EF87A7B5A0F260' - 'A99F0460508DE0CECC632D07C354124E46C5D2234EB8') - k = Key(Enctype.RC4, kb) - assert(encrypt(k, keyusage, plain, conf) == ctxt) - assert(decrypt(k, keyusage, ctxt) == plain) - - # RC4 string-to-key - string = b'foo' - kb = h('AC8E657F83DF82BEEA5D43BDAF7800CC') - k = string_to_key(Enctype.RC4, string, None) - assert(k.contents == kb) - - # RC4 checksum - kb = h('F7D3A155AF5E238A0B7A871A96BA2AB2') - keyusage = 6 - plain = b'seventeen eighteen nineteen twenty' - cksum = h('EB38CC97E2230F59DA4117DC5859D7EC') - k = Key(Enctype.RC4, kb) - verify_checksum(Cksumtype.HMAC_MD5, k, keyusage, plain, cksum) - - # RC4 cf2 - kb = h('24D7F6B6BAE4E5C00D2082C5EBAB3672') - k1 = string_to_key(Enctype.RC4, b'key1', b'key1') - k2 = string_to_key(Enctype.RC4, b'key2', b'key2') - k = cf2(Enctype.RC4, k1, k2, b'a', b'b') - assert(k.contents == kb) +def h(hexstr): + return bytes.fromhex(hexstr) + +class KcrytoTest(TestCase): + """kcrypto Test case.""" + + def test_aes128_crypr(self): + # AES128 encrypt and decrypt + kb = h('9062430C8CDA3388922E6D6A509F5B7A') + conf = h('94B491F481485B9A0678CD3C4EA386AD') + keyusage = 2 + plain = b'9 bytesss' + ctxt = h('68FB9679601F45C78857B2BF820FD6E53ECA8D42FD4B1D7024A09205ABB7CD2E' + 'C26C355D2F') + k = Key(Enctype.AES128, kb) + self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) + self.assertEqual(decrypt(k, keyusage, ctxt), plain) + + def test_aes256_crypt(self): + # AES256 encrypt and decrypt + kb = h('F1C795E9248A09338D82C3F8D5B567040B0110736845041347235B1404231398') + conf = h('E45CA518B42E266AD98E165E706FFB60') + keyusage = 4 + plain = b'30 bytes bytes bytes bytes byt' + ctxt = h('D1137A4D634CFECE924DBC3BF6790648BD5CFF7DE0E7B99460211D0DAEF3D79A' + '295C688858F3B34B9CBD6EEBAE81DAF6B734D4D498B6714F1C1D') + k = Key(Enctype.AES256, kb) + self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) + self.assertEqual(decrypt(k, keyusage, ctxt), plain) + + def test_aes128_checksum(self): + # AES128 checksum + kb = h('9062430C8CDA3388922E6D6A509F5B7A') + keyusage = 3 + plain = b'eight nine ten eleven twelve thirteen' + cksum = h('01A4B088D45628F6946614E3') + k = Key(Enctype.AES128, kb) + verify_checksum(Cksumtype.SHA1_AES128, k, keyusage, plain, cksum) + + def test_aes256_checksum(self): + # AES256 checksum + kb = h('B1AE4CD8462AFF1677053CC9279AAC30B796FB81CE21474DD3DDBCFEA4EC76D7') + keyusage = 4 + plain = b'fourteen' + cksum = h('E08739E3279E2903EC8E3836') + k = Key(Enctype.AES256, kb) + verify_checksum(Cksumtype.SHA1_AES256, k, keyusage, plain, cksum) + + def test_aes128_string_to_key(self): + # AES128 string-to-key + string = b'password' + salt = b'ATHENA.MIT.EDUraeburn' + params = h('00000002') + kb = h('C651BF29E2300AC27FA469D693BDDA13') + k = string_to_key(Enctype.AES128, string, salt, params) + self.assertEqual(k.contents, kb) + + def test_aes256_string_to_key(self): + # AES256 string-to-key + string = b'X' * 64 + salt = b'pass phrase equals block size' + params = h('000004B0') + kb = h('89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56C553BA4B34') + k = string_to_key(Enctype.AES256, string, salt, params) + self.assertEqual(k.contents, kb) + + def test_aes128_prf(self): + # AES128 prf + kb = h('77B39A37A868920F2A51F9DD150C5717') + k = string_to_key(Enctype.AES128, b'key1', b'key1') + self.assertEqual(prf(k, b'\x01\x61'), kb) + + def test_aes256_prf(self): + # AES256 prf + kb = h('0D674DD0F9A6806525A4D92E828BD15A') + k = string_to_key(Enctype.AES256, b'key2', b'key2') + self.assertEqual(prf(k, b'\x02\x62'), kb) + + def test_aes128_cf2(self): + # AES128 cf2 + kb = h('97DF97E4B798B29EB31ED7280287A92A') + k1 = string_to_key(Enctype.AES128, b'key1', b'key1') + k2 = string_to_key(Enctype.AES128, b'key2', b'key2') + k = cf2(Enctype.AES128, k1, k2, b'a', b'b') + self.assertEqual(k.contents, kb) + + def test_aes256_cf2(self): + # AES256 cf2 + kb = h('4D6CA4E629785C1F01BAF55E2E548566B9617AE3A96868C337CB93B5E72B1C7B') + k1 = string_to_key(Enctype.AES256, b'key1', b'key1') + k2 = string_to_key(Enctype.AES256, b'key2', b'key2') + k = cf2(Enctype.AES256, k1, k2, b'a', b'b') + self.assertEqual(k.contents, kb) + + def test_des3_crypt(self): + # DES3 encrypt and decrypt + kb = h('0DD52094E0F41CECCB5BE510A764B35176E3981332F1E598') + conf = h('94690A17B2DA3C9B') + keyusage = 3 + plain = b'13 bytes byte' + ctxt = h('839A17081ECBAFBCDC91B88C6955DD3C4514023CF177B77BF0D0177A16F705E8' + '49CB7781D76A316B193F8D30') + k = Key(Enctype.DES3, kb) + self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) + self.assertEqual(decrypt(k, keyusage, ctxt), _zeropad(plain, 8)) + + def test_des3_string_to_key(self): + # DES3 string-to-key + string = b'password' + salt = b'ATHENA.MIT.EDUraeburn' + kb = h('850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E') + k = string_to_key(Enctype.DES3, string, salt) + self.assertEqual(k.contents, kb) + + def test_des3_checksum(self): + # DES3 checksum + kb = h('7A25DF8992296DCEDA0E135BC4046E2375B3C14C98FBC162') + keyusage = 2 + plain = b'six seven' + cksum = h('0EEFC9C3E049AABC1BA5C401677D9AB699082BB4') + k = Key(Enctype.DES3, kb) + verify_checksum(Cksumtype.SHA1_DES3, k, keyusage, plain, cksum) + + def test_des3_cf2(self): + # DES3 cf2 + kb = h('E58F9EB643862C13AD38E529313462A7F73E62834FE54A01') + k1 = string_to_key(Enctype.DES3, b'key1', b'key1') + k2 = string_to_key(Enctype.DES3, b'key2', b'key2') + k = cf2(Enctype.DES3, k1, k2, b'a', b'b') + self.assertEqual(k.contents, kb) + + def test_rc4_crypt(self): + # RC4 encrypt and decrypt + kb = h('68F263DB3FCE15D031C9EAB02D67107A') + conf = h('37245E73A45FBF72') + keyusage = 4 + plain = b'30 bytes bytes bytes bytes byt' + ctxt = h('95F9047C3AD75891C2E9B04B16566DC8B6EB9CE4231AFB2542EF87A7B5A0F260' + 'A99F0460508DE0CECC632D07C354124E46C5D2234EB8') + k = Key(Enctype.RC4, kb) + self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) + self.assertEqual(decrypt(k, keyusage, ctxt), plain) + + def test_rc4_string_to_key(self): + # RC4 string-to-key + string = b'foo' + kb = h('AC8E657F83DF82BEEA5D43BDAF7800CC') + k = string_to_key(Enctype.RC4, string, None) + self.assertEqual(k.contents, kb) + + def test_rc4_checksum(self): + # RC4 checksum + kb = h('F7D3A155AF5E238A0B7A871A96BA2AB2') + keyusage = 6 + plain = b'seventeen eighteen nineteen twenty' + cksum = h('EB38CC97E2230F59DA4117DC5859D7EC') + k = Key(Enctype.RC4, kb) + verify_checksum(Cksumtype.HMAC_MD5, k, keyusage, plain, cksum) + + def test_rc4_cf2(self): + # RC4 cf2 + kb = h('24D7F6B6BAE4E5C00D2082C5EBAB3672') + k1 = string_to_key(Enctype.RC4, b'key1', b'key1') + k2 = string_to_key(Enctype.RC4, b'key2', b'key2') + k = cf2(Enctype.RC4, k1, k2, b'a', b'b') + self.assertEqual(k.contents, kb) + +if __name__ == "__main__": + import unittest + unittest.main() -- 2.25.1 From 8c6f3165cef55fc648bc46a9da06660016d50622 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 25 Mar 2020 22:07:39 +0100 Subject: [PATCH 016/645] s4:selftest: run samba.tests.krb5.kcrypto test Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 7010a1311d193c78e9f26adeafe98458217edbca) --- source4/selftest/tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 7d55aed89b4..9194c9b04f7 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -742,6 +742,8 @@ planoldpythontestsuite("nt4_dc", "samba.tests.netbios", extra_args=['-U"$USERNAM planoldpythontestsuite("ad_dc:local", "samba.tests.gpo", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$USERNAME%$PASSWORD"']) +planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") + for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite(env + ":local", "samba.tests.ntacls_backup", -- 2.25.1 From b01f92a03087aed4bed0686682dea73d99961fea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Mar 2020 08:53:54 +0100 Subject: [PATCH 017/645] python/tests/krb5: add support for Cksumtype.MD5 Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 47385248c8e462162e01afc3d3d68b97dff3542c) --- python/samba/tests/krb5/kcrypto.py | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index 0907d881b68..ed3c84fa186 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -526,6 +526,13 @@ class _HMACMD5(_ChecksumProfile): super(_HMACMD5, cls).verify(key, keyusage, text, cksum) +class _MD5(_ChecksumProfile): + @classmethod + def checksum(cls, key, keyusage, text): + # This is unkeyed! + return SIMPLE_HASH(text, hashes.MD5) + + _enctype_table = { Enctype.DES3: _DES3CBC, Enctype.AES128: _AES128CTS, @@ -538,7 +545,8 @@ _checksum_table = { Cksumtype.SHA1_DES3: _SHA1DES3, Cksumtype.SHA1_AES128: _SHA1AES128, Cksumtype.SHA1_AES256: _SHA1AES256, - Cksumtype.HMAC_MD5: _HMACMD5 + Cksumtype.HMAC_MD5: _HMACMD5, + Cksumtype.MD5: _MD5, } @@ -794,6 +802,39 @@ class KcrytoTest(TestCase): k = cf2(Enctype.RC4, k1, k2, b'a', b'b') self.assertEqual(k.contents, kb) + def _test_md5_unkeyed_checksum(self, etype, usage): + # MD5 unkeyed checksum + pw = b'pwd' + salt = b'bytes' + key = string_to_key(etype, pw, salt) + plain = b'seventeen eighteen nineteen twenty' + cksum = h('9d9588cdef3a8cefc9d2c208d978f60c') + verify_checksum(Cksumtype.MD5, key, usage, plain, cksum) + + def test_md5_unkeyed_checksum_des3_usage_40(self): + return self._test_md5_unkeyed_checksum(Enctype.DES3, 40) + + def test_md5_unkeyed_checksum_des3_usage_50(self): + return self._test_md5_unkeyed_checksum(Enctype.DES3, 50) + + def test_md5_unkeyed_checksum_rc4_usage_40(self): + return self._test_md5_unkeyed_checksum(Enctype.RC4, 40) + + def test_md5_unkeyed_checksum_rc4_usage_50(self): + return self._test_md5_unkeyed_checksum(Enctype.RC4, 50) + + def test_md5_unkeyed_checksum_aes128_usage_40(self): + return self._test_md5_unkeyed_checksum(Enctype.AES128, 40) + + def test_md5_unkeyed_checksum_aes128_usage_50(self): + return self._test_md5_unkeyed_checksum(Enctype.AES128, 50) + + def test_md5_unkeyed_checksum_aes256_usage_40(self): + return self._test_md5_unkeyed_checksum(Enctype.AES256, 40) + + def test_md5_unkeyed_checksum_aes256_usage_50(self): + return self._test_md5_unkeyed_checksum(Enctype.AES256, 50) + if __name__ == "__main__": import unittest unittest.main() -- 2.25.1 From 86b6a91bd50749cdadc55505c3072cfd02c8aec3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2020 16:29:38 +0100 Subject: [PATCH 018/645] python/tests/krb5: add rfc4120.asn1 Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit a2f75c314e9946f74e9dacceac690295999925b5) --- python/samba/tests/krb5/rfc4120.asn1 | 392 +++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 python/samba/tests/krb5/rfc4120.asn1 diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 new file mode 100644 index 00000000000..ec44557f45a --- /dev/null +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -0,0 +1,392 @@ +KerberosV5Spec2 { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) krb5spec2(2) +} DEFINITIONS EXPLICIT TAGS ::= BEGIN + +-- OID arc for KerberosV5 +-- +-- This OID may be used to identify Kerberos protocol messages +-- encapsulated in other protocols. +-- +-- This OID also designates the OID arc for KerberosV5-related OIDs. +-- +-- NOTE: RFC 1510 had an incorrect value (5) for "dod" in its OID. +id-krb5 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) +} + +Int32 ::= INTEGER (-2147483648..2147483647) + -- signed values representable in 32 bits + +UInt32 ::= INTEGER (0..4294967295) + -- unsigned 32 bit values + +Microseconds ::= INTEGER (0..999999) + -- microseconds + +KerberosString ::= GeneralString (IA5String) + +Realm ::= KerberosString + +PrincipalName ::= SEQUENCE { + name-type [0] Int32, + name-string [1] SEQUENCE OF KerberosString +} + +KerberosTime ::= GeneralizedTime -- with no fractional seconds + +HostAddress ::= SEQUENCE { + addr-type [0] Int32, + address [1] OCTET STRING +} + +-- NOTE: HostAddresses is always used as an OPTIONAL field and +-- should not be empty. +HostAddresses -- NOTE: subtly different from rfc1510, + -- but has a value mapping and encodes the same + ::= SEQUENCE OF HostAddress + +-- NOTE: AuthorizationData is always used as an OPTIONAL field and +-- should not be empty. +AuthorizationData ::= SEQUENCE OF SEQUENCE { + ad-type [0] Int32, + ad-data [1] OCTET STRING +} + +PA-DATA ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + padata-type [1] Int32, + padata-value [2] OCTET STRING -- might be encoded AP-REQ +} + +KerberosFlags ::= BIT STRING (SIZE (32..MAX)) + -- minimum number of bits shall be sent, + -- but no fewer than 32 + +EncryptedData ::= SEQUENCE { + etype [0] Int32 -- EncryptionType --, + kvno [1] UInt32 OPTIONAL, + cipher [2] OCTET STRING -- ciphertext +} + +EncryptionKey ::= SEQUENCE { + keytype [0] Int32 -- actually encryption type --, + keyvalue [1] OCTET STRING +} + +Checksum ::= SEQUENCE { + cksumtype [0] Int32, + checksum [1] OCTET STRING +} + +Ticket ::= [APPLICATION 1] SEQUENCE { + tkt-vno [0] INTEGER (5), + realm [1] Realm, + sname [2] PrincipalName, + enc-part [3] EncryptedData -- EncTicketPart +} + +-- Encrypted part of ticket +EncTicketPart ::= [APPLICATION 3] SEQUENCE { + flags [0] TicketFlags, + key [1] EncryptionKey, + crealm [2] Realm, + cname [3] PrincipalName, + transited [4] TransitedEncoding, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + caddr [9] HostAddresses OPTIONAL, + authorization-data [10] AuthorizationData OPTIONAL +} + +-- encoded Transited field +TransitedEncoding ::= SEQUENCE { + tr-type [0] Int32 -- must be registered --, + contents [1] OCTET STRING +} + +TicketFlags ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- may-postdate(5), + -- postdated(6), + -- invalid(7), + -- renewable(8), + -- initial(9), + -- pre-authent(10), + -- hw-authent(11), +-- the following are new since 1510 + -- transited-policy-checked(12), + -- ok-as-delegate(13) + +AS-REQ ::= [APPLICATION 10] KDC-REQ + +TGS-REQ ::= [APPLICATION 12] KDC-REQ + +KDC-REQ ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + pvno [1] INTEGER (5) , + msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + padata [3] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + req-body [4] KDC-REQ-BODY +} + +KDC-REQ-BODY ::= SEQUENCE { + kdc-options [0] KDCOptions, + cname [1] PrincipalName OPTIONAL + -- Used only in AS-REQ --, + realm [2] Realm + -- Server's realm + -- Also client's in AS-REQ --, + sname [3] PrincipalName OPTIONAL, + from [4] KerberosTime OPTIONAL, + till [5] KerberosTime, + rtime [6] KerberosTime OPTIONAL, + nonce [7] UInt32, + etype [8] SEQUENCE OF Int32 -- EncryptionType + -- in preference order --, + addresses [9] HostAddresses OPTIONAL, + enc-authorization-data [10] EncryptedData OPTIONAL + -- AuthorizationData --, + additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + -- NOTE: not empty +} + +KDCOptions ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- allow-postdate(5), + -- postdated(6), + -- unused7(7), + -- renewable(8), + -- unused9(9), + -- unused10(10), + -- opt-hardware-auth(11), + -- unused12(12), + -- unused13(13), +-- 15 is reserved for canonicalize + -- unused15(15), +-- 26 was unused in 1510 + -- disable-transited-check(26), +-- + -- renewable-ok(27), + -- enc-tkt-in-skey(28), + -- renew(30), + -- validate(31) + +AS-REP ::= [APPLICATION 11] KDC-REP + +TGS-REP ::= [APPLICATION 13] KDC-REP + +KDC-REP ::= SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), + padata [2] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + crealm [3] Realm, + cname [4] PrincipalName, + ticket [5] Ticket, + enc-part [6] EncryptedData + -- EncASRepPart or EncTGSRepPart, + -- as appropriate +} + +EncASRepPart ::= [APPLICATION 25] EncKDCRepPart + +EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart + +EncKDCRepPart ::= SEQUENCE { + key [0] EncryptionKey, + last-req [1] LastReq, + nonce [2] UInt32, + key-expiration [3] KerberosTime OPTIONAL, + flags [4] TicketFlags, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + srealm [9] Realm, + sname [10] PrincipalName, + caddr [11] HostAddresses OPTIONAL +} + +LastReq ::= SEQUENCE OF SEQUENCE { + lr-type [0] Int32, + lr-value [1] KerberosTime +} + +AP-REQ ::= [APPLICATION 14] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (14), + ap-options [2] APOptions, + ticket [3] Ticket, + authenticator [4] EncryptedData -- Authenticator +} + +APOptions ::= KerberosFlags + -- reserved(0), + -- use-session-key(1), + -- mutual-required(2) + +-- Unencrypted authenticator +Authenticator ::= [APPLICATION 2] SEQUENCE { + authenticator-vno [0] INTEGER (5), + crealm [1] Realm, + cname [2] PrincipalName, + cksum [3] Checksum OPTIONAL, + cusec [4] Microseconds, + ctime [5] KerberosTime, + subkey [6] EncryptionKey OPTIONAL, + seq-number [7] UInt32 OPTIONAL, + authorization-data [8] AuthorizationData OPTIONAL +} + +AP-REP ::= [APPLICATION 15] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (15), + enc-part [2] EncryptedData -- EncAPRepPart +} + +EncAPRepPart ::= [APPLICATION 27] SEQUENCE { + ctime [0] KerberosTime, + cusec [1] Microseconds, + subkey [2] EncryptionKey OPTIONAL, + seq-number [3] UInt32 OPTIONAL +} + +KRB-SAFE ::= [APPLICATION 20] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (20), + safe-body [2] KRB-SAFE-BODY, + cksum [3] Checksum +} + +KRB-SAFE-BODY ::= SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress, + r-address [5] HostAddress OPTIONAL +} + +KRB-PRIV ::= [APPLICATION 21] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (21), + -- NOTE: there is no [2] tag + enc-part [3] EncryptedData -- EncKrbPrivPart +} + +EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress -- sender's addr --, + r-address [5] HostAddress OPTIONAL -- recip's addr +} + +KRB-CRED ::= [APPLICATION 22] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (22), + tickets [2] SEQUENCE OF Ticket, + enc-part [3] EncryptedData -- EncKrbCredPart +} + +EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { + ticket-info [0] SEQUENCE OF KrbCredInfo, + nonce [1] UInt32 OPTIONAL, + timestamp [2] KerberosTime OPTIONAL, + usec [3] Microseconds OPTIONAL, + s-address [4] HostAddress OPTIONAL, + r-address [5] HostAddress OPTIONAL +} + +KrbCredInfo ::= SEQUENCE { + key [0] EncryptionKey, + prealm [1] Realm OPTIONAL, + pname [2] PrincipalName OPTIONAL, + flags [3] TicketFlags OPTIONAL, + authtime [4] KerberosTime OPTIONAL, + starttime [5] KerberosTime OPTIONAL, + endtime [6] KerberosTime OPTIONAL, + renew-till [7] KerberosTime OPTIONAL, + srealm [8] Realm OPTIONAL, + sname [9] PrincipalName OPTIONAL, + caddr [10] HostAddresses OPTIONAL +} + +KRB-ERROR ::= [APPLICATION 30] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (30), + ctime [2] KerberosTime OPTIONAL, + cusec [3] Microseconds OPTIONAL, + stime [4] KerberosTime, + susec [5] Microseconds, + error-code [6] Int32, + crealm [7] Realm OPTIONAL, + cname [8] PrincipalName OPTIONAL, + realm [9] Realm -- service realm --, + sname [10] PrincipalName -- service name --, + e-text [11] KerberosString OPTIONAL, + e-data [12] OCTET STRING OPTIONAL +} + +METHOD-DATA ::= SEQUENCE OF PA-DATA + +TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + data-type [0] Int32, + data-value [1] OCTET STRING OPTIONAL +} + +-- preauth stuff follows + +PA-ENC-TIMESTAMP ::= EncryptedData -- PA-ENC-TS-ENC + +PA-ENC-TS-ENC ::= SEQUENCE { + patimestamp [0] KerberosTime -- client's time --, + pausec [1] Microseconds OPTIONAL +} + +ETYPE-INFO-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] OCTET STRING OPTIONAL +} + +ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY + +ETYPE-INFO2-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] KerberosString OPTIONAL, + s2kparams [2] OCTET STRING OPTIONAL +} + +ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY + +AD-IF-RELEVANT ::= AuthorizationData + +AD-KDCIssued ::= SEQUENCE { + ad-checksum [0] Checksum, + i-realm [1] Realm OPTIONAL, + i-sname [2] PrincipalName OPTIONAL, + elements [3] AuthorizationData +} + +AD-AND-OR ::= SEQUENCE { + condition-count [0] Int32, + elements [1] AuthorizationData +} + +AD-MANDATORY-FOR-KDC ::= AuthorizationData + +END -- 2.25.1 From 2e180b414ec501e9b3f48d7a947f86e11f211a7e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2020 16:29:38 +0100 Subject: [PATCH 019/645] python/tests/krb5: modify rfc4120.asn1 in order to generate pyasn1 code The pyasn1 bindings are generated by pyasn1gen.py from https://github.com/kimgr/asn1ate.git Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris (cherry picked from commit 94d068427f6cf23ab68c135ed9833db4b9155b65) --- python/samba/tests/krb5/rfc4120.asn1 | 293 +++++- python/samba/tests/krb5/rfc4120_pyasn1.py | 914 ++++++++++++++++++ .../samba/tests/krb5/rfc4120_pyasn1_regen.sh | 41 + python/samba/tests/source.py | 6 + 4 files changed, 1243 insertions(+), 11 deletions(-) create mode 100644 python/samba/tests/krb5/rfc4120_pyasn1.py create mode 100755 python/samba/tests/krb5/rfc4120_pyasn1_regen.sh diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index ec44557f45a..05b43106034 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -25,15 +25,23 @@ UInt32 ::= INTEGER (0..4294967295) Microseconds ::= INTEGER (0..999999) -- microseconds -KerberosString ::= GeneralString (IA5String) +-- +-- asn1ate doesn't support 'GeneralString (IA5String)' +-- only 'GeneralString' or 'IA5String', on the wire +-- GeneralString is used. +-- +-- KerberosString ::= GeneralString (IA5String) +KerberosString ::= GeneralString Realm ::= KerberosString PrincipalName ::= SEQUENCE { - name-type [0] Int32, + name-type [0] NameType, -- Int32, name-string [1] SEQUENCE OF KerberosString } +NameType ::= Int32 + KerberosTime ::= GeneralizedTime -- with no fractional seconds HostAddress ::= SEQUENCE { @@ -50,36 +58,48 @@ HostAddresses -- NOTE: subtly different from rfc1510, -- NOTE: AuthorizationData is always used as an OPTIONAL field and -- should not be empty. AuthorizationData ::= SEQUENCE OF SEQUENCE { - ad-type [0] Int32, + ad-type [0] AuthDataType, -- Int32, ad-data [1] OCTET STRING } +AuthDataType ::= Int32 + PA-DATA ::= SEQUENCE { -- NOTE: first tag is [1], not [0] - padata-type [1] Int32, + padata-type [1] PADataType, -- Int32 padata-value [2] OCTET STRING -- might be encoded AP-REQ } -KerberosFlags ::= BIT STRING (SIZE (32..MAX)) +PADataType ::= Int32 + +-- +-- asn1ate doesn't support 'MAX' nor a lower range != 1. +-- We'll use a custom enodeValue() hooks for BitString +-- in order to encode them with at least 32-Bit. +-- +-- KerberosFlags ::= BIT STRING (SIZE (32..MAX)) +KerberosFlags ::= BIT STRING (SIZE (1..32)) -- minimum number of bits shall be sent, -- but no fewer than 32 EncryptedData ::= SEQUENCE { - etype [0] Int32 -- EncryptionType --, + etype [0] EncryptionType, --Int32 EncryptionType -- kvno [1] UInt32 OPTIONAL, cipher [2] OCTET STRING -- ciphertext } EncryptionKey ::= SEQUENCE { - keytype [0] Int32 -- actually encryption type --, + keytype [0] EncryptionType, -- Int32 actually encryption type -- keyvalue [1] OCTET STRING } Checksum ::= SEQUENCE { - cksumtype [0] Int32, + cksumtype [0] ChecksumType, -- Int32, checksum [1] OCTET STRING } +ChecksumType ::= Int32 + Ticket ::= [APPLICATION 1] SEQUENCE { tkt-vno [0] INTEGER (5), realm [1] Realm, @@ -150,7 +170,7 @@ KDC-REQ-BODY ::= SEQUENCE { till [5] KerberosTime, rtime [6] KerberosTime OPTIONAL, nonce [7] UInt32, - etype [8] SEQUENCE OF Int32 -- EncryptionType + etype [8] SEQUENCE OF EncryptionType -- Int32 - EncryptionType -- in preference order --, addresses [9] HostAddresses OPTIONAL, enc-authorization-data [10] EncryptedData OPTIONAL @@ -159,6 +179,8 @@ KDC-REQ-BODY ::= SEQUENCE { -- NOTE: not empty } +EncryptionType ::= Int32 + KDCOptions ::= KerberosFlags -- reserved(0), -- forwardable(1), @@ -344,7 +366,11 @@ KRB-ERROR ::= [APPLICATION 30] SEQUENCE { METHOD-DATA ::= SEQUENCE OF PA-DATA -TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { +-- +-- asn1ate doesn't support 'MAX' +-- +-- TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { +TYPED-DATA ::= SEQUENCE SIZE (1..256) OF SEQUENCE { data-type [0] Int32, data-value [1] OCTET STRING OPTIONAL } @@ -371,7 +397,7 @@ ETYPE-INFO2-ENTRY ::= SEQUENCE { s2kparams [2] OCTET STRING OPTIONAL } -ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY +ETYPE-INFO2 ::= SEQUENCE SIZE (1..256) OF ETYPE-INFO2-ENTRY AD-IF-RELEVANT ::= AuthorizationData @@ -389,4 +415,249 @@ AD-AND-OR ::= SEQUENCE { AD-MANDATORY-FOR-KDC ::= AuthorizationData + + + + + +-- +-- +-- prettyPrint values +-- +-- + +NameTypeValues ::= INTEGER { -- Int32 + kRB5-NT-UNKNOWN(0), -- Name type not known + kRB5-NT-PRINCIPAL(1), -- Just the name of the principal as in + kRB5-NT-SRV-INST(2), -- Service and other unique instance (krbtgt) + kRB5-NT-SRV-HST(3), -- Service with host name as instance + kRB5-NT-SRV-XHST(4), -- Service with host as remaining components + kRB5-NT-UID(5), -- Unique ID + kRB5-NT-X500-PRINCIPAL(6), -- PKINIT + kRB5-NT-SMTP-NAME(7), -- Name in form of SMTP email name + kRB5-NT-ENTERPRISE-PRINCIPAL(10), -- Windows 2000 UPN + kRB5-NT-WELLKNOWN(11), -- Wellknown + kRB5-NT-ENT-PRINCIPAL-AND-ID(-130), -- Windows 2000 UPN and SID + kRB5-NT-MS-PRINCIPAL(-128), -- NT 4 style name + kRB5-NT-MS-PRINCIPAL-AND-ID(-129) -- NT style name and SID +} +NameTypeSequence ::= SEQUENCE { + dummy [0] NameTypeValues +} + +TicketFlagsValues ::= BIT STRING { -- KerberosFlags + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + may-postdate(5), + postdated(6), + invalid(7), + renewable(8), + initial(9), + pre-authent(10), + hw-authent(11), +-- the following are new since 1510 + transited-policy-checked(12), + ok-as-delegate(13) +} +TicketFlagsSequence ::= SEQUENCE { + dummy [0] TicketFlagsValues +} + +KDCOptionsValues ::= BIT STRING { -- KerberosFlags + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + allow-postdate(5), + postdated(6), + unused7(7), + renewable(8), + unused9(9), + unused10(10), + opt-hardware-auth(11), + unused12(12), + unused13(13), +-- 15 is reserved for canonicalize + unused15(15), +-- 26 was unused in 1510 + disable-transited-check(26), +-- + renewable-ok(27), + enc-tkt-in-skey(28), + renew(30), + validate(31) +} +KDCOptionsSequence ::= SEQUENCE { + dummy [0] KDCOptionsValues +} + +MessageTypeValues ::= INTEGER { + krb-as-req(10), -- Request for initial authentication + krb-as-rep(11), -- Response to KRB_AS_REQ request + krb-tgs-req(12), -- Request for authentication based on TGT + krb-tgs-rep(13), -- Response to KRB_TGS_REQ request + krb-ap-req(14), -- application request to server + krb-ap-rep(15), -- Response to KRB_AP_REQ_MUTUAL + krb-safe(20), -- Safe (checksummed) application message + krb-priv(21), -- Private (encrypted) application message + krb-cred(22), -- Private (encrypted) message to forward credentials + krb-error(30) -- Error response +} +MessageTypeSequence ::= SEQUENCE { + dummy [0] MessageTypeValues +} + +PADataTypeValues ::= INTEGER { + kRB5-PADATA-NONE(0), + -- kRB5-PADATA-TGS-REQ(1), + -- kRB5-PADATA-AP-REQ(1), + kRB5-PADATA-KDC-REQ(1), + kRB5-PADATA-ENC-TIMESTAMP(2), + kRB5-PADATA-PW-SALT(3), + kRB5-PADATA-ENC-UNIX-TIME(5), + kRB5-PADATA-SANDIA-SECUREID(6), + kRB5-PADATA-SESAME(7), + kRB5-PADATA-OSF-DCE(8), + kRB5-PADATA-CYBERSAFE-SECUREID(9), + kRB5-PADATA-AFS3-SALT(10), + kRB5-PADATA-ETYPE-INFO(11), + kRB5-PADATA-SAM-CHALLENGE(12), -- (sam/otp) + kRB5-PADATA-SAM-RESPONSE(13), -- (sam/otp) + kRB5-PADATA-PK-AS-REQ-19(14), -- (PKINIT-19) + kRB5-PADATA-PK-AS-REP-19(15), -- (PKINIT-19) + -- kRB5-PADATA-PK-AS-REQ-WIN(15), - (PKINIT - old number) + kRB5-PADATA-PK-AS-REQ(16), -- (PKINIT-25) + kRB5-PADATA-PK-AS-REP(17), -- (PKINIT-25) + kRB5-PADATA-PA-PK-OCSP-RESPONSE(18), + kRB5-PADATA-ETYPE-INFO2(19), + -- kRB5-PADATA-USE-SPECIFIED-KVNO(20), + kRB5-PADATA-SVR-REFERRAL-INFO(20), --- old ms referral number + kRB5-PADATA-SAM-REDIRECT(21), -- (sam/otp) + kRB5-PADATA-GET-FROM-TYPED-DATA(22), + kRB5-PADATA-SAM-ETYPE-INFO(23), + kRB5-PADATA-SERVER-REFERRAL(25), + kRB5-PADATA-ALT-PRINC(24), -- (crawdad@fnal.gov) + kRB5-PADATA-SAM-CHALLENGE2(30), -- (kenh@pobox.com) + kRB5-PADATA-SAM-RESPONSE2(31), -- (kenh@pobox.com) + kRB5-PA-EXTRA-TGT(41), -- Reserved extra TGT + kRB5-PADATA-TD-KRB-PRINCIPAL(102), -- PrincipalName + kRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT + kRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT + kRB5-PADATA-TD-APP-DEFINED-ERROR(106), -- application specific + kRB5-PADATA-TD-REQ-NONCE(107), -- INTEGER + kRB5-PADATA-TD-REQ-SEQ(108), -- INTEGER + kRB5-PADATA-PA-PAC-REQUEST(128), -- jbrezak@exchange.microsoft.com + kRB5-PADATA-FOR-USER(129), -- MS-KILE + kRB5-PADATA-FOR-X509-USER(130), -- MS-KILE + kRB5-PADATA-FOR-CHECK-DUPS(131), -- MS-KILE + kRB5-PADATA-AS-CHECKSUM(132), -- MS-KILE + -- kRB5-PADATA-PK-AS-09-BINDING(132), - client send this to + -- tell KDC that is supports + -- the asCheckSum in the + -- PK-AS-REP + kRB5-PADATA-FX-COOKIE(133), -- krb-wg-preauth-framework + kRB5-PADATA-AUTHENTICATION-SET(134), -- krb-wg-preauth-framework + kRB5-PADATA-AUTH-SET-SELECTED(135), -- krb-wg-preauth-framework + kRB5-PADATA-FX-FAST(136), -- krb-wg-preauth-framework + kRB5-PADATA-FX-ERROR(137), -- krb-wg-preauth-framework + kRB5-PADATA-ENCRYPTED-CHALLENGE(138), -- krb-wg-preauth-framework + kRB5-PADATA-OTP-CHALLENGE(141), -- (gareth.richards@rsa.com) + kRB5-PADATA-OTP-REQUEST(142), -- (gareth.richards@rsa.com) + kBB5-PADATA-OTP-CONFIRM(143), -- (gareth.richards@rsa.com) + kRB5-PADATA-OTP-PIN-CHANGE(144), -- (gareth.richards@rsa.com) + kRB5-PADATA-EPAK-AS-REQ(145), + kRB5-PADATA-EPAK-AS-REP(146), + kRB5-PADATA-PKINIT-KX(147), -- krb-wg-anon + kRB5-PADATA-PKU2U-NAME(148), -- zhu-pku2u + kRB5-PADATA-REQ-ENC-PA-REP(149), -- + kRB5-PADATA-SUPPORTED-ETYPES(165) -- MS-KILE +} +PADataTypeSequence ::= SEQUENCE { + dummy [0] PADataTypeValues +} + +AuthDataTypeValues ::= INTEGER { + kRB5-AUTHDATA-IF-RELEVANT(1), + kRB5-AUTHDATA-INTENDED-FOR-SERVER(2), + kRB5-AUTHDATA-INTENDED-FOR-APPLICATION-CLASS(3), + kRB5-AUTHDATA-KDC-ISSUED(4), + kRB5-AUTHDATA-AND-OR(5), + kRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6), + kRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7), + kRB5-AUTHDATA-MANDATORY-FOR-KDC(8), + kRB5-AUTHDATA-INITIAL-VERIFIED-CAS(9), + kRB5-AUTHDATA-OSF-DCE(64), + kRB5-AUTHDATA-SESAME(65), + kRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66), + kRB5-AUTHDATA-WIN2K-PAC(128), + kRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129), -- Authenticator only + kRB5-AUTHDATA-SIGNTICKET-OLDER(-17), + kRB5-AUTHDATA-SIGNTICKET-OLD(142), + kRB5-AUTHDATA-SIGNTICKET(512) +} +AuthDataTypeSequence ::= SEQUENCE { + dummy [0] AuthDataTypeValues +} + +ChecksumTypeValues ::= INTEGER { + kRB5-CKSUMTYPE-NONE(0), + kRB5-CKSUMTYPE-CRC32(1), + kRB5-CKSUMTYPE-RSA-MD4(2), + kRB5-CKSUMTYPE-RSA-MD4-DES(3), + kRB5-CKSUMTYPE-DES-MAC(4), + kRB5-CKSUMTYPE-DES-MAC-K(5), + kRB5-CKSUMTYPE-RSA-MD4-DES-K(6), + kRB5-CKSUMTYPE-RSA-MD5(7), + kRB5-CKSUMTYPE-RSA-MD5-DES(8), + kRB5-CKSUMTYPE-RSA-MD5-DES3(9), + kRB5-CKSUMTYPE-SHA1-OTHER(10), + kRB5-CKSUMTYPE-HMAC-SHA1-DES3(12), + kRB5-CKSUMTYPE-SHA1(14), + kRB5-CKSUMTYPE-HMAC-SHA1-96-AES-128(15), + kRB5-CKSUMTYPE-HMAC-SHA1-96-AES-256(16), + kRB5-CKSUMTYPE-GSSAPI(32771), -- 0x8003 + kRB5-CKSUMTYPE-HMAC-MD5(-138), -- unofficial microsoft number + kRB5-CKSUMTYPE-HMAC-MD5-ENC(-1138) -- even more unofficial +} +ChecksumTypeSequence ::= SEQUENCE { + dummy [0] ChecksumTypeValues +} + +EncryptionTypeValues ::= INTEGER { + kRB5-ENCTYPE-NULL(0), + kRB5-ENCTYPE-DES-CBC-CRC(1), + kRB5-ENCTYPE-DES-CBC-MD4(2), + kRB5-ENCTYPE-DES-CBC-MD5(3), + kRB5-ENCTYPE-DES3-CBC-MD5(5), + kRB5-ENCTYPE-OLD-DES3-CBC-SHA1(7), + kRB5-ENCTYPE-SIGN-DSA-GENERATE(8), + kRB5-ENCTYPE-ENCRYPT-RSA-PRIV(9), + kRB5-ENCTYPE-ENCRYPT-RSA-PUB(10), + kRB5-ENCTYPE-DES3-CBC-SHA1(16), -- with key derivation + kRB5-ENCTYPE-AES128-CTS-HMAC-SHA1-96(17), + kRB5-ENCTYPE-AES256-CTS-HMAC-SHA1-96(18), + kRB5-ENCTYPE-ARCFOUR-HMAC-MD5(23), + kRB5-ENCTYPE-ARCFOUR-HMAC-MD5-56(24), + kRB5-ENCTYPE-ENCTYPE-PK-CROSS(48), +-- some "old" windows types + kRB5-ENCTYPE-ARCFOUR-MD4(-128), + kRB5-ENCTYPE-ARCFOUR-HMAC-OLD(-133), + kRB5-ENCTYPE-ARCFOUR-HMAC-OLD-EXP(-135), +-- these are for Heimdal internal use +-- kRB5-ENCTYPE-DES-CBC-NONE(-0x1000), +-- kRB5-ENCTYPE-DES3-CBC-NONE(-0x1001), +-- kRB5-ENCTYPE-DES-CFB64-NONE(-0x1002), +-- kRB5-ENCTYPE-DES-PCBC-NONE(-0x1003), +-- kRB5-ENCTYPE-DIGEST-MD5-NONE(-0x1004), - private use, lukeh@padl.com +-- kRB5-ENCTYPE-CRAM-MD5-NONE(-0x1005) - private use, lukeh@padl.com + kRB5-ENCTYPE-DUMMY(-1111) +} +EncryptionTypeSequence ::= SEQUENCE { + dummy [0] EncryptionTypeValues +} + END diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py new file mode 100644 index 00000000000..b2627aa3dcb --- /dev/null +++ b/python/samba/tests/krb5/rfc4120_pyasn1.py @@ -0,0 +1,914 @@ +# Auto-generated by asn1ate v.0.6.1.dev0 from rfc4120.asn1 +# (last modified on 2020-03-26 10:28:24.346775) + +# KerberosV5Spec2 +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +class Int32(univ.Integer): + pass + + +Int32.subtypeSpec = constraint.ValueRangeConstraint(-2147483648, 2147483647) + + +class AuthDataType(Int32): + pass + + +class AuthorizationData(univ.SequenceOf): + pass + + +AuthorizationData.componentType = univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('ad-type', AuthDataType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('ad-data', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +)) + + +class AD_AND_OR(univ.Sequence): + pass + + +AD_AND_OR.componentType = namedtype.NamedTypes( + namedtype.NamedType('condition-count', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('elements', AuthorizationData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class AD_IF_RELEVANT(AuthorizationData): + pass + + +class ChecksumType(Int32): + pass + + +class Checksum(univ.Sequence): + pass + + +Checksum.componentType = namedtype.NamedTypes( + namedtype.NamedType('cksumtype', ChecksumType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('checksum', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class KerberosString(char.GeneralString): + pass + + +class NameType(Int32): + pass + + +class PrincipalName(univ.Sequence): + pass + + +PrincipalName.componentType = namedtype.NamedTypes( + namedtype.NamedType('name-type', NameType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('name-string', univ.SequenceOf(componentType=KerberosString()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class Realm(KerberosString): + pass + + +class AD_KDCIssued(univ.Sequence): + pass + + +AD_KDCIssued.componentType = namedtype.NamedTypes( + namedtype.NamedType('ad-checksum', Checksum().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('i-realm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('i-sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.NamedType('elements', AuthorizationData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) +) + + +class AD_MANDATORY_FOR_KDC(AuthorizationData): + pass + + +class EncryptionType(Int32): + pass + + +class UInt32(univ.Integer): + pass + + +UInt32.subtypeSpec = constraint.ValueRangeConstraint(0, 4294967295) + + +class EncryptedData(univ.Sequence): + pass + + +EncryptedData.componentType = namedtype.NamedTypes( + namedtype.NamedType('etype', EncryptionType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('kvno', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('cipher', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class AP_REP(univ.Sequence): + pass + + +AP_REP.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 15)) +AP_REP.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(15)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('enc-part', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + + +class KerberosFlags(univ.BitString): + pass + + +KerberosFlags.subtypeSpec=constraint.ValueSizeConstraint(1, 32) + + +class APOptions(KerberosFlags): + pass + + +class Ticket(univ.Sequence): + pass + + +Ticket.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 1)) +Ticket.componentType = namedtype.NamedTypes( + namedtype.NamedType('tkt-vno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('realm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.NamedType('enc-part', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) +) + + +class AP_REQ(univ.Sequence): + pass + + +AP_REQ.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 14)) +AP_REQ.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(14)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('ap-options', APOptions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('ticket', Ticket().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('authenticator', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))) +) + + +class PADataType(Int32): + pass + + +class PA_DATA(univ.Sequence): + pass + + +PA_DATA.componentType = namedtype.NamedTypes( + namedtype.NamedType('padata-type', PADataType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('padata-value', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class KDC_REP(univ.Sequence): + pass + + +KDC_REP.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(11, 13)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('padata', univ.SequenceOf(componentType=PA_DATA()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('crealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.NamedType('ticket', Ticket().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.NamedType('enc-part', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 6))) +) + + +class AS_REP(KDC_REP): + pass + + +AS_REP.tagSet = KDC_REP.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 11)) + + +class HostAddress(univ.Sequence): + pass + + +HostAddress.componentType = namedtype.NamedTypes( + namedtype.NamedType('addr-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('address', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class HostAddresses(univ.SequenceOf): + pass + + +HostAddresses.componentType = HostAddress() + + +class KDCOptions(KerberosFlags): + pass + + +class KerberosTime(useful.GeneralizedTime): + pass + + +class KDC_REQ_BODY(univ.Sequence): + pass + + +KDC_REQ_BODY.componentType = namedtype.NamedTypes( + namedtype.NamedType('kdc-options', KDCOptions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.NamedType('realm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.OptionalNamedType('from', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.NamedType('till', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.OptionalNamedType('rtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))), + namedtype.NamedType('nonce', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.NamedType('etype', univ.SequenceOf(componentType=EncryptionType()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))), + namedtype.OptionalNamedType('addresses', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9))), + namedtype.OptionalNamedType('enc-authorization-data', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 10))), + namedtype.OptionalNamedType('additional-tickets', univ.SequenceOf(componentType=Ticket()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11))) +) + + +class KDC_REQ(univ.Sequence): + pass + + +KDC_REQ.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(10, 12)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('padata', univ.SequenceOf(componentType=PA_DATA()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('req-body', KDC_REQ_BODY().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))) +) + + +class AS_REQ(KDC_REQ): + pass + + +AS_REQ.tagSet = KDC_REQ.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 10)) + + +class AuthDataTypeValues(univ.Integer): + pass + + +AuthDataTypeValues.namedValues = namedval.NamedValues( + ('kRB5-AUTHDATA-IF-RELEVANT', 1), + ('kRB5-AUTHDATA-INTENDED-FOR-SERVER', 2), + ('kRB5-AUTHDATA-INTENDED-FOR-APPLICATION-CLASS', 3), + ('kRB5-AUTHDATA-KDC-ISSUED', 4), + ('kRB5-AUTHDATA-AND-OR', 5), + ('kRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS', 6), + ('kRB5-AUTHDATA-IN-TICKET-EXTENSIONS', 7), + ('kRB5-AUTHDATA-MANDATORY-FOR-KDC', 8), + ('kRB5-AUTHDATA-INITIAL-VERIFIED-CAS', 9), + ('kRB5-AUTHDATA-OSF-DCE', 64), + ('kRB5-AUTHDATA-SESAME', 65), + ('kRB5-AUTHDATA-OSF-DCE-PKI-CERTID', 66), + ('kRB5-AUTHDATA-WIN2K-PAC', 128), + ('kRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION', 129), + ('kRB5-AUTHDATA-SIGNTICKET-OLDER', -17), + ('kRB5-AUTHDATA-SIGNTICKET-OLD', 142), + ('kRB5-AUTHDATA-SIGNTICKET', 512) +) + + +class AuthDataTypeSequence(univ.Sequence): + pass + + +AuthDataTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', AuthDataTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class EncryptionKey(univ.Sequence): + pass + + +EncryptionKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('keytype', EncryptionType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('keyvalue', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class Microseconds(univ.Integer): + pass + + +Microseconds.subtypeSpec = constraint.ValueRangeConstraint(0, 999999) + + +class Authenticator(univ.Sequence): + pass + + +Authenticator.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 2)) +Authenticator.componentType = namedtype.NamedTypes( + namedtype.NamedType('authenticator-vno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('crealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('cksum', Checksum().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.NamedType('cusec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.NamedType('ctime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.OptionalNamedType('subkey', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 6))), + namedtype.OptionalNamedType('seq-number', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.OptionalNamedType('authorization-data', AuthorizationData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))) +) + + +class ChecksumTypeValues(univ.Integer): + pass + + +ChecksumTypeValues.namedValues = namedval.NamedValues( + ('kRB5-CKSUMTYPE-NONE', 0), + ('kRB5-CKSUMTYPE-CRC32', 1), + ('kRB5-CKSUMTYPE-RSA-MD4', 2), + ('kRB5-CKSUMTYPE-RSA-MD4-DES', 3), + ('kRB5-CKSUMTYPE-DES-MAC', 4), + ('kRB5-CKSUMTYPE-DES-MAC-K', 5), + ('kRB5-CKSUMTYPE-RSA-MD4-DES-K', 6), + ('kRB5-CKSUMTYPE-RSA-MD5', 7), + ('kRB5-CKSUMTYPE-RSA-MD5-DES', 8), + ('kRB5-CKSUMTYPE-RSA-MD5-DES3', 9), + ('kRB5-CKSUMTYPE-SHA1-OTHER', 10), + ('kRB5-CKSUMTYPE-HMAC-SHA1-DES3', 12), + ('kRB5-CKSUMTYPE-SHA1', 14), + ('kRB5-CKSUMTYPE-HMAC-SHA1-96-AES-128', 15), + ('kRB5-CKSUMTYPE-HMAC-SHA1-96-AES-256', 16), + ('kRB5-CKSUMTYPE-GSSAPI', 32771), + ('kRB5-CKSUMTYPE-HMAC-MD5', -138), + ('kRB5-CKSUMTYPE-HMAC-MD5-ENC', -1138) +) + + +class ChecksumTypeSequence(univ.Sequence): + pass + + +ChecksumTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', ChecksumTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class ETYPE_INFO_ENTRY(univ.Sequence): + pass + + +ETYPE_INFO_ENTRY.componentType = namedtype.NamedTypes( + namedtype.NamedType('etype', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('salt', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class ETYPE_INFO(univ.SequenceOf): + pass + + +ETYPE_INFO.componentType = ETYPE_INFO_ENTRY() + + +class ETYPE_INFO2_ENTRY(univ.Sequence): + pass + + +ETYPE_INFO2_ENTRY.componentType = namedtype.NamedTypes( + namedtype.NamedType('etype', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('salt', KerberosString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('s2kparams', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class ETYPE_INFO2(univ.SequenceOf): + pass + + +ETYPE_INFO2.componentType = ETYPE_INFO2_ENTRY() +ETYPE_INFO2.subtypeSpec=constraint.ValueSizeConstraint(1, 256) + + +class EncAPRepPart(univ.Sequence): + pass + + +EncAPRepPart.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 27)) +EncAPRepPart.componentType = namedtype.NamedTypes( + namedtype.NamedType('ctime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('cusec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('subkey', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('seq-number', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) +) + + +class LastReq(univ.SequenceOf): + pass + + +LastReq.componentType = univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('lr-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('lr-value', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +)) + + +class TicketFlags(KerberosFlags): + pass + + +class EncKDCRepPart(univ.Sequence): + pass + + +EncKDCRepPart.componentType = namedtype.NamedTypes( + namedtype.NamedType('key', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('last-req', LastReq().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('nonce', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('key-expiration', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('flags', TicketFlags().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.NamedType('authtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.OptionalNamedType('starttime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))), + namedtype.NamedType('endtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.OptionalNamedType('renew-till', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))), + namedtype.NamedType('srealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9))), + namedtype.NamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 10))), + namedtype.OptionalNamedType('caddr', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11))) +) + + +class EncASRepPart(EncKDCRepPart): + pass + + +EncASRepPart.tagSet = EncKDCRepPart.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 25)) + + +class KrbCredInfo(univ.Sequence): + pass + + +KrbCredInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('key', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('prealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('pname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('flags', TicketFlags().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('authtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.OptionalNamedType('starttime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.OptionalNamedType('endtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))), + namedtype.OptionalNamedType('renew-till', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.OptionalNamedType('srealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))), + namedtype.OptionalNamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 9))), + namedtype.OptionalNamedType('caddr', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10))) +) + + +class EncKrbCredPart(univ.Sequence): + pass + + +EncKrbCredPart.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 29)) +EncKrbCredPart.componentType = namedtype.NamedTypes( + namedtype.NamedType('ticket-info', univ.SequenceOf(componentType=KrbCredInfo()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('nonce', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('timestamp', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('usec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('s-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.OptionalNamedType('r-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 5))) +) + + +class EncKrbPrivPart(univ.Sequence): + pass + + +EncKrbPrivPart.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 28)) +EncKrbPrivPart.componentType = namedtype.NamedTypes( + namedtype.NamedType('user-data', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('timestamp', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('usec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('seq-number', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('s-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.OptionalNamedType('r-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 5))) +) + + +class EncTGSRepPart(EncKDCRepPart): + pass + + +EncTGSRepPart.tagSet = EncKDCRepPart.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 26)) + + +class TransitedEncoding(univ.Sequence): + pass + + +TransitedEncoding.componentType = namedtype.NamedTypes( + namedtype.NamedType('tr-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('contents', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class EncTicketPart(univ.Sequence): + pass + + +EncTicketPart.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 3)) +EncTicketPart.componentType = namedtype.NamedTypes( + namedtype.NamedType('flags', TicketFlags().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('key', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.NamedType('crealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.NamedType('transited', TransitedEncoding().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.NamedType('authtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.OptionalNamedType('starttime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))), + namedtype.NamedType('endtime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.OptionalNamedType('renew-till', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))), + namedtype.OptionalNamedType('caddr', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9))), + namedtype.OptionalNamedType('authorization-data', AuthorizationData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10))) +) + + +class EncryptionTypeValues(univ.Integer): + pass + + +EncryptionTypeValues.namedValues = namedval.NamedValues( + ('kRB5-ENCTYPE-NULL', 0), + ('kRB5-ENCTYPE-DES-CBC-CRC', 1), + ('kRB5-ENCTYPE-DES-CBC-MD4', 2), + ('kRB5-ENCTYPE-DES-CBC-MD5', 3), + ('kRB5-ENCTYPE-DES3-CBC-MD5', 5), + ('kRB5-ENCTYPE-OLD-DES3-CBC-SHA1', 7), + ('kRB5-ENCTYPE-SIGN-DSA-GENERATE', 8), + ('kRB5-ENCTYPE-ENCRYPT-RSA-PRIV', 9), + ('kRB5-ENCTYPE-ENCRYPT-RSA-PUB', 10), + ('kRB5-ENCTYPE-DES3-CBC-SHA1', 16), + ('kRB5-ENCTYPE-AES128-CTS-HMAC-SHA1-96', 17), + ('kRB5-ENCTYPE-AES256-CTS-HMAC-SHA1-96', 18), + ('kRB5-ENCTYPE-ARCFOUR-HMAC-MD5', 23), + ('kRB5-ENCTYPE-ARCFOUR-HMAC-MD5-56', 24), + ('kRB5-ENCTYPE-ENCTYPE-PK-CROSS', 48), + ('kRB5-ENCTYPE-ARCFOUR-MD4', -128), + ('kRB5-ENCTYPE-ARCFOUR-HMAC-OLD', -133), + ('kRB5-ENCTYPE-ARCFOUR-HMAC-OLD-EXP', -135), + ('kRB5-ENCTYPE-DUMMY', -1111) +) + + +class EncryptionTypeSequence(univ.Sequence): + pass + + +EncryptionTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', EncryptionTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class KDCOptionsValues(univ.BitString): + pass + + +KDCOptionsValues.namedValues = namedval.NamedValues( + ('reserved', 0), + ('forwardable', 1), + ('forwarded', 2), + ('proxiable', 3), + ('proxy', 4), + ('allow-postdate', 5), + ('postdated', 6), + ('unused7', 7), + ('renewable', 8), + ('unused9', 9), + ('unused10', 10), + ('opt-hardware-auth', 11), + ('unused12', 12), + ('unused13', 13), + ('unused15', 15), + ('disable-transited-check', 26), + ('renewable-ok', 27), + ('enc-tkt-in-skey', 28), + ('renew', 30), + ('validate', 31) +) + + +class KDCOptionsSequence(univ.Sequence): + pass + + +KDCOptionsSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', KDCOptionsValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class KRB_CRED(univ.Sequence): + pass + + +KRB_CRED.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 22)) +KRB_CRED.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(22)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('tickets', univ.SequenceOf(componentType=Ticket()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('enc-part', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) +) + + +class KRB_ERROR(univ.Sequence): + pass + + +KRB_ERROR.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 30)) +KRB_ERROR.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(30)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('ctime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('cusec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('stime', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.NamedType('susec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.NamedType('error-code', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))), + namedtype.OptionalNamedType('crealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.OptionalNamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 8))), + namedtype.NamedType('realm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9))), + namedtype.NamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 10))), + namedtype.OptionalNamedType('e-text', KerberosString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11))), + namedtype.OptionalNamedType('e-data', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12))) +) + + +class KRB_PRIV(univ.Sequence): + pass + + +KRB_PRIV.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 21)) +KRB_PRIV.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(21)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('enc-part', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) +) + + +class KRB_SAFE_BODY(univ.Sequence): + pass + + +KRB_SAFE_BODY.componentType = namedtype.NamedTypes( + namedtype.NamedType('user-data', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('timestamp', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('usec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('seq-number', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('s-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.OptionalNamedType('r-address', HostAddress().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 5))) +) + + +class KRB_SAFE(univ.Sequence): + pass + + +KRB_SAFE.tagSet = univ.Sequence.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 20)) +KRB_SAFE.componentType = namedtype.NamedTypes( + namedtype.NamedType('pvno', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(5)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('msg-type', univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(20)).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('safe-body', KRB_SAFE_BODY().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.NamedType('cksum', Checksum().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) +) + + +class METHOD_DATA(univ.SequenceOf): + pass + + +METHOD_DATA.componentType = PA_DATA() + + +class MessageTypeValues(univ.Integer): + pass + + +MessageTypeValues.namedValues = namedval.NamedValues( + ('krb-as-req', 10), + ('krb-as-rep', 11), + ('krb-tgs-req', 12), + ('krb-tgs-rep', 13), + ('krb-ap-req', 14), + ('krb-ap-rep', 15), + ('krb-safe', 20), + ('krb-priv', 21), + ('krb-cred', 22), + ('krb-error', 30) +) + + +class MessageTypeSequence(univ.Sequence): + pass + + +MessageTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', MessageTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class NameTypeValues(univ.Integer): + pass + + +NameTypeValues.namedValues = namedval.NamedValues( + ('kRB5-NT-UNKNOWN', 0), + ('kRB5-NT-PRINCIPAL', 1), + ('kRB5-NT-SRV-INST', 2), + ('kRB5-NT-SRV-HST', 3), + ('kRB5-NT-SRV-XHST', 4), + ('kRB5-NT-UID', 5), + ('kRB5-NT-X500-PRINCIPAL', 6), + ('kRB5-NT-SMTP-NAME', 7), + ('kRB5-NT-ENTERPRISE-PRINCIPAL', 10), + ('kRB5-NT-WELLKNOWN', 11), + ('kRB5-NT-ENT-PRINCIPAL-AND-ID', -130), + ('kRB5-NT-MS-PRINCIPAL', -128), + ('kRB5-NT-MS-PRINCIPAL-AND-ID', -129) +) + + +class NameTypeSequence(univ.Sequence): + pass + + +NameTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', NameTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class PA_ENC_TIMESTAMP(EncryptedData): + pass + + +class PA_ENC_TS_ENC(univ.Sequence): + pass + + +PA_ENC_TS_ENC.componentType = namedtype.NamedTypes( + namedtype.NamedType('patimestamp', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('pausec', Microseconds().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class PADataTypeValues(univ.Integer): + pass + + +PADataTypeValues.namedValues = namedval.NamedValues( + ('kRB5-PADATA-NONE', 0), + ('kRB5-PADATA-KDC-REQ', 1), + ('kRB5-PADATA-ENC-TIMESTAMP', 2), + ('kRB5-PADATA-PW-SALT', 3), + ('kRB5-PADATA-ENC-UNIX-TIME', 5), + ('kRB5-PADATA-SANDIA-SECUREID', 6), + ('kRB5-PADATA-SESAME', 7), + ('kRB5-PADATA-OSF-DCE', 8), + ('kRB5-PADATA-CYBERSAFE-SECUREID', 9), + ('kRB5-PADATA-AFS3-SALT', 10), + ('kRB5-PADATA-ETYPE-INFO', 11), + ('kRB5-PADATA-SAM-CHALLENGE', 12), + ('kRB5-PADATA-SAM-RESPONSE', 13), + ('kRB5-PADATA-PK-AS-REQ-19', 14), + ('kRB5-PADATA-PK-AS-REP-19', 15), + ('kRB5-PADATA-PK-AS-REQ', 16), + ('kRB5-PADATA-PK-AS-REP', 17), + ('kRB5-PADATA-PA-PK-OCSP-RESPONSE', 18), + ('kRB5-PADATA-ETYPE-INFO2', 19), + ('kRB5-PADATA-SVR-REFERRAL-INFO', 20), + ('kRB5-PADATA-SAM-REDIRECT', 21), + ('kRB5-PADATA-GET-FROM-TYPED-DATA', 22), + ('kRB5-PADATA-SAM-ETYPE-INFO', 23), + ('kRB5-PADATA-SERVER-REFERRAL', 25), + ('kRB5-PADATA-ALT-PRINC', 24), + ('kRB5-PADATA-SAM-CHALLENGE2', 30), + ('kRB5-PADATA-SAM-RESPONSE2', 31), + ('kRB5-PA-EXTRA-TGT', 41), + ('kRB5-PADATA-TD-KRB-PRINCIPAL', 102), + ('kRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS', 104), + ('kRB5-PADATA-PK-TD-CERTIFICATE-INDEX', 105), + ('kRB5-PADATA-TD-APP-DEFINED-ERROR', 106), + ('kRB5-PADATA-TD-REQ-NONCE', 107), + ('kRB5-PADATA-TD-REQ-SEQ', 108), + ('kRB5-PADATA-PA-PAC-REQUEST', 128), + ('kRB5-PADATA-FOR-USER', 129), + ('kRB5-PADATA-FOR-X509-USER', 130), + ('kRB5-PADATA-FOR-CHECK-DUPS', 131), + ('kRB5-PADATA-AS-CHECKSUM', 132), + ('kRB5-PADATA-FX-COOKIE', 133), + ('kRB5-PADATA-AUTHENTICATION-SET', 134), + ('kRB5-PADATA-AUTH-SET-SELECTED', 135), + ('kRB5-PADATA-FX-FAST', 136), + ('kRB5-PADATA-FX-ERROR', 137), + ('kRB5-PADATA-ENCRYPTED-CHALLENGE', 138), + ('kRB5-PADATA-OTP-CHALLENGE', 141), + ('kRB5-PADATA-OTP-REQUEST', 142), + ('kBB5-PADATA-OTP-CONFIRM', 143), + ('kRB5-PADATA-OTP-PIN-CHANGE', 144), + ('kRB5-PADATA-EPAK-AS-REQ', 145), + ('kRB5-PADATA-EPAK-AS-REP', 146), + ('kRB5-PADATA-PKINIT-KX', 147), + ('kRB5-PADATA-PKU2U-NAME', 148), + ('kRB5-PADATA-REQ-ENC-PA-REP', 149), + ('kRB5-PADATA-SUPPORTED-ETYPES', 165) +) + + +class PADataTypeSequence(univ.Sequence): + pass + + +PADataTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', PADataTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class TGS_REP(KDC_REP): + pass + + +TGS_REP.tagSet = KDC_REP.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 13)) + + +class TGS_REQ(KDC_REQ): + pass + + +TGS_REQ.tagSet = KDC_REQ.tagSet.tagExplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 12)) + + +class TYPED_DATA(univ.SequenceOf): + pass + + +TYPED_DATA.componentType = univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('data-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('data-value', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +)) + +TYPED_DATA.subtypeSpec=constraint.ValueSizeConstraint(1, 256) + + +class TicketFlagsValues(univ.BitString): + pass + + +TicketFlagsValues.namedValues = namedval.NamedValues( + ('reserved', 0), + ('forwardable', 1), + ('forwarded', 2), + ('proxiable', 3), + ('proxy', 4), + ('may-postdate', 5), + ('postdated', 6), + ('invalid', 7), + ('renewable', 8), + ('initial', 9), + ('pre-authent', 10), + ('hw-authent', 11), + ('transited-policy-checked', 12), + ('ok-as-delegate', 13) +) + + +class TicketFlagsSequence(univ.Sequence): + pass + + +TicketFlagsSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', TicketFlagsValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +id_krb5 = _OID(1, 3, 6, 1, 5, 2) + + diff --git a/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh b/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh new file mode 100755 index 00000000000..2e3995688f2 --- /dev/null +++ b/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# + +# +# I used https://github.com/kimgr/asn1ate.git +# to generate pyasn1 bindings for rfc4120.asn1 +# + +PATH_TO_ASN1ATE_CHECKOUT=$1 +PATH_TO_ASN1_INPUT_FILE=$2 + +set -u +set -e + +usage() { + echo "usage: $0 PATH_TO_ASN1ATE_CHECKOUT PATH_TO_ASN1_INPUT_FILE > PATH_TO_PYASN1_OUTPUT_FILE" +} + +test -n "${PATH_TO_ASN1ATE_CHECKOUT}" || { + usage + exit 1 +} +test -n "${PATH_TO_ASN1_INPUT_FILE}" || { + usage + exit 1 +} +test -d "${PATH_TO_ASN1ATE_CHECKOUT}" || { + usage + exit 1 +} +test -f "${PATH_TO_ASN1_INPUT_FILE}" || { + usage + exit 1 +} + +PATH_TO_PYASN1GEN_PY="${PATH_TO_ASN1ATE_CHECKOUT}/asn1ate/pyasn1gen.py" + +PYTHONPATH="${PATH_TO_ASN1ATE_CHECKOUT}:${PYTHONPATH-}" +export PYTHONPATH + +python3 "${PATH_TO_PYASN1GEN_PY}" "${PATH_TO_ASN1_INPUT_FILE}" diff --git a/python/samba/tests/source.py b/python/samba/tests/source.py index b7608b1bab3..cebfb9ae8fb 100644 --- a/python/samba/tests/source.py +++ b/python/samba/tests/source.py @@ -93,6 +93,9 @@ class TestSource(TestCase): if fname.endswith("python/samba/tests/krb5/kcrypto.py"): # Imported from MIT testing repo continue + if fname.endswith("python/samba/tests/krb5/rfc4120_pyasn1.py"): + # Autogenerated + continue match = copyright_re.search(text) if not match: incorrect.append((fname, 'no copyright line found\n')) @@ -138,6 +141,9 @@ class TestSource(TestCase): if fname.endswith("python/samba/tests/krb5/kcrypto.py"): # Imported from MIT testing repo continue + if fname.endswith("python/samba/tests/krb5/rfc4120_pyasn1.py"): + # Autogenerated + continue if not gpl_re.search(text): incorrect.append(fname) -- 2.25.1 From ae39d8c5397cb4a05c6727349f4da26110a27091 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2020 16:29:38 +0100 Subject: [PATCH 020/645] python/tests/krb5: add raw_testcase.py as the base for our Kerberos protocol testing Pair-Programmed-With: Isaac Boukris Signed-off-by: Stefan Metzmacher Signed-off-by: Isaac Boukris Reviewed-by: Isaac Boukris (cherry picked from commit fb7cba50ae3472b29aa806208badc1ded8979073) --- python/samba/tests/krb5/raw_testcase.py | 869 ++++++++++++++++++++++++ 1 file changed, 869 insertions(+) create mode 100644 python/samba/tests/krb5/raw_testcase.py diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py new file mode 100644 index 00000000000..6c7bcd418a0 --- /dev/null +++ b/python/samba/tests/krb5/raw_testcase.py @@ -0,0 +1,869 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) Isaac Boukris 2020 +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import socket +import struct +import time +import datetime +import random + +import samba.tests +from samba.credentials import Credentials +from samba.tests import TestCase +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +import samba.tests.krb5.kcrypto as kcrypto + +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 +from pyasn1.codec.native.encoder import encode as pyasn1_native_encode + +from pyasn1.codec.ber.encoder import BitStringEncoder as BitStringEncoder +def BitStringEncoder_encodeValue32(self, value, asn1Spec, encodeFun, **options): + # + # BitStrings like KDCOptions or TicketFlags should at least + # be 32-Bit on the wire + # + if asn1Spec is not None: + # TODO: try to avoid ASN.1 schema instantiation + value = asn1Spec.clone(value) + + valueLength = len(value) + if valueLength % 8: + alignedValue = value << (8 - valueLength % 8) + else: + alignedValue = value + + substrate = alignedValue.asOctets() + length = len(substrate) + # We need at least 32-Bit / 4-Bytes + if length < 4: + padding = 4 - length + else: + padding = 0 + ret = b'\x00' + substrate + (b'\x00' * padding) + return ret, False, True +BitStringEncoder.encodeValue = BitStringEncoder_encodeValue32 + +def BitString_NamedValues_prettyPrint(self, scope=0): + ret = "%s" % self.asBinary() + bits = [] + highest_bit = 32 + for byte in self.asNumbers(): + for bit in [7,6,5,4,3,2,1,0]: + mask = 1 << bit + if byte & mask: + val = 1 + else: + val = 0 + bits.append(val) + if len(bits) < highest_bit: + for bitPosition in range(len(bits), highest_bit): + bits.append(0) + indent = " " * scope + delim = ": (\n%s " % indent + for bitPosition in range(highest_bit): + if bitPosition in self.prettyPrintNamedValues: + name = self.prettyPrintNamedValues[bitPosition] + elif bits[bitPosition] != 0: + name = "unknown-bit-%u" % bitPosition + else: + continue + ret += "%s%s:%u" % (delim, name, bits[bitPosition]) + delim = ",\n%s " % indent + ret += "\n%s)" % indent + return ret +krb5_asn1.TicketFlags.prettyPrintNamedValues = krb5_asn1.TicketFlagsValues.namedValues +krb5_asn1.TicketFlags.namedValues = krb5_asn1.TicketFlagsValues.namedValues +krb5_asn1.TicketFlags.prettyPrint = BitString_NamedValues_prettyPrint +krb5_asn1.KDCOptions.prettyPrintNamedValues = krb5_asn1.KDCOptionsValues.namedValues +krb5_asn1.KDCOptions.namedValues = krb5_asn1.KDCOptionsValues.namedValues +krb5_asn1.KDCOptions.prettyPrint = BitString_NamedValues_prettyPrint + +def Integer_NamedValues_prettyPrint(self, scope=0): + intval = int(self) + if intval in self.prettyPrintNamedValues: + name = self.prettyPrintNamedValues[intval] + else: + name = "<__unknown__>" + ret = "%d (0x%x) %s" % (intval, intval, name) + return ret +krb5_asn1.NameType.prettyPrintNamedValues = krb5_asn1.NameTypeValues.namedValues +krb5_asn1.NameType.prettyPrint = Integer_NamedValues_prettyPrint +krb5_asn1.AuthDataType.prettyPrintNamedValues = krb5_asn1.AuthDataTypeValues.namedValues +krb5_asn1.AuthDataType.prettyPrint = Integer_NamedValues_prettyPrint +krb5_asn1.PADataType.prettyPrintNamedValues = krb5_asn1.PADataTypeValues.namedValues +krb5_asn1.PADataType.prettyPrint = Integer_NamedValues_prettyPrint +krb5_asn1.EncryptionType.prettyPrintNamedValues = krb5_asn1.EncryptionTypeValues.namedValues +krb5_asn1.EncryptionType.prettyPrint = Integer_NamedValues_prettyPrint +krb5_asn1.ChecksumType.prettyPrintNamedValues = krb5_asn1.ChecksumTypeValues.namedValues +krb5_asn1.ChecksumType.prettyPrint = Integer_NamedValues_prettyPrint + +class Krb5EncryptionKey(object): + def __init__(self, key, kvno): + EncTypeChecksum = { + kcrypto.Enctype.AES256: kcrypto.Cksumtype.SHA1_AES256, + kcrypto.Enctype.AES128: kcrypto.Cksumtype.SHA1_AES128, + kcrypto.Enctype.RC4: kcrypto.Cksumtype.HMAC_MD5, + } + self.key = key + self.etype = key.enctype + self.ctype = EncTypeChecksum[self.etype] + self.kvno = kvno + return + + def encrypt(self, usage, plaintext): + ciphertext = kcrypto.encrypt(self.key, usage, plaintext) + return ciphertext + + def decrypt(self, usage, ciphertext): + plaintext = kcrypto.decrypt(self.key, usage, ciphertext) + return plaintext + + def make_checksum(self, usage, plaintext, ctype=None): + if ctype is None: + ctype = self.ctype + cksum = kcrypto.make_checksum(ctype, self.key, usage, plaintext) + return cksum + + def export_obj(self): + EncryptionKey_obj = { + 'keytype': self.etype, + 'keyvalue': self.key.contents, + }; + return EncryptionKey_obj + +class RawKerberosTest(TestCase): + """A raw Kerberos Test case.""" + + def setUp(self): + super(RawKerberosTest, self).setUp() + self.do_asn1_print = False + self.do_hexdump = False + + self.host = samba.tests.env_get_var_value('SERVER') + + self.s = None + + def tearDown(self): + self._disconnect("tearDown") + super(TestCase, self).tearDown() + + def _disconnect(self, reason): + if self.s is None: + return + self.s.close() + self.s = None + if self.do_hexdump: + sys.stderr.write("disconnect[%s]\n" % reason) + + def _connect_tcp(self): + tcp_port = 88 + try: + self.a = socket.getaddrinfo(self.host, tcp_port, socket.AF_UNSPEC, + socket.SOCK_STREAM, socket.SOL_TCP, + 0) + self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2]) + self.s.settimeout(10) + self.s.connect(self.a[0][4]) + except socket.error as e: + self.s.close() + raise + except IOError as e: + self.s.close() + raise + except Exception as e: + raise + finally: + pass + + def connect(self): + self.assertNotConnected() + self._connect_tcp() + if self.do_hexdump: + sys.stderr.write("connected[%s]\n" % self.host) + return + + def get_user_creds(self): + c = Credentials() + c.guess() + domain = samba.tests.env_get_var_value('DOMAIN') + realm = samba.tests.env_get_var_value('REALM') + username = samba.tests.env_get_var_value('USERNAME') + password = samba.tests.env_get_var_value('PASSWORD') + c.set_domain(domain) + c.set_realm(realm) + c.set_username(username) + c.set_password(password) + return c + + def get_service_creds(self, allow_missing_password=False): + c = Credentials() + c.guess() + domain = samba.tests.env_get_var_value('DOMAIN') + realm = samba.tests.env_get_var_value('REALM') + username = samba.tests.env_get_var_value('SERVICE_USERNAME') + password = samba.tests.env_get_var_value('SERVICE_PASSWORD', + allow_missing=allow_missing_password) + c.set_domain(domain) + c.set_realm(realm) + c.set_username(username) + if password is not None: + c.set_password(password) + return c + + def get_anon_creds(self): + c = Credentials() + c.set_anonymous() + return c + + def asn1_dump(self, name, obj, asn1_print=None): + if asn1_print is None: + asn1_print = self.do_asn1_print + if asn1_print: + if name is not None: + sys.stderr.write("%s:\n%s" % (name, obj)) + else: + sys.stderr.write("%s" % (obj)) + + def hex_dump(self, name, blob, hexdump=None): + if hexdump is None: + hexdump = self.do_hexdump + if hexdump: + sys.stderr.write("%s: %d\n%s" % (name, len(blob), self.hexdump(blob))) + + def der_decode(self, blob, asn1Spec=None, native_encode=True, asn1_print=None, hexdump=None): + if asn1Spec is not None: + class_name = type(asn1Spec).__name__.split(':')[0] + else: + class_name = "" + self.hex_dump(class_name, blob, hexdump=hexdump) + obj,_ = pyasn1_der_decode(blob, asn1Spec=asn1Spec) + self.asn1_dump(None, obj, asn1_print=asn1_print) + if native_encode: + obj = pyasn1_native_encode(obj) + return obj + + def der_encode(self, obj, asn1Spec=None, native_decode=True, asn1_print=None, hexdump=None): + if native_decode: + obj = pyasn1_native_decode(obj, asn1Spec=asn1Spec) + class_name = type(obj).__name__.split(':')[0] + if class_name is not None: + self.asn1_dump(None, obj, asn1_print=asn1_print) + blob = pyasn1_der_encode(obj) + if class_name is not None: + self.hex_dump(class_name, blob, hexdump=hexdump) + return blob + + def send_pdu(self, req, asn1_print=None, hexdump=None): + 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 + req_pdu = req_pdu[sent:] + except socket.error as e: + self._disconnect("send_pdu: %s" % e) + raise + except IOError as e: + self._disconnect("send_pdu: %s" % e) + raise + finally: + pass + + def recv_raw(self, num_recv=0xffff, hexdump=None, timeout=None): + rep_pdu = None + try: + if timeout is not None: + self.s.settimeout(timeout) + rep_pdu = self.s.recv(num_recv, 0) + self.s.settimeout(10) + if len(rep_pdu) == 0: + self._disconnect("recv_raw: EOF") + return None + self.hex_dump("recv_raw", rep_pdu, hexdump=hexdump) + except socket.timeout as e: + self.s.settimeout(10) + sys.stderr.write("recv_raw: TIMEOUT\n") + pass + except socket.error as e: + self._disconnect("recv_raw: %s" % e) + raise + except IOError as e: + self._disconnect("recv_raw: %s" % e) + raise + finally: + pass + return rep_pdu + + def recv_pdu_raw(self, asn1_print=None, hexdump=None, timeout=None): + rep_pdu = None + rep = None + try: + raw_pdu = self.recv_raw(num_recv=4, hexdump=hexdump, timeout=timeout) + if raw_pdu is None: + return (None, None) + header = struct.unpack(">I", raw_pdu[0:4]) + k5_len = header[0] + if k5_len == 0: + return (None, "") + missing = k5_len + rep_pdu = b'' + while missing > 0: + raw_pdu = self.recv_raw(num_recv=missing, hexdump=hexdump, timeout=timeout) + self.assertGreaterEqual(len(raw_pdu), 1) + rep_pdu += raw_pdu + missing = k5_len - len(rep_pdu) + k5_raw = self.der_decode(rep_pdu, asn1Spec=None, native_encode=False, + asn1_print=False, hexdump=False) + pvno=k5_raw['field-0'] + self.assertEqual(pvno, 5) + msg_type=k5_raw['field-1'] + self.assertIn(msg_type, [11,13,30]) + if msg_type == 11: + asn1Spec=krb5_asn1.AS_REP() + elif msg_type == 13: + asn1Spec=krb5_asn1.TGS_REP() + elif msg_type == 30: + asn1Spec=krb5_asn1.KRB_ERROR() + rep = self.der_decode(rep_pdu, asn1Spec=asn1Spec, + asn1_print=asn1_print, hexdump=False) + finally: + pass + 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) + return rep + + def assertIsConnected(self): + self.assertIsNotNone(self.s, msg="Not connected") + return + + def assertNotConnected(self): + self.assertIsNone(self.s, msg="Is connected") + return + + def send_recv_transaction(self, req, asn1_print=None, hexdump=None, timeout=None): + self.connect() + try: + self.send_pdu(req, asn1_print=asn1_print, hexdump=hexdump) + rep = self.recv_pdu(asn1_print=asn1_print, hexdump=hexdump, timeout=timeout) + except Exception: + self._disconnect("transaction failed") + raise + self._disconnect("transaction done") + return rep + + def assertNoValue(self, value): + self.assertTrue(value.isNoValue) + return + + def assertHasValue(self, value): + self.assertIsNotNone(value) + return + + def assertPrincipalEqual(self, princ1, princ2): + self.assertEqual(princ1['name-type'], princ2['name-type']) + self.assertEqual(len(princ1['name-string']), len(princ2['name-string']), + msg="princ1=%s != princ2=%s" % (princ1, princ2)) + for idx in range(len(princ1['name-string'])): + self.assertEqual(princ1['name-string'][idx], princ2['name-string'][idx], + msg="princ1=%s != princ2=%s" % (princ1, princ2)) + return + + def get_KerberosTimeWithUsec(self, epoch=None, offset=None): + if epoch is None: + epoch = time.time() + if offset is not None: + epoch = epoch + int(offset) + dt = datetime.datetime.fromtimestamp(epoch, tz=datetime.timezone.utc) + return (dt.strftime("%Y%m%d%H%M%SZ"), dt.microsecond) + + def get_KerberosTime(self, epoch=None, offset=None): + (s, _) = self.get_KerberosTimeWithUsec(epoch=epoch, offset=offset) + return s + + def SessionKey_create(self, etype, contents, kvno=None): + key = kcrypto.Key(etype, contents) + return Krb5EncryptionKey(key, kvno) + + def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None): + key = kcrypto.string_to_key(etype, pwd, salt) + return Krb5EncryptionKey(key, kvno) + + def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): + e = etype_info2['etype'] + salt = None + try: + salt = etype_info2['salt'] + except: + pass + + if e == kcrypto.Enctype.RC4: + self.assertIsNone(salt) + nthash = creds.get_nt_hash() + return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno) + + password = creds.get_password() + return self.PasswordKey_create(etype=e, pwd=password, salt=salt, kvno=kvno) + + def RandomKey(self, etype): + e = kcrypto._get_enctype_profile(etype) + contents = samba.generate_random_bytes(e.keysize) + return self.SessionKey_create(etype=etype, contents=contents) + + def EncryptionKey_import(self, EncryptionKey_obj): + return self.SessionKey_create(EncryptionKey_obj['keytype'], + EncryptionKey_obj['keyvalue']) + + def EncryptedData_create(self, key, usage, plaintext): + # EncryptedData ::= SEQUENCE { + # etype [0] Int32 -- EncryptionType --, + # kvno [1] UInt32 OPTIONAL, + # cipher [2] OCTET STRING -- ciphertext + # } + ciphertext = key.encrypt(usage, plaintext) + EncryptedData_obj = { + 'etype': key.etype, + 'cipher': ciphertext + } + if key.kvno is not None: + EncryptedData_obj['kvno'] = key.kvno + return EncryptedData_obj + + def Checksum_create(self, key, usage, plaintext, ctype=None): + #Checksum ::= SEQUENCE { + # cksumtype [0] Int32, + # checksum [1] OCTET STRING + #} + if ctype is None: + ctype = key.ctype + checksum = key.make_checksum(usage, plaintext, ctype=ctype) + Checksum_obj = { + 'cksumtype': ctype, + 'checksum': checksum, + } + return Checksum_obj + + def PrincipalName_create(self, name_type, names): + # PrincipalName ::= SEQUENCE { + # name-type [0] Int32, + # name-string [1] SEQUENCE OF KerberosString + # } + PrincipalName_obj = { + 'name-type': name_type, + 'name-string': names, + } + return PrincipalName_obj + + def PA_DATA_create(self, padata_type, padata_value): + # PA-DATA ::= SEQUENCE { + # -- NOTE: first tag is [1], not [0] + # padata-type [1] Int32, + # padata-value [2] OCTET STRING -- might be encoded AP-REQ + # } + PA_DATA_obj = { + 'padata-type': padata_type, + 'padata-value': padata_value, + } + return PA_DATA_obj + + def PA_ENC_TS_ENC_create(self, ts, usec): + #PA-ENC-TS-ENC ::= SEQUENCE { + # patimestamp[0] KerberosTime, -- client's time + # pausec[1] krb5int32 OPTIONAL + #} + PA_ENC_TS_ENC_obj = { + 'patimestamp': ts, + 'pausec': usec, + } + return PA_ENC_TS_ENC_obj + + def KDC_REQ_BODY_create(self, + kdc_options, + cname, + realm, + sname, + from_time, + till_time, + renew_time, + nonce, + etypes, + addresses, + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + asn1_print=None, + hexdump=None): + #KDC-REQ-BODY ::= SEQUENCE { + # kdc-options [0] KDCOptions, + # cname [1] PrincipalName OPTIONAL + # -- Used only in AS-REQ --, + # realm [2] Realm + # -- Server's realm + # -- Also client's in AS-REQ --, + # sname [3] PrincipalName OPTIONAL, + # from [4] KerberosTime OPTIONAL, + # till [5] KerberosTime, + # rtime [6] KerberosTime OPTIONAL, + # nonce [7] UInt32, + # etype [8] SEQUENCE OF Int32 -- EncryptionType + # -- in preference order --, + # addresses [9] HostAddresses OPTIONAL, + # enc-authorization-data [10] EncryptedData OPTIONAL + # -- AuthorizationData --, + # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + # -- NOTE: not empty + #} + if EncAuthorizationData is not None: + enc_ad_plain = self.der_encode(EncAuthorizationData, + asn1Spec=krb5_asn1.AuthorizationData(), + asn1_print=asn1_print, + hexdump=hexdump) + enc_ad = self.EncryptedData_create(EncAuthorizationData_key, enc_ad_plain) + else: + enc_ad = None + KDC_REQ_BODY_obj = { + 'kdc-options': kdc_options, + 'realm': realm, + 'till': till_time, + 'nonce': nonce, + 'etype': etypes, + } + if cname is not None: + KDC_REQ_BODY_obj['cname'] = cname + if sname is not None: + KDC_REQ_BODY_obj['sname'] = sname + if from_time is not None: + KDC_REQ_BODY_obj['from'] = from_time + if renew_time is not None: + KDC_REQ_BODY_obj['rtime'] = renew_time + if addresses is not None: + KDC_REQ_BODY_obj['addresses'] = addresses + if enc_ad is not None: + KDC_REQ_BODY_obj['enc-authorization-data'] = enc_ad + if additional_tickets is not None: + KDC_REQ_BODY_obj['additional-tickets'] = additional_tickets + return KDC_REQ_BODY_obj + + def KDC_REQ_create(self, + msg_type, + padata, + kdc_options, + cname, + realm, + sname, + from_time, + till_time, + renew_time, + nonce, + etypes, + addresses, + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + asn1Spec=None, + asn1_print=None, + hexdump=None): + #KDC-REQ ::= SEQUENCE { + # -- NOTE: first tag is [1], not [0] + # pvno [1] INTEGER (5) , + # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + # padata [3] SEQUENCE OF PA-DATA OPTIONAL + # -- NOTE: not empty --, + # req-body [4] KDC-REQ-BODY + #} + # + KDC_REQ_BODY_obj = self.KDC_REQ_BODY_create(kdc_options, + cname, + realm, + sname, + from_time, + till_time, + renew_time, + nonce, + etypes, + addresses, + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + asn1_print=asn1_print, + hexdump=hexdump) + KDC_REQ_obj = { + 'pvno': 5, + 'msg-type': msg_type, + 'req-body': KDC_REQ_BODY_obj, + } + if padata is not None: + KDC_REQ_obj['padata'] = padata + if asn1Spec is not None: + KDC_REQ_decoded = pyasn1_native_decode(KDC_REQ_obj, asn1Spec=asn1Spec) + else: + KDC_REQ_decoded = None + return KDC_REQ_obj, KDC_REQ_decoded + + def AS_REQ_create(self, + padata, # optional + kdc_options, # required + cname, # optional + realm, # required + sname, # optional + from_time, # optional + till_time, # required + renew_time, # optional + nonce, # required + etypes, # required + addresses, # optional + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + native_decoded_only=True, + asn1_print=None, + hexdump=None): + #KDC-REQ ::= SEQUENCE { + # -- NOTE: first tag is [1], not [0] + # pvno [1] INTEGER (5) , + # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + # padata [3] SEQUENCE OF PA-DATA OPTIONAL + # -- NOTE: not empty --, + # req-body [4] KDC-REQ-BODY + #} + # + #KDC-REQ-BODY ::= SEQUENCE { + # kdc-options [0] KDCOptions, + # cname [1] PrincipalName OPTIONAL + # -- Used only in AS-REQ --, + # realm [2] Realm + # -- Server's realm + # -- Also client's in AS-REQ --, + # sname [3] PrincipalName OPTIONAL, + # from [4] KerberosTime OPTIONAL, + # till [5] KerberosTime, + # rtime [6] KerberosTime OPTIONAL, + # nonce [7] UInt32, + # etype [8] SEQUENCE OF Int32 -- EncryptionType + # -- in preference order --, + # addresses [9] HostAddresses OPTIONAL, + # enc-authorization-data [10] EncryptedData OPTIONAL + # -- AuthorizationData --, + # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + # -- NOTE: not empty + #} + obj,decoded = self.KDC_REQ_create(msg_type=10, + padata=padata, + kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets, + asn1Spec=krb5_asn1.AS_REQ(), + asn1_print=asn1_print, + hexdump=hexdump) + if native_decoded_only: + return decoded + return decoded, obj + + def AP_REQ_create(self, ap_options, ticket, authenticator): + # AP-REQ ::= [APPLICATION 14] SEQUENCE { + # pvno [0] INTEGER (5), + # msg-type [1] INTEGER (14), + # ap-options [2] APOptions, + # ticket [3] Ticket, + # authenticator [4] EncryptedData -- Authenticator + #} + AP_REQ_obj = { + 'pvno': 5, + 'msg-type': 14, + 'ap-options': ap_options, + 'ticket': ticket, + 'authenticator': authenticator, + } + return AP_REQ_obj + + def Authenticator_create(self, crealm, cname, cksum, cusec, ctime, subkey, seq_number, + authorization_data): + # -- Unencrypted authenticator + # Authenticator ::= [APPLICATION 2] SEQUENCE { + # authenticator-vno [0] INTEGER (5), + # crealm [1] Realm, + # cname [2] PrincipalName, + # cksum [3] Checksum OPTIONAL, + # cusec [4] Microseconds, + # ctime [5] KerberosTime, + # subkey [6] EncryptionKey OPTIONAL, + # seq-number [7] UInt32 OPTIONAL, + # authorization-data [8] AuthorizationData OPTIONAL + #} + Authenticator_obj = { + 'authenticator-vno': 5, + 'crealm': crealm, + 'cname': cname, + 'cusec': cusec, + 'ctime': ctime, + } + if cksum is not None: + Authenticator_obj['cksum'] = cksum + if subkey is not None: + Authenticator_obj['subkey'] = subkey + if seq_number is not None: + Authenticator_obj['seq-number'] = seq_number + if authorization_data is not None: + Authenticator_obj['authorization-data'] = authorization_data + return Authenticator_obj + + def TGS_REQ_create(self, + padata, # optional + cusec, + ctime, + ticket, + kdc_options, # required + cname, # optional + realm, # required + sname, # optional + from_time, # optional + till_time, # required + renew_time, # optional + nonce, # required + etypes, # required + addresses, # optional + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + ticket_session_key, + authenticator_subkey=None, + body_checksum_type=None, + native_decoded_only=True, + asn1_print=None, + hexdump=None): + #KDC-REQ ::= SEQUENCE { + # -- NOTE: first tag is [1], not [0] + # pvno [1] INTEGER (5) , + # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + # padata [3] SEQUENCE OF PA-DATA OPTIONAL + # -- NOTE: not empty --, + # req-body [4] KDC-REQ-BODY + #} + # + #KDC-REQ-BODY ::= SEQUENCE { + # kdc-options [0] KDCOptions, + # cname [1] PrincipalName OPTIONAL + # -- Used only in AS-REQ --, + # realm [2] Realm + # -- Server's realm + # -- Also client's in AS-REQ --, + # sname [3] PrincipalName OPTIONAL, + # from [4] KerberosTime OPTIONAL, + # till [5] KerberosTime, + # rtime [6] KerberosTime OPTIONAL, + # nonce [7] UInt32, + # etype [8] SEQUENCE OF Int32 -- EncryptionType + # -- in preference order --, + # addresses [9] HostAddresses OPTIONAL, + # enc-authorization-data [10] EncryptedData OPTIONAL + # -- AuthorizationData --, + # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + # -- NOTE: not empty + #} + + req_body = self.KDC_REQ_BODY_create(kdc_options=kdc_options, + cname=None, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets) + req_body = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), + asn1_print=asn1_print, hexdump=hexdump) + + req_body_checksum = self.Checksum_create(ticket_session_key, 6, req_body, + ctype=body_checksum_type) + + subkey_obj = None + if authenticator_subkey is not None: + subkey_obj = authenticator_subkey.export_obj() + seq_number = random.randint(0, 0xfffffffe) + authenticator = self.Authenticator_create(crealm=realm, + cname=cname, + cksum=req_body_checksum, + cusec=cusec, + ctime=ctime, + subkey=subkey_obj, + seq_number=seq_number, + authorization_data=None) + authenticator = self.der_encode(authenticator, asn1Spec=krb5_asn1.Authenticator(), + asn1_print=asn1_print, hexdump=hexdump) + + authenticator = self.EncryptedData_create(ticket_session_key, 7, authenticator) + + ap_options = krb5_asn1.APOptions('0') + ap_req = self.AP_REQ_create(ap_options=str(ap_options), + ticket=ticket, + authenticator=authenticator) + ap_req = self.der_encode(ap_req, asn1Spec=krb5_asn1.AP_REQ(), + asn1_print=asn1_print, hexdump=hexdump) + pa_tgs_req = self.PA_DATA_create(1, ap_req) + if padata is not None: + padata.append(pa_tgs_req) + else: + padata = [pa_tgs_req] + + obj,decoded = self.KDC_REQ_create(msg_type=12, + padata=padata, + kdc_options=kdc_options, + cname=None, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets, + asn1Spec=krb5_asn1.TGS_REQ(), + asn1_print=asn1_print, + hexdump=hexdump) + if native_decoded_only: + return decoded + return decoded, obj -- 2.25.1 From 5278f81a1563fbe44b9da4657717afc51b9f1bcc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2020 16:29:38 +0100 Subject: [PATCH 021/645] python/tests/krb5: add simple_tests.py with the first simple test This just demonstrates that the infrastructure works:-) I'm running this as: SERVER=172.31.9.188 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE \ USERNAME=administrator PASSWORD=A1b2C3d4 SERVICE_USERNAME="w2012r2-188" \ python/samba/tests/krb5/simple_tests.py Pair-Programmed-With: Isaac Boukris Signed-off-by: Stefan Metzmacher Signed-off-by: Isaac Boukris Reviewed-by: Isaac Boukris (cherry picked from commit 4f6d26609a66a42df671a540677af15e67efc0df) --- python/samba/tests/krb5/simple_tests.py | 171 ++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + 2 files changed, 172 insertions(+) create mode 100755 python/samba/tests/krb5/simple_tests.py diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py new file mode 100755 index 00000000000..c9998c4d2db --- /dev/null +++ b/python/samba/tests/krb5/simple_tests.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + +global_asn1_print = False +global_hexdump = False + +class SimpleKerberosTests(RawKerberosTest): + + def setUp(self): + super(SimpleKerberosTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def test_simple(self): + user_creds = self.get_user_creds() + user = user_creds.get_username() + realm = user_creds.get_realm() + + cname = self.PrincipalName_create(name_type=1, names=[user]) + sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + + till = self.get_KerberosTime(offset=36000) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = None + + etypes=(18,17,23) + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == 19: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(2, pa_ts) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = [pa_ts] + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 11) + + usage = 3 + enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + + # TGS Request + service_creds = self.get_service_creds(allow_missing_password=True) + service_name = service_creds.get_username() + + sname = self.PrincipalName_create(name_type=2, names=["host", service_name]) + kdc_options = krb5_asn1.KDCOptions('forwardable') + till = self.get_KerberosTime(offset=36000) + ticket = rep['ticket'] + ticket_session_key = self.EncryptionKey_import(enc_part2['key']) + padata = [] + + subkey = self.RandomKey(ticket_session_key.etype) + subkey_usage = 9 + + (ctime, cusec) = self.get_KerberosTimeWithUsec() + + req = self.TGS_REQ_create(padata=padata, + cusec=cusec, + ctime=ctime, + ticket=ticket, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7ffffffe, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None, + ticket_session_key=ticket_session_key, + authenticator_subkey=subkey) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 13) + + enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + + return + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 06fdc9afacb..18e9fad232f 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -86,6 +86,7 @@ EXCLUDE_USAGE = { 'bin/python/samba/subunit/run.py', 'python/samba/tests/dcerpc/raw_protocol.py', 'python/samba/tests/krb5/kcrypto.py', + 'python/samba/tests/krb5/simple_tests.py', } EXCLUDE_HELP = { -- 2.25.1 From 410f981c611ffdd3a0f661208736120a9d86723c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Feb 2020 16:29:38 +0100 Subject: [PATCH 022/645] s4:selftest: run samba.tests.krb5.simple_tests against ad_dc_default Signed-off-by: Stefan Metzmacher Reviewed-by: Isaac Boukris Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Fri Mar 27 19:54:25 UTC 2020 on sn-devel-184 (cherry picked from commit c4ccdf4b30de1b1e63d3fd99d33b924b816a5d37) --- source4/selftest/tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 9194c9b04f7..693209f2d1e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -743,6 +743,8 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.gpo", extra_args=['-U"$USERNA planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", + environ={'SERVICE_USERNAME':'$SERVER'}) for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From 6fe467d921213dbc3cd51dd0712197472beb06ea Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 7 May 2020 17:16:53 +0200 Subject: [PATCH 023/645] Revert "selftest: allow any kdc error in mitm-s4u2self test" This reverts commit a53fa8ffe3e36f7921baf5d31a1052747f90aa7d. This allows a clean revert (and so removal) of the test. Signed-off-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit ce65e8979dda9774b170db7a9fa7ba458af4cee9) --- source4/torture/krb5/kdc-canon-heimdal.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source4/torture/krb5/kdc-canon-heimdal.c b/source4/torture/krb5/kdc-canon-heimdal.c index 700e1c2b37e..8dc3e24a8d5 100644 --- a/source4/torture/krb5/kdc-canon-heimdal.c +++ b/source4/torture/krb5/kdc-canon-heimdal.c @@ -737,12 +737,13 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex error.pvno, 5, "Got wrong error.pvno"); expected_error = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE; - if (!test_context->test_data->mitm_s4u2self) { - torture_assert_int_equal(test_context->tctx, - error.error_code, - expected_error, - "Got wrong error.error_code"); + if (error.error_code != expected_error && test_context->test_data->mitm_s4u2self) { + expected_error = KRB5KRB_AP_ERR_INAPP_CKSUM - KRB5KDC_ERR_NONE; } + torture_assert_int_equal(test_context->tctx, + error.error_code, + expected_error, + "Got wrong error.error_code"); } else { torture_assert_int_equal(test_context->tctx, decode_TGS_REP(recv_buf->data, recv_buf->length, @@ -2089,7 +2090,8 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * || test_data->upn == false)) { if (test_data->mitm_s4u2self) { - torture_assert_int_not_equal(tctx, k5ret, 0, assertion_message); + torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_INAPP_CKSUM, + assertion_message); /* Done testing mitm-s4u2self */ return true; } -- 2.25.1 From 7620840700f6c4810821e821c645542da9279ace Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 7 May 2020 17:17:00 +0200 Subject: [PATCH 024/645] Revert "selftest: mitm-s4u2self: use zlib for CRC32_checksum calc" This reverts commit 151f8c0f31d3d17b9418db3793ec14ba7dbf2143. This allows a clean revert (and so removal) of the test. Signed-off-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit b5adc112771f22c2d7c4319063c3e89074c4f4ab) --- source4/torture/krb5/kdc-canon-heimdal.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/source4/torture/krb5/kdc-canon-heimdal.c b/source4/torture/krb5/kdc-canon-heimdal.c index 8dc3e24a8d5..dffebd74038 100644 --- a/source4/torture/krb5/kdc-canon-heimdal.c +++ b/source4/torture/krb5/kdc-canon-heimdal.c @@ -33,7 +33,6 @@ #include "auth/auth_sam_reply.h" #include "auth/gensec/gensec.h" #include "param/param.h" -#include "zlib.h" #define TEST_CANONICALIZE 0x0000001 #define TEST_ENTERPRISE 0x0000002 @@ -215,17 +214,6 @@ static bool test_accept_ticket(struct torture_context *tctx, return true; } -static void -zCRC32_checksum(const void *data, - size_t len, - Checksum *C) -{ - uint32_t *crc = C->checksum.data; - *crc = ~(crc32(0xffffffff, data, len)); - C->checksum.length = 4; - C->cksumtype = 1; -} - krb5_error_code _krb5_s4u2self_to_checksumdata(krb5_context context, const PA_S4U2Self *self, @@ -264,7 +252,11 @@ static bool change_for_user_principal(struct torture_krb5_context *test_context, torture_assert_int_equal(test_context->tctx, _krb5_s4u2self_to_checksumdata(k5_ctx, &mod_self, &cksum_data), 0, "_krb5_s4u2self_to_checksumdata() failed"); - zCRC32_checksum(cksum_data.data, cksum_data.length, &mod_self.cksum); + torture_assert_int_equal(test_context->tctx, + krb5_create_checksum(k5_ctx, NULL, KRB5_KU_OTHER_CKSUM, + CKSUMTYPE_CRC32, cksum_data.data, + cksum_data.length, &mod_self.cksum), + 0, "krb5_create_checksum() failed"); ASN1_MALLOC_ENCODE(PA_S4U2Self, for_user->padata_value.data, for_user->padata_value.length, &mod_self, &used, ret); @@ -278,6 +270,7 @@ static bool change_for_user_principal(struct torture_krb5_context *test_context, free_PA_S4U2Self(&self); krb5_data_free(&cksum_data); + free_Checksum(&mod_self.cksum); return true; } -- 2.25.1 From 22b18f728ca3e03b27c6324f0d4004a4afafddeb Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 7 May 2020 17:17:12 +0200 Subject: [PATCH 025/645] Revert "CVE-2018-16860 selftest: Add test for S4U2Self with unkeyed checksum" This reverts commit 5639e973c1f6f1b28b122741763f1d05b47bc2d8. This is no longer needed as the next commit includes a Python test for this, without the complexity of being inside krb5.kdc.canon. Signed-off-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 19875a37318a7cd5585572616cf12a775591193f) --- source4/torture/krb5/kdc-canon-heimdal.c | 105 +---------------------- 1 file changed, 4 insertions(+), 101 deletions(-) diff --git a/source4/torture/krb5/kdc-canon-heimdal.c b/source4/torture/krb5/kdc-canon-heimdal.c index dffebd74038..9e0808b134c 100644 --- a/source4/torture/krb5/kdc-canon-heimdal.c +++ b/source4/torture/krb5/kdc-canon-heimdal.c @@ -44,8 +44,7 @@ #define TEST_S4U2SELF 0x0000080 #define TEST_REMOVEDOLLAR 0x0000100 #define TEST_AS_REQ_SPN 0x0000200 -#define TEST_MITM_S4U2SELF 0x0000400 -#define TEST_ALL 0x00007FF +#define TEST_ALL 0x00003FF struct test_data { const char *test_name; @@ -63,7 +62,6 @@ struct test_data { bool upn; bool other_upn_suffix; bool s4u2self; - bool mitm_s4u2self; bool removedollar; bool as_req_spn; bool spn_is_upn; @@ -214,67 +212,6 @@ static bool test_accept_ticket(struct torture_context *tctx, return true; } -krb5_error_code -_krb5_s4u2self_to_checksumdata(krb5_context context, - const PA_S4U2Self *self, - krb5_data *data); - -/* Helper function to modify the principal in PA_FOR_USER padata */ -static bool change_for_user_principal(struct torture_krb5_context *test_context, - krb5_data *modified_send_buf) -{ - PA_DATA *for_user; - int i = 0; - size_t used; - krb5_error_code ret; - PA_S4U2Self self, mod_self; - krb5_data cksum_data; - krb5_principal admin; - heim_octet_string orig_padata_value; - krb5_context k5_ctx = test_context->smb_krb5_context->krb5_context; - - for_user = krb5_find_padata(test_context->tgs_req.padata->val, - test_context->tgs_req.padata->len, KRB5_PADATA_FOR_USER, &i); - torture_assert(test_context->tctx, for_user != NULL, "No PA_FOR_USER in s4u2self request"); - orig_padata_value = for_user->padata_value; - - torture_assert_int_equal(test_context->tctx, - krb5_make_principal(k5_ctx, &admin, test_context->test_data->realm, - "Administrator", NULL), - 0, "krb5_make_principal() failed"); - torture_assert_int_equal(test_context->tctx, - decode_PA_S4U2Self(for_user->padata_value.data, - for_user->padata_value.length, &self, NULL), - 0, "decode_PA_S4U2Self() failed"); - mod_self = self; - mod_self.name = admin->name; - - torture_assert_int_equal(test_context->tctx, - _krb5_s4u2self_to_checksumdata(k5_ctx, &mod_self, &cksum_data), - 0, "_krb5_s4u2self_to_checksumdata() failed"); - torture_assert_int_equal(test_context->tctx, - krb5_create_checksum(k5_ctx, NULL, KRB5_KU_OTHER_CKSUM, - CKSUMTYPE_CRC32, cksum_data.data, - cksum_data.length, &mod_self.cksum), - 0, "krb5_create_checksum() failed"); - - ASN1_MALLOC_ENCODE(PA_S4U2Self, for_user->padata_value.data, for_user->padata_value.length, - &mod_self, &used, ret); - torture_assert(test_context->tctx, ret == 0, "Failed to encode PA_S4U2Self ASN1 struct"); - ASN1_MALLOC_ENCODE(TGS_REQ, modified_send_buf->data, modified_send_buf->length, - &test_context->tgs_req, &used, ret); - torture_assert(test_context->tctx, ret == 0, "Failed to encode TGS_REQ ASN1 struct"); - - free(for_user->padata_value.data); - for_user->padata_value = orig_padata_value; - - free_PA_S4U2Self(&self); - krb5_data_free(&cksum_data); - free_Checksum(&mod_self.cksum); - - return true; -} - /* * TEST_AS_REQ and TEST_AS_REQ_SELF - SEND * @@ -694,12 +631,7 @@ static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context } - if (test_context->test_data->mitm_s4u2self) { - torture_assert(test_context->tctx, change_for_user_principal(test_context, modified_send_buf), - "Failed to modify PA_FOR_USER principal name"); - } else { - *modified_send_buf = *send_buf; - } + *modified_send_buf = *send_buf; return true; } @@ -718,7 +650,6 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex { KRB_ERROR error; size_t used; - krb5_error_code expected_error; /* * If this account did not have a servicePrincipalName, then @@ -729,13 +660,9 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); - expected_error = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE; - if (error.error_code != expected_error && test_context->test_data->mitm_s4u2self) { - expected_error = KRB5KRB_AP_ERR_INAPP_CKSUM - KRB5KDC_ERR_NONE; - } torture_assert_int_equal(test_context->tctx, error.error_code, - expected_error, + KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE, "Got wrong error.error_code"); } else { torture_assert_int_equal(test_context->tctx, @@ -778,8 +705,6 @@ static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_contex torture_assert_int_equal(test_context->tctx, *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000, 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO"); - torture_assert(test_context->tctx, test_context->test_data->mitm_s4u2self == false, - "KDC accepted PA_S4U2Self with unkeyed checksum!"); free_TGS_REP(&test_context->tgs_rep); } torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets"); @@ -2081,23 +2006,7 @@ static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void * && (test_data->enterprise || test_data->spn_is_upn || test_data->upn == false)) { - - if (test_data->mitm_s4u2self) { - torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_INAPP_CKSUM, - assertion_message); - /* Done testing mitm-s4u2self */ - return true; - } - torture_assert_int_equal(tctx, k5ret, 0, assertion_message); - - /* Check that the impersonate principal is not being canonicalized by the KDC. */ - if (test_data->s4u2self) { - torture_assert(tctx, krb5_principal_compare(k5_context, server_creds->client, - principal), - "TGS-REP cname does not match requested client principal"); - } - torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context, ccache, server_creds), 0, "krb5_cc_store_cred failed"); @@ -2571,7 +2480,7 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) (i & TEST_UPN) ? "upn" : ((i & TEST_AS_REQ_SPN) ? "spn" : ((i & TEST_REMOVEDOLLAR) ? "removedollar" : "samaccountname")), - (i & TEST_S4U2SELF) ? (i & TEST_MITM_S4U2SELF) ? "mitm-s4u2self" : "s4u2self" : "normal"); + (i & TEST_S4U2SELF) ? "s4u2self" : "normal"); struct torture_suite *sub_suite = torture_suite_create(mem_ctx, name); struct test_data *test_data = talloc_zero(suite, struct test_data); @@ -2585,11 +2494,6 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) continue; } } - if (i & TEST_MITM_S4U2SELF) { - if (!(i & TEST_S4U2SELF)) { - continue; - } - } test_data->test_name = name; test_data->real_realm @@ -2610,7 +2514,6 @@ struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx) test_data->win2k = (i & TEST_WIN2K) != 0; test_data->upn = (i & TEST_UPN) != 0; test_data->s4u2self = (i & TEST_S4U2SELF) != 0; - test_data->mitm_s4u2self = (i & TEST_MITM_S4U2SELF) != 0; test_data->removedollar = (i & TEST_REMOVEDOLLAR) != 0; test_data->as_req_spn = (i & TEST_AS_REQ_SPN) != 0; torture_suite_add_simple_tcase_const(sub_suite, name, torture_krb5_as_req_canon, -- 2.25.1 From 2e6b6ccb8e2b47e883c924738d05559622d4476f Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 4 May 2020 18:09:53 +0200 Subject: [PATCH 026/645] selftest: add python S4U2Self tests including unkeyed checksums To test the CRC32 I reverted the unkeyed-checksum fix (43958af1) and the weak-crypto fix (389d1b97). Note that the unkeyed-md5 still worked even with weak-crypto disabled, and that the unkeyed-sha1 never worked but I left it anyway. Signed-off-by: Isaac Boukris Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri May 15 12:25:40 UTC 2020 on sn-devel-184 (cherry picked from commit 8b5e7644130146bcc4e5a0dd05da6458a6025dd8) --- python/samba/tests/krb5/kcrypto.py | 85 ++++++++++ python/samba/tests/krb5/raw_testcase.py | 23 +++ python/samba/tests/krb5/rfc4120.asn1 | 8 + python/samba/tests/krb5/rfc4120_pyasn1.py | 14 +- python/samba/tests/krb5/s4u_tests.py | 197 ++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail | 2 + selftest/skip_mit_kdc | 1 + selftest/target/Samba4.pm | 23 +++ source4/selftest/tests.py | 4 + 10 files changed, 357 insertions(+), 1 deletion(-) create mode 100755 python/samba/tests/krb5/s4u_tests.py diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index ed3c84fa186..2572fa5bab3 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -51,6 +51,7 @@ os.environ["PYTHONUNBUFFERED"] = "1" from math import gcd from functools import reduce from struct import pack, unpack +from binascii import crc32 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac from cryptography.hazmat.primitives.ciphers import algorithms as ciphers @@ -533,6 +534,21 @@ class _MD5(_ChecksumProfile): return SIMPLE_HASH(text, hashes.MD5) +class _SHA1(_ChecksumProfile): + @classmethod + def checksum(cls, key, keyusage, text): + # This is unkeyed! + return SIMPLE_HASH(text, hashes.SHA1) + + +class _CRC32(_ChecksumProfile): + @classmethod + def checksum(cls, key, keyusage, text): + # This is unkeyed! + cksum = (~crc32(text, 0xffffffff)) & 0xffffffff + return pack('. +# + +import sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests import env_get_var_value +from samba.tests.krb5.kcrypto import Cksumtype +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + +global_asn1_print = False +global_hexdump = False + +class S4UKerberosTests(RawKerberosTest): + + def setUp(self): + super(S4UKerberosTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def _test_s4u2self(self, pa_s4u2self_ctype=None): + service_creds = self.get_service_creds() + service = service_creds.get_username() + realm = service_creds.get_realm() + + cname = self.PrincipalName_create(name_type=1, names=[service]) + sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + + till = self.get_KerberosTime(offset=36000) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = None + + etypes=(18,17,23) + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == 19: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(service_creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(2, pa_ts) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = [pa_ts] + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 11) + + usage = 3 + enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + + # S4U2Self Request + sname = cname + + for_user_name = env_get_var_value('FOR_USER') + uname = self.PrincipalName_create(name_type=1, names=[for_user_name]) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + till = self.get_KerberosTime(offset=36000) + ticket = rep['ticket'] + ticket_session_key = self.EncryptionKey_import(enc_part2['key']) + pa_s4u = self.PA_S4U2Self_create(name=uname, realm=realm, + tgt_session_key=ticket_session_key, + ctype=pa_s4u2self_ctype) + padata = [pa_s4u] + + subkey = self.RandomKey(ticket_session_key.etype) + subkey_usage = 9 + + (ctime, cusec) = self.get_KerberosTimeWithUsec() + + req = self.TGS_REQ_create(padata=padata, + cusec=cusec, + ctime=ctime, + ticket=ticket, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7ffffffe, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None, + ticket_session_key=ticket_session_key, + authenticator_subkey=subkey) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + if msg_type == 13: + enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + + return msg_type + + # Using the checksum type from the tgt_session_key happens to work everywhere + def test_s4u2self(self): + msg_type = self._test_s4u2self() + self.assertEqual(msg_type, 13) + + # Per spec, the checksum of PA-FOR-USER is HMAC_MD5, see [MS-SFU] 2.2.1 + def test_s4u2self_hmac_md5_checksum(self): + msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.HMAC_MD5) + self.assertEqual(msg_type, 13) + + def test_s4u2self_md5_unkeyed_checksum(self): + msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.MD5) + self.assertEqual(msg_type, 30) + + def test_s4u2self_sha1_unkeyed_checksum(self): + msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.SHA1) + self.assertEqual(msg_type, 30) + + def test_s4u2self_crc32_unkeyed_checksum(self): + msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.CRC32) + self.assertEqual(msg_type, 30) + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 18e9fad232f..58053474e03 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -87,6 +87,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/dcerpc/raw_protocol.py', 'python/samba/tests/krb5/kcrypto.py', 'python/samba/tests/krb5/simple_tests.py', + 'python/samba/tests/krb5/s4u_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail b/selftest/knownfail index f5466fccd8c..44ab3e59069 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -380,3 +380,5 @@ ^samba.tests.ntlmdisabled.python\(ktest\).python2.ntlmdisabled.NtlmDisabledTests.test_samr_change_password\(ktest\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python3.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python2.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) +# Fixed upstream heimdal in PR #439 +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_hmac_md5_checksum diff --git a/selftest/skip_mit_kdc b/selftest/skip_mit_kdc index 4a51c98ea0b..ea644638c9f 100644 --- a/selftest/skip_mit_kdc +++ b/selftest/skip_mit_kdc @@ -3,3 +3,4 @@ .*RODC ^samba4.ntvfs.cifs.ntlm.base.unlink ^samba4.ntvfs.cifs.krb5.base.unlink +^samba.tests.krb5.s4u_tests diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 860cc06d99b..927638cb7c4 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -895,6 +895,29 @@ sub provision_raw_step2($$$) return undef; } + my $srv_account = "srv_account"; + $samba_tool_cmd = ""; + $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; + $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; + $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") + . " user create --configfile=$ctx->{smb_conf} $srv_account $ctx->{password}"; + unless (system($samba_tool_cmd) == 0) { + warn("Unable to add $srv_account user: \n$samba_tool_cmd\n"); + return undef; + } + + $samba_tool_cmd = ""; + $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; + $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; + $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") + . " spn add HOST/$srv_account --configfile=$ctx->{smb_conf} $srv_account"; + unless (system($samba_tool_cmd) == 0) { + warn("Unable to add spn for $srv_account: \n$samba_tool_cmd\n"); + return undef; + } + my $ldbmodify = ""; $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 693209f2d1e..59b447de40a 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -745,6 +745,10 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$U planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", environ={'SERVICE_USERNAME':'$SERVER'}) +planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", + environ={'SERVICE_USERNAME':'srv_account', + 'SERVICE_PASSWORD':'$PASSWORD', + 'FOR_USER':'$USERNAME'}) for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From efdad55260a4a5c68ca646a2f101d36013cc3f60 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 19 Jan 2020 16:24:24 +0100 Subject: [PATCH 027/645] selftest: add test for disallowed-forwardable server BUG: https://bugzilla.samba.org/show_bug.cgi?id=14233 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit 197f97bc13c513ae6ae2b4129b23489081f63c64) --- selftest/knownfail.d/disallowed_forwardable_server | 1 + testprogs/blackbox/test_s4u_heimdal.sh | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 selftest/knownfail.d/disallowed_forwardable_server diff --git a/selftest/knownfail.d/disallowed_forwardable_server b/selftest/knownfail.d/disallowed_forwardable_server new file mode 100644 index 00000000000..2e05909ab89 --- /dev/null +++ b/selftest/knownfail.d/disallowed_forwardable_server @@ -0,0 +1 @@ +^samba4.blackbox.krb5.s4u.test S4U2Proxy using received ticket diff --git a/testprogs/blackbox/test_s4u_heimdal.sh b/testprogs/blackbox/test_s4u_heimdal.sh index 0e12c7ec096..c6ada54e85b 100755 --- a/testprogs/blackbox/test_s4u_heimdal.sh +++ b/testprogs/blackbox/test_s4u_heimdal.sh @@ -54,7 +54,7 @@ testit "set not-delegated flag" $samba_tool user sensitive $princ on || failed=` echo $PASSWORD > $PREFIX/tmppassfile -testit "kinit with password" $samba4kinit -f --password-file=$PREFIX/tmppassfile $impersonator || failed=`expr $failed + 1` +testit "kinit impersonator" $samba4kinit -f --password-file=$PREFIX/tmppassfile $impersonator || failed=`expr $failed + 1` testit "test S4U2Self with normal user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=${USERNAME} $impersonator || failed=`expr $failed + 1` testit "test S4U2Proxy with normal user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` @@ -68,6 +68,15 @@ testit "unset not-delegated flag" $samba_tool user sensitive $princ off || faile testit "test S4U2Self after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` testit "test S4U2Proxy after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` +testit "kinit user cache" $samba4kinit -c $ocache -f --password-file=$PREFIX/tmppassfile $USERNAME || failed=`expr $failed + 1` +testit "get a ticket to impersonator" $samba4kgetcred -c $ocache --forwardable $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy evidence ticket obtained by TGS" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` -rm -f $ocache $PREFIX/tmpccache tmppassfile +testit "set not-delegated on impersonator" $samba_tool user sensitive $impersonator on || failed=`expr $failed + 1` +testit "kinit user cache again" $samba4kinit -c $ocache -f --password-file=$PREFIX/tmppassfile $USERNAME || failed=`expr $failed + 1` +testit "get a ticket to sensitive impersonator" $samba4kgetcred -c $ocache --forwardable $impersonator || failed=`expr $failed + 1` +testit_expect_failure "test S4U2Proxy using received ticket" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + + +rm -f $ocache $PREFIX/tmpccache $PREFIX/tmppassfile exit $failed -- 2.25.1 From 30cacb3e63225077f94578d52f1228a7d690ed7d Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 13 Jan 2020 23:42:54 +0100 Subject: [PATCH 028/645] heimdal: apply disallow-forwardable on server in TGS request upstream commit: 839b073facd2aecda6740224d73e560bc79965dc BUG: https://bugzilla.samba.org/show_bug.cgi?id=14233 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit 8fdff19c5461315556014d25d237a958edeed1a2) --- selftest/knownfail.d/disallowed_forwardable_server | 1 - source4/heimdal/kdc/krb5tgs.c | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/disallowed_forwardable_server diff --git a/selftest/knownfail.d/disallowed_forwardable_server b/selftest/knownfail.d/disallowed_forwardable_server deleted file mode 100644 index 2e05909ab89..00000000000 --- a/selftest/knownfail.d/disallowed_forwardable_server +++ /dev/null @@ -1 +0,0 @@ -^samba4.blackbox.krb5.s4u.test S4U2Proxy using received ticket diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ee3ac3d8f53..efbdd6ed77f 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -866,6 +866,12 @@ tgs_make_reply(krb5_context context, et.flags.anonymous = tgt->flags.anonymous; et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate; + /* See MS-KILE 3.3.5.1 */ + if (!server->entry.flags.forwardable) + et.flags.forwardable = 0; + if (!server->entry.flags.proxiable) + et.flags.proxiable = 0; + if(rspac->length) { /* * No not need to filter out the any PAC from the -- 2.25.1 From 29ea1a6f61f89680a881f2ab324231872c171477 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Thu, 7 May 2020 01:25:36 +0200 Subject: [PATCH 029/645] selftest: allow EncASRepPart to be encoded as EncTGSRepPart that's how MIT kdc encodes it, clients accept both. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14233 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit a823cc1e8bc9a68a7e662022705039397a5df7e1) --- python/samba/tests/krb5/simple_tests.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index c9998c4d2db..236fbda1cd5 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -115,7 +115,12 @@ class SimpleKerberosTests(RawKerberosTest): usage = 3 enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 + try: + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + except Exception: + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # TGS Request service_creds = self.get_service_creds(allow_missing_password=True) -- 2.25.1 From f879fcbe345da12b1aa610fbd34f9036f53873fb Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 6 May 2020 15:54:55 +0200 Subject: [PATCH 030/645] selftest: test forwardable flag in cross-realm tgt tickets BUG: https://bugzilla.samba.org/show_bug.cgi?id=14233 Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett (cherry picked from commit 9b302a57ff0d4c3a373f762f2ad4daf736b0853b) --- python/samba/tests/krb5/xrealm_tests.py | 180 ++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail.d/xrealm | 1 + source4/selftest/tests.py | 2 + 4 files changed, 184 insertions(+) create mode 100755 python/samba/tests/krb5/xrealm_tests.py create mode 100644 selftest/knownfail.d/xrealm diff --git a/python/samba/tests/krb5/xrealm_tests.py b/python/samba/tests/krb5/xrealm_tests.py new file mode 100755 index 00000000000..64064b8a670 --- /dev/null +++ b/python/samba/tests/krb5/xrealm_tests.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +import samba.tests + +global_asn1_print = False +global_hexdump = False + +class XrealmKerberosTests(RawKerberosTest): + + def setUp(self): + super(XrealmKerberosTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def test_xrealm(self): + user_creds = self.get_user_creds() + user = user_creds.get_username() + realm = user_creds.get_realm() + + cname = self.PrincipalName_create(name_type=1, names=[user]) + sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + + till = self.get_KerberosTime(offset=36000) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = None + + etypes=(18,17,23) + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == 19: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(2, pa_ts) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = [pa_ts] + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 11) + + usage = 3 + enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 + try: + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + except Exception: + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + + # TGS Request (for cross-realm TGT) + trust_realm = samba.tests.env_get_var_value('TRUST_REALM') + sname = self.PrincipalName_create(name_type=2, names=["krbtgt", trust_realm]) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + till = self.get_KerberosTime(offset=36000) + ticket = rep['ticket'] + ticket_session_key = self.EncryptionKey_import(enc_part2['key']) + padata = [] + + subkey = self.RandomKey(ticket_session_key.etype) + subkey_usage = 9 + + (ctime, cusec) = self.get_KerberosTimeWithUsec() + + req = self.TGS_REQ_create(padata=padata, + cusec=cusec, + ctime=ctime, + ticket=ticket, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7ffffffe, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None, + ticket_session_key=ticket_session_key, + authenticator_subkey=subkey) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 13) + + enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + + # Check the forwardable flag + fwd_pos = len(tuple(krb5_asn1.TicketFlags('forwardable'))) -1 + assert(krb5_asn1.TicketFlags(enc_part2['flags'])[fwd_pos]) + + return + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 58053474e03..89b5e957407 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -88,6 +88,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/kcrypto.py', 'python/samba/tests/krb5/simple_tests.py', 'python/samba/tests/krb5/s4u_tests.py', + 'python/samba/tests/krb5/xrealm_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail.d/xrealm b/selftest/knownfail.d/xrealm new file mode 100644 index 00000000000..2e09644b1d8 --- /dev/null +++ b/selftest/knownfail.d/xrealm @@ -0,0 +1 @@ +^samba.tests.krb5.xrealm_tests.samba.tests.krb5.xrealm_tests.XrealmKerberosTests.test_xrealm diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 59b447de40a..52a61a2cced 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -750,6 +750,8 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", 'SERVICE_PASSWORD':'$PASSWORD', 'FOR_USER':'$USERNAME'}) +planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") + for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite(env + ":local", "samba.tests.ntacls_backup", -- 2.25.1 From a4ffa145736a9a4ba6ad020d27dbbb7fbf32ceac Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sat, 9 May 2020 16:26:45 +0200 Subject: [PATCH 031/645] selftest: test forwardable flag in cross-realm with s4u2proxy Signed-off-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit fb7dfdbe8f94f7f053d67832e7f28a751136d733) --- selftest/knownfail.d/s4u2p_fwd | 2 ++ source4/selftest/tests.py | 2 +- testprogs/blackbox/test_s4u_heimdal.sh | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 selftest/knownfail.d/s4u2p_fwd diff --git a/selftest/knownfail.d/s4u2p_fwd b/selftest/knownfail.d/s4u2p_fwd new file mode 100644 index 00000000000..63ade3eece0 --- /dev/null +++ b/selftest/knownfail.d/s4u2p_fwd @@ -0,0 +1,2 @@ +^samba4.blackbox.krb5.s4u.get a ticket to impersonator for trust user +^samba4.blackbox.krb5.s4u.test S4U2Proxy evidence ticket obtained by TGS of trust user diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 52a61a2cced..b10ac26e964 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -482,7 +482,7 @@ if have_heimdal_support: plantestsuite("samba4.blackbox.kinit_trust", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external", "arcfour-hmac-md5"]) plantestsuite("samba4.blackbox.export.keytab", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4]) plantestsuite("samba4.blackbox.kpasswd", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"]) - plantestsuite("samba4.blackbox.krb5.s4u", "fl2008r2dc:local", [os.path.join(bbdir, "test_s4u_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', configuration]) + plantestsuite("samba4.blackbox.krb5.s4u", "fl2008r2dc:local", [os.path.join(bbdir, "test_s4u_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', configuration]) else: plantestsuite("samba4.blackbox.kinit", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) plantestsuite("samba4.blackbox.kinit", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) diff --git a/testprogs/blackbox/test_s4u_heimdal.sh b/testprogs/blackbox/test_s4u_heimdal.sh index c6ada54e85b..c63eeaa2e30 100755 --- a/testprogs/blackbox/test_s4u_heimdal.sh +++ b/testprogs/blackbox/test_s4u_heimdal.sh @@ -12,8 +12,13 @@ USERNAME=$2 PASSWORD=$3 REALM=$4 DOMAIN=$5 -PREFIX=$6 -shift 6 +TRUST_SERVER=$6 +TRUST_USERNAME=$7 +TRUST_PASSWORD=$8 +TRUST_REALM=$9 +TRUST_DOMAIN=${10} +PREFIX=${11} +shift 11 failed=0 @@ -39,7 +44,7 @@ export KRB5CCNAME rm -rf $KRB5CCNAME_PATH princ=test_impersonate_princ -impersonator=test_impersonator +impersonator=test_impersonator.$REALM target="CIFS/$SERVER.$REALM" @@ -72,6 +77,12 @@ testit "kinit user cache" $samba4kinit -c $ocache -f --password-file=$PREFIX/tmp testit "get a ticket to impersonator" $samba4kgetcred -c $ocache --forwardable $impersonator || failed=`expr $failed + 1` testit "test S4U2Proxy evidence ticket obtained by TGS" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` +echo $TRUST_PASSWORD > $PREFIX/tmppassfile +testit "kinit trust user cache" $samba4kinit -c $ocache -f --password-file=$PREFIX/tmppassfile $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` +testit "get a ticket to impersonator for trust user" $samba4kgetcred -c $ocache --forwardable $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy evidence ticket obtained by TGS of trust user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +echo $PASSWORD > $PREFIX/tmppassfile testit "set not-delegated on impersonator" $samba_tool user sensitive $impersonator on || failed=`expr $failed + 1` testit "kinit user cache again" $samba4kinit -c $ocache -f --password-file=$PREFIX/tmppassfile $USERNAME || failed=`expr $failed + 1` testit "get a ticket to sensitive impersonator" $samba4kgetcred -c $ocache --forwardable $impersonator || failed=`expr $failed + 1` -- 2.25.1 From cf78e03fc45ea1e8396751875e26b87926e9b9e9 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Tue, 14 Jan 2020 13:16:02 +0100 Subject: [PATCH 032/645] db-glue.c: set forwardable flag on cross-realm tgt tickets BUG: https://bugzilla.samba.org/show_bug.cgi?id=14233 Match Windows behavior and allow the forwardable flag to be set in cross-realm tickets. We used to allow forwardable to any server, but now that we apply disallow-forwardable policy in heimdal we need to explicitly allow in the corss-realm case (and remove the workaround we have for it the MIT plugin). Signed-off-by: Isaac Boukris Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri Jun 12 22:10:34 UTC 2020 on sn-devel-184 (cherry picked from commit 7655a0298e5f55582bf48ec776d8cd8b79fb5dd9) --- selftest/knownfail.d/s4u2p_fwd | 2 -- selftest/knownfail.d/xrealm | 1 - source4/kdc/db-glue.c | 3 +++ source4/kdc/mit_samba.c | 5 ----- 4 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 selftest/knownfail.d/s4u2p_fwd delete mode 100644 selftest/knownfail.d/xrealm diff --git a/selftest/knownfail.d/s4u2p_fwd b/selftest/knownfail.d/s4u2p_fwd deleted file mode 100644 index 63ade3eece0..00000000000 --- a/selftest/knownfail.d/s4u2p_fwd +++ /dev/null @@ -1,2 +0,0 @@ -^samba4.blackbox.krb5.s4u.get a ticket to impersonator for trust user -^samba4.blackbox.krb5.s4u.test S4U2Proxy evidence ticket obtained by TGS of trust user diff --git a/selftest/knownfail.d/xrealm b/selftest/knownfail.d/xrealm deleted file mode 100644 index 2e09644b1d8..00000000000 --- a/selftest/knownfail.d/xrealm +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.krb5.xrealm_tests.samba.tests.krb5.xrealm_tests.XrealmKerberosTests.test_xrealm diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index d2a79920ab5..5fd0f431cdf 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -1562,6 +1562,9 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, entry_ex->entry.max_renew = NULL; + /* Match Windows behavior and allow forwardable flag in cross-realm. */ + entry_ex->entry.flags.forwardable = 1; + ret = samba_kdc_sort_encryption_keys(entry_ex); if (ret != 0) { krb5_clear_error_message(context); diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 5a4f6e73e97..54dcd545ea1 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -304,11 +304,6 @@ fetch_referral_principal: sdb_free_entry(&sentry); - if ((kflags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) == 0) { - kentry->attributes &= ~KRB5_KDB_DISALLOW_FORWARDABLE; - kentry->attributes &= ~KRB5_KDB_DISALLOW_PROXIABLE; - } - done: krb5_free_principal(ctx->context, referral_principal); referral_principal = NULL; -- 2.25.1 From fe2411ad9a1bc5bb734f4c2500d85ff4f326e202 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 3 Nov 2020 09:25:48 +1300 Subject: [PATCH 033/645] selftest: add mit kdc specific known fail Add a MIT kerberos specific known fail, will be needed by subsequent commits. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 04248f5e868d38498bdc8f9705c9a60fcfe79c09) --- selftest/knownfail_mit_kdc | 0 selftest/wscript | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 selftest/knownfail_mit_kdc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/selftest/wscript b/selftest/wscript index 501a5df5824..95086b4f0ed 100644 --- a/selftest/wscript +++ b/selftest/wscript @@ -263,6 +263,8 @@ def cmd_testonly(opt): if CONFIG_GET(opt, 'USING_SYSTEM_KRB5') and CONFIG_GET(opt, 'MIT_KDC_PATH'): env.OPTIONS += " --mitkrb5 --exclude=${srcdir}/selftest/skip_mit_kdc" + env.FILTER_XFAIL += " --expected-failures=${srcdir}/selftest/"\ + "knownfail_mit_kdc" if not CONFIG_GET(opt, 'HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X'): # older MIT krb5 libraries (< 1.14) don't have -- 2.25.1 From 415e1ee1929aaef1ebe62ee4d55e2a62cece5795 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 27 Oct 2020 09:29:56 +1300 Subject: [PATCH 034/645] tests python krb5: Make PrincipalName_create a class method Make PrincipalName_create a class method, so it can be used in helper classes. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b14dca7c1c063e069517ff01b33c63a000d398c3) --- python/samba/tests/krb5/raw_testcase.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f43ce9cbc3c..45e46e0b7ba 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -470,6 +470,7 @@ class RawKerberosTest(TestCase): } return Checksum_obj + @classmethod def PrincipalName_create(self, name_type, names): # PrincipalName ::= SEQUENCE { # name-type [0] Int32, -- 2.25.1 From 7d4dd909317f1c8377771eed129ed95f58f661a5 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 27 Oct 2020 09:31:24 +1300 Subject: [PATCH 035/645] tests python krb5: Add canonicalize flag to ASN1 Add the canonicalize flag to KerberosFlags, so that it can be used in python based canonicalization tests. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 41c8aa4b991aad306d731b08d068c480eb5c7fed) --- python/samba/tests/krb5/rfc4120.asn1 | 8 ++++---- python/samba/tests/krb5/rfc4120_pyasn1.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index 98ba887729d..58e0c1636a1 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -196,8 +196,8 @@ KDCOptions ::= KerberosFlags -- opt-hardware-auth(11), -- unused12(12), -- unused13(13), --- 15 is reserved for canonicalize - -- unused15(15), +-- Canonicalize is used in RFC 6806 + -- canonicalize(15), -- 26 was unused in 1510 -- disable-transited-check(26), -- @@ -489,8 +489,8 @@ KDCOptionsValues ::= BIT STRING { -- KerberosFlags opt-hardware-auth(11), unused12(12), unused13(13), --- 15 is reserved for canonicalize - unused15(15), +-- Canonicalize is used by RFC 6806 + canonicalize(15), -- 26 was unused in 1510 disable-transited-check(26), -- diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index 05304a8a099..b4ea678afd8 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/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 2020-05-06 17:51:00.323318) +# (last modified on 2020-11-03 14:07:15.270009) # KerberosV5Spec2 from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful @@ -610,7 +610,7 @@ KDCOptionsValues.namedValues = namedval.NamedValues( ('opt-hardware-auth', 11), ('unused12', 12), ('unused13', 13), - ('unused15', 15), + ('canonicalize', 15), ('disable-transited-check', 26), ('renewable-ok', 27), ('enc-tkt-in-skey', 28), -- 2.25.1 From 0e4a44f7e46d4f19d5362411c1c433a56106a77b Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 27 Oct 2020 09:32:21 +1300 Subject: [PATCH 036/645] tests python krb5: Add python kerberos canonicalization tests Add python canonicalization tests, loosely based on the code in source4/torture/krb5/kdc-canon-heimdal.c. The long term goal is to move the integration level tests out of kdc-canon-heimdal, leaving it as a heimdal library unit test. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 005435dc4d7de9d442c7513edec8c782fe20fda3) --- .../tests/krb5/as_canonicalization_tests.py | 499 ++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_mit_kdc | 144 +++++ source4/selftest/tests.py | 1 + 4 files changed, 645 insertions(+) create mode 100755 python/samba/tests/krb5/as_canonicalization_tests.py diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py new file mode 100755 index 00000000000..7b599ad6e44 --- /dev/null +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -0,0 +1,499 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# +# Copyright (C) Catalyst IT Ltd. 2020 +# +# 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 sys +import os +from enum import Enum, unique +import pyasn1 + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +import samba +from samba.auth import system_session +from samba.credentials import ( + Credentials, + CLI_CRED_NTLMv2_AUTH, + CLI_CRED_NTLM_AUTH, + DONT_USE_KERBEROS) +from samba.dcerpc.misc import SEC_CHAN_WKSTA +from samba.dsdb import ( + UF_WORKSTATION_TRUST_ACCOUNT, + UF_PASSWD_NOTREQD, + UF_NORMAL_ACCOUNT) +from samba.samdb import SamDB +from samba.tests import delete_force, DynamicTestCase + +global_asn1_print = False +global_hexdump = False + + +@unique +class TestOptions(Enum): + Canonicalize = 1 + Enterprise = 2 + UpperRealm = 4 + UpperUserName = 8 + NetbiosRealm = 16 + UPN = 32 + RemoveDollar = 64 + Last = 128 + + def is_set(self, x): + return self.value & x + + +@unique +class CredentialsType(Enum): + User = 1 + Machine = 2 + + def is_set(self, x): + return self.value & x + + +class TestData: + + def __init__(self, options, creds): + self.options = options + self.user_creds = creds + self.user_name = self.get_username(options, creds) + self.realm = self.get_realm(options, creds) + self.cname = RawKerberosTest.PrincipalName_create( + name_type=1, names=[self.user_name]) + self.sname = RawKerberosTest.PrincipalName_create( + name_type=2, names=["krbtgt", self.realm]) + self.canonicalize = TestOptions.Canonicalize.is_set(options) + + def get_realm(self, options, creds): + realm = creds.get_realm() + if TestOptions.NetbiosRealm.is_set(options): + realm = creds.get_domain() + if TestOptions.UpperRealm.is_set(options): + realm = realm.upper() + else: + realm = realm.lower() + return realm + + def get_username(self, options, creds): + name = creds.get_username() + if TestOptions.RemoveDollar.is_set(options) and name.endswith("$"): + name = name[:-1] + if TestOptions.Enterprise.is_set(options): + realm = creds.get_realm() + name = "{0}@{1}".format(name, realm) + if TestOptions.UpperUserName.is_set(options): + name = name.upper() + return name + + def __repr__(self): + rep = "Test Data: " + rep += "options = '" + "{:08b}".format(self.options) + "'" + rep += "user name = '" + self.user_name + "'" + rep += ", realm = '" + self.realm + "'" + rep += ", cname = '" + str(self.cname) + "'" + rep += ", sname = '" + str(self.sname) + "'" + return rep + + +MACHINE_NAME = "tstkrb5cnnusr" +USER_NAME = "tstkrb5cnnmch" + +# Encryption types +AES256_CTS_HMAC_SHA1_96 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES256-CTS-HMAC-SHA1-96')) +AES128_CTS_HMAC_SHA1_96 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES128-CTS-HMAC-SHA1-96')) +ARCFOUR_HMAC_MD5 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-ARCFOUR-HMAC-MD5')) + +# Message types +KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) +KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) + +# PAData types +PADATA_ENC_TIMESTAMP = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ENC-TIMESTAMP')) +PADATA_ETYPE_INFO2 = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) + +# Error codes +KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 +KDC_ERR_PREAUTH_REQUIRED = 25 + +# Name types +NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) +NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) +NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) + + +@DynamicTestCase +class KerberosASCanonicalizationTests(RawKerberosTest): + + @classmethod + def setUpDynamicTestCases(cls): + + def skip(ct, options): + ''' Filter out any mutually exclusive test options ''' + if ct != CredentialsType.Machine and\ + TestOptions.RemoveDollar.is_set(options): + return True + return False + + def build_test_name(ct, options): + name = "%sCredentials" % ct.name + for opt in TestOptions: + if opt.is_set(options): + name += ("_%s" % opt.name) + return name + + for ct in CredentialsType: + for x in range(TestOptions.Last.value): + if skip(ct, x): + continue + name = build_test_name(ct, x) + cls.generate_dynamic_test("test", name, x, ct) + + @classmethod + def setUpClass(cls): + cls.lp = cls.get_loadparm(cls) + cls.username = os.environ["USERNAME"] + cls.password = os.environ["PASSWORD"] + cls.domain = os.environ["DOMAIN"] + cls.realm = os.environ["REALM"] + cls.host = os.environ["SERVER"] + + c = Credentials() + c.set_username(cls.username) + c.set_password(cls.password) + c.set_domain(cls.domain) + c.set_realm(cls.realm) + cls.credentials = c + + cls.session = system_session() + cls.ldb = SamDB(url="ldap://%s" % cls.host, + session_info=cls.session, + credentials=cls.credentials, + lp=cls.lp) + cls.create_machine_account() + cls.create_user_account() + + @classmethod + def tearDownClass(cls): + super(KerberosASCanonicalizationTests, cls).tearDownClass() + delete_force(cls.ldb, cls.machine_dn) + delete_force(cls.ldb, cls.user_dn) + + def setUp(self): + super(KerberosASCanonicalizationTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + # + # Create a test user account + @classmethod + def create_user_account(cls): + cls.user_pass = samba.generate_random_password(32, 32) + cls.user_name = USER_NAME + cls.user_dn = "cn=%s,%s" % (cls.user_name, cls.ldb.domain_dn()) + + # remove the account if it exists, this will happen if a previous test + # run failed + delete_force(cls.ldb, cls.user_dn) + + utf16pw = ('"%s"' % cls.user_pass).encode('utf-16-le') + cls.ldb.add({ + "dn": cls.user_dn, + "objectclass": "user", + "sAMAccountName": "%s" % cls.user_name, + "userAccountControl": str(UF_NORMAL_ACCOUNT), + "unicodePwd": utf16pw}) + + cls.user_creds = Credentials() + cls.user_creds.guess(cls.lp) + cls.user_creds.set_password(cls.user_pass) + cls.user_creds.set_username(cls.user_name) + cls.user_creds.set_workstation(cls.machine_name) + + # + # Create the machine account + @classmethod + def create_machine_account(cls): + cls.machine_pass = samba.generate_random_password(32, 32) + cls.machine_name = MACHINE_NAME + cls.machine_dn = "cn=%s,%s" % (cls.machine_name, cls.ldb.domain_dn()) + + # remove the account if it exists, this will happen if a previous test + # run failed + delete_force(cls.ldb, cls.machine_dn) + + utf16pw = ('"%s"' % cls.machine_pass).encode('utf-16-le') + cls.ldb.add({ + "dn": cls.machine_dn, + "objectclass": "computer", + "sAMAccountName": "%s$" % cls.machine_name, + "userAccountControl": + str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), + "unicodePwd": utf16pw}) + + cls.machine_creds = Credentials() + cls.machine_creds.guess(cls.lp) + cls.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) + cls.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) + cls.machine_creds.set_password(cls.machine_pass) + cls.machine_creds.set_username(cls.machine_name + "$") + cls.machine_creds.set_workstation(cls.machine_name) + + def _test_with_args(self, x, ct): + if ct == CredentialsType.User: + creds = self.user_creds + elif ct == CredentialsType.Machine: + creds = self.machine_creds + else: + raise Exception("Unexpected credential type") + data = TestData(x, creds) + + try: + (rep, as_rep) = self.as_req(data) + except pyasn1.error.PyAsn1Error as e: + import traceback + self.fail("ASN1 Error, Options {0:08b}:{1} {2}".format( + traceback.format_exc(), + data.options, + e)) + # If as_req triggered an expected server error response + # No need to test the response data. + if rep is not None: + # The kvno is optional, heimdal includes it + # MIT does not. + if 'kvno' in rep['enc-part']: + kvno = rep['enc-part']['kvno'] + self.check_kvno(kvno, data) + + cname = rep['cname'] + self.check_cname(cname, data) + + crealm = rep['crealm'].decode('ascii') + self.check_crealm(crealm, data) + + sname = as_rep['sname'] + self.check_sname(sname, data) + + srealm = as_rep['srealm'].decode('ascii') + self.check_srealm(srealm, data) + + def as_req(self, data): + user_creds = data.user_creds + realm = data.realm + + cname = data.cname + sname = data.sname + + till = self.get_KerberosTime(offset=36000) + + kdc_options = "0" + if data.canonicalize: + kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) + + padata = None + + # Set the allowable encryption types + etypes = ( + AES256_CTS_HMAC_SHA1_96, + AES128_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5) + + req = self.AS_REQ_create(padata=padata, + kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + # + # Check the protocol version, should be 5 + self.assertEqual( + rep['pvno'], 5, "Data {0}".format(str(data))) + + self.assertEqual( + rep['msg-type'], KRB_ERROR, "Data {0}".format(str(data))) + + # We should get KDC_ERR_PREAUTH_REQUIRED + # unless the RemoveDollar and Enterprise options are set + # then we should get a KDC_ERR_C_PRINCIPAL_UNKNOWN + if TestOptions.RemoveDollar.is_set(data.options) and\ + TestOptions.Enterprise.is_set(data.options): + self.assertEqual( + rep['error-code'], + KDC_ERR_C_PRINCIPAL_UNKNOWN, + "Error code {0}, Data {1}".format(rep['error-code'], str(data))) + return (None, None) + + self.assertEqual( + rep['error-code'], + KDC_ERR_PREAUTH_REQUIRED, + "Error code {0}, Data {1}".format(rep['error-code'], str(data))) + + rep_padata = self.der_decode( + rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == 19: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode( + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) + + kdc_options = "0" + if data.canonicalize: + kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) + padata = [pa_ts] + + req = self.AS_REQ_create(padata=padata, + kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + # + # Check the protocol version, should be 5 + self.assertEqual( + rep['pvno'], 5, "Data {0}".format(str(data))) + + msg_type = rep['msg-type'] + # Should not have got an error. + # If we did, fail and print the error code to help debugging + self.assertNotEqual( + msg_type, + KRB_ERROR, + "Error code {0}, Data {1}".format( + rep.get('error-code', ''), + str(data))) + + self.assertEqual(msg_type, KRB_AS_REP, "Data {0}".format(str(data))) + + # Decrypt and decode the EncKdcRepPart + enc = key.decrypt(3, rep['enc-part']['cipher']) + if enc[0] == 0x7A: + # MIT Kerberos Tags the EncASRepPart as a EncKDCRepPart + # i.e. tag number 26 instead of tag number 25 + as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncTGSRepPart()) + else: + as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncASRepPart()) + + return (rep, as_rep) + + def check_cname(self, cname, data): + nt = cname['name-type'] + self.assertEqual( + NT_PRINCIPAL, + nt, + "cname name-type, Options {0:08b}".format(data.options)) + + ns = cname['name-string'] + name = ns[0].decode('ascii') + + expected = data.user_name + if TestOptions.Canonicalize.is_set(data.options): + expected = data.user_creds.get_username() + self.assertEqual( + expected, + name, + "cname principal, Options {0:08b}".format(data.options)) + + def check_crealm(self, crealm, data): + realm = data.user_creds.get_realm() + self.assertEqual( + realm, crealm, "crealm, Options {0:08b}".format(data.options)) + + def check_sname(self, sname, data): + nt = sname['name-type'] + self.assertEqual( + NT_SRV_INST, + nt, + "sname name-type, Options {0:08b}".format(data.options)) + + ns = sname['name-string'] + name = ns[0].decode('ascii') + self.assertEqual( + 'krbtgt', + name, + "sname principal, Options {0:08b}".format(data.options)) + + realm = ns[1].decode('ascii') + expected = data.realm + if TestOptions.Canonicalize.is_set(data.options): + expected = data.user_creds.get_realm().upper() + self.assertEqual( + expected, + realm, + "sname realm, Options {0:08b}".format(data.options)) + + def check_srealm(self, srealm, data): + realm = data.user_creds.get_realm() + self.assertEqual( + realm, srealm, "srealm, Options {0:08b}".format(data.options)) + + def check_kvno(self, kvno, data): + self.assertEqual( + 1, kvno, "kvno, Options {0:08b}".format(data.options)) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 89b5e957407..2f813760814 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -89,6 +89,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/simple_tests.py', 'python/samba/tests/krb5/s4u_tests.py', 'python/samba/tests/krb5/xrealm_tests.py', + 'python/samba/tests/krb5/as_canonicalization_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index e69de29bb2d..96d3e51da5c 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -0,0 +1,144 @@ +# +# Currently MOST but not quite all the Canonicalization tests fail on the +# MIT KDC +# +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_RemoveDollar\( +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_NetbiosRealm\( +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_UPN\( +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_UPN\( +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_UPN\( +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_UPN\( +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_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\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_Enterprise_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Canonicalize_UpperUserName_UPN\( +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_UserCredentials_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperRealm_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperRealm_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperRealm_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName_NetbiosRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName_NetbiosRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName_UPN\( diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index b10ac26e964..78b1a8494f3 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1284,6 +1284,7 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: '--option=torture:expect_machine_account=true'] + extra_options, "samba4.krb5.kdc with machine account") +planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests") for env in [ 'vampire_dc', -- 2.25.1 From 7189760a7c4bd64e8d360b2e569bd69ad2f92327 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 11:09:13 +1300 Subject: [PATCH 037/645] selftest: Send enterprise principals tagged as such This test passed against Samba but failed against Windows when an enterprise principal (user@domain.com@REALM) was encoded as NT_PRINCIPAL. Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d7f731ed3577b407370d8fe7a62b4c3ee2dd9c75) --- .../tests/krb5/as_canonicalization_tests.py | 24 ++++++-- selftest/knownfail.d/kdc-enterprise | 57 +++++++++++++++++++ selftest/knownfail_mit_kdc | 8 +++ 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 selftest/knownfail.d/kdc-enterprise diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 7b599ad6e44..3f8ed5c5a11 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -77,10 +77,16 @@ class TestData: self.user_creds = creds self.user_name = self.get_username(options, creds) self.realm = self.get_realm(options, creds) + + if TestOptions.Enterprise.is_set(options): + client_name_type = NT_ENTERPRISE_PRINCIPAL + else: + client_name_type = NT_PRINCIPAL + self.cname = RawKerberosTest.PrincipalName_create( - name_type=1, names=[self.user_name]) + name_type=client_name_type, names=[self.user_name]) self.sname = RawKerberosTest.PrincipalName_create( - name_type=2, names=["krbtgt", self.realm]) + name_type=NT_SRV_INST, names=["krbtgt", self.realm]) self.canonicalize = TestOptions.Canonicalize.is_set(options) def get_realm(self, options, creds): @@ -143,6 +149,7 @@ KDC_ERR_PREAUTH_REQUIRED = 25 NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) +NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-ENTERPRISE-PRINCIPAL')) @DynamicTestCase @@ -436,10 +443,17 @@ class KerberosASCanonicalizationTests(RawKerberosTest): return (rep, as_rep) def check_cname(self, cname, data): - nt = cname['name-type'] + if TestOptions.Canonicalize.is_set(data.options): + expected_name_type = NT_PRINCIPAL + elif TestOptions.Enterprise.is_set(data.options): + expected_name_type = NT_ENTERPRISE_PRINCIPAL + else: + expected_name_type = NT_PRINCIPAL + + name_type = cname['name-type'] self.assertEqual( - NT_PRINCIPAL, - nt, + expected_name_type, + name_type, "cname name-type, Options {0:08b}".format(data.options)) ns = cname['name-string'] diff --git a/selftest/knownfail.d/kdc-enterprise b/selftest/knownfail.d/kdc-enterprise new file mode 100644 index 00000000000..4e4f8a93e03 --- /dev/null +++ b/selftest/knownfail.d/kdc-enterprise @@ -0,0 +1,57 @@ +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_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_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_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_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_UpperRealm_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_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\( + diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 96d3e51da5c..9bac4737591 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -142,3 +142,11 @@ 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_UserCredentials_UpperUserName_NetbiosRealm\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName_NetbiosRealm_UPN\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_UPN\( -- 2.25.1 From 31bffef894818d8012876d6b7b8d6d4f54905f2f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 11:09:59 +1300 Subject: [PATCH 038/645] selftest: Fix flipped machine and user constants This naturally does not change the test, but reduces developer confusion. Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 579a3c641c72b65f6ba39141a55c765b517bd7f8) --- python/samba/tests/krb5/as_canonicalization_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 3f8ed5c5a11..7cdf614482e 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -120,8 +120,8 @@ class TestData: return rep -MACHINE_NAME = "tstkrb5cnnusr" -USER_NAME = "tstkrb5cnnmch" +MACHINE_NAME = "tstkrb5cnnmch" +USER_NAME = "tstkrb5cnnusr" # Encryption types AES256_CTS_HMAC_SHA1_96 = int( -- 2.25.1 From 5f06624f40f9068f6ea94d585bb381c63c39f91a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 11:12:13 +1300 Subject: [PATCH 039/645] selftest: Make as_canonicalization_tests.py easier to run outside "make test" This takes the realm from the LDAP base DN and so avoids one easy mistake to make. So far the NT4 domain name is not auto-detected, so much be read from the smb.conf. By using .guess() the smb.conf is read for the unspecified parts (eg workstation for an NTLM login to the LDAP server if the target server is an IP address). Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d85e71f449037fa035fa2fae6b64caf695c53cb3) --- python/samba/tests/krb5/as_canonicalization_tests.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 7cdf614482e..c0c3208d216 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -185,14 +185,20 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.username = os.environ["USERNAME"] cls.password = os.environ["PASSWORD"] cls.domain = os.environ["DOMAIN"] - cls.realm = os.environ["REALM"] cls.host = os.environ["SERVER"] c = Credentials() c.set_username(cls.username) c.set_password(cls.password) c.set_domain(cls.domain) - c.set_realm(cls.realm) + try: + realm = os.environ["REALM"] + c.set_realm(realm) + except KeyError: + pass + + c.guess() + cls.credentials = c cls.session = system_session() @@ -236,6 +242,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.user_creds = Credentials() cls.user_creds.guess(cls.lp) + cls.user_creds.set_realm(cls.ldb.domain_dns_name().upper()) cls.user_creds.set_password(cls.user_pass) cls.user_creds.set_username(cls.user_name) cls.user_creds.set_workstation(cls.machine_name) @@ -263,6 +270,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.machine_creds = Credentials() cls.machine_creds.guess(cls.lp) + cls.machine_creds.set_realm(cls.ldb.domain_dns_name().upper()) cls.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) cls.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) cls.machine_creds.set_password(cls.machine_pass) -- 2.25.1 From d3dd1fdcdf374101f3c9e30a5426fe99b382ecc3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 13:46:28 +1300 Subject: [PATCH 040/645] samdb: Add samdb.domain_netbios_name() Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 [abartlet@samba.org: Backported from commit d79218dbba3d0f26d6a0e22b3c91b0731bf641dd as this backport to Samba 4.13 does not include 07ce48088824bba2054e029edfa6fbae972c1921 (samba-tool: Create unix user with modified template homedir)] --- python/samba/netcmd/user.py | 10 ++-------- python/samba/samdb.py | 15 +++++++++++++++ python/samba/tests/samdb.py | 13 ++++++++++--- selftest/tests.py | 1 + 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py index 26db3105da0..aa8e96a2581 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -3001,14 +3001,8 @@ The users gecos field will be set to 'User4 test' if unix_home is None: # obtain nETBIOS Domain Name - filter = "(&(objectClass=crossRef)(nETBIOSName=*))" - searchdn = ("CN=Partitions,CN=Configuration," + domaindn) - try: - res = samdb.search(searchdn, - scope=ldb.SCOPE_SUBTREE, - expression=filter) - unix_domain = res[0]["nETBIOSName"][0] - except IndexError: + unix_domain = samdb.domain_netbios_name() + if unix_domain is None: raise CommandError('Unable to find Unix domain') unix_home = "/home/{0}/{1}".format(unix_domain, username) diff --git a/python/samba/samdb.py b/python/samba/samdb.py index d903babb406..e4030099b5c 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -928,6 +928,21 @@ accountExpires: %u domain_dn = self.get_default_basedn() return domain_dn.canonical_str().split('/')[0] + def domain_netbios_name(self): + """return the NetBIOS name of the domain root""" + domain_dn = self.get_default_basedn() + dns_name = self.domain_dns_name() + filter = "(&(objectClass=crossRef)(nETBIOSName=*)(ncName=%s)(dnsroot=%s))" % (domain_dn, dns_name) + partitions_dn = self.get_partitions_dn() + res = self.search(partitions_dn, + scope=ldb.SCOPE_ONELEVEL, + expression=filter) + try: + netbios_domain = res[0]["nETBIOSName"][0].decode() + except IndexError: + return None + return netbios_domain + def forest_dns_name(self): """return the DNS name of the forest root""" forest_dn = self.get_root_basedn() diff --git a/python/samba/tests/samdb.py b/python/samba/tests/samdb.py index a185a1566e3..834c5a204a6 100644 --- a/python/samba/tests/samdb.py +++ b/python/samba/tests/samdb.py @@ -38,13 +38,13 @@ class SamDBTestCase(TestCaseInTempDir): super(SamDBTestCase, self).setUp() self.session = system_session() logger = logging.getLogger("selftest") - domain = "dsdb" - realm = "dsdb.samba.example.com" + self.domain = "dsdb" + self.realm = "dsdb.samba.example.com" host_name = "test" server_role = "active directory domain controller" self.result = provision(logger, self.session, targetdir=self.tempdir, - realm=realm, domain=domain, + realm=self.realm, domain=self.domain, hostname=host_name, use_ntvfs=True, serverrole=server_role, @@ -61,3 +61,10 @@ class SamDBTestCase(TestCaseInTempDir): shutil.rmtree(os.path.join(self.tempdir, d)) super(SamDBTestCase, self).tearDown() + + +class SamDBTests(SamDBTestCase): + + def test_get_domain(self): + self.assertEqual(self.samdb.domain_dns_name(), self.realm.lower()) + self.assertEqual(self.samdb.domain_netbios_name(), self.domain.upper()) diff --git a/selftest/tests.py b/selftest/tests.py index 91c75b0ebed..b9b95d800cc 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -211,6 +211,7 @@ planpythontestsuite("none", "samba.tests.graph") plantestsuite("wafsamba.duplicate_symbols", "none", [os.path.join(srcdir(), "buildtools/wafsamba/test_duplicate_symbol.sh")]) planpythontestsuite("none", "samba.tests.glue") planpythontestsuite("none", "samba.tests.tdb_util") +planpythontestsuite("none", "samba.tests.samdb") planpythontestsuite("none", "samba.tests.samdb_api") if with_pam: -- 2.25.1 From 8bbaf0e3a3d44ffc727b4288b37bb01583c1adb2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 13:47:30 +1300 Subject: [PATCH 041/645] selftest: Make as_canonicalization_tests.py auto-detect the NT4 domain name Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2693f12fbe321e0f4932b1f74d7006dbac140e8e) --- python/samba/tests/krb5/as_canonicalization_tests.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index c0c3208d216..221ff486fd8 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -184,18 +184,21 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.lp = cls.get_loadparm(cls) cls.username = os.environ["USERNAME"] cls.password = os.environ["PASSWORD"] - cls.domain = os.environ["DOMAIN"] cls.host = os.environ["SERVER"] c = Credentials() c.set_username(cls.username) c.set_password(cls.password) - c.set_domain(cls.domain) try: realm = os.environ["REALM"] c.set_realm(realm) except KeyError: pass + try: + domain = os.environ["DOMAIN"] + c.set_domain(domain) + except KeyError: + pass c.guess() @@ -243,6 +246,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.user_creds = Credentials() cls.user_creds.guess(cls.lp) cls.user_creds.set_realm(cls.ldb.domain_dns_name().upper()) + cls.user_creds.set_domain(cls.ldb.domain_netbios_name().upper()) cls.user_creds.set_password(cls.user_pass) cls.user_creds.set_username(cls.user_name) cls.user_creds.set_workstation(cls.machine_name) @@ -271,6 +275,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): cls.machine_creds = Credentials() cls.machine_creds.guess(cls.lp) cls.machine_creds.set_realm(cls.ldb.domain_dns_name().upper()) + cls.machine_creds.set_domain(cls.ldb.domain_netbios_name().upper()) cls.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) cls.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) cls.machine_creds.set_password(cls.machine_pass) -- 2.25.1 From 648c162e4a15a179ca15b294290e0511288bff28 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 11:21:24 +1300 Subject: [PATCH 042/645] selftest: Fix formatting of failure (traceback and options swapped in format string) Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ab8c0a181bebe17a597af49790f6e7b17e13c29b) --- python/samba/tests/krb5/as_canonicalization_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 221ff486fd8..f0e9f6307f6 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -296,8 +296,8 @@ class KerberosASCanonicalizationTests(RawKerberosTest): except pyasn1.error.PyAsn1Error as e: import traceback self.fail("ASN1 Error, Options {0:08b}:{1} {2}".format( - traceback.format_exc(), data.options, + traceback.format_exc(), e)) # If as_req triggered an expected server error response # No need to test the response data. -- 2.25.1 From 2b43617bc7e44ef231a79dc1e5b51eda9f88d78c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 11:27:06 +1300 Subject: [PATCH 043/645] selftest: Add in encrypted-pa-data from RFC 6806 This comes from Windows 2019 which supports FAST. Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit fc77ece0e2b5fd324809e17a9b208cc7854cee4b) --- python/samba/tests/krb5/rfc4120.asn1 | 3 ++- python/samba/tests/krb5/rfc4120_pyasn1.py | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index 58e0c1636a1..654f9788ca7 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -239,7 +239,8 @@ EncKDCRepPart ::= SEQUENCE { renew-till [8] KerberosTime OPTIONAL, srealm [9] Realm, sname [10] PrincipalName, - caddr [11] HostAddresses OPTIONAL + caddr [11] HostAddresses OPTIONAL, + encrypted-pa-data[12] METHOD-DATA OPTIONAL } LastReq ::= SEQUENCE OF SEQUENCE { diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index b4ea678afd8..1d89f94adf1 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/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 2020-11-03 14:07:15.270009) +# (last modified on 2020-11-06 11:30:42.476808) # KerberosV5Spec2 from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful @@ -438,6 +438,13 @@ LastReq.componentType = univ.Sequence(componentType=namedtype.NamedTypes( )) +class METHOD_DATA(univ.SequenceOf): + pass + + +METHOD_DATA.componentType = PA_DATA() + + class TicketFlags(KerberosFlags): pass @@ -458,7 +465,8 @@ EncKDCRepPart.componentType = namedtype.NamedTypes( namedtype.OptionalNamedType('renew-till', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8))), namedtype.NamedType('srealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 9))), namedtype.NamedType('sname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 10))), - namedtype.OptionalNamedType('caddr', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11))) + namedtype.OptionalNamedType('caddr', HostAddresses().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 11))), + namedtype.OptionalNamedType('encrypted-pa-data', METHOD_DATA().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12))) ) @@ -702,13 +710,6 @@ KRB_SAFE.componentType = namedtype.NamedTypes( ) -class METHOD_DATA(univ.SequenceOf): - pass - - -METHOD_DATA.componentType = PA_DATA() - - class MessageTypeValues(univ.Integer): pass -- 2.25.1 From d8fd226773b933a662943d5200efc67528324354 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Nov 2020 13:50:37 +1300 Subject: [PATCH 044/645] selftest: Windows 2019 implements the RemoveDollar behaviour for Enterprise principals This is documented in MS-KILE. Signed-off-by: Andrew Bartlett Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Gary Lockyer Autobuild-Date(master): Wed Nov 11 02:38:46 UTC 2020 on sn-devel-184 (cherry picked from commit f214a3ba5a3e9f129f10062392ae03edd62d8186) --- .../tests/krb5/as_canonicalization_tests.py | 11 ---------- selftest/knownfail.d/kdc-enterprise | 20 ------------------- selftest/knownfail_mit_kdc | 20 +++++++++++++++++++ 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index f0e9f6307f6..caa186bed41 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -366,17 +366,6 @@ class KerberosASCanonicalizationTests(RawKerberosTest): self.assertEqual( rep['msg-type'], KRB_ERROR, "Data {0}".format(str(data))) - # We should get KDC_ERR_PREAUTH_REQUIRED - # unless the RemoveDollar and Enterprise options are set - # then we should get a KDC_ERR_C_PRINCIPAL_UNKNOWN - if TestOptions.RemoveDollar.is_set(data.options) and\ - TestOptions.Enterprise.is_set(data.options): - self.assertEqual( - rep['error-code'], - KDC_ERR_C_PRINCIPAL_UNKNOWN, - "Error code {0}, Data {1}".format(rep['error-code'], str(data))) - return (None, None) - self.assertEqual( rep['error-code'], KDC_ERR_PREAUTH_REQUIRED, diff --git a/selftest/knownfail.d/kdc-enterprise b/selftest/knownfail.d/kdc-enterprise index 4e4f8a93e03..d15d67c8af6 100644 --- a/selftest/knownfail.d/kdc-enterprise +++ b/selftest/knownfail.d/kdc-enterprise @@ -1,19 +1,3 @@ -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_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_NetbiosRealm\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\( @@ -26,14 +10,10 @@ 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_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_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_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_UpperRealm_UpperUserName_RemoveDollar\( -samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_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\( diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 9bac4737591..00edbc0c34d 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -150,3 +150,23 @@ 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_UserCredentials_Enterprise_UpperRealm_UPN\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_UPN\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UPN_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_RemoveDollar\( +samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar\( -- 2.25.1 From a87cfead30a4f630aaa5e22ccb8b3646bb94e989 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Wed, 4 Nov 2020 13:54:46 +1300 Subject: [PATCH 045/645] selftest: add heimdal kdc specific known fail Add a heimdal kerberos specific known fail, will be needed by subsequent commits. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 5cb5134377f099353e0f91c44cc11e45d548d40f) --- selftest/knownfail_heimdal_kdc | 0 selftest/wscript | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 selftest/knownfail_heimdal_kdc diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/selftest/wscript b/selftest/wscript index 95086b4f0ed..82354071d5b 100644 --- a/selftest/wscript +++ b/selftest/wscript @@ -265,6 +265,9 @@ def cmd_testonly(opt): env.OPTIONS += " --mitkrb5 --exclude=${srcdir}/selftest/skip_mit_kdc" env.FILTER_XFAIL += " --expected-failures=${srcdir}/selftest/"\ "knownfail_mit_kdc" + else: + env.FILTER_XFAIL += " --expected-failures=${srcdir}/selftest/"\ + "knownfail_heimdal_kdc" if not CONFIG_GET(opt, 'HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X'): # older MIT krb5 libraries (< 1.14) don't have -- 2.25.1 From 2fe18d5ebb4af139bed09d9ea8718aac901b9e9b Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Wed, 4 Nov 2020 13:58:24 +1300 Subject: [PATCH 046/645] tests python krb5: Add python kerberos compatability tests Add new python test to document the differences between the MIT and Heimdal Kerberos implementations. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1e1d8b9c83f32c06ecab31214a20b77529ee038e) --- .../samba/tests/krb5/compatability_tests.py | 174 ++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 4 + selftest/knownfail_mit_kdc | 4 + source4/selftest/tests.py | 1 + 5 files changed, 184 insertions(+) create mode 100755 python/samba/tests/krb5/compatability_tests.py diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py new file mode 100755 index 00000000000..63bd5269c2b --- /dev/null +++ b/python/samba/tests/krb5/compatability_tests.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) Catalyst.Net Ltd 2020 +# +# 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + +global_asn1_print = False +global_hexdump = False + + +class SimpleKerberosTests(RawKerberosTest): + + def setUp(self): + super(SimpleKerberosTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def test_mit_EncASRepPart_tag(self): + creds = self.get_user_creds() + (enc, _) = self.as_req(creds) + self.assertEqual(0x7a, enc[0]) + + def test_heimdal_EncASRepPart_tag(self): + creds = self.get_user_creds() + (enc, _) = self.as_req(creds) + self.assertEqual(0x79, enc[0]) + + def test_mit_EncryptedData_kvno(self): + creds = self.get_user_creds() + (_, enc) = self.as_req(creds) + if 'kvno' in enc: + self.fail("kvno present in EncryptedData") + + def test_heimdal_EncryptedData_kvno(self): + creds = self.get_user_creds() + (_, enc) = self.as_req(creds) + if 'kvno' not in enc: + self.fail("kvno absent in EncryptedData") + + def test_mit_EncASRepPart_FAST_support(self): + creds = self.get_user_creds() + (enc, _) = self.as_req(creds) + self.assertEqual(0x7A, enc[0]) + as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncTGSRepPart()) + flags = int(as_rep['flags'], base=2) + # MIT sets enc-pa-rep, flag bit 15 + # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests + self.assertTrue(0x00010000 & flags) + + def test_heimdal_EncASRepPart_FAST_support(self): + creds = self.get_user_creds() + (enc, _) = self.as_req(creds) + self.assertEqual(0x79, enc[0]) + as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncASRepPart()) + flags = as_rep['flags'] + flags = int(as_rep['flags'], base=2) + # Heimdal does not set enc-pa-rep, flag bit 15 + # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests + self.assertFalse(0x00010000 & flags) + + def as_req(self, creds): + user = creds.get_username() + realm = creds.get_realm() + + cname = self.PrincipalName_create(name_type=1, names=[user]) + sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + + till = self.get_KerberosTime(offset=36000) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = None + + etypes = (18, 17, 23) + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + rep_padata = self.der_decode( + rep['e-data'], + asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == 19: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode( + etype_info2, + asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(2, pa_ts) + + kdc_options = krb5_asn1.KDCOptions('forwardable') + padata = [pa_ts] + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + self.assertEqual(msg_type, 11) + + usage = 3 + enc_part = rep['enc-part'] + enc_as_rep_part = key.decrypt(usage, rep['enc-part']['cipher']) + return (enc_as_rep_part, enc_part) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 2f813760814..fbb9a06d99e 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -90,6 +90,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/s4u_tests.py', 'python/samba/tests/krb5/xrealm_tests.py', 'python/samba/tests/krb5/as_canonicalization_tests.py', + 'python/samba/tests/krb5/compatability_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index e69de29bb2d..7ab56b6721b 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -0,0 +1,4 @@ +# +# We expect all the MIT specific compatability tests to fail on heimdal +# kerberos +^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_ diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 00edbc0c34d..9953d51f21d 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -1,4 +1,8 @@ # +# We expect all the heimdal specific compatability tests to fail on MIT +# kerberos +^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_heimdal_ +# # Currently MOST but not quite all the Canonicalization tests fail on the # MIT KDC # diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 78b1a8494f3..76828e27d66 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1285,6 +1285,7 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: "samba4.krb5.kdc with machine account") planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests") +planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests") for env in [ 'vampire_dc', -- 2.25.1 From 03911f9334e64ca0a7412613f5332270a73dd3ee Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 11:19:02 +1300 Subject: [PATCH 047/645] tests python krb5: Add constants module Extract the constants used in the tests into a separate module. To reduce code duplication Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 532c941fbb8fc5fc5da4aa2d0e170229076e9aa7) --- python/samba/tests/krb5/rfc4120_constants.py | 49 ++++++++++++++++++++ python/samba/tests/usage.py | 1 + 2 files changed, 50 insertions(+) create mode 100644 python/samba/tests/krb5/rfc4120_constants.py diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py new file mode 100644 index 00000000000..e939bb75e82 --- /dev/null +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -0,0 +1,49 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) 2020 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 samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + +# Encryption types +AES256_CTS_HMAC_SHA1_96 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES256-CTS-HMAC-SHA1-96')) +AES128_CTS_HMAC_SHA1_96 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES128-CTS-HMAC-SHA1-96')) +ARCFOUR_HMAC_MD5 = int( + krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-ARCFOUR-HMAC-MD5')) + +# Message types +KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) +KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) + +# PAData types +PADATA_ENC_TIMESTAMP = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ENC-TIMESTAMP')) +PADATA_ETYPE_INFO2 = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) + +# Error codes +KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 +KDC_ERR_PREAUTH_FAILED = 24 +KDC_ERR_PREAUTH_REQUIRED = 25 +KDC_ERR_SKEW = 37 + +# Name types +NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) +NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) +NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) +NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues( + 'kRB5-NT-ENTERPRISE-PRINCIPAL')) diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index fbb9a06d99e..536721a1f86 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -91,6 +91,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/xrealm_tests.py', 'python/samba/tests/krb5/as_canonicalization_tests.py', 'python/samba/tests/krb5/compatability_tests.py', + 'python/samba/tests/krb5/rfc4120_constants.py', } EXCLUDE_HELP = { -- 2.25.1 From a4f77bd26a05784e93090b3721ebd1529aea2cb4 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 11:20:03 +1300 Subject: [PATCH 048/645] tests python krb5: Refactor canonicalization test constants Modify tests to use the constants defined in rfc4120_constants.py Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 97b830cbcac53fcf49bbcd272812d1ba019bac51) --- .../tests/krb5/as_canonicalization_tests.py | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index caa186bed41..303788b672e 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -41,6 +41,7 @@ from samba.dsdb import ( UF_NORMAL_ACCOUNT) from samba.samdb import SamDB from samba.tests import delete_force, DynamicTestCase +from samba.tests.krb5.rfc4120_constants import * global_asn1_print = False global_hexdump = False @@ -123,35 +124,6 @@ class TestData: MACHINE_NAME = "tstkrb5cnnmch" USER_NAME = "tstkrb5cnnusr" -# Encryption types -AES256_CTS_HMAC_SHA1_96 = int( - krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES256-CTS-HMAC-SHA1-96')) -AES128_CTS_HMAC_SHA1_96 = int( - krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-AES128-CTS-HMAC-SHA1-96')) -ARCFOUR_HMAC_MD5 = int( - krb5_asn1.EncryptionTypeValues('kRB5-ENCTYPE-ARCFOUR-HMAC-MD5')) - -# Message types -KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) -KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) - -# PAData types -PADATA_ENC_TIMESTAMP = int( - krb5_asn1.PADataTypeValues('kRB5-PADATA-ENC-TIMESTAMP')) -PADATA_ETYPE_INFO2 = int( - krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) - -# Error codes -KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 -KDC_ERR_PREAUTH_REQUIRED = 25 - -# Name types -NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) -NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) -NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) -NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-ENTERPRISE-PRINCIPAL')) - - @DynamicTestCase class KerberosASCanonicalizationTests(RawKerberosTest): -- 2.25.1 From 93f1e420cf2d6d01aeb96b47fca5c6bea799a6f5 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 11:20:58 +1300 Subject: [PATCH 049/645] tests python krb5: Refactor compatability test constants Modify tests to use the constants defined in rfc4120_constants.py Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 82a413f48b7ef71feb68fc34f7ca753d45eb8974) --- .../samba/tests/krb5/compatability_tests.py | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index 63bd5269c2b..bf561346ab3 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -25,10 +25,17 @@ os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests.krb5.raw_testcase import RawKerberosTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +from samba.tests.krb5.rfc4120_constants import * global_asn1_print = False global_hexdump = False +HIEMDAL_ENC_AS_REP_PART_TYPE_TAG = 0x79 +# MIT uses the EncTGSRepPart tag for the EncASRepPart +MIT_ENC_AS_REP_PART_TYPE_TAG = 0x7A + +ENC_PA_REP_FLAG = 0x00010000 + class SimpleKerberosTests(RawKerberosTest): @@ -40,12 +47,12 @@ class SimpleKerberosTests(RawKerberosTest): def test_mit_EncASRepPart_tag(self): creds = self.get_user_creds() (enc, _) = self.as_req(creds) - self.assertEqual(0x7a, enc[0]) + self.assertEqual(MIT_ENC_AS_REP_PART_TYPE_TAG, enc[0]) def test_heimdal_EncASRepPart_tag(self): creds = self.get_user_creds() (enc, _) = self.as_req(creds) - self.assertEqual(0x79, enc[0]) + self.assertEqual(HIEMDAL_ENC_AS_REP_PART_TYPE_TAG, enc[0]) def test_mit_EncryptedData_kvno(self): creds = self.get_user_creds() @@ -62,37 +69,44 @@ class SimpleKerberosTests(RawKerberosTest): def test_mit_EncASRepPart_FAST_support(self): creds = self.get_user_creds() (enc, _) = self.as_req(creds) - self.assertEqual(0x7A, enc[0]) + self.assertEqual(MIT_ENC_AS_REP_PART_TYPE_TAG, enc[0]) as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncTGSRepPart()) flags = int(as_rep['flags'], base=2) # MIT sets enc-pa-rep, flag bit 15 # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests - self.assertTrue(0x00010000 & flags) + self.assertTrue(ENC_PA_REP_FLAG & flags) def test_heimdal_EncASRepPart_FAST_support(self): creds = self.get_user_creds() (enc, _) = self.as_req(creds) - self.assertEqual(0x79, enc[0]) + self.assertEqual(HIEMDAL_ENC_AS_REP_PART_TYPE_TAG, enc[0]) as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncASRepPart()) flags = as_rep['flags'] flags = int(as_rep['flags'], base=2) # Heimdal does not set enc-pa-rep, flag bit 15 # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests - self.assertFalse(0x00010000 & flags) + self.assertFalse(ENC_PA_REP_FLAG & flags) def as_req(self, creds): user = creds.get_username() realm = creds.get_realm() - cname = self.PrincipalName_create(name_type=1, names=[user]) - sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, + names=["krbtgt", realm]) till = self.get_KerberosTime(offset=36000) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - etypes = (18, 17, 23) + etypes = ( + AES256_CTS_HMAC_SHA1_96, + AES128_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5) req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), @@ -111,14 +125,14 @@ class SimpleKerberosTests(RawKerberosTest): rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 25) + self.assertEqual(rep['msg-type'], KRB_ERROR) + self.assertEqual(rep['error-code'], KDC_ERR_PREAUTH_REQUIRED) rep_padata = self.der_decode( rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: - if pa['padata-type'] == 19: + if pa['padata-type'] == PADATA_ETYPE_INFO2: etype_info2 = pa['padata-value'] break @@ -136,7 +150,7 @@ class SimpleKerberosTests(RawKerberosTest): pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) - pa_ts = self.PA_DATA_create(2, pa_ts) + pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = [pa_ts] @@ -159,7 +173,7 @@ class SimpleKerberosTests(RawKerberosTest): self.assertIsNotNone(rep) msg_type = rep['msg-type'] - self.assertEqual(msg_type, 11) + self.assertEqual(msg_type, KRB_AS_REP) usage = 3 enc_part = rep['enc-part'] -- 2.25.1 From 0186a9dda5e3b7a4e312efe1742d2f231ebff9b4 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 13:51:39 +1300 Subject: [PATCH 050/645] tests python krb5: raw_testcase permit RC4 salts MIT kerberos returns a salt when ARCFOUR_HMAC_MD5, this commit removes the check that a salt is not returned. A test for the difference between MIT and Heimdal will be added in the subsequent commits. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1bab87c50baf0fecb5d4cd09e1a9896730c6377e) --- python/samba/tests/krb5/raw_testcase.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 45e46e0b7ba..e67f5464e59 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -425,7 +425,6 @@ class RawKerberosTest(TestCase): pass if e == kcrypto.Enctype.RC4: - self.assertIsNone(salt) nthash = creds.get_nt_hash() return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno) -- 2.25.1 From 74f23242a07b722a0fe472d23a5b8d609dc532cc Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Fri, 6 Nov 2020 09:07:04 +1300 Subject: [PATCH 051/645] tests python krb5: Convert kdc-heimdal to python Implement the tests in source4/torture/krb5/kdc-heimdal.c in python. The following tests were not re-implemented as they are client side tests for the "Orpheus Lyre" attack: TORTURE_KRB5_TEST_CHANGE_SERVER_OUT TORTURE_KRB5_TEST_CHANGE_SERVER_IN TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit a00a1c9745033dae05eee17cfa4e2c5354a81e68) --- python/samba/tests/krb5/kdc_tests.py | 219 +++++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + source4/selftest/tests.py | 1 + 3 files changed, 221 insertions(+) create mode 100755 python/samba/tests/krb5/kdc_tests.py diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py new file mode 100755 index 00000000000..57a25448965 --- /dev/null +++ b/python/samba/tests/krb5/kdc_tests.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +from samba.tests.krb5.rfc4120_constants import * + +global_asn1_print = False +global_hexdump = False + + +class KdcTests(RawKerberosTest): + """ Port of the tests in source4/torture/krb5/kdc-heimdal.c + To python. + """ + + def setUp(self): + super(KdcTests, self).setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def as_req(self, creds, etypes, padata=None): + user = creds.get_username() + realm = creds.get_realm() + + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, + names=["krbtgt", realm]) + till = self.get_KerberosTime(offset=36000) + + kdc_options = 0 + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + return rep + + def get_pa_data(self, creds, rep, skew=0): + rep_padata = self.der_decode( + rep['e-data'], + asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == PADATA_ETYPE_INFO2: + etype_info2 = pa['padata-value'] + break + + etype_info2 = self.der_decode( + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) + + (patime, pausec) = self.get_KerberosTimeWithUsec(offset=skew) + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = 1 + pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) + + padata = [pa_ts] + return padata + + def check_pre_authenication(self, rep): + """ Check that the kdc response was pre-authentication required + """ + self.check_error_rep(rep, KDC_ERR_PREAUTH_REQUIRED) + + def check_as_reply(self, rep): + """ Check that the kdc response is an AS-REP and that the + values for: + msg-type + pvno + tkt-pvno + kvno + match the expected values + """ + + # Should have a reply, and it should an AS-REP message. + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], KRB_AS_REP) + + # Protocol version number should be 5 + pvno = int(rep['pvno']) + self.assertEqual(5, pvno) + + # The ticket version number should be 5 + tkt_vno = int(rep['ticket']['tkt-vno']) + self.assertEqual(5, tkt_vno) + + # Check that the kvno is not an RODC kvno + # MIT kerberos does not provide the kvno, so we treat it as optional. + # This is tested in compatability_test.py + if 'kvno' in rep['enc-part']: + kvno = int(rep['enc-part']['kvno']) + # If the high order bits are set this is an RODC kvno. + self.assertEqual(0, kvno & 0xFFFF0000) + + def check_error_rep(self, rep, expected): + """ Check that the reply is an error message, with the expected + error-code specified. + """ + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], KRB_ERROR) + self.assertEqual(rep['error-code'], expected) + + def test_aes256_cts_hmac_sha1_96(self): + creds = self.get_user_creds() + etype = (AES256_CTS_HMAC_SHA1_96,) + + rep = self.as_req(creds, etype) + self.check_pre_authenication(rep) + + padata = self.get_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=padata) + self.check_as_reply(rep) + + etype = rep['enc-part']['etype'] + self.assertEquals(AES256_CTS_HMAC_SHA1_96, etype) + + def test_arc4_hmac_md5(self): + creds = self.get_user_creds() + etype = (ARCFOUR_HMAC_MD5,) + + rep = self.as_req(creds, etype) + self.check_pre_authenication(rep) + + padata = self.get_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=padata) + self.check_as_reply(rep) + + etype = rep['enc-part']['etype'] + self.assertEquals(ARCFOUR_HMAC_MD5, etype) + + def test_aes_rc4(self): + creds = self.get_user_creds() + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + rep = self.as_req(creds, etype) + self.check_pre_authenication(rep) + + padata = self.get_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=padata) + self.check_as_reply(rep) + + etype = rep['enc-part']['etype'] + self.assertEquals(AES256_CTS_HMAC_SHA1_96, etype) + + def test_clock_skew(self): + creds = self.get_user_creds() + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + rep = self.as_req(creds, etype) + self.check_pre_authenication(rep) + + padata = self.get_pa_data(creds, rep, skew=3600) + rep = self.as_req(creds, etype, padata=padata) + + self.check_error_rep(rep, KDC_ERR_SKEW) + + def test_invalid_password(self): + creds = self.insta_creds(template=self.get_user_creds()) + creds.set_password("Not the correct password") + + etype = (AES256_CTS_HMAC_SHA1_96,) + + rep = self.as_req(creds, etype) + self.check_pre_authenication(rep) + + padata = self.get_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=padata) + + self.check_error_rep(rep, KDC_ERR_PREAUTH_FAILED) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 536721a1f86..35abaf2dafa 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -92,6 +92,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/as_canonicalization_tests.py', 'python/samba/tests/krb5/compatability_tests.py', 'python/samba/tests/krb5/rfc4120_constants.py', + 'python/samba/tests/krb5/kdc_tests.py', } EXCLUDE_HELP = { diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 76828e27d66..f72060e9870 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1286,6 +1286,7 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests") planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests") +planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") for env in [ 'vampire_dc', -- 2.25.1 From 66c868177ea79fc608f02776f9074fc19f6f3c19 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 16:56:46 +1300 Subject: [PATCH 052/645] tests python krb5: refactor compatability tests Refactor to aid the adding of tests for the inclusion of a salt when ARCFOUR_HMAC_MD5 encryption selected Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d492355f293e2da400318665035b056dfaba852c) --- .../samba/tests/krb5/compatability_tests.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index bf561346ab3..5990d2ce8df 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -87,7 +87,7 @@ class SimpleKerberosTests(RawKerberosTest): # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests self.assertFalse(ENC_PA_REP_FLAG & flags) - def as_req(self, creds): + def as_pre_auth_req(self, creds, etypes): user = creds.get_username() realm = creds.get_realm() @@ -103,10 +103,6 @@ class SimpleKerberosTests(RawKerberosTest): kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - etypes = ( - AES256_CTS_HMAC_SHA1_96, - AES128_CTS_HMAC_SHA1_96, - ARCFOUR_HMAC_MD5) req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), @@ -123,10 +119,16 @@ class SimpleKerberosTests(RawKerberosTest): EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) - self.assertIsNotNone(rep) + return (rep, cname, sname, realm, till) + + def check_preauth_rep(self, rep): + self.assertIsNotNone(rep) self.assertEqual(rep['msg-type'], KRB_ERROR) self.assertEqual(rep['error-code'], KDC_ERR_PREAUTH_REQUIRED) + + def get_etype_info2(self, rep): + rep_padata = self.der_decode( rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) @@ -139,7 +141,17 @@ class SimpleKerberosTests(RawKerberosTest): etype_info2 = self.der_decode( etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + return etype_info2 + + def as_req(self, creds): + etypes = ( + AES256_CTS_HMAC_SHA1_96, + AES128_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5) + (rep, cname, sname, realm, till) = self.as_pre_auth_req(creds, etypes) + self.check_preauth_rep(rep) + etype_info2 = self.get_etype_info2(rep) key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) (patime, pausec) = self.get_KerberosTimeWithUsec() -- 2.25.1 From cb18851317987279cca0249feeddce85e489710c Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 10 Nov 2020 16:57:11 +1300 Subject: [PATCH 053/645] tests python krb5: add arcfour salt tests MIT kerberos returns a salt when ARCFOUR_HMAC_MD5 encryption selected, Heimdal does not. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Thu Nov 12 22:54:22 UTC 2020 on sn-devel-184 (cherry picked from commit 2ba6d596ff0a3580eca9285fd83569bcb147ce77) --- .../samba/tests/krb5/compatability_tests.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index 5990d2ce8df..e4b1453e712 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -87,6 +87,26 @@ class SimpleKerberosTests(RawKerberosTest): # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests self.assertFalse(ENC_PA_REP_FLAG & flags) + def test_mit_arcfour_salt(self): + creds = self.get_user_creds() + etypes = (ARCFOUR_HMAC_MD5,) + (rep, *_) = self.as_pre_auth_req(creds, etypes) + self.check_preauth_rep(rep) + etype_info2 = self.get_etype_info2(rep) + if 'salt' not in etype_info2[0]: + self.fail( + "(MIT) Salt not populated for ARCFOUR_HMAC_MD5 encryption") + + def test_heimdal_arcfour_salt(self): + creds = self.get_user_creds() + etypes = (ARCFOUR_HMAC_MD5,) + (rep, *_) = self.as_pre_auth_req(creds, etypes) + self.check_preauth_rep(rep) + etype_info2 = self.get_etype_info2(rep) + if 'salt' in etype_info2[0]: + self.fail( + "(Heimdal) Salt populated for ARCFOUR_HMAC_MD5 encryption") + def as_pre_auth_req(self, creds, etypes): user = creds.get_username() realm = creds.get_realm() -- 2.25.1 From 573e9ad57b84033bf101c5cd3cb2acad4d89ff78 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Wed, 18 Nov 2020 14:49:28 +1300 Subject: [PATCH 054/645] tests python krb5: Extra canonicalization tests Add tests that set the server name to the client name for the machine account in the kerberos AS_REQ. This replicates the TEST_AS_REQ_SELF test phase in source4/torture/krb5/kdc-canon-heimdal.c. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Mon Nov 30 05:21:42 UTC 2020 on sn-devel-184 (cherry picked from commit 7f7e2b0e1e17321d800de787098bb2b2c8259ecd) --- .../tests/krb5/as_canonicalization_tests.py | 74 +++++++++----- selftest/knownfail.d/kdc-enterprise | 26 +++++ selftest/knownfail_mit_kdc | 96 +++++++++++++++++++ 3 files changed, 172 insertions(+), 24 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 303788b672e..6ea3ff0491e 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -56,7 +56,8 @@ class TestOptions(Enum): NetbiosRealm = 16 UPN = 32 RemoveDollar = 64 - Last = 128 + AsReqSelf = 128 + Last = 256 def is_set(self, x): return self.value & x @@ -76,8 +77,8 @@ class TestData: def __init__(self, options, creds): self.options = options self.user_creds = creds - self.user_name = self.get_username(options, creds) - self.realm = self.get_realm(options, creds) + self.user_name = self._get_username(options, creds) + self.realm = self._get_realm(options, creds) if TestOptions.Enterprise.is_set(options): client_name_type = NT_ENTERPRISE_PRINCIPAL @@ -86,11 +87,14 @@ class TestData: self.cname = RawKerberosTest.PrincipalName_create( name_type=client_name_type, names=[self.user_name]) - self.sname = RawKerberosTest.PrincipalName_create( - name_type=NT_SRV_INST, names=["krbtgt", self.realm]) + if TestOptions.AsReqSelf.is_set(options): + self.sname = self.cname + else: + self.sname = RawKerberosTest.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", self.realm]) self.canonicalize = TestOptions.Canonicalize.is_set(options) - def get_realm(self, options, creds): + def _get_realm(self, options, creds): realm = creds.get_realm() if TestOptions.NetbiosRealm.is_set(options): realm = creds.get_domain() @@ -100,7 +104,7 @@ class TestData: realm = realm.lower() return realm - def get_username(self, options, creds): + def _get_username(self, options, creds): name = creds.get_username() if TestOptions.RemoveDollar.is_set(options) and name.endswith("$"): name = name[:-1] @@ -135,6 +139,9 @@ class KerberosASCanonicalizationTests(RawKerberosTest): if ct != CredentialsType.Machine and\ TestOptions.RemoveDollar.is_set(options): return True + if ct != CredentialsType.Machine and\ + TestOptions.AsReqSelf.is_set(options): + return True return False def build_test_name(ct, options): @@ -448,26 +455,45 @@ class KerberosASCanonicalizationTests(RawKerberosTest): def check_sname(self, sname, data): nt = sname['name-type'] - self.assertEqual( - NT_SRV_INST, - nt, - "sname name-type, Options {0:08b}".format(data.options)) - ns = sname['name-string'] name = ns[0].decode('ascii') - self.assertEqual( - 'krbtgt', - name, - "sname principal, Options {0:08b}".format(data.options)) - realm = ns[1].decode('ascii') - expected = data.realm - if TestOptions.Canonicalize.is_set(data.options): - expected = data.user_creds.get_realm().upper() - self.assertEqual( - expected, - realm, - "sname realm, Options {0:08b}".format(data.options)) + if TestOptions.AsReqSelf.is_set(data.options): + expected_name_type = NT_PRINCIPAL + if not TestOptions.Canonicalize.is_set(data.options)\ + and TestOptions.Enterprise.is_set(data.options): + + expected_name_type = NT_ENTERPRISE_PRINCIPAL + + self.assertEqual( + expected_name_type, + nt, + "sname name-type, Options {0:08b}".format(data.options)) + expected = data.user_name + if TestOptions.Canonicalize.is_set(data.options): + expected = data.user_creds.get_username() + self.assertEqual( + expected, + name, + "sname principal, Options {0:08b}".format(data.options)) + else: + self.assertEqual( + NT_SRV_INST, + nt, + "sname name-type, Options {0:08b}".format(data.options)) + self.assertEqual( + 'krbtgt', + name, + "sname principal, Options {0:08b}".format(data.options)) + + realm = ns[1].decode('ascii') + expected = data.realm + if TestOptions.Canonicalize.is_set(data.options): + expected = data.user_creds.get_realm().upper() + self.assertEqual( + expected, + realm, + "sname realm, Options {0:08b}".format(data.options)) def check_srealm(self, srealm, data): realm = data.user_creds.get_realm() diff --git a/selftest/knownfail.d/kdc-enterprise b/selftest/knownfail.d/kdc-enterprise index d15d67c8af6..c9b6c98a2ee 100644 --- a/selftest/knownfail.d/kdc-enterprise +++ b/selftest/knownfail.d/kdc-enterprise @@ -35,3 +35,29 @@ 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_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 a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 9953d51f21d..f1a4971430e 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -174,3 +174,99 @@ 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_Enterprise_UpperRealm_UPN_RemoveDollar\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_RemoveDollar\( samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\(ad_dc +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperRealm_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_RemoveDollar_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN_AsReqSelf\( +^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN_RemoveDollar_AsReqSelf\( -- 2.25.1 From 06a7429bd97934a68a916c1a97ce2b9169b624d0 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 10 Dec 2020 10:15:28 +1300 Subject: [PATCH 055/645] tests python krb5: Add Authorization data ad-type constants Add constants for the Authorization Data Type values. RFC 4120 7.5.4. Authorization Data Types Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d74c9dcf3aaa613abfac49288f427484468bf6e1) --- python/samba/tests/krb5/rfc4120_constants.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index e939bb75e82..e1d0c5baa68 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -47,3 +47,17 @@ NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues( 'kRB5-NT-ENTERPRISE-PRINCIPAL')) + +# Authorization data ad-type values + +AD_IF_RELEVANT = 1 +AD_INTENDED_FOR_SERVER = 2 +AD_INTENDED_FOR_APPLICATION_CLASS = 3 +AD_KDC_ISSUED = 4 +AD_AND_OR = 5 +AD_MANDATORY_TICKET_EXTENSIONS = 6 +AD_IN_TICKET_EXTENSIONS = 7 +AD_MANDATORY_FOR_KDC = 8 +AD_INITIAL_VERIFIED_CAS = 9 +AD_WIN2K_PAC = 128 +AD_SIGNTICKET = 512 -- 2.25.1 From 6b873cf67d374902b8482f41a42bf9bd8f714d20 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Mon, 30 Nov 2020 14:16:28 +1300 Subject: [PATCH 056/645] tests python krb5: add test base class Add a base class for the KDC tests to reduce the amount of code duplication in the tests. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 0f232ed42fb2671d025643cafb19891373562e4a) --- python/samba/tests/krb5/kdc_base_test.py | 419 +++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100755 python/samba/tests/krb5/kdc_base_test.py diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py new file mode 100755 index 00000000000..4fc7ee85ba9 --- /dev/null +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -0,0 +1,419 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" +from collections import namedtuple +from ldb import SCOPE_BASE +from samba import generate_random_password +from samba.auth import system_session +from samba.credentials import Credentials +from samba.dcerpc import krb5pac +from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_NORMAL_ACCOUNT +from samba.ndr import ndr_unpack +from samba.samdb import SamDB + +from samba.tests import delete_force +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +from samba.tests.krb5.rfc4120_constants import ( + AD_IF_RELEVANT, + AD_WIN2K_PAC, + KDC_ERR_PREAUTH_REQUIRED, + KRB_AS_REP, + KRB_TGS_REP, + KRB_ERROR, + PADATA_ENC_TIMESTAMP, + PADATA_ETYPE_INFO2, +) + +global_asn1_print = False +global_hexdump = False + + +class KDCBaseTest(RawKerberosTest): + """ Base class for KDC tests. + """ + + @classmethod + def setUpClass(cls): + cls.lp = cls.get_loadparm(cls) + cls.username = os.environ["USERNAME"] + cls.password = os.environ["PASSWORD"] + cls.host = os.environ["SERVER"] + + c = Credentials() + c.set_username(cls.username) + c.set_password(cls.password) + try: + realm = os.environ["REALM"] + c.set_realm(realm) + except KeyError: + pass + try: + domain = os.environ["DOMAIN"] + c.set_domain(domain) + except KeyError: + pass + + c.guess() + + cls.credentials = c + + cls.session = system_session() + cls.ldb = SamDB(url="ldap://%s" % cls.host, + session_info=cls.session, + credentials=cls.credentials, + lp=cls.lp) + # fetch the dnsHostName from the RootDse + res = cls.ldb.search( + base="", expression="", scope=SCOPE_BASE, attrs=["dnsHostName"]) + cls.dns_host_name = str(res[0]['dnsHostName']) + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + self.accounts = [] + + def tearDown(self): + # Clean up any accounts created by create_account + for dn in self.accounts: + delete_force(self.ldb, dn) + + def create_account(self, name, machine_account=False, spn=None): + '''Create an account for testing. + The dn of the created account is added to self.accounts, + which is used by tearDown to clean up the created accounts. + ''' + dn = "cn=%s,%s" % (name, self.ldb.domain_dn()) + + # remove the account if it exists, this will happen if a previous test + # run failed + delete_force(self.ldb, dn) + if machine_account: + object_class = "computer" + account_name = "%s$" % name + account_control = str(UF_WORKSTATION_TRUST_ACCOUNT) + else: + object_class = "user" + account_name = name + account_control = str(UF_NORMAL_ACCOUNT) + + password = generate_random_password(32, 32) + utf16pw = ('"%s"' % password).encode('utf-16-le') + + details = { + "dn": dn, + "objectclass": object_class, + "sAMAccountName": account_name, + "userAccountControl": account_control, + "unicodePwd": utf16pw} + if spn is not None: + details["servicePrincipalName"] = spn + self.ldb.add(details) + + creds = Credentials() + creds.guess(self.lp) + creds.set_realm(self.ldb.domain_dns_name().upper()) + creds.set_domain(self.ldb.domain_netbios_name().upper()) + creds.set_password(password) + creds.set_username(account_name) + if machine_account: + creds.set_workstation(name) + # + # Save the account name so it can be deleted in the tearDown + self.accounts.append(dn) + + return (creds, dn) + + def as_req(self, cname, sname, realm, etypes, padata=None): + '''Send a Kerberos AS_REQ, returns the undecoded response + ''' + + till = self.get_KerberosTime(offset=36000) + kdc_options = 0 + + req = self.AS_REQ_create(padata=padata, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7fffffff, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None) + rep = self.send_recv_transaction(req) + return rep + + def get_as_rep_key(self, creds, rep): + '''Extract the session key from an AS-REP + ''' + rep_padata = self.der_decode( + rep['e-data'], + asn1Spec=krb5_asn1.METHOD_DATA()) + + for pa in rep_padata: + if pa['padata-type'] == PADATA_ETYPE_INFO2: + padata_value = pa['padata-value'] + break + + etype_info2 = self.der_decode( + padata_value, asn1Spec=krb5_asn1.ETYPE_INFO2()) + + key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) + return key + + def get_pa_data(self, creds, rep, skew=0): + '''generate the pa_data data element for an AS-REQ + ''' + key = self.get_as_rep_key(creds, rep) + + (patime, pausec) = self.get_KerberosTimeWithUsec(offset=skew) + padata = self.PA_ENC_TS_ENC_create(patime, pausec) + padata = self.der_encode(padata, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + usage = 1 + padata = self.EncryptedData_create(key, usage, padata) + padata = self.der_encode(padata, asn1Spec=krb5_asn1.EncryptedData()) + + padata = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, padata) + + return [padata] + + def get_as_rep_enc_data(self, key, rep): + ''' Decrypt and Decode the encrypted data in an AS-REP + ''' + usage = 3 + enc_part = key.decrypt(usage, rep['enc-part']['cipher']) + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with + # application tag 26 + try: + enc_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncASRepPart()) + except Exception: + enc_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) + + return enc_part + + def check_pre_authenication(self, rep): + """ Check that the kdc response was pre-authentication required + """ + self.check_error_rep(rep, KDC_ERR_PREAUTH_REQUIRED) + + def check_as_reply(self, rep): + """ Check that the kdc response is an AS-REP and that the + values for: + msg-type + pvno + tkt-pvno + kvno + match the expected values + """ + + # Should have a reply, and it should an AS-REP message. + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], KRB_AS_REP, "rep = {%s}" % rep) + + # Protocol version number should be 5 + pvno = int(rep['pvno']) + self.assertEqual(5, pvno, "rep = {%s}" % rep) + + # The ticket version number should be 5 + tkt_vno = int(rep['ticket']['tkt-vno']) + self.assertEqual(5, tkt_vno, "rep = {%s}" % rep) + + # Check that the kvno is not an RODC kvno + # MIT kerberos does not provide the kvno, so we treat it as optional. + # This is tested in compatability_test.py + if 'kvno' in rep['enc-part']: + kvno = int(rep['enc-part']['kvno']) + # If the high order bits are set this is an RODC kvno. + self.assertEqual(0, kvno & 0xFFFF0000, "rep = {%s}" % rep) + + def check_tgs_reply(self, rep): + """ Check that the kdc response is an TGS-REP and that the + values for: + msg-type + pvno + tkt-pvno + kvno + match the expected values + """ + + # Should have a reply, and it should an TGS-REP message. + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], KRB_TGS_REP, "rep = {%s}" % rep) + + # Protocol version number should be 5 + pvno = int(rep['pvno']) + self.assertEqual(5, pvno, "rep = {%s}" % rep) + + # The ticket version number should be 5 + tkt_vno = int(rep['ticket']['tkt-vno']) + self.assertEqual(5, tkt_vno, "rep = {%s}" % rep) + + # Check that the kvno is not an RODC kvno + # MIT kerberos does not provide the kvno, so we treat it as optional. + # This is tested in compatability_test.py + if 'kvno' in rep['enc-part']: + kvno = int(rep['enc-part']['kvno']) + # If the high order bits are set this is an RODC kvno. + self.assertEqual(0, kvno & 0xFFFF0000, "rep = {%s}" % rep) + + def check_error_rep(self, rep, expected): + """ Check that the reply is an error message, with the expected + error-code specified. + """ + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], KRB_ERROR, "rep = {%s}" % rep) + self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) + + def tgs_req(self, cname, sname, realm, ticket, key, etypes): + '''Send a TGS-REQ, returns the response and the decrypted and + decoded enc-part + ''' + + kdc_options = "0" + till = self.get_KerberosTime(offset=36000) + padata = [] + + subkey = self.RandomKey(key.etype) + subkey_usage = 9 + + (ctime, cusec) = self.get_KerberosTimeWithUsec() + + req = self.TGS_REQ_create(padata=padata, + cusec=cusec, + ctime=ctime, + ticket=ticket, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + from_time=None, + till_time=till, + renew_time=None, + nonce=0x7ffffffe, + etypes=etypes, + addresses=None, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + additional_tickets=None, + ticket_session_key=key, + authenticator_subkey=subkey) + rep = self.send_recv_transaction(req) + self.assertIsNotNone(rep) + + msg_type = rep['msg-type'] + enc_part = None + if msg_type == KRB_TGS_REP: + enc_part = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) + return (rep, enc_part) + + # Named tuple to contain values of interest when the PAC is decoded. + PacData = namedtuple( + "PacData", + "account_name account_sid logon_name upn domain_name") + PAC_LOGON_INFO = 1 + PAC_CREDENTIAL_INFO = 2 + PAC_SRV_CHECKSUM = 6 + PAC_KDC_CHECKSUM = 7 + PAC_LOGON_NAME = 10 + PAC_CONSTRAINED_DELEGATION = 11 + PAC_UPN_DNS_INFO = 12 + + def get_pac_data(self, authorization_data): + '''Decode the PAC element contained in the authorization-data element + ''' + account_name = None + user_sid = None + logon_name = None + upn = None + domain_name = None + + # The PAC data will be wrapped in an AD_IF_RELEVANT element + ad_if_relevant_elements = ( + x for x in authorization_data if x['ad-type'] == AD_IF_RELEVANT) + for dt in ad_if_relevant_elements: + buf = self.der_decode( + dt['ad-data'], asn1Spec=krb5_asn1.AD_IF_RELEVANT()) + # The PAC data is further wrapped in a AD_WIN2K_PAC element + for ad in (x for x in buf if x['ad-type'] == AD_WIN2K_PAC): + pb = ndr_unpack(krb5pac.PAC_DATA, ad['ad-data']) + for pac in pb.buffers: + if pac.type == self.PAC_LOGON_INFO: + account_name = ( + pac.info.info.info3.base.account_name) + user_sid = ( + str(pac.info.info.info3.base.domain_sid) + + "-" + str(pac.info.info.info3.base.rid)) + elif pac.type == self.PAC_LOGON_NAME: + logon_name = pac.info.account_name + elif pac.type == self.PAC_UPN_DNS_INFO: + upn = pac.info.upn_name + domain_name = pac.info.dns_domain_name + + return self.PacData( + account_name, + user_sid, + logon_name, + upn, + domain_name) + + def decode_service_ticket(self, creds, ticket): + '''Decrypt and decode a service ticket + ''' + + name = creds.get_username() + if name.endswith('$'): + name = name[:-1] + realm = creds.get_realm() + salt = "%s.%s@%s" % (name, realm.lower(), realm.upper()) + + key = self.PasswordKey_create( + ticket['enc-part']['etype'], + creds.get_password(), + salt, + ticket['enc-part']['kvno']) + + enc_part = key.decrypt(2, ticket['enc-part']['cipher']) + enc_ticket_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncTicketPart()) + return enc_ticket_part + + def get_objectSid(self, dn): + ''' Get the objectSID for a DN + Note: performs an Ldb query. + ''' + res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["objectSID"]) + self.assertTrue(len(res) == 1, "did not get objectSid for %s" % dn) + sid = self.ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + return sid.decode('utf8') -- 2.25.1 From c23166453f549e089d3270ec6d9184a0695a4c40 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Mon, 30 Nov 2020 14:19:15 +1300 Subject: [PATCH 057/645] tests python krb5: initial TGS tests Initial tests on the KDC TGS Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1ed461a142f68f5de5e21b873ebddfcf5ae0ca1e) --- python/samba/tests/krb5/kdc_base_test.py | 1 - python/samba/tests/krb5/kdc_tgs_tests.py | 210 +++++++++++++++++++ python/samba/tests/krb5/rfc4120_constants.py | 2 + python/samba/tests/usage.py | 2 + selftest/knownfail_mit_kdc | 5 + source4/selftest/tests.py | 3 + 6 files changed, 222 insertions(+), 1 deletion(-) mode change 100755 => 100644 python/samba/tests/krb5/kdc_base_test.py create mode 100755 python/samba/tests/krb5/kdc_tgs_tests.py diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py old mode 100755 new mode 100644 index 4fc7ee85ba9..1a823d173e3 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # Unix SMB/CIFS implementation. # Copyright (C) Stefan Metzmacher 2020 # Copyright (C) 2020 Catalyst.Net Ltd diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py new file mode 100755 index 00000000000..23a1d868a79 --- /dev/null +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KRB_ERROR, + KDC_ERR_BADMATCH, + NT_PRINCIPAL, + NT_SRV_INST, +) + +global_asn1_print = False +global_hexdump = False + + +class KdcTgsTests(KDCBaseTest): + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def test_tgs_req_cname_does_not_not_match_authenticator_cname(self): + ''' Try and obtain a ticket from the TGS, but supply a cname + that differs from that provided to the krbtgt + ''' + # Create the user account + user_name = "tsttktusr" + (uc, _) = self.create_account(user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96,) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a service ticket, but use a cname that does not match + # that in the original AS-REQ + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + ticket = rep['ticket'] + + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=["Administrator"]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=["host", self.dns_host_name]) + + (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype) + + self.assertIsNone( + enc_part, + "rep = {%s}, enc_part = {%s}" % (rep, enc_part)) + self.assertEqual(KRB_ERROR, rep['msg-type'], "rep = {%s}" % rep) + self.assertEqual( + KDC_ERR_BADMATCH, + rep['error-code'], + "rep = {%s}" % rep) + + def test_ldap_service_ticket(self): + '''Get a ticket to the ldap service + ''' + # Create the user account + user_name = "tsttktusr" + (uc, _) = self.create_account(user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96,) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + ticket = rep['ticket'] + + # Request a ticket to the ldap service + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, + names=["ldap", self.dns_host_name]) + + (rep, _) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + + self.check_tgs_reply(rep) + + def test_get_ticket_for_host_service_of_machine_account(self): + + # Create a user and machine account for the test. + # + user_name = "tsttktusr" + (uc, dn) = self.create_account(user_name) + (mc, _) = self.create_account("tsttktmac", machine_account=True) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the service ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + + pac_data = self.get_pac_data(enc_part['authorization-data']) + sid = self.get_objectSid(dn) + upn = "%s@%s" % (uc.get_username(), realm) + self.assertEqual( + uc.get_username(), + str(pac_data.account_name), + "rep = {%s},%s" % (rep, pac_data)) + self.assertEqual( + uc.get_username(), + pac_data.logon_name, + "rep = {%s},%s" % (rep, pac_data)) + self.assertEqual( + uc.get_realm(), + pac_data.domain_name, + "rep = {%s},%s" % (rep, pac_data)) + self.assertEqual( + upn, + pac_data.upn, + "rep = {%s},%s" % (rep, pac_data)) + self.assertEqual( + sid, + pac_data.account_sid, + "rep = {%s},%s" % (rep, pac_data)) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index e1d0c5baa68..19bb6691d43 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -28,6 +28,7 @@ ARCFOUR_HMAC_MD5 = int( # Message types KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) +KRB_TGS_REP = int(krb5_asn1.MessageTypeValues('krb-tgs-rep')) # PAData types PADATA_ENC_TIMESTAMP = int( @@ -39,6 +40,7 @@ PADATA_ETYPE_INFO2 = int( KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 +KDC_ERR_BADMATCH = 36 KDC_ERR_SKEW = 37 # Name types diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 35abaf2dafa..222d1dbfa41 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -93,6 +93,8 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/compatability_tests.py', 'python/samba/tests/krb5/rfc4120_constants.py', 'python/samba/tests/krb5/kdc_tests.py', + 'python/samba/tests/krb5/kdc_base_test.py', + 'python/samba/tests/krb5/kdc_tgs_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index f1a4971430e..e64303c6b0f 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -270,3 +270,8 @@ 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_UpperUserName_RemoveDollar_AsReqSelf\( ^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN_AsReqSelf\( ^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +# +# MIT currently returns an error code of 12 KRB5KDC_ERR_POLICY: KDC policy rejects request, to the +# following tests +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_ldap_service_ticket\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index f72060e9870..b2a09b3ecb2 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1287,6 +1287,9 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests") planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests") planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") +planpythontestsuite( + "ad_dc", + "samba.tests.krb5.kdc_tgs_tests") for env in [ 'vampire_dc', -- 2.25.1 From 92d6db2c1ac72eead9a6b5b385152c451b02f140 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 10 Dec 2020 16:26:06 +1300 Subject: [PATCH 058/645] tests python krb5: Add key usage constants Signed-off-by: Gary Lockyer Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d8ed73b75ad67da99be392b2db18fe2e1ffed87f) --- python/samba/tests/krb5/rfc4120_constants.py | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 19bb6691d43..9de56578c99 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -63,3 +63,53 @@ AD_MANDATORY_FOR_KDC = 8 AD_INITIAL_VERIFIED_CAS = 9 AD_WIN2K_PAC = 128 AD_SIGNTICKET = 512 + +# Key usage numbers +# RFC 4120 Section 7.5.1. Key Usage Numbers +KU_PA_ENC_TIMESTAMP = 1 +''' AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the + client key (section 5.2.7.2) ''' +KU_TICKET = 2 +''' AS-REP Ticket and TGS-REP Ticket (includes tgs session key or + application session key), encrypted with the service key + (section 5.3) ''' +KU_AS_REP_ENC_PART = 3 +''' AS-REP encrypted part (includes tgs session key or application + session key), encrypted with the client key (section 5.4.2) ''' +KU_TGS_REQ_AUTH_DAT_SESSION = 4 +''' TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + session key (section 5.4.1) ''' +KU_TGS_REQ_AUTH_DAT_SUBKEY = 5 +''' TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + authenticator subkey (section 5.4.1) ''' +KU_TGS_REQ_AUTH_CKSUM = 6 +''' TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, keyed + with the tgs session key (section 5.5.1) ''' +KU_TGS_REQ_AUTH = 7 +''' TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes tgs + authenticator subkey), encrypted with the tgs session key + (section 5.5.1) ''' +KU_TGS_REP_ENC_PART_SESSION = 8 +''' TGS-REP encrypted part (includes application session key), + encrypted with the tgs session key (section 5.4.2) ''' +KU_TGS_REP_ENC_PART_SUB_KEY = 9 +''' TGS-REP encrypted part (includes application session key), + encrypted with the tgs authenticator subkey (section 5.4.2) ''' +KU_AP_REQ_AUTH_CKSUM = 10 +''' AP-REQ Authenticator cksum, keyed with the application session + key (section 5.5.1) ''' +KU_AP_REQ_AUTH = 11 +''' AP-REQ Authenticator (includes application authenticator + subkey), encrypted with the application session key (section 5.5.1) ''' +KU_AP_REQ_ENC_PART = 12 +''' AP-REP encrypted part (includes application session subkey), + encrypted with the application session key (section 5.5.2) ''' +KU_KRB_PRIV = 13 +''' KRB-PRIV encrypted part, encrypted with a key chosen by the + application (section 5.7.1) ''' +KU_KRB_CRED = 14 +''' KRB-CRED encrypted part, encrypted with a key chosen by the + application (section 5.8.1) ''' +KU_KRB_SAFE_CKSUM = 15 +''' KRB-SAFE cksum, keyed with a key chosen by the application + (section 5.6.1) ''' -- 2.25.1 From 827e21e2653310af463dd1df186065d6b16a74c1 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 10 Dec 2020 16:27:17 +1300 Subject: [PATCH 059/645] tests python krb5: use key usage constants Signed-off-by: Gary Lockyer Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 03676a4a5c55ab5f4958a86cbd4d7be0f0a8a294) --- .../tests/krb5/as_canonicalization_tests.py | 5 ++--- python/samba/tests/krb5/compatability_tests.py | 7 +++---- python/samba/tests/krb5/kdc_base_test.py | 16 +++++++++------- python/samba/tests/krb5/kdc_tests.py | 3 +-- python/samba/tests/krb5/s4u_tests.py | 15 +++++++++------ python/samba/tests/krb5/simple_tests.py | 15 +++++++++------ python/samba/tests/krb5/xrealm_tests.py | 15 +++++++++------ 7 files changed, 42 insertions(+), 34 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 6ea3ff0491e..e89b40eab8f 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -367,8 +367,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) @@ -413,7 +412,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): self.assertEqual(msg_type, KRB_AS_REP, "Data {0}".format(str(data))) # Decrypt and decode the EncKdcRepPart - enc = key.decrypt(3, rep['enc-part']['cipher']) + enc = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) if enc[0] == 0x7A: # MIT Kerberos Tags the EncASRepPart as a EncKDCRepPart # i.e. tag number 26 instead of tag number 25 diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index e4b1453e712..0b3701cd60d 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -178,8 +178,7 @@ class SimpleKerberosTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) @@ -207,9 +206,9 @@ class SimpleKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, KRB_AS_REP) - usage = 3 enc_part = rep['enc-part'] - enc_as_rep_part = key.decrypt(usage, rep['enc-part']['cipher']) + enc_as_rep_part = key.decrypt( + KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) return (enc_as_rep_part, enc_part) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1a823d173e3..e835d389f1c 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -41,6 +41,10 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_AS_REP, KRB_TGS_REP, KRB_ERROR, + KU_AS_REP_ENC_PART, + KU_PA_ENC_TIMESTAMP, + KU_TGS_REP_ENC_PART_SUB_KEY, + KU_TICKET, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO2, ) @@ -196,8 +200,7 @@ class KDCBaseTest(RawKerberosTest): padata = self.PA_ENC_TS_ENC_create(patime, pausec) padata = self.der_encode(padata, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - usage = 1 - padata = self.EncryptedData_create(key, usage, padata) + padata = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, padata) padata = self.der_encode(padata, asn1Spec=krb5_asn1.EncryptedData()) padata = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, padata) @@ -207,8 +210,7 @@ class KDCBaseTest(RawKerberosTest): def get_as_rep_enc_data(self, key, rep): ''' Decrypt and Decode the encrypted data in an AS-REP ''' - usage = 3 - enc_part = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with # application tag 26 try: @@ -303,7 +305,6 @@ class KDCBaseTest(RawKerberosTest): padata = [] subkey = self.RandomKey(key.etype) - subkey_usage = 9 (ctime, cusec) = self.get_KerberosTimeWithUsec() @@ -332,7 +333,8 @@ class KDCBaseTest(RawKerberosTest): msg_type = rep['msg-type'] enc_part = None if msg_type == KRB_TGS_REP: - enc_part = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part = subkey.decrypt( + KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part = self.der_decode( enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) return (rep, enc_part) @@ -403,7 +405,7 @@ class KDCBaseTest(RawKerberosTest): salt, ticket['enc-part']['kvno']) - enc_part = key.decrypt(2, ticket['enc-part']['cipher']) + enc_part = key.decrypt(KU_TICKET, ticket['enc-part']['cipher']) enc_ticket_part = self.der_decode( enc_part, asn1Spec=krb5_asn1.EncTicketPart()) return enc_ticket_part diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py index 57a25448965..17b9d154bd9 100755 --- a/python/samba/tests/krb5/kdc_tests.py +++ b/python/samba/tests/krb5/kdc_tests.py @@ -91,8 +91,7 @@ class KdcTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index ae38635c53b..2e1bd3fbe1f 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -25,6 +25,11 @@ os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests import env_get_var_value from samba.tests.krb5.kcrypto import Cksumtype from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.rfc4120_constants import ( + KU_PA_ENC_TIMESTAMP, + KU_AS_REP_ENC_PART, + KU_TGS_REP_ENC_PART_SUB_KEY, +) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 global_asn1_print = False @@ -86,8 +91,7 @@ class S4UKerberosTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) @@ -115,8 +119,7 @@ class S4UKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, 11) - usage = 3 - enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) # S4U2Self Request @@ -135,7 +138,6 @@ class S4UKerberosTests(RawKerberosTest): padata = [pa_s4u] subkey = self.RandomKey(ticket_session_key.etype) - subkey_usage = 9 (ctime, cusec) = self.get_KerberosTimeWithUsec() @@ -163,7 +165,8 @@ class S4UKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] if msg_type == 13: - enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = subkey.decrypt( + KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return msg_type diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 236fbda1cd5..6c090af3d46 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -23,6 +23,11 @@ sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.rfc4120_constants import ( + KU_AS_REP_ENC_PART, + KU_PA_ENC_TIMESTAMP, + KU_TGS_REP_ENC_PART_SUB_KEY, +) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 global_asn1_print = False @@ -84,8 +89,7 @@ class SimpleKerberosTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) @@ -113,8 +117,7 @@ class SimpleKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, 11) - usage = 3 - enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 try: @@ -134,7 +137,6 @@ class SimpleKerberosTests(RawKerberosTest): padata = [] subkey = self.RandomKey(ticket_session_key.etype) - subkey_usage = 9 (ctime, cusec) = self.get_KerberosTimeWithUsec() @@ -163,7 +165,8 @@ class SimpleKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, 13) - enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = subkey.decrypt( + KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return diff --git a/python/samba/tests/krb5/xrealm_tests.py b/python/samba/tests/krb5/xrealm_tests.py index 64064b8a670..b4a02bff33a 100755 --- a/python/samba/tests/krb5/xrealm_tests.py +++ b/python/samba/tests/krb5/xrealm_tests.py @@ -23,6 +23,11 @@ sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.rfc4120_constants import ( + KU_PA_ENC_TIMESTAMP, + KU_AS_REP_ENC_PART, + KU_TGS_REP_ENC_PART_SUB_KEY, +) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 import samba.tests @@ -85,8 +90,7 @@ class XrealmKerberosTests(RawKerberosTest): pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) - enc_pa_ts_usage = 1 - pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) + pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) @@ -114,8 +118,7 @@ class XrealmKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, 11) - usage = 3 - enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) + enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 try: @@ -134,7 +137,6 @@ class XrealmKerberosTests(RawKerberosTest): padata = [] subkey = self.RandomKey(ticket_session_key.etype) - subkey_usage = 9 (ctime, cusec) = self.get_KerberosTimeWithUsec() @@ -163,7 +165,8 @@ class XrealmKerberosTests(RawKerberosTest): msg_type = rep['msg-type'] self.assertEqual(msg_type, 13) - enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) + enc_part2 = subkey.decrypt( + KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # Check the forwardable flag -- 2.25.1 From c139411bf2beeb3e95025c8ec29788dea7ba006c Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Fri, 11 Dec 2020 11:55:01 +1300 Subject: [PATCH 060/645] tests python krb5: PEP8 cleanups Fix all the PEP8 warnings in samba/tests/krb5. With the exception of rfc4120_pyasn1.py, which is generated from rfc4120.asn1. As these tests are new, it makes sense to ensure that they conform to PEP8. And set an aspirational goal for the rest of our python code. Signed-off-by: Gary Lockyer Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Gary Lockyer Autobuild-Date(master): Mon Dec 21 21:29:28 UTC 2020 on sn-devel-184 (cherry picked from commit c00d537526ca881c540ff66e703ad9c96dd1face) --- .../tests/krb5/as_canonicalization_tests.py | 54 ++- .../samba/tests/krb5/compatability_tests.py | 24 +- python/samba/tests/krb5/kcrypto.py | 67 +-- python/samba/tests/krb5/kdc_base_test.py | 4 +- python/samba/tests/krb5/kdc_tests.py | 17 +- python/samba/tests/krb5/raw_testcase.py | 409 +++++++++++------- python/samba/tests/krb5/rfc4120_constants.py | 32 +- python/samba/tests/krb5/s4u_tests.py | 19 +- python/samba/tests/krb5/simple_tests.py | 24 +- python/samba/tests/krb5/xrealm_tests.py | 26 +- 10 files changed, 413 insertions(+), 263 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index e89b40eab8f..43f532dc483 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -31,8 +31,6 @@ import samba from samba.auth import system_session from samba.credentials import ( Credentials, - CLI_CRED_NTLMv2_AUTH, - CLI_CRED_NTLM_AUTH, DONT_USE_KERBEROS) from samba.dcerpc.misc import SEC_CHAN_WKSTA from samba.dsdb import ( @@ -41,7 +39,20 @@ from samba.dsdb import ( UF_NORMAL_ACCOUNT) from samba.samdb import SamDB from samba.tests import delete_force, DynamicTestCase -from samba.tests.krb5.rfc4120_constants import * +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + AES128_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_PREAUTH_REQUIRED, + KRB_AS_REP, + KU_AS_REP_ENC_PART, + KRB_ERROR, + KU_PA_ENC_TIMESTAMP, + PADATA_ENC_TIMESTAMP, + NT_ENTERPRISE_PRINCIPAL, + NT_PRINCIPAL, + NT_SRV_INST, +) global_asn1_print = False global_hexdump = False @@ -49,15 +60,15 @@ global_hexdump = False @unique class TestOptions(Enum): - Canonicalize = 1 - Enterprise = 2 - UpperRealm = 4 - UpperUserName = 8 - NetbiosRealm = 16 - UPN = 32 - RemoveDollar = 64 - AsReqSelf = 128 - Last = 256 + Canonicalize = 1 + Enterprise = 2 + UpperRealm = 4 + UpperUserName = 8 + NetbiosRealm = 16 + UPN = 32 + RemoveDollar = 64 + AsReqSelf = 128 + Last = 256 def is_set(self, x): return self.value & x @@ -65,7 +76,7 @@ class TestOptions(Enum): @unique class CredentialsType(Enum): - User = 1 + User = 1 Machine = 2 def is_set(self, x): @@ -126,7 +137,8 @@ class TestData: MACHINE_NAME = "tstkrb5cnnmch" -USER_NAME = "tstkrb5cnnusr" +USER_NAME = "tstkrb5cnnusr" + @DynamicTestCase class KerberosASCanonicalizationTests(RawKerberosTest): @@ -160,21 +172,21 @@ class KerberosASCanonicalizationTests(RawKerberosTest): @classmethod def setUpClass(cls): - cls.lp = cls.get_loadparm(cls) + cls.lp = cls.get_loadparm(cls) cls.username = os.environ["USERNAME"] cls.password = os.environ["PASSWORD"] - cls.host = os.environ["SERVER"] + cls.host = os.environ["SERVER"] c = Credentials() c.set_username(cls.username) c.set_password(cls.password) try: - realm = os.environ["REALM"] + realm = os.environ["REALM"] c.set_realm(realm) except KeyError: pass try: - domain = os.environ["DOMAIN"] + domain = os.environ["DOMAIN"] c.set_domain(domain) except KeyError: pass @@ -200,7 +212,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): def setUp(self): super(KerberosASCanonicalizationTests, self).setUp() self.do_asn1_print = global_asn1_print - self.do_hexdump = global_hexdump + self.do_hexdump = global_hexdump # # Create a test user account @@ -340,7 +352,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): # # Check the protocol version, should be 5 self.assertEqual( - rep['pvno'], 5, "Data {0}".format(str(data))) + rep['pvno'], 5, "Data {0}".format(str(data))) self.assertEqual( rep['msg-type'], KRB_ERROR, "Data {0}".format(str(data))) @@ -397,7 +409,7 @@ class KerberosASCanonicalizationTests(RawKerberosTest): # # Check the protocol version, should be 5 self.assertEqual( - rep['pvno'], 5, "Data {0}".format(str(data))) + rep['pvno'], 5, "Data {0}".format(str(data))) msg_type = rep['msg-type'] # Should not have got an error. diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index 0b3701cd60d..5a1ef02ef80 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -25,7 +25,20 @@ os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests.krb5.raw_testcase import RawKerberosTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 -from samba.tests.krb5.rfc4120_constants import * +from samba.tests.krb5.rfc4120_constants import ( + AES128_CTS_HMAC_SHA1_96, + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_PREAUTH_REQUIRED, + KRB_AS_REP, + KRB_ERROR, + KU_AS_REP_ENC_PART, + KU_PA_ENC_TIMESTAMP, + PADATA_ENC_TIMESTAMP, + PADATA_ETYPE_INFO2, + NT_PRINCIPAL, + NT_SRV_INST, +) global_asn1_print = False global_hexdump = False @@ -112,18 +125,17 @@ class SimpleKerberosTests(RawKerberosTest): realm = creds.get_realm() cname = self.PrincipalName_create( - name_type=NT_PRINCIPAL, - names=[user]) + name_type=NT_PRINCIPAL, + names=[user]) sname = self.PrincipalName_create( - name_type=NT_SRV_INST, - names=["krbtgt", realm]) + name_type=NT_SRV_INST, + names=["krbtgt", realm]) till = self.get_KerberosTime(offset=36000) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), cname=cname, diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index 2572fa5bab3..23502d7bb62 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -64,6 +64,7 @@ from samba.credentials import Credentials from samba import generate_random_bytes as get_random_bytes from samba.compat import get_string, get_bytes + class Enctype(object): DES_CRC = 1 DES_MD4 = 2 @@ -112,26 +113,30 @@ def _mac_equal(mac1, mac2): res |= x ^ y return res == 0 + def SIMPLE_HASH(string, algo_cls): hash_ctx = hashes.Hash(algo_cls(), default_backend()) hash_ctx.update(string) return hash_ctx.finalize() + def HMAC_HASH(key, string, algo_cls): hmac_ctx = hmac.HMAC(key, algo_cls(), default_backend()) hmac_ctx.update(string) return hmac_ctx.finalize() + def _nfold(str, nbytes): # Convert str to a string of length nbytes using the RFC 3961 nfold # operation. # Rotate the bytes in str to the right by nbits bits. def rotate_right(str, nbits): - nbytes, remain = (nbits//8) % len(str), nbits % 8 - return bytes([(str[i-nbytes] >> remain) | - (str[i-nbytes-1] << (8-remain) & 0xff) - for i in range(len(str))]) + nbytes, remain = (nbits // 8) % len(str), nbits % 8 + return bytes([ + (str[i - nbytes] >> remain) + | (str[i - nbytes - 1] << (8 - remain) & 0xff) + for i in range(len(str))]) # Add equal-length strings together with end-around carry. def add_ones_complement(str1, str2): @@ -139,7 +144,7 @@ def _nfold(str, nbytes): v = [a + b for a, b in zip(str1, str2)] # Propagate carry bits to the left until there aren't any left. while any(x & ~0xff for x in v): - v = [(v[i-n+1]>>8) + (v[i]&0xff) for i in range(n)] + v = [(v[i - n + 1] >> 8) + (v[i] & 0xff) for i in range(n)] return bytes([x for x in v]) # Concatenate copies of str to produce the least common multiple @@ -150,7 +155,7 @@ def _nfold(str, nbytes): slen = len(str) lcm = nbytes * slen // gcd(nbytes, slen) bigstr = b''.join((rotate_right(str, 13 * i) for i in range(lcm // slen))) - slices = (bigstr[p:p+nbytes] for p in range(0, lcm, nbytes)) + slices = (bigstr[p:p + nbytes] for p in range(0, lcm, nbytes)) return reduce(add_ones_complement, slices) @@ -275,7 +280,7 @@ class _DES3CBC(_SimplifiedEnctype): return b if bin(b & ~1).count('1') % 2 else b | 1 assert len(seed) == 7 firstbytes = [parity(b & ~1) for b in seed] - lastbyte = parity(sum((seed[i]&1) << i+1 for i in range(7))) + lastbyte = parity(sum((seed[i] & 1) << i + 1 for i in range(7))) keybytes = bytes([b for b in firstbytes + [lastbyte]]) if _is_weak_des_key(keybytes): keybytes[7] = bytes([keybytes[7] ^ 0xF0]) @@ -369,7 +374,7 @@ class _AESEnctype(_SimplifiedEnctype): if len(ciphertext) == 16: return aes_decrypt(ciphertext) # Split the ciphertext into blocks. The last block may be partial. - cblocks = [ciphertext[p:p+16] for p in range(0, len(ciphertext), 16)] + cblocks = [ciphertext[p:p + 16] for p in range(0, len(ciphertext), 16)] lastlen = len(cblocks[-1]) # CBC-decrypt all but the last two blocks. prev_cblock = bytes(16) @@ -383,7 +388,7 @@ class _AESEnctype(_SimplifiedEnctype): # will be the omitted bytes of ciphertext from the final # block. b = aes_decrypt(cblocks[-2]) - lastplaintext =_xorbytes(b[:lastlen], cblocks[-1]) + lastplaintext = _xorbytes(b[:lastlen], cblocks[-1]) omitted = b[lastlen:] # Decrypt the final cipher block plus the omitted bytes to get # the second-to-last plaintext block. @@ -433,7 +438,8 @@ class _RC4(_EnctypeProfile): cksum = HMAC_HASH(ki, confounder + plaintext, hashes.MD5) ke = HMAC_HASH(ki, cksum, hashes.MD5) - encryptor = Cipher(ciphers.ARC4(ke), None, default_backend()).encryptor() + encryptor = Cipher( + ciphers.ARC4(ke), None, default_backend()).encryptor() ctext = encryptor.update(confounder + plaintext) return cksum + ctext @@ -446,7 +452,8 @@ class _RC4(_EnctypeProfile): ki = HMAC_HASH(key.contents, cls.usage_str(keyusage), hashes.MD5) ke = HMAC_HASH(ki, cksum, hashes.MD5) - decryptor = Cipher(ciphers.ARC4(ke), None, default_backend()).decryptor() + decryptor = Cipher( + ciphers.ARC4(ke), None, default_backend()).decryptor() basic_plaintext = decryptor.update(basic_ctext) exp_cksum = HMAC_HASH(ki, basic_plaintext, hashes.MD5) @@ -636,14 +643,14 @@ def verify_checksum(cksumtype, key, keyusage, text, cksum): c.verify(key, keyusage, text, cksum) -def prfplus(key, pepper, l): - # Produce l bytes of output using the RFC 6113 PRF+ function. +def prfplus(key, pepper, ln): + # Produce ln bytes of output using the RFC 6113 PRF+ function. out = b'' count = 1 - while len(out) < l: + while len(out) < ln: out += prf(key, bytes([count]) + pepper) count += 1 - return out[:l] + return out[:ln] def cf2(enctype, key1, key2, pepper1, pepper2): @@ -653,9 +660,11 @@ def cf2(enctype, key1, key2, pepper1, pepper2): return e.random_to_key(_xorbytes(prfplus(key1, pepper1, e.seedsize), prfplus(key2, pepper2, e.seedsize))) + def h(hexstr): return bytes.fromhex(hexstr) + class KcrytoTest(TestCase): """kcrypto Test case.""" @@ -665,20 +674,21 @@ class KcrytoTest(TestCase): conf = h('94B491F481485B9A0678CD3C4EA386AD') keyusage = 2 plain = b'9 bytesss' - ctxt = h('68FB9679601F45C78857B2BF820FD6E53ECA8D42FD4B1D7024A09205ABB7CD2E' - 'C26C355D2F') + ctxt = h('68FB9679601F45C78857B2BF820FD6E53ECA8D42FD4B1D7024A09205ABB7' + 'CD2EC26C355D2F') k = Key(Enctype.AES128, kb) self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) self.assertEqual(decrypt(k, keyusage, ctxt), plain) def test_aes256_crypt(self): # AES256 encrypt and decrypt - kb = h('F1C795E9248A09338D82C3F8D5B567040B0110736845041347235B1404231398') + kb = h('F1C795E9248A09338D82C3F8D5B567040B0110736845041347235B14042313' + '98') conf = h('E45CA518B42E266AD98E165E706FFB60') keyusage = 4 plain = b'30 bytes bytes bytes bytes byt' - ctxt = h('D1137A4D634CFECE924DBC3BF6790648BD5CFF7DE0E7B99460211D0DAEF3D79A' - '295C688858F3B34B9CBD6EEBAE81DAF6B734D4D498B6714F1C1D') + ctxt = h('D1137A4D634CFECE924DBC3BF6790648BD5CFF7DE0E7B99460211D0DAEF3' + 'D79A295C688858F3B34B9CBD6EEBAE81DAF6B734D4D498B6714F1C1D') k = Key(Enctype.AES256, kb) self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) self.assertEqual(decrypt(k, keyusage, ctxt), plain) @@ -694,7 +704,8 @@ class KcrytoTest(TestCase): def test_aes256_checksum(self): # AES256 checksum - kb = h('B1AE4CD8462AFF1677053CC9279AAC30B796FB81CE21474DD3DDBCFEA4EC76D7') + kb = h('B1AE4CD8462AFF1677053CC9279AAC30B796FB81CE21474DD3DDBC' + 'FEA4EC76D7') keyusage = 4 plain = b'fourteen' cksum = h('E08739E3279E2903EC8E3836') @@ -715,7 +726,8 @@ class KcrytoTest(TestCase): string = b'X' * 64 salt = b'pass phrase equals block size' params = h('000004B0') - kb = h('89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56C553BA4B34') + kb = h('89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56' + 'C553BA4B34') k = string_to_key(Enctype.AES256, string, salt, params) self.assertEqual(k.contents, kb) @@ -741,7 +753,8 @@ class KcrytoTest(TestCase): def test_aes256_cf2(self): # AES256 cf2 - kb = h('4D6CA4E629785C1F01BAF55E2E548566B9617AE3A96868C337CB93B5E72B1C7B') + kb = h('4D6CA4E629785C1F01BAF55E2E548566B9617AE3A96868C337CB93B5' + 'E72B1C7B') k1 = string_to_key(Enctype.AES256, b'key1', b'key1') k2 = string_to_key(Enctype.AES256, b'key2', b'key2') k = cf2(Enctype.AES256, k1, k2, b'a', b'b') @@ -753,8 +766,8 @@ class KcrytoTest(TestCase): conf = h('94690A17B2DA3C9B') keyusage = 3 plain = b'13 bytes byte' - ctxt = h('839A17081ECBAFBCDC91B88C6955DD3C4514023CF177B77BF0D0177A16F705E8' - '49CB7781D76A316B193F8D30') + ctxt = h('839A17081ECBAFBCDC91B88C6955DD3C4514023CF177B77BF0D0177A16F7' + '05E849CB7781D76A316B193F8D30') k = Key(Enctype.DES3, kb) self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) self.assertEqual(decrypt(k, keyusage, ctxt), _zeropad(plain, 8)) @@ -790,8 +803,8 @@ class KcrytoTest(TestCase): conf = h('37245E73A45FBF72') keyusage = 4 plain = b'30 bytes bytes bytes bytes byt' - ctxt = h('95F9047C3AD75891C2E9B04B16566DC8B6EB9CE4231AFB2542EF87A7B5A0F260' - 'A99F0460508DE0CECC632D07C354124E46C5D2234EB8') + ctxt = h('95F9047C3AD75891C2E9B04B16566DC8B6EB9CE4231AFB2542EF87A7B5A0' + 'F260A99F0460508DE0CECC632D07C354124E46C5D2234EB8') k = Key(Enctype.RC4, kb) self.assertEqual(encrypt(k, keyusage, plain, conf), ctxt) self.assertEqual(decrypt(k, keyusage, ctxt), plain) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e835d389f1c..bef5458c881 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -374,8 +374,8 @@ class KDCBaseTest(RawKerberosTest): account_name = ( pac.info.info.info3.base.account_name) user_sid = ( - str(pac.info.info.info3.base.domain_sid) + - "-" + str(pac.info.info.info3.base.rid)) + str(pac.info.info.info3.base.domain_sid) + + "-" + str(pac.info.info.info3.base.rid)) elif pac.type == self.PAC_LOGON_NAME: logon_name = pac.info.account_name elif pac.type == self.PAC_UPN_DNS_INFO: diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py index 17b9d154bd9..c7c53953a86 100755 --- a/python/samba/tests/krb5/kdc_tests.py +++ b/python/samba/tests/krb5/kdc_tests.py @@ -25,7 +25,20 @@ os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests.krb5.raw_testcase import RawKerberosTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 -from samba.tests.krb5.rfc4120_constants import * +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_PREAUTH_FAILED, + KDC_ERR_PREAUTH_REQUIRED, + KDC_ERR_SKEW, + KRB_AS_REP, + KRB_ERROR, + KU_PA_ENC_TIMESTAMP, + PADATA_ENC_TIMESTAMP, + PADATA_ETYPE_INFO2, + NT_PRINCIPAL, + NT_SRV_INST, +) global_asn1_print = False global_hexdump = False @@ -83,7 +96,7 @@ class KdcTests(RawKerberosTest): break etype_info2 = self.der_decode( - etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e67f5464e59..82e68ee7019 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -35,7 +35,10 @@ from pyasn1.codec.native.decoder import decode as pyasn1_native_decode from pyasn1.codec.native.encoder import encode as pyasn1_native_encode from pyasn1.codec.ber.encoder import BitStringEncoder as BitStringEncoder -def BitStringEncoder_encodeValue32(self, value, asn1Spec, encodeFun, **options): + + +def BitStringEncoder_encodeValue32( + self, value, asn1Spec, encodeFun, **options): # # BitStrings like KDCOptions or TicketFlags should at least # be 32-Bit on the wire @@ -59,14 +62,17 @@ def BitStringEncoder_encodeValue32(self, value, asn1Spec, encodeFun, **options): padding = 0 ret = b'\x00' + substrate + (b'\x00' * padding) return ret, False, True + + BitStringEncoder.encodeValue = BitStringEncoder_encodeValue32 + def BitString_NamedValues_prettyPrint(self, scope=0): ret = "%s" % self.asBinary() bits = [] highest_bit = 32 for byte in self.asNumbers(): - for bit in [7,6,5,4,3,2,1,0]: + for bit in [7, 6, 5, 4, 3, 2, 1, 0]: mask = 1 << bit if byte & mask: val = 1 @@ -89,12 +95,21 @@ def BitString_NamedValues_prettyPrint(self, scope=0): delim = ",\n%s " % indent ret += "\n%s)" % indent return ret -krb5_asn1.TicketFlags.prettyPrintNamedValues = krb5_asn1.TicketFlagsValues.namedValues -krb5_asn1.TicketFlags.namedValues = krb5_asn1.TicketFlagsValues.namedValues -krb5_asn1.TicketFlags.prettyPrint = BitString_NamedValues_prettyPrint -krb5_asn1.KDCOptions.prettyPrintNamedValues = krb5_asn1.KDCOptionsValues.namedValues -krb5_asn1.KDCOptions.namedValues = krb5_asn1.KDCOptionsValues.namedValues -krb5_asn1.KDCOptions.prettyPrint = BitString_NamedValues_prettyPrint + + +krb5_asn1.TicketFlags.prettyPrintNamedValues =\ + krb5_asn1.TicketFlagsValues.namedValues +krb5_asn1.TicketFlags.namedValues =\ + krb5_asn1.TicketFlagsValues.namedValues +krb5_asn1.TicketFlags.prettyPrint =\ + BitString_NamedValues_prettyPrint +krb5_asn1.KDCOptions.prettyPrintNamedValues =\ + krb5_asn1.KDCOptionsValues.namedValues +krb5_asn1.KDCOptions.namedValues =\ + krb5_asn1.KDCOptionsValues.namedValues +krb5_asn1.KDCOptions.prettyPrint =\ + BitString_NamedValues_prettyPrint + def Integer_NamedValues_prettyPrint(self, scope=0): intval = int(self) @@ -104,16 +119,29 @@ def Integer_NamedValues_prettyPrint(self, scope=0): name = "<__unknown__>" ret = "%d (0x%x) %s" % (intval, intval, name) return ret -krb5_asn1.NameType.prettyPrintNamedValues = krb5_asn1.NameTypeValues.namedValues -krb5_asn1.NameType.prettyPrint = Integer_NamedValues_prettyPrint -krb5_asn1.AuthDataType.prettyPrintNamedValues = krb5_asn1.AuthDataTypeValues.namedValues -krb5_asn1.AuthDataType.prettyPrint = Integer_NamedValues_prettyPrint -krb5_asn1.PADataType.prettyPrintNamedValues = krb5_asn1.PADataTypeValues.namedValues -krb5_asn1.PADataType.prettyPrint = Integer_NamedValues_prettyPrint -krb5_asn1.EncryptionType.prettyPrintNamedValues = krb5_asn1.EncryptionTypeValues.namedValues -krb5_asn1.EncryptionType.prettyPrint = Integer_NamedValues_prettyPrint -krb5_asn1.ChecksumType.prettyPrintNamedValues = krb5_asn1.ChecksumTypeValues.namedValues -krb5_asn1.ChecksumType.prettyPrint = Integer_NamedValues_prettyPrint + + +krb5_asn1.NameType.prettyPrintNamedValues =\ + krb5_asn1.NameTypeValues.namedValues +krb5_asn1.NameType.prettyPrint =\ + Integer_NamedValues_prettyPrint +krb5_asn1.AuthDataType.prettyPrintNamedValues =\ + krb5_asn1.AuthDataTypeValues.namedValues +krb5_asn1.AuthDataType.prettyPrint =\ + Integer_NamedValues_prettyPrint +krb5_asn1.PADataType.prettyPrintNamedValues =\ + krb5_asn1.PADataTypeValues.namedValues +krb5_asn1.PADataType.prettyPrint =\ + Integer_NamedValues_prettyPrint +krb5_asn1.EncryptionType.prettyPrintNamedValues =\ + krb5_asn1.EncryptionTypeValues.namedValues +krb5_asn1.EncryptionType.prettyPrint =\ + Integer_NamedValues_prettyPrint +krb5_asn1.ChecksumType.prettyPrintNamedValues =\ + krb5_asn1.ChecksumTypeValues.namedValues +krb5_asn1.ChecksumType.prettyPrint =\ + Integer_NamedValues_prettyPrint + class Krb5EncryptionKey(object): def __init__(self, key, kvno): @@ -146,9 +174,10 @@ class Krb5EncryptionKey(object): EncryptionKey_obj = { 'keytype': self.etype, 'keyvalue': self.key.contents, - }; + } return EncryptionKey_obj + class RawKerberosTest(TestCase): """A raw Kerberos Test case.""" @@ -182,13 +211,13 @@ class RawKerberosTest(TestCase): self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2]) self.s.settimeout(10) self.s.connect(self.a[0][4]) - except socket.error as e: + except socket.error: self.s.close() raise - except IOError as e: + except IOError: self.s.close() raise - except Exception as e: + except Exception: raise finally: pass @@ -219,8 +248,9 @@ class RawKerberosTest(TestCase): domain = samba.tests.env_get_var_value('DOMAIN') realm = samba.tests.env_get_var_value('REALM') username = samba.tests.env_get_var_value('SERVICE_USERNAME') - password = samba.tests.env_get_var_value('SERVICE_PASSWORD', - allow_missing=allow_missing_password) + password = samba.tests.env_get_var_value( + 'SERVICE_PASSWORD', + allow_missing=allow_missing_password) c.set_domain(domain) c.set_realm(realm) c.set_username(username) @@ -246,21 +276,34 @@ class RawKerberosTest(TestCase): if hexdump is None: hexdump = self.do_hexdump if hexdump: - sys.stderr.write("%s: %d\n%s" % (name, len(blob), self.hexdump(blob))) - - def der_decode(self, blob, asn1Spec=None, native_encode=True, asn1_print=None, hexdump=None): + sys.stderr.write( + "%s: %d\n%s" % (name, len(blob), self.hexdump(blob))) + + def der_decode( + self, + blob, + asn1Spec=None, + native_encode=True, + asn1_print=None, + hexdump=None): if asn1Spec is not None: class_name = type(asn1Spec).__name__.split(':')[0] else: class_name = "" self.hex_dump(class_name, blob, hexdump=hexdump) - obj,_ = pyasn1_der_decode(blob, asn1Spec=asn1Spec) + obj, _ = pyasn1_der_decode(blob, asn1Spec=asn1Spec) self.asn1_dump(None, obj, asn1_print=asn1_print) if native_encode: obj = pyasn1_native_encode(obj) return obj - def der_encode(self, obj, asn1Spec=None, native_decode=True, asn1_print=None, hexdump=None): + def der_encode( + self, + obj, + asn1Spec=None, + native_decode=True, + asn1_print=None, + hexdump=None): if native_decode: obj = pyasn1_native_decode(obj, asn1Spec=asn1Spec) class_name = type(obj).__name__.split(':')[0] @@ -273,7 +316,8 @@ class RawKerberosTest(TestCase): def send_pdu(self, req, asn1_print=None, hexdump=None): try: - k5_pdu = self.der_encode(req, native_decode=False, asn1_print=asn1_print, hexdump=False) + 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 @@ -304,7 +348,7 @@ class RawKerberosTest(TestCase): self._disconnect("recv_raw: EOF") return None self.hex_dump("recv_raw", rep_pdu, hexdump=hexdump) - except socket.timeout as e: + except socket.timeout: self.s.settimeout(10) sys.stderr.write("recv_raw: TIMEOUT\n") pass @@ -322,7 +366,8 @@ class RawKerberosTest(TestCase): rep_pdu = None rep = None try: - raw_pdu = self.recv_raw(num_recv=4, hexdump=hexdump, timeout=timeout) + raw_pdu = self.recv_raw( + num_recv=4, hexdump=hexdump, timeout=timeout) if raw_pdu is None: return (None, None) header = struct.unpack(">I", raw_pdu[0:4]) @@ -332,22 +377,27 @@ class RawKerberosTest(TestCase): missing = k5_len rep_pdu = b'' while missing > 0: - raw_pdu = self.recv_raw(num_recv=missing, hexdump=hexdump, timeout=timeout) + raw_pdu = self.recv_raw( + num_recv=missing, hexdump=hexdump, timeout=timeout) self.assertGreaterEqual(len(raw_pdu), 1) rep_pdu += raw_pdu missing = k5_len - len(rep_pdu) - k5_raw = self.der_decode(rep_pdu, asn1Spec=None, native_encode=False, - asn1_print=False, hexdump=False) - pvno=k5_raw['field-0'] + k5_raw = self.der_decode( + rep_pdu, + asn1Spec=None, + native_encode=False, + asn1_print=False, + hexdump=False) + pvno = k5_raw['field-0'] self.assertEqual(pvno, 5) - msg_type=k5_raw['field-1'] - self.assertIn(msg_type, [11,13,30]) + msg_type = k5_raw['field-1'] + self.assertIn(msg_type, [11, 13, 30]) if msg_type == 11: - asn1Spec=krb5_asn1.AS_REP() + asn1Spec = krb5_asn1.AS_REP() elif msg_type == 13: - asn1Spec=krb5_asn1.TGS_REP() + asn1Spec = krb5_asn1.TGS_REP() elif msg_type == 30: - asn1Spec=krb5_asn1.KRB_ERROR() + asn1Spec = krb5_asn1.KRB_ERROR() rep = self.der_decode(rep_pdu, asn1Spec=asn1Spec, asn1_print=asn1_print, hexdump=False) finally: @@ -368,11 +418,17 @@ class RawKerberosTest(TestCase): self.assertIsNone(self.s, msg="Is connected") return - def send_recv_transaction(self, req, asn1_print=None, hexdump=None, timeout=None): + def send_recv_transaction( + self, + req, + asn1_print=None, + hexdump=None, + timeout=None): self.connect() try: self.send_pdu(req, asn1_print=asn1_print, hexdump=hexdump) - rep = self.recv_pdu(asn1_print=asn1_print, hexdump=hexdump, timeout=timeout) + rep = self.recv_pdu( + asn1_print=asn1_print, hexdump=hexdump, timeout=timeout) except Exception: self._disconnect("transaction failed") raise @@ -389,11 +445,15 @@ class RawKerberosTest(TestCase): def assertPrincipalEqual(self, princ1, princ2): self.assertEqual(princ1['name-type'], princ2['name-type']) - self.assertEqual(len(princ1['name-string']), len(princ2['name-string']), - msg="princ1=%s != princ2=%s" % (princ1, princ2)) + self.assertEqual( + len(princ1['name-string']), + len(princ2['name-string']), + msg="princ1=%s != princ2=%s" % (princ1, princ2)) for idx in range(len(princ1['name-string'])): - self.assertEqual(princ1['name-string'][idx], princ2['name-string'][idx], - msg="princ1=%s != princ2=%s" % (princ1, princ2)) + self.assertEqual( + princ1['name-string'][idx], + princ2['name-string'][idx], + msg="princ1=%s != princ2=%s" % (princ1, princ2)) return def get_KerberosTimeWithUsec(self, epoch=None, offset=None): @@ -421,7 +481,7 @@ class RawKerberosTest(TestCase): salt = None try: salt = etype_info2['salt'] - except: + except Exception: pass if e == kcrypto.Enctype.RC4: @@ -429,7 +489,8 @@ class RawKerberosTest(TestCase): return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno) password = creds.get_password() - return self.PasswordKey_create(etype=e, pwd=password, salt=salt, kvno=kvno) + return self.PasswordKey_create( + etype=e, pwd=password, salt=salt, kvno=kvno) def RandomKey(self, etype): e = kcrypto._get_enctype_profile(etype) @@ -452,14 +513,14 @@ class RawKerberosTest(TestCase): 'cipher': ciphertext } if key.kvno is not None: - EncryptedData_obj['kvno'] = key.kvno + EncryptedData_obj['kvno'] = key.kvno return EncryptedData_obj def Checksum_create(self, key, usage, plaintext, ctype=None): - #Checksum ::= SEQUENCE { + # Checksum ::= SEQUENCE { # cksumtype [0] Int32, # checksum [1] OCTET STRING - #} + # } if ctype is None: ctype = key.ctype checksum = key.make_checksum(usage, plaintext, ctype=ctype) @@ -494,10 +555,10 @@ class RawKerberosTest(TestCase): return PA_DATA_obj def PA_ENC_TS_ENC_create(self, ts, usec): - #PA-ENC-TS-ENC ::= SEQUENCE { + # PA-ENC-TS-ENC ::= SEQUENCE { # patimestamp[0] KerberosTime, -- client's time # pausec[1] krb5int32 OPTIONAL - #} + # } PA_ENC_TS_ENC_obj = { 'patimestamp': ts, 'pausec': usec, @@ -520,7 +581,7 @@ class RawKerberosTest(TestCase): additional_tickets, asn1_print=None, hexdump=None): - #KDC-REQ-BODY ::= SEQUENCE { + # KDC-REQ-BODY ::= SEQUENCE { # kdc-options [0] KDCOptions, # cname [1] PrincipalName OPTIONAL # -- Used only in AS-REQ --, @@ -532,20 +593,23 @@ class RawKerberosTest(TestCase): # till [5] KerberosTime, # rtime [6] KerberosTime OPTIONAL, # nonce [7] UInt32, - # etype [8] SEQUENCE OF Int32 -- EncryptionType + # etype [8] SEQUENCE OF Int32 + # -- EncryptionType # -- in preference order --, # addresses [9] HostAddresses OPTIONAL, # enc-authorization-data [10] EncryptedData OPTIONAL # -- AuthorizationData --, # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL # -- NOTE: not empty - #} + # } if EncAuthorizationData is not None: - enc_ad_plain = self.der_encode(EncAuthorizationData, - asn1Spec=krb5_asn1.AuthorizationData(), - asn1_print=asn1_print, - hexdump=hexdump) - enc_ad = self.EncryptedData_create(EncAuthorizationData_key, enc_ad_plain) + enc_ad_plain = self.der_encode( + EncAuthorizationData, + asn1Spec=krb5_asn1.AuthorizationData(), + asn1_print=asn1_print, + hexdump=hexdump) + enc_ad = self.EncryptedData_create( + EncAuthorizationData_key, enc_ad_plain) else: enc_ad = None KDC_REQ_BODY_obj = { @@ -590,14 +654,14 @@ class RawKerberosTest(TestCase): asn1Spec=None, asn1_print=None, hexdump=None): - #KDC-REQ ::= SEQUENCE { + # KDC-REQ ::= SEQUENCE { # -- NOTE: first tag is [1], not [0] # pvno [1] INTEGER (5) , # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), # padata [3] SEQUENCE OF PA-DATA OPTIONAL # -- NOTE: not empty --, # req-body [4] KDC-REQ-BODY - #} + # } # KDC_REQ_BODY_obj = self.KDC_REQ_BODY_create(kdc_options, cname, @@ -622,39 +686,40 @@ class RawKerberosTest(TestCase): if padata is not None: KDC_REQ_obj['padata'] = padata if asn1Spec is not None: - KDC_REQ_decoded = pyasn1_native_decode(KDC_REQ_obj, asn1Spec=asn1Spec) + KDC_REQ_decoded = pyasn1_native_decode( + KDC_REQ_obj, asn1Spec=asn1Spec) else: KDC_REQ_decoded = None return KDC_REQ_obj, KDC_REQ_decoded def AS_REQ_create(self, - padata, # optional - kdc_options, # required - cname, # optional - realm, # required - sname, # optional - from_time, # optional - till_time, # required - renew_time, # optional - nonce, # required - etypes, # required - addresses, # optional + padata, # optional + kdc_options, # required + cname, # optional + realm, # required + sname, # optional + from_time, # optional + till_time, # required + renew_time, # optional + nonce, # required + etypes, # required + addresses, # optional EncAuthorizationData, EncAuthorizationData_key, additional_tickets, native_decoded_only=True, asn1_print=None, hexdump=None): - #KDC-REQ ::= SEQUENCE { + # KDC-REQ ::= SEQUENCE { # -- NOTE: first tag is [1], not [0] # pvno [1] INTEGER (5) , # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), # padata [3] SEQUENCE OF PA-DATA OPTIONAL # -- NOTE: not empty --, # req-body [4] KDC-REQ-BODY - #} + # } # - #KDC-REQ-BODY ::= SEQUENCE { + # KDC-REQ-BODY ::= SEQUENCE { # kdc-options [0] KDCOptions, # cname [1] PrincipalName OPTIONAL # -- Used only in AS-REQ --, @@ -666,32 +731,34 @@ class RawKerberosTest(TestCase): # till [5] KerberosTime, # rtime [6] KerberosTime OPTIONAL, # nonce [7] UInt32, - # etype [8] SEQUENCE OF Int32 -- EncryptionType + # etype [8] SEQUENCE OF Int32 + # -- EncryptionType # -- in preference order --, # addresses [9] HostAddresses OPTIONAL, # enc-authorization-data [10] EncryptedData OPTIONAL # -- AuthorizationData --, # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL # -- NOTE: not empty - #} - obj,decoded = self.KDC_REQ_create(msg_type=10, - padata=padata, - kdc_options=kdc_options, - cname=cname, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets, - asn1Spec=krb5_asn1.AS_REQ(), - asn1_print=asn1_print, - hexdump=hexdump) + # } + obj, decoded = self.KDC_REQ_create( + msg_type=10, + padata=padata, + kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets, + asn1Spec=krb5_asn1.AS_REQ(), + asn1_print=asn1_print, + hexdump=hexdump) if native_decoded_only: return decoded return decoded, obj @@ -703,7 +770,7 @@ class RawKerberosTest(TestCase): # ap-options [2] APOptions, # ticket [3] Ticket, # authenticator [4] EncryptedData -- Authenticator - #} + # } AP_REQ_obj = { 'pvno': 5, 'msg-type': 14, @@ -713,8 +780,9 @@ class RawKerberosTest(TestCase): } return AP_REQ_obj - def Authenticator_create(self, crealm, cname, cksum, cusec, ctime, subkey, seq_number, - authorization_data): + def Authenticator_create( + self, crealm, cname, cksum, cusec, ctime, subkey, seq_number, + authorization_data): # -- Unencrypted authenticator # Authenticator ::= [APPLICATION 2] SEQUENCE { # authenticator-vno [0] INTEGER (5), @@ -726,7 +794,7 @@ class RawKerberosTest(TestCase): # subkey [6] EncryptionKey OPTIONAL, # seq-number [7] UInt32 OPTIONAL, # authorization-data [8] AuthorizationData OPTIONAL - #} + # } Authenticator_obj = { 'authenticator-vno': 5, 'crealm': crealm, @@ -745,20 +813,20 @@ class RawKerberosTest(TestCase): return Authenticator_obj def TGS_REQ_create(self, - padata, # optional + padata, # optional cusec, ctime, ticket, - kdc_options, # required - cname, # optional - realm, # required - sname, # optional - from_time, # optional - till_time, # required - renew_time, # optional - nonce, # required - etypes, # required - addresses, # optional + kdc_options, # required + cname, # optional + realm, # required + sname, # optional + from_time, # optional + till_time, # required + renew_time, # optional + nonce, # required + etypes, # required + addresses, # optional EncAuthorizationData, EncAuthorizationData_key, additional_tickets, @@ -768,16 +836,16 @@ class RawKerberosTest(TestCase): native_decoded_only=True, asn1_print=None, hexdump=None): - #KDC-REQ ::= SEQUENCE { + # KDC-REQ ::= SEQUENCE { # -- NOTE: first tag is [1], not [0] # pvno [1] INTEGER (5) , # msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), # padata [3] SEQUENCE OF PA-DATA OPTIONAL # -- NOTE: not empty --, # req-body [4] KDC-REQ-BODY - #} + # } # - #KDC-REQ-BODY ::= SEQUENCE { + # KDC-REQ-BODY ::= SEQUENCE { # kdc-options [0] KDCOptions, # cname [1] PrincipalName OPTIONAL # -- Used only in AS-REQ --, @@ -789,50 +857,57 @@ class RawKerberosTest(TestCase): # till [5] KerberosTime, # rtime [6] KerberosTime OPTIONAL, # nonce [7] UInt32, - # etype [8] SEQUENCE OF Int32 -- EncryptionType + # etype [8] SEQUENCE OF Int32 + # -- EncryptionType # -- in preference order --, # addresses [9] HostAddresses OPTIONAL, # enc-authorization-data [10] EncryptedData OPTIONAL # -- AuthorizationData --, # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL # -- NOTE: not empty - #} - - req_body = self.KDC_REQ_BODY_create(kdc_options=kdc_options, - cname=None, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets) + # } + + req_body = self.KDC_REQ_BODY_create( + kdc_options=kdc_options, + cname=None, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets) req_body = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), asn1_print=asn1_print, hexdump=hexdump) - req_body_checksum = self.Checksum_create(ticket_session_key, 6, req_body, - ctype=body_checksum_type) + req_body_checksum = self.Checksum_create( + ticket_session_key, 6, req_body, ctype=body_checksum_type) subkey_obj = None if authenticator_subkey is not None: subkey_obj = authenticator_subkey.export_obj() seq_number = random.randint(0, 0xfffffffe) - authenticator = self.Authenticator_create(crealm=realm, - cname=cname, - cksum=req_body_checksum, - cusec=cusec, - ctime=ctime, - subkey=subkey_obj, - seq_number=seq_number, - authorization_data=None) - authenticator = self.der_encode(authenticator, asn1Spec=krb5_asn1.Authenticator(), - asn1_print=asn1_print, hexdump=hexdump) - - authenticator = self.EncryptedData_create(ticket_session_key, 7, authenticator) + authenticator = self.Authenticator_create( + crealm=realm, + cname=cname, + cksum=req_body_checksum, + cusec=cusec, + ctime=ctime, + subkey=subkey_obj, + seq_number=seq_number, + authorization_data=None) + authenticator = self.der_encode( + authenticator, + asn1Spec=krb5_asn1.Authenticator(), + asn1_print=asn1_print, + hexdump=hexdump) + + authenticator = self.EncryptedData_create( + ticket_session_key, 7, authenticator) ap_options = krb5_asn1.APOptions('0') ap_req = self.AP_REQ_create(ap_options=str(ap_options), @@ -846,24 +921,25 @@ class RawKerberosTest(TestCase): else: padata = [pa_tgs_req] - obj,decoded = self.KDC_REQ_create(msg_type=12, - padata=padata, - kdc_options=kdc_options, - cname=None, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets, - asn1Spec=krb5_asn1.TGS_REQ(), - asn1_print=asn1_print, - hexdump=hexdump) + obj, decoded = self.KDC_REQ_create( + msg_type=12, + padata=padata, + kdc_options=kdc_options, + cname=None, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets, + asn1Spec=krb5_asn1.TGS_REQ(), + asn1_print=asn1_print, + hexdump=hexdump) if native_decoded_only: return decoded return decoded, obj @@ -888,5 +964,6 @@ class RawKerberosTest(TestCase): 'cksum': cksum, 'auth': "Kerberos", } - pa_s4u2self = self.der_encode(PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) + pa_s4u2self = self.der_encode( + PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) return self.PA_DATA_create(129, pa_s4u2self) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 9de56578c99..5bbf1229d09 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -38,31 +38,31 @@ PADATA_ETYPE_INFO2 = int( # Error codes KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 -KDC_ERR_PREAUTH_FAILED = 24 -KDC_ERR_PREAUTH_REQUIRED = 25 -KDC_ERR_BADMATCH = 36 -KDC_ERR_SKEW = 37 +KDC_ERR_PREAUTH_FAILED = 24 +KDC_ERR_PREAUTH_REQUIRED = 25 +KDC_ERR_BADMATCH = 36 +KDC_ERR_SKEW = 37 # Name types -NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) +NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) -NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) +NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues( 'kRB5-NT-ENTERPRISE-PRINCIPAL')) # Authorization data ad-type values -AD_IF_RELEVANT = 1 -AD_INTENDED_FOR_SERVER = 2 +AD_IF_RELEVANT = 1 +AD_INTENDED_FOR_SERVER = 2 AD_INTENDED_FOR_APPLICATION_CLASS = 3 -AD_KDC_ISSUED = 4 -AD_AND_OR = 5 -AD_MANDATORY_TICKET_EXTENSIONS = 6 -AD_IN_TICKET_EXTENSIONS = 7 -AD_MANDATORY_FOR_KDC = 8 -AD_INITIAL_VERIFIED_CAS = 9 -AD_WIN2K_PAC = 128 -AD_SIGNTICKET = 512 +AD_KDC_ISSUED = 4 +AD_AND_OR = 5 +AD_MANDATORY_TICKET_EXTENSIONS = 6 +AD_IN_TICKET_EXTENSIONS = 7 +AD_MANDATORY_FOR_KDC = 8 +AD_INITIAL_VERIFIED_CAS = 9 +AD_WIN2K_PAC = 128 +AD_SIGNTICKET = 512 # Key usage numbers # RFC 4120 Section 7.5.1. Key Usage Numbers diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 2e1bd3fbe1f..30a58d6345a 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -35,6 +35,7 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 global_asn1_print = False global_hexdump = False + class S4UKerberosTests(RawKerberosTest): def setUp(self): @@ -55,7 +56,7 @@ class S4UKerberosTests(RawKerberosTest): kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - etypes=(18,17,23) + etypes = (18, 17, 23) req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), @@ -76,14 +77,16 @@ class S4UKerberosTests(RawKerberosTest): self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) - rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + rep_padata = self.der_decode( + rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break - etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + etype_info2 = self.der_decode( + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(service_creds, etype_info2[0]) @@ -120,7 +123,8 @@ class S4UKerberosTests(RawKerberosTest): self.assertEqual(msg_type, 11) enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) # S4U2Self Request sname = cname @@ -167,11 +171,13 @@ class S4UKerberosTests(RawKerberosTest): if msg_type == 13: enc_part2 = subkey.decrypt( KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return msg_type - # Using the checksum type from the tgt_session_key happens to work everywhere + # Using the checksum type from the tgt_session_key happens to work + # everywhere def test_s4u2self(self): msg_type = self._test_s4u2self() self.assertEqual(msg_type, 13) @@ -193,6 +199,7 @@ class S4UKerberosTests(RawKerberosTest): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.CRC32) self.assertEqual(msg_type, 30) + if __name__ == "__main__": global_asn1_print = True global_hexdump = True diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 6c090af3d46..889b91a9bf0 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -33,6 +33,7 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 global_asn1_print = False global_hexdump = False + class SimpleKerberosTests(RawKerberosTest): def setUp(self): @@ -53,7 +54,7 @@ class SimpleKerberosTests(RawKerberosTest): kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - etypes=(18,17,23) + etypes = (18, 17, 23) req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), @@ -74,14 +75,16 @@ class SimpleKerberosTests(RawKerberosTest): self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) - rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + rep_padata = self.der_decode( + rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break - etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + etype_info2 = self.der_decode( + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) @@ -119,17 +122,21 @@ class SimpleKerberosTests(RawKerberosTest): enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) - # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with + # application tag 26 try: - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) except Exception: - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # TGS Request service_creds = self.get_service_creds(allow_missing_password=True) service_name = service_creds.get_username() - sname = self.PrincipalName_create(name_type=2, names=["host", service_name]) + sname = self.PrincipalName_create( + name_type=2, names=["host", service_name]) kdc_options = krb5_asn1.KDCOptions('forwardable') till = self.get_KerberosTime(offset=36000) ticket = rep['ticket'] @@ -167,7 +174,8 @@ class SimpleKerberosTests(RawKerberosTest): enc_part2 = subkey.decrypt( KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return diff --git a/python/samba/tests/krb5/xrealm_tests.py b/python/samba/tests/krb5/xrealm_tests.py index b4a02bff33a..efb953bdf7e 100755 --- a/python/samba/tests/krb5/xrealm_tests.py +++ b/python/samba/tests/krb5/xrealm_tests.py @@ -34,6 +34,7 @@ import samba.tests global_asn1_print = False global_hexdump = False + class XrealmKerberosTests(RawKerberosTest): def setUp(self): @@ -54,7 +55,7 @@ class XrealmKerberosTests(RawKerberosTest): kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None - etypes=(18,17,23) + etypes = (18, 17, 23) req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), @@ -75,14 +76,16 @@ class XrealmKerberosTests(RawKerberosTest): self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) - rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + rep_padata = self.der_decode( + rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break - etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) + etype_info2 = self.der_decode( + etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) @@ -120,15 +123,19 @@ class XrealmKerberosTests(RawKerberosTest): enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) - # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with + # application tag 26 try: - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) except Exception: - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # TGS Request (for cross-realm TGT) trust_realm = samba.tests.env_get_var_value('TRUST_REALM') - sname = self.PrincipalName_create(name_type=2, names=["krbtgt", trust_realm]) + sname = self.PrincipalName_create( + name_type=2, names=["krbtgt", trust_realm]) kdc_options = krb5_asn1.KDCOptions('forwardable') till = self.get_KerberosTime(offset=36000) @@ -167,10 +174,11 @@ class XrealmKerberosTests(RawKerberosTest): enc_part2 = subkey.decrypt( KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) - enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # Check the forwardable flag - fwd_pos = len(tuple(krb5_asn1.TicketFlags('forwardable'))) -1 + fwd_pos = len(tuple(krb5_asn1.TicketFlags('forwardable'))) - 1 assert(krb5_asn1.TicketFlags(enc_part2['flags'])[fwd_pos]) return -- 2.25.1 From 02edeb45860dc5676003dcca9629d7eea96c75ec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Apr 2021 17:22:12 +0200 Subject: [PATCH 061/645] librpc: Add py_descriptor_richcmp() equality function Only a python3 version. Do we still need the python2 flavor? Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 439b7ccdc1b1c91c66c1a7c83e340fa044c26377) --- source4/librpc/ndr/py_security.c | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index 26989c1a433..0b8a1c66b7a 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -309,9 +309,46 @@ static PyMethodDef py_descriptor_extra_methods[] = { { NULL } }; +static PyObject *py_descriptor_richcmp( + PyObject *py_self, PyObject *py_other, int op) +{ + struct security_descriptor *self = pytalloc_get_ptr(py_self); + struct security_descriptor *other = pytalloc_get_ptr(py_other); + bool eq; + + if (other == NULL) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + eq = security_descriptor_equal(self, other); + + switch(op) { + case Py_EQ: + if (eq) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } + break; + case Py_NE: + if (eq) { + Py_RETURN_FALSE; + } else { + Py_RETURN_TRUE; + } + break; + default: + break; + } + + return Py_NotImplemented; +} + static void py_descriptor_patch(PyTypeObject *type) { type->tp_new = py_descriptor_new; + type->tp_richcompare = py_descriptor_richcmp; PyType_AddMethods(type, py_descriptor_extra_methods); } -- 2.25.1 From 1590663c4b1971ba1ae7d6636ada646dd6619345 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Wed, 17 Feb 2021 12:15:50 +1300 Subject: [PATCH 062/645] tests python krb5: MS-KILE client principal look-up Tests of [MS-KILE]: Kerberos Protocol Extensions section 3.3.5.6.1 Client Principal Lookup Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Mon Apr 12 00:38:26 UTC 2021 on sn-devel-184 (cherry picked from commit 768d48fca9f8c7527c0d12e7acc8942b5fd36ac2) --- python/samba/tests/krb5/kdc_base_test.py | 29 +- .../ms_kile_client_principal_lookup_tests.py | 814 ++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 12 + selftest/knownfail_mit_kdc | 16 + source4/selftest/tests.py | 3 + 6 files changed, 874 insertions(+), 1 deletion(-) create mode 100755 python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index bef5458c881..1c7f05dda6d 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -22,6 +22,7 @@ import os sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" from collections import namedtuple +import ldb from ldb import SCOPE_BASE from samba import generate_random_password from samba.auth import system_session @@ -103,7 +104,7 @@ class KDCBaseTest(RawKerberosTest): for dn in self.accounts: delete_force(self.ldb, dn) - def create_account(self, name, machine_account=False, spn=None): + def create_account(self, name, machine_account=False, spn=None, upn=None): '''Create an account for testing. The dn of the created account is added to self.accounts, which is used by tearDown to clean up the created accounts. @@ -133,6 +134,8 @@ class KDCBaseTest(RawKerberosTest): "unicodePwd": utf16pw} if spn is not None: details["servicePrincipalName"] = spn + if upn is not None: + details["userPrincipalName"] = upn self.ldb.add(details) creds = Credentials() @@ -418,3 +421,27 @@ class KDCBaseTest(RawKerberosTest): self.assertTrue(len(res) == 1, "did not get objectSid for %s" % dn) sid = self.ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) return sid.decode('utf8') + + def add_attribute(self, dn_str, name, value): + if isinstance(value, list): + values = value + else: + values = [value] + flag = ldb.FLAG_MOD_ADD + + dn = ldb.Dn(self.ldb, dn_str) + msg = ldb.Message(dn) + msg[name] = ldb.MessageElement(values, flag, name) + self.ldb.modify(msg) + + def modify_attribute(self, dn_str, name, value): + if isinstance(value, list): + values = value + else: + values = [value] + flag = ldb.FLAG_MOD_REPLACE + + dn = ldb.Dn(self.ldb, dn_str) + msg = ldb.Message(dn) + msg[name] = ldb.MessageElement(values, flag, name) + self.ldb.modify(msg) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py new file mode 100755 index 00000000000..356a25f8e18 --- /dev/null +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -0,0 +1,814 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.dsdb import UF_NORMAL_ACCOUNT, UF_DONT_REQUIRE_PREAUTH +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + NT_ENTERPRISE_PRINCIPAL, + NT_PRINCIPAL, + NT_SRV_INST, + KDC_ERR_C_PRINCIPAL_UNKNOWN, +) + +global_asn1_print = False +global_hexdump = False + + +class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): + ''' Tests for MS-KILE client principal look-up + See [MS-KILE]: Kerberos Protocol Extensions + secion 3.3.5.6.1 Client Principal Lookup + ''' + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def check_pac(self, auth_data, dn, uc, name, upn=None): + + pac_data = self.get_pac_data(auth_data) + sid = self.get_objectSid(dn) + if upn is None: + upn = "%s@%s" % (name, uc.get_realm().lower()) + if name.endswith('$'): + name = name[:-1] + + self.assertEqual( + uc.get_username(), + str(pac_data.account_name), + "pac_data = {%s}" % str(pac_data)) + self.assertEqual( + name, + pac_data.logon_name, + "pac_data = {%s}" % str(pac_data)) + self.assertEqual( + uc.get_realm(), + pac_data.domain_name, + "pac_data = {%s}" % str(pac_data)) + self.assertEqual( + upn, + pac_data.upn, + "pac_data = {%s}" % str(pac_data)) + self.assertEqual( + sid, + pac_data.account_sid, + "pac_data = {%s}" % str(pac_data)) + + def test_nt_principal_step_1(self): + ''' Step 1 + For an NT_PRINCIPAL cname with no realm or the realm matches the + DC's domain + search for an account with the + sAMAccountName matching the cname. + ''' + + # Create user and machine accounts for the test. + # + user_name = "mskileusr" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac(enc_part['authorization-data'], dn, uc, user_name) + # check the crealm and cname + cname = enc_part['cname'] + self.assertEqual(NT_PRINCIPAL, cname['name-type']) + self.assertEqual(user_name.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) + + def test_nt_principal_step_2(self): + ''' Step 2 + If not found + search for sAMAccountName equal to the cname + "$" + + ''' + + # Create a machine account for the test. + # + user_name = "mskilemac" + (mc, dn) = self.create_account(user_name, machine_account=True) + realm = mc.get_realm().lower() + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(mc, rep) + key = self.get_as_rep_key(mc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, mc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac(enc_part['authorization-data'], dn, mc, mach_name + '$') + # check the crealm and cname + cname = enc_part['cname'] + self.assertEqual(NT_PRINCIPAL, cname['name-type']) + self.assertEqual(user_name.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) + + def test_nt_principal_step_3(self): + ''' Step 3 + + If not found + search for a matching UPN name where the UPN is set to + cname@realm or cname@DC's domain name + + ''' + # Create a user account for the test. + # + user_name = "mskileusr" + upn_name = "mskileupn" + upn = upn_name + "@" + self.credentials.get_realm().lower() + (uc, dn) = self.create_account(user_name, upn=upn) + realm = uc.get_realm().lower() + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[upn_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[upn_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the service ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac(enc_part['authorization-data'], dn, uc, upn_name) + # check the crealm and cname + cname = enc_part['cname'] + self.assertEqual(NT_PRINCIPAL, cname['name-type']) + self.assertEqual(upn_name.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) + + def test_nt_principal_step_4_a(self): + ''' Step 4, no pre-authentication + If not found and no pre-authentication + search for a matching altSecurityIdentity + ''' + # Create a user account for the test. + # with an altSecurityIdentity, and with UF_DONT_REQUIRE_PREAUTH + # set. + # + # note that in this case IDL_DRSCrackNames is called with + # pmsgIn.formatOffered set to + # DS_USER_PRINCIPAL_NAME_AND_ALTSECID + # + # setting UF_DONT_REQUIRE_PREAUTH seems to be the only way + # to trigger the no pre-auth step + + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.modify_attribute( + dn, + "userAccountControl", + str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH + # we should get a valid AS-RESP + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[alt_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_as_reply(rep) + salt = "%s%s" % (realm.upper(), user_name) + key = self.PasswordKey_create( + rep['enc-part']['etype'], + uc.get_password(), + salt.encode('UTF8'), + rep['enc-part']['kvno']) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[alt_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + 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']) + + def test_nt_principal_step_4_b(self): + ''' Step 4, pre-authentication + If not found and pre-authentication + search for a matching user principal name + ''' + + # Create user and machine accounts for the test. + # + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[alt_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + # Note: although we used the alt security id for the pre-auth + # we need to use the username for the auth + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[user_name]) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac(enc_part['authorization-data'], dn, uc, user_name) + # check the crealm and cname + cname = enc_part['cname'] + self.assertEqual(NT_PRINCIPAL, cname['name-type']) + self.assertEqual(user_name.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) + + def test_nt_principal_step_4_c(self): + ''' Step 4, pre-authentication + If not found and pre-authentication + search for a matching user principal name + + This test uses the altsecid, so the AS-REQ should fail. + ''' + + # Create user and machine accounts for the test. + # + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[alt_name]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + # Use the alternate security identifier + # this should fail + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[alt_sec]) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_error_rep(rep, KDC_ERR_C_PRINCIPAL_UNKNOWN) + + def test_enterprise_principal_step_1_3(self): + ''' Steps 1-3 + For an NT_ENTERPRISE_PRINCIPAL cname + search for a user principal name matching the cname + + ''' + + # Create a user account for the test. + # + user_name = "mskileusr" + upn_name = "mskileupn" + upn = upn_name + "@" + self.credentials.get_realm().lower() + (uc, dn) = self.create_account(user_name, upn=upn) + realm = uc.get_realm().lower() + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[upn]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[upn]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac( + enc_part['authorization-data'], dn, uc, upn, upn=upn) + # check the crealm and cname + cname = enc_part['cname'] + crealm = enc_part['crealm'] + self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) + self.assertEqual(upn.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), crealm) + + def test_enterprise_principal_step_4(self): + ''' Step 4 + + If that fails + search for an account where the sAMAccountName matches + the name before the @ + + ''' + + # Create a user account for the test. + # + user_name = "mskileusr" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + ename = user_name + "@" + realm + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac( + enc_part['authorization-data'], dn, uc, ename, upn=ename) + # check the crealm and cname + cname = enc_part['cname'] + crealm = enc_part['crealm'] + self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) + self.assertEqual(ename.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), crealm) + + def test_enterprise_principal_step_5(self): + ''' Step 5 + + If that fails + search for an account where the sAMAccountName matches + the name before the @ with a $ appended. + + ''' + + # Create a user account for the test. + # + user_name = "mskileusr" + (uc, _) = self.create_account(user_name) + realm = uc.get_realm().lower() + + mach_name = "mskilemac" + (mc, dn) = self.create_account(mach_name, machine_account=True) + ename = mach_name + "@" + realm + uname = mach_name + "$@" + realm + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(mc, rep) + key = self.get_as_rep_key(mc, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac( + enc_part['authorization-data'], dn, mc, ename, upn=uname) + # check the crealm and cname + cname = enc_part['cname'] + crealm = enc_part['crealm'] + self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) + self.assertEqual(ename.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), crealm) + + def test_enterprise_principal_step_6_a(self): + ''' Step 6, no pre-authentication + If not found and no pre-authentication + search for a matching altSecurityIdentity + ''' + # Create a user account for the test. + # with an altSecurityIdentity, and with UF_DONT_REQUIRE_PREAUTH + # set. + # + # note that in this case IDL_DRSCrackNames is called with + # pmsgIn.formatOffered set to + # DS_USER_PRINCIPAL_NAME_AND_ALTSECID + # + # setting UF_DONT_REQUIRE_PREAUTH seems to be the only way + # to trigger the no pre-auth step + + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.modify_attribute( + dn, + "userAccountControl", + str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) + ename = alt_name + "@" + realm + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH + # we should get a valid AS-RESP + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_as_reply(rep) + salt = "%s%s" % (realm.upper(), user_name) + key = self.PasswordKey_create( + rep['enc-part']['etype'], + uc.get_password(), + salt.encode('UTF8'), + rep['enc-part']['kvno']) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + 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']) + + def test_nt_enterprise_principal_step_6_b(self): + ''' Step 4, pre-authentication + If not found and pre-authentication + search for a matching user principal name + ''' + + # Create user and machine accounts for the test. + # + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + ename = alt_name + "@" + realm + uname = user_name + "@" + realm + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + key = self.get_as_rep_key(uc, rep) + # Note: although we used the alt security id for the pre-auth + # we need to use the username for the auth + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[uname]) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part2 = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part2['key']) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, + names=[uname]) + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=[mc.get_username()]) + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype) + self.check_tgs_reply(rep) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + enc_part = self.decode_service_ticket(mc, ticket) + self.check_pac( + enc_part['authorization-data'], dn, uc, uname, upn=uname) + # check the crealm and cname + cname = enc_part['cname'] + self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) + self.assertEqual(uname.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) + + def test_nt_principal_step_6_c(self): + ''' Step 4, pre-authentication + If not found and pre-authentication + search for a matching user principal name + + This test uses the altsecid, so the AS-REQ should fail. + ''' + + # Create user and machine accounts for the test. + # + user_name = "mskileusr" + alt_name = "mskilealtsec" + (uc, dn) = self.create_account(user_name) + realm = uc.get_realm().lower() + alt_sec = "Kerberos:%s@%s" % (alt_name, realm) + self.add_attribute(dn, "altSecurityIdentities", alt_sec) + ename = alt_name + "@" + realm + + mach_name = "mskilemac" + (mc, _) = self.create_account(mach_name, machine_account=True) + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(uc, rep) + # Use the alternate security identifier + # this should fail + cname = self.PrincipalName_create( + name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_error_rep(rep, KDC_ERR_C_PRINCIPAL_UNKNOWN) + + +if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 222d1dbfa41..1b22461c735 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -95,6 +95,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/kdc_tests.py', 'python/samba/tests/krb5/kdc_base_test.py', 'python/samba/tests/krb5/kdc_tgs_tests.py', + 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 7ab56b6721b..4e6ee93ce96 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -2,3 +2,15 @@ # We expect all the MIT specific compatability tests to fail on heimdal # kerberos ^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_ +# +# 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 +^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_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_c +^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_6_c diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index e64303c6b0f..2c2a643944c 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -275,3 +275,19 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # following tests ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_ldap_service_ticket\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) +# +# MIT currently fails the following MS-KILE 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_1 +^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_2 +^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_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_nt_principal_step_4_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_principal_step_4_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_c +^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_6_c + diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index b2a09b3ecb2..9bb2ff2e1ed 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1290,6 +1290,9 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") planpythontestsuite( "ad_dc", "samba.tests.krb5.kdc_tgs_tests") +planpythontestsuite( + "ad_dc", + "samba.tests.krb5.ms_kile_client_principal_lookup_tests") for env in [ 'vampire_dc', -- 2.25.1 From 7e880971d6fee4ab24b3b23419fa9576397eafbf Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 10:54:05 +1200 Subject: [PATCH 063/645] auth:creds: Remove unused variable Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1ea2de561839ad948efab5112fbe4c1eae44d9ee) --- auth/credentials/pycredentials.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 7427e286dca..1edb22bd867 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -603,8 +603,6 @@ static PyObject *py_creds_get_forced_sasl_mech(PyObject *self, PyObject *unused) static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args) { char *newval; - enum credentials_obtained obt = CRED_SPECIFIED; - int _obt = obt; struct cli_credentials *creds = PyCredentials_AsCliCredentials(self); if (creds == NULL) { PyErr_Format(PyExc_TypeError, "Credentials expected"); @@ -614,7 +612,6 @@ static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s", &newval)) { return NULL; } - obt = _obt; cli_credentials_set_forced_sasl_mech(creds, newval); Py_RETURN_NONE; -- 2.25.1 From f7227612a89022789ba48e7cb87ca5dd7629acde Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 10:55:13 +1200 Subject: [PATCH 064/645] auth:creds: Fix parameter in creds.set_named_ccache() Use the passed-in value for 'obtained' rather than always using CRED_SPECIFIED. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2d05268aa0904221c452fc650fcdfb680efc20bb) --- auth/credentials/pycredentials.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 1edb22bd867..314f0eba894 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -763,6 +763,7 @@ static PyObject *py_creds_set_named_ccache(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s|iO", &newval, &_obt, &py_lp_ctx)) return NULL; + obt = _obt; mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { @@ -778,7 +779,7 @@ static PyObject *py_creds_set_named_ccache(PyObject *self, PyObject *args) ret = cli_credentials_set_ccache(creds, lp_ctx, - newval, CRED_SPECIFIED, + newval, obt, &error_string); if (ret != 0) { -- 2.25.1 From bbe01ec142411b2b970fb5fe0fa4ffb2d2491773 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 11:07:22 +1200 Subject: [PATCH 065/645] pygensec: Fix method documentation This changes the docstrings to use the correct method names. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 50ade4cadc766a196316fd5c5a57f8c502f0ea22) --- source4/auth/gensec/pygensec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index 986f32904e7..35b3307ab8f 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -654,13 +654,13 @@ static PyMethodDef py_gensec_security_methods[] = { METH_VARARGS|METH_KEYWORDS|METH_CLASS, "S.start_server(auth_ctx, settings) -> gensec" }, { "set_credentials", (PyCFunction)py_gensec_set_credentials, METH_VARARGS, - "S.start_client(credentials)" }, + "S.set_credentials(credentials)" }, { "set_target_hostname", (PyCFunction)py_gensec_set_target_hostname, METH_VARARGS, - "S.start_target_hostname(target_hostname) \n This sets the Kerberos target hostname to obtain a ticket for." }, + "S.set_target_hostname(target_hostname) \n This sets the Kerberos target hostname to obtain a ticket for." }, { "set_target_service", (PyCFunction)py_gensec_set_target_service, METH_VARARGS, - "S.start_target_service(target_service) \n This sets the Kerberos target service to obtain a ticket for. The default value is 'host'" }, + "S.set_target_service(target_service) \n This sets the Kerberos target service to obtain a ticket for. The default value is 'host'" }, { "set_target_service_description", (PyCFunction)py_gensec_set_target_service_description, METH_VARARGS, - "S.start_target_service_description(target_service_description) \n This description is set server-side and used in authentication and authorization logs. The default value is that provided to set_target_service() or None."}, + "S.set_target_service_description(target_service_description) \n This description is set server-side and used in authentication and authorization logs. The default value is that provided to set_target_service() or None."}, { "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS, "S.session_info() -> info" }, { "session_key", (PyCFunction)py_gensec_session_key, METH_NOARGS, -- 2.25.1 From 19b36346d7498f512295df0e45974ffaec637c40 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 15 Apr 2021 10:32:41 +1200 Subject: [PATCH 066/645] Revert "s4-test: fixed ndrdump test for top level build" This essentially reverts commit b84c0a9ed6d556eb2d3797d606edcd03f9766606, but the datapath is now in the source4 directory. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 6f144d49b5281a08bf7be550b949f4d91e8fe19b) --- python/samba/tests/blackbox/ndrdump.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py index 6795aed41b7..f9a3bd98862 100644 --- a/python/samba/tests/blackbox/ndrdump.py +++ b/python/samba/tests/blackbox/ndrdump.py @@ -24,13 +24,7 @@ from __future__ import print_function import os from samba.tests import BlackboxTestCase, BlackboxProcessError -for p in ["../../../../../source4/librpc/tests", - "../../../../../librpc/tests"]: - data_path_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), p)) - print(data_path_dir) - if os.path.exists(data_path_dir): - break - +data_path_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../../source4/librpc/tests")) class NdrDumpTests(BlackboxTestCase): """Blackbox tests for ndrdump.""" -- 2.25.1 From 4bc1f4d789dae7f6bdb7b50c01ec950ffa2e7c3c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 10:57:00 +1200 Subject: [PATCH 067/645] krb5ccache.idl: Add definition for a Kerberos credentials cache Based on specifications found at https://web.mit.edu/kerberos/krb5-devel/doc/formats/ccache_file_format.html This is primarily designed for parsing and storing a single Kerberos ticket, due to the limitations of PIDL. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 74fb2cc473cea0eebf641fc4d32d706bac8aa6f2) --- librpc/idl/krb5ccache.idl | 115 +++++++++++++++++++++++++++++++++++ librpc/idl/wscript_build | 1 + librpc/wscript_build | 8 ++- source4/librpc/wscript_build | 7 +++ 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 librpc/idl/krb5ccache.idl diff --git a/librpc/idl/krb5ccache.idl b/librpc/idl/krb5ccache.idl new file mode 100644 index 00000000000..1f0cfa752a9 --- /dev/null +++ b/librpc/idl/krb5ccache.idl @@ -0,0 +1,115 @@ +/* + krb5 credentials cache (version 3 or 4) + specification: https://web.mit.edu/kerberos/krb5-devel/doc/formats/ccache_file_format.html +*/ + +#include "idl_types.h" + +[ + uuid("1702b695-99ca-4f32-93e4-1e1c4d5ddb53"), + version(0.0), + pointer_default(unique), + helpstring("KRB5 credentials cache") +] +interface krb5ccache +{ + typedef struct { + uint32 name_type; + uint32 component_count; + [flag(STR_SIZE4|STR_NOTERM|STR_UTF8)] string realm; + [flag(STR_SIZE4|STR_NOTERM|STR_UTF8)] string components[component_count]; + } PRINCIPAL; + + typedef struct { + uint16 enctype; + DATA_BLOB data; + } KEYBLOCK; + + typedef struct { + uint16 addrtype; + DATA_BLOB data; + } ADDRESS; + + typedef struct { + uint32 count; + ADDRESS data[count]; + } ADDRESSES; + + typedef struct { + uint16 ad_type; + DATA_BLOB data; + } AUTHDATUM; + + typedef struct { + uint32 count; + AUTHDATUM data[count]; + } AUTHDATA; + + typedef struct { + PRINCIPAL client; + PRINCIPAL server; + KEYBLOCK keyblock; + uint32 authtime; + uint32 starttime; + uint32 endtime; + uint32 renew_till; + uint8 is_skey; + uint32 ticket_flags; + ADDRESSES addresses; + AUTHDATA authdata; + DATA_BLOB ticket; + DATA_BLOB second_ticket; + } CREDENTIAL; + + typedef struct { + [value(0)] int32 kdc_sec_offset; + [value(0)] int32 kdc_usec_offset; + } DELTATIME_TAG; + + typedef [nodiscriminant] union { + [case(1)] DELTATIME_TAG deltatime_tag; + } FIELD; + + typedef struct { + [value(1)] uint16 tag; + [subcontext(2),switch_is(tag)] FIELD field; + } V4TAG; + + typedef struct { + V4TAG tag; + /* + * We should allow for more than one tag to be properly parsed, but that + * would require manual parsing. + */ + [flag(NDR_REMAINING)] DATA_BLOB further_tags; + } V4TAGS; + + typedef struct { + [subcontext(2)] V4TAGS v4tags; + } V4HEADER; + + typedef [nodiscriminant] union { + /* + * We don't attempt to support file format versions 1 and 2 as they + * assume native CPU byte order, which makes no sense in PIDL. + */ + [case(3)] ; + [case(4)] V4HEADER v4header; + } OPTIONAL_HEADER; + + /* Public structures. */ + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + [value(5)] uint8 pvno; + [value(4)] uint8 version; + [switch_is(version)] OPTIONAL_HEADER optional_header; + PRINCIPAL principal; + CREDENTIAL cred; + [flag(NDR_REMAINING)] DATA_BLOB further_creds; + } CCACHE; + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + CREDENTIAL cred; + [flag(NDR_REMAINING)] DATA_BLOB further_creds; + } MULTIPLE_CREDENTIALS; +} diff --git a/librpc/idl/wscript_build b/librpc/idl/wscript_build index b66f27be901..2eb575e6a4c 100644 --- a/librpc/idl/wscript_build +++ b/librpc/idl/wscript_build @@ -147,6 +147,7 @@ bld.SAMBA_PIDL_LIST('PIDL', drsblobs.idl idmap.idl krb5pac.idl + krb5ccache.idl messaging.idl misc.idl nbt.idl diff --git a/librpc/wscript_build b/librpc/wscript_build index 30763907aaa..08cfc439282 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -374,6 +374,11 @@ bld.SAMBA_LIBRARY('ndr-krb5pac', vnum='0.0.1' ) +bld.SAMBA_SUBSYSTEM('NDR_KRB5CCACHE', + source='gen_ndr/ndr_krb5ccache.c', + deps='ndr NDR_COMPRESSION NDR_SECURITY ndr-standard asn1util' + ) + bld.SAMBA_LIBRARY('ndr-standard', source='', vnum='0.0.1', @@ -616,7 +621,8 @@ bld.SAMBA_LIBRARY('ndr-samba', source=[], deps='''NDR_DRSBLOBS NDR_DRSUAPI NDR_IDMAP NDR_NTLMSSP NDR_NEGOEX NDR_SCHANNEL NDR_MGMT NDR_DNSSERVER NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM - NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV''', + NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV + NDR_KRB5CCACHE''', private_library=True, grouping_library=True ) diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build index 009b2e13d2e..ea9c4853d7a 100644 --- a/source4/librpc/wscript_build +++ b/source4/librpc/wscript_build @@ -229,6 +229,13 @@ bld.SAMBA_PYTHON('python_krb5pac', cflags_end=gen_cflags ) +bld.SAMBA_PYTHON('python_krb5ccache', + source='../../librpc/gen_ndr/py_krb5ccache.c', + deps='NDR_KRB5CCACHE %s %s' % (pytalloc_util, pyrpc_util), + realname='samba/dcerpc/krb5ccache.so', + cflags_end=gen_cflags + ) + bld.SAMBA_PYTHON('python_netlogon', source='../../librpc/gen_ndr/py_netlogon.c', deps='RPC_NDR_NETLOGON %s %s' % (pytalloc_util, pyrpc_util), -- 2.25.1 From ec6c8920a0882711d5debe1313dce2a505a8c011 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 10:58:48 +1200 Subject: [PATCH 068/645] librpc: Test parsing a Kerberos 5 credentials cache with ndrdump This is the format used by the FILE: credentials cache type. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1f17b1edca9c1638ef404fadce3ca7a4d176de12) --- python/samba/tests/blackbox/ndrdump.py | 37 + source3/selftest/ktest-krb5_ccache-2.txt | 1574 ++++++++++++++++++++++ source3/selftest/ktest-krb5_ccache-3.txt | 832 ++++++++++++ 3 files changed, 2443 insertions(+) create mode 100644 source3/selftest/ktest-krb5_ccache-2.txt create mode 100644 source3/selftest/ktest-krb5_ccache-3.txt diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py index f9a3bd98862..b8a025b8dce 100644 --- a/python/samba/tests/blackbox/ndrdump.py +++ b/python/samba/tests/blackbox/ndrdump.py @@ -307,6 +307,43 @@ dump OK # convert expected to bytes for python 3 self.assertEqual(actual, expected.encode('utf-8')) + def test_ndrdump_Krb5ccache(self): + expected = open(self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-2.txt")).read() + try: + # Specify -d1 to match the generated output file, because ndrdump + # only outputs some additional info if this parameter is specified, + # and the --configfile parameter gives us an empty smb.conf to avoid + # extraneous output. + actual = self.check_output( + "ndrdump krb5ccache CCACHE struct " + "--configfile /dev/null -d1 --validate " + + self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-2")) + except BlackboxProcessError as e: + self.fail(e) + # check_output will return bytes + # convert expected to bytes for python 3 + self.assertEqual(actual, expected.encode('utf-8')) + + expected = open(self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-3.txt")).read() + try: + # Specify -d1 to match the generated output file, because ndrdump + # only outputs some additional info if this parameter is specified, + # and the --configfile parameter gives us an empty smb.conf to avoid + # extraneous output. + actual = self.check_output( + "ndrdump krb5ccache CCACHE struct " + "--configfile /dev/null -d1 --validate " + + self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-3")) + except BlackboxProcessError as e: + self.fail(e) + # check_output will return bytes + # convert expected to bytes for python 3 + self.assertEqual(actual, expected.encode('utf-8')) + # This is a good example of a union with an empty default # and no buffers to parse. def test_ndrdump_fuzzed_spoolss_EnumForms(self): diff --git a/source3/selftest/ktest-krb5_ccache-2.txt b/source3/selftest/ktest-krb5_ccache-2.txt new file mode 100644 index 00000000000..c86750ae585 --- /dev/null +++ b/source3/selftest/ktest-krb5_ccache-2.txt @@ -0,0 +1,1574 @@ +pull returned Success + CCACHE: struct CCACHE + pvno : 0x05 (5) + version : 0x04 (4) + optional_header : union OPTIONAL_HEADER(case 0x4) + v4header: struct V4HEADER + v4tags: struct V4TAGS + tag: struct V4TAG + tag : 0x0001 (1) + field : union FIELD(case 0x1) + deltatime_tag: struct DELTATIME_TAG + kdc_sec_offset : 0 + kdc_usec_offset : 0 + further_tags : DATA_BLOB length=0 + principal: struct PRINCIPAL + name_type : 0x00000001 (1) + component_count : 0x00000001 (1) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(1) + components : 'administrator' + cred: struct CREDENTIAL + client: struct PRINCIPAL + name_type : 0x00000001 (1) + component_count : 0x00000001 (1) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(1) + components : 'administrator' + server: struct PRINCIPAL + name_type : 0x00000000 (0) + component_count : 0x00000002 (2) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(2) + components : 'krbtgt' + components : 'KTEST.SAMBA.EXAMPLE.COM' + keyblock: struct KEYBLOCK + enctype : 0x0017 (23) + data : DATA_BLOB length=16 +[0000] 8B 94 0B 31 51 5B F7 A7 15 E9 EE D7 D7 0C 8C 90 ...1Q[.. ........ + authtime : 0x4d994f6a (1301892970) + starttime : 0x4d994f6a (1301892970) + endtime : 0x7d440b68 (2101611368) + renew_till : 0x7d440b68 (2101611368) + is_skey : 0x00 (0) + ticket_flags : 0x40e00000 (1088421888) + addresses: struct ADDRESSES + count : 0x00000000 (0) + data: ARRAY(0) + authdata: struct AUTHDATA + count : 0x00000000 (0) + data: ARRAY(0) + ticket : DATA_BLOB length=1032 +[0000] 61 82 04 04 30 82 04 00 A0 03 02 01 05 A1 19 1B a...0... ........ +[0010] 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 .KTEST.S AMBA.EXA +[0020] 4D 50 4C 45 2E 43 4F 4D A2 2C 30 2A A0 03 02 01 MPLE.COM .,0*.... +[0030] 00 A1 23 30 21 1B 06 6B 72 62 74 67 74 1B 17 4B ..#0!..k rbtgt..K +[0040] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0050] 4C 45 2E 43 4F 4D A3 82 03 AE 30 82 03 AA A0 03 LE.COM.. ..0..... +[0060] 02 01 17 A1 03 02 01 01 A2 82 03 9C 04 82 03 98 ........ ........ +[0070] 80 66 8F CF AB 24 9D C8 76 E4 28 F5 25 6B 73 B2 .f...$.. v.(.%ks. +[0080] 4B 94 ED 09 10 29 05 C4 C0 B8 B9 33 FA C4 46 AB K....).. ...3..F. +[0090] F4 B5 9E 5B 07 54 D6 58 1D B8 CA 04 41 A6 33 A6 ...[.T.X ....A.3. +[00A0] 67 9D EB 83 70 65 A9 2D 65 A5 19 8C 55 2A 0F FC g...pe.- e...U*.. +[00B0] 1B BB 7A BD 86 C0 32 06 F2 2F 0A A5 93 E7 D1 1E ..z...2. ./...... +[00C0] 16 C4 27 DD 1F A7 61 03 FF 05 81 EF 49 B7 25 A3 ..'...a. ....I.%. +[00D0] 6E EA E6 E8 15 E3 10 AF A3 F1 21 B3 D9 C0 67 2F n....... ..!...g/ +[00E0] 0C 0C B7 42 D6 9A 34 8E D4 5E 55 C2 FE 62 03 37 ...B..4. .^U..b.7 +[00F0] A5 58 9B 43 E7 26 E3 71 B2 E5 F1 91 B4 23 8F AC .X.C.&.q .....#.. +[0100] 7A 31 3C 4E B4 94 E4 81 36 98 71 3B 98 7B B7 AB z1....... +[0150] 1A 69 EE 8C 4E A4 D8 55 A5 0B 23 0F D0 89 48 C4 .i..N..U ..#...H. +[0160] 51 FE 32 FD CC F6 71 E1 95 2D CC 1D 0A 0C 8A A2 Q.2...q. .-...... +[0170] 69 58 3B 65 88 53 EC D0 2E E1 C6 CC 6B BC 09 E5 iX;e.S.. ....k... +[0180] B9 15 27 8B E4 B2 24 18 61 42 BB 8B 09 1B 8A 7B ..'...$. aB.....{ +[0190] 13 D8 51 E1 0B 79 12 48 DE A9 54 04 00 6D DD E6 ..Q..y.H ..T..m.. +[01A0] 5E 03 91 FF C7 6D 0B 7C 91 44 E1 0F C0 7E 32 34 ^....m.| .D...~24 +[01B0] 82 86 94 F7 CD 53 EC 52 38 18 AA ED FF FC 5C 01 .....S.R 8.....\. +[01C0] D2 EE 99 45 8E 5B E6 B3 46 B0 F6 3B 22 29 EC 11 ...E.[.. F..;").. +[01D0] 30 6A F6 A1 1F 9E AE 71 E3 A6 E7 3F F3 7D 2B 75 0j.....q ...?.}+u +[01E0] 70 4D 63 47 5C 18 2C 8B B1 1A 69 B6 C5 46 01 17 pMcG\.,. ..i..F.. +[01F0] 8E 64 3D 47 88 20 1C AA D7 60 32 28 11 60 EA 28 .d=G. .. .`2(.`.( +[0200] 66 99 4C B1 2A 28 96 BF 18 2A 3E F4 D6 84 E5 A0 f.L.*(.. .*>..... +[0210] F4 4E E7 F9 54 95 22 96 2A 87 01 CC 3E A7 FF 42 .N..T.". *...>..B +[0220] 6A A4 4A 3A B9 24 10 65 99 53 58 2A 4E 72 E7 1F j.J:.$.e .SX*Nr.. +[0230] 82 BC BD 3C 6C 9D 33 3A CE C6 6E 72 A2 81 B3 84 ........ +[0280] AB F0 D0 93 08 42 E5 37 19 24 4E C1 AF FC 92 A9 .....B.7 .$N..... +[0290] B1 27 B1 9A 2A 62 34 F1 DC C0 6B 83 AE C3 74 E8 .'..*b4. ..k...t. +[02A0] A3 05 DD 82 DD A3 D7 90 A8 E3 9C EB 64 16 23 06 ........ ....d.#. +[02B0] 5D FB E4 35 7C 22 29 78 E3 3B 75 92 91 0C 9D A1 ]..5|")x .;u..... +[02C0] 87 7C 2E 82 AE 49 9D 4A 50 A9 C2 D5 85 B0 16 5D .|...I.J P......] +[02D0] A2 CD B0 DD 29 3F 6F 66 C9 C1 9F 5C F0 B6 FC D2 ....)?of ...\.... +[02E0] 52 BE 7B F0 1F 26 AF 8A FC C3 A6 24 8C C0 10 06 R.{..&.. ...$.... +[02F0] 73 1E 17 9E 6E 6F 32 44 6A DF 82 5D D0 6B 74 CE s...no2D j..].kt. +[0300] 58 0B 4C 7B EB A1 13 44 B1 3E D8 F8 BA F4 4E 55 X.L{...D .>....NU +[0310] 71 3D C1 09 D9 E7 97 9A 14 5C 54 7E 57 81 5F 6B q=...... .\T~W._k +[0320] 30 BE 9A E1 98 29 47 D4 C0 8F 63 0A F8 27 1F CE 0....)G. ..c..'.. +[0330] ED D9 BB 7B 12 24 D0 34 2A 7C F0 F7 77 F4 F1 1D ...{.$.4 *|..w... +[0340] 4C 5D 75 2D 6B 0D 80 35 82 CC D8 7A 6B FA A0 55 L]u-k..5 ...zk..U +[0350] 34 CD 87 15 61 38 78 D4 69 0F AA 72 D6 AC FA 99 4...a8x. i..r.... +[0360] BC 70 39 27 A7 25 2E 1B 6F 36 01 FD E9 B4 9A 79 .p9'.%.. o6.....y +[0370] 6C 19 DD A6 8C 78 B0 40 92 60 58 F0 28 AD 08 78 l....x.@ .`X.(..x +[0380] 4A 29 06 2C 82 2B 1A E3 91 0B 5F EE D6 B8 66 47 J).,.+.. .._...fG +[0390] 31 9B A3 DF 9F 79 D7 BB 0E 2C FA 0E C9 66 84 8D 1....y.. .,...f.. +[03A0] FF BA BB 21 27 9E AD 86 84 55 8D 4C 4C 47 D9 5F ...!'... .U.LLG._ +[03B0] B2 7D 26 CA B7 49 3C 9D 1B 67 71 11 3A 8A EB EA .}&..I<. .gq.:... +[03C0] 0F 15 EB F0 1E 46 F7 A4 34 04 D7 E3 50 67 47 D3 .....F.. 4...PgG. +[03D0] 66 21 17 77 51 A7 1F 1D 84 3B 7C B1 5D 4E B8 D4 f!.wQ... .;|.]N.. +[03E0] F9 C5 75 06 AA 19 45 1C E9 06 9E AD 23 26 6B 10 ..u...E. ....#&k. +[03F0] 53 A0 36 D3 58 9F 5E 8C CB A5 F6 BC C9 30 3C BC S.6.X.^. .....0<. +[0400] AD FF 7C 92 F0 C6 9A 02 ..|..... + second_ticket : DATA_BLOB length=0 + further_creds : DATA_BLOB length=10683 +[0000] 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 ........ ....KTES +[0010] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0020] 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 COM....a dministr +[0030] 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 ator.... ........ +[0040] 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D KTEST.SA MBA.EXAM +[0050] 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 73 00 PLE.COM. ...cifs. +[0060] 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 00 17 ...local ktest6.. +[0070] 00 00 00 10 00 6E A1 B2 31 6D 48 C7 90 72 3A 0C .....n.. 1mH..r:. +[0080] 4B 8B 83 8C 4D 99 4F 6A 4D 99 50 85 7D 44 0B 68 K...M.Oj M.P.}D.h +[0090] 00 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 .....@(. ........ +[00A0] 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 .....a.. .0...... +[00B0] 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[00C0] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 A.EXAMPL E.COM..0 +[00D0] 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 69 66 73 ........ 0...cifs +[00E0] 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 A3 82 03 ..localk test6... +[00F0] AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 02 A2 .0...... ........ +[0100] 82 03 9C 04 82 03 98 C6 BB 64 A8 31 00 FC 5E 51 ........ .d.1..^Q +[0110] 3C 87 F8 34 47 3B D0 6F 6F FD 9E A6 91 12 74 2D <..4G;.o o.....t- +[0120] 44 BB AA 91 A0 2D 46 3E 9E FB FB C4 FB F1 15 FD D....-F> ........ +[0130] BB DA EE 06 A9 20 6A 38 DC 46 06 27 D9 A2 9D 2D ..... j8 .F.'...- +[0140] 1F FD 0D 7D 8A BB 0A 7C E8 47 17 BC 7B 70 E4 51 ...}...| .G..{p.Q +[0150] 6A BA 51 68 62 28 4A 1E 51 D1 0D CD 02 55 75 44 j.Qhb(J. Q....UuD +[0160] 8A B9 C2 84 F4 17 34 92 9B 31 85 9E 43 C1 0C 3A ......4. .1..C..: +[0170] B2 69 7F 20 1A 18 1F 65 4F C0 20 C9 B5 AF E1 61 .i. ...e O. ....a +[0180] 8C 90 10 63 26 A6 5D 05 3C CD 29 BB 7B 74 D5 8F ...c&.]. <.).{t.. +[0190] 2C 7F 4B E8 84 24 57 37 8A C6 F7 91 FD 22 9A A5 ,.K..$W7 .....".. +[01A0] 0D E9 4A 78 93 36 FC A8 8C 8A 27 8A C6 28 4B 7B ..Jx.6.. ..'..(K{ +[01B0] DA 11 42 BC 09 10 81 82 14 0F 9C B8 48 26 91 78 ..B..... ....H&.x +[01C0] A8 DD 97 6C 24 A1 D2 E8 85 19 B3 D3 85 4D 38 C7 ...l$... .....M8. +[01D0] 7D 49 55 8E 85 46 E1 EE 7B BA 11 62 63 53 C5 16 }IU..F.. {..bcS.. +[01E0] 4A 0C 1C 99 7C 0E FB 45 1D B4 98 58 67 7E 40 65 J...|..E ...Xg~@e +[01F0] 4B 48 E2 89 9C 8B C2 B8 39 D1 04 C0 A8 56 E8 A1 KH...... 9....V.. +[0200] 04 7A 7A C9 60 18 A0 29 E2 DC 82 4C 8F 18 CE 2F .zz.`..) ...L.../ +[0210] 14 F0 18 5B 6C FF 85 45 88 73 CB A4 55 08 FC BF ...[l..E .s..U... +[0220] C7 9F 51 0A DB 2C C1 E3 3C DD F6 F0 A3 2D F1 3B ..Q..,.. <....-.; +[0230] A0 12 1D FC 2A 67 F5 1A 7F E5 7C 6C FB 8A 18 BD ....*g.. ..|l.... +[0240] D1 5D E5 5E 68 30 AA 58 9E 10 13 E0 26 7E 7D C4 .].^h0.X ....&~}. +[0250] E1 A5 B6 86 0F 1C 0F 13 A4 5E 5E 6A ED 42 79 31 ........ .^^j.By1 +[0260] BB B3 5F 3A 3F DD CB 63 82 FB 06 AE 12 36 C9 1E .._:?..c .....6.. +[0270] 06 7D 41 82 2E D2 FA 26 EC 17 50 5E D0 DE 26 85 .}A....& ..P^..&. +[0280] 30 71 BC 45 3B DA 2E 08 8D B2 2A 3C E0 79 8F 77 0q.E;... ..*<.y.w +[0290] 4C 01 69 7A 09 C7 88 E1 D1 DC FF 78 DB 25 7B B1 L.iz.... ...x.%{. +[02A0] 3C BB 22 27 80 0D 75 96 18 B6 40 95 6D C8 AB 04 <."'..u. ..@.m... +[02B0] 05 41 A1 C4 25 71 C4 53 3A A6 9C B2 4D E6 15 2C .A..%q.S :...M.., +[02C0] B2 47 6C DA A8 7D CC A3 89 8B C9 1E 21 F5 E9 B2 .Gl..}.. ....!... +[02D0] 42 95 68 28 AF C6 37 22 BA 30 8D 53 FA 08 0D CE B.h(..7" .0.S.... +[02E0] CA 81 61 0D 84 A5 2D 75 BD 41 85 4C 88 56 72 C6 ..a...-u .A.L.Vr. +[02F0] B6 10 F8 34 CD B2 F4 5C 94 FA 80 90 82 A0 BD 68 ...4...\ .......h +[0300] EC 08 32 C3 B6 51 1E 3F 67 CB 7B EB 70 83 84 D4 ..2..Q.? g.{.p... +[0310] CB 52 55 36 61 1E 60 90 5B 6F FE 9A 62 05 CF 26 .RU6a.`. [o..b..& +[0320] 8E 65 E2 60 4B ED 63 B4 C4 E6 44 B4 2F B0 B8 07 .e.`K.c. ..D./... +[0330] FE BE 0D 50 E4 56 A4 2E 0D 25 76 0B 0F 44 09 20 ...P.V.. .%v..D. +[0340] 80 E5 C4 94 63 E0 54 46 1D AB 5E 0B 09 93 B1 30 ....c.TF ..^....0 +[0350] 31 7B 04 DC 23 43 3B DB 7D 39 67 FE 9A 1F C1 08 1{..#C;. }9g..... +[0360] AF 34 24 F6 74 E4 14 DA 34 8F 61 57 6A 7F 1D 4A .4$.t... 4.aWj..J +[0370] 88 0A 90 78 93 F1 86 54 DB 22 86 D6 69 0F DF 44 ...x...T ."..i..D +[0380] 7C D3 6B 9D 41 63 50 98 3A 97 B9 7B 4C 53 E3 85 |.k.AcP. :..{LS.. +[0390] 73 9A C9 08 A0 75 12 50 02 87 B0 CF CC 84 84 D9 s....u.P ........ +[03A0] BC FC 94 79 AF 6A A6 08 FF 19 7E E9 22 9B EC 5C ...y.j.. ..~."..\ +[03B0] C1 6B 1D A4 B4 55 32 5E 23 C3 C0 D4 8B 80 E6 67 .k...U2^ #......g +[03C0] B1 59 EB 9D 5D 9B AD C6 0E 7D E2 FE B1 24 8A B1 .Y..]... .}...$.. +[03D0] 37 1E 60 7F 83 35 48 32 F7 03 E8 12 E6 21 7C 3D 7.`..5H2 .....!|= +[03E0] 21 7F 6B 14 31 9C 1A A3 4C 2B 1C 5E EC 34 C1 2D !.k.1... L+.^.4.- +[03F0] DA 19 6C E6 6D 8D 60 D7 55 9E E6 D0 B5 07 06 72 ..l.m.`. U......r +[0400] C0 E9 4E 91 94 6B 3E 0B F1 0A 75 4D E8 CB 53 6B ..N..k>. ..uM..Sk +[0410] 34 A4 2F 96 A5 39 1A 18 6E 27 00 6D 41 B7 D8 F5 4./..9.. n'.mA... +[0420] 9A E5 01 FC 0B A8 97 56 EE 98 04 1D 98 84 5E 82 .......V ......^. +[0430] C8 E8 EC 17 D5 FA 96 00 3B E1 98 1C D8 FA 66 A0 ........ ;.....f. +[0440] DC 32 60 F6 03 46 08 3C E5 16 6F F2 8B 4D 72 9F .2`..F.< ..o..Mr. +[0450] 0F E0 A9 71 6E 7C AE AA FB A3 4D F1 A1 B6 1B 9F ...qn|.. ..M..... +[0460] 62 71 E1 2C 82 9B AE E3 07 9B 79 90 F1 C2 69 E5 bq.,.... ..y...i. +[0470] 7E CB 57 E6 C9 1C 4E A8 C7 12 EA 4F 4C 52 17 03 ~.W...N. ...OLR.. +[0480] AB D4 FD 34 60 F4 7C BE 9E 36 30 37 88 95 61 2E ...4`.|. .607..a. +[0490] CF 70 AF 22 70 DB E8 AA 6E 3D 30 F7 4D 84 D5 00 .p."p... n=0.M... +[04A0] 00 00 00 00 00 00 01 00 00 00 01 00 00 00 17 4B ........ .......K +[04B0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[04C0] 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 LE.COM.. ..admini +[04D0] 73 74 72 61 74 6F 72 00 00 00 01 00 00 00 02 00 strator. ........ +[04E0] 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 ...KTEST .SAMBA.E +[04F0] 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 XAMPLE.C OM....ci +[0500] 66 73 00 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 fs....lo calktest +[0510] 36 00 17 00 00 00 10 00 6E A1 B2 31 6D 48 C7 90 6....... n..1mH.. +[0520] 72 3A 0C 4B 8B 83 8C 4D 99 4F 6A 4D 99 50 85 7D r:.K...M .OjM.P.} +[0530] 44 0B 68 00 00 00 00 00 40 28 00 00 00 00 00 00 D.h..... @(...... +[0540] 00 00 00 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 ........ a...0... +[0550] A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0560] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0570] A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 ..0..... ...0...c +[0580] 69 66 73 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 ifs..loc alktest6 +[0590] A3 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 03 02 ....0... ........ +[05A0] 01 02 A2 82 03 9C 04 82 03 98 C6 BB 64 A8 31 00 ........ ....d.1. +[05B0] FC 5E 51 3C 87 F8 34 47 3B D0 6F 6F FD 9E A6 91 .^Q<..4G ;.oo.... +[05C0] 12 74 2D 44 BB AA 91 A0 2D 46 3E 9E FB FB C4 FB .t-D.... -F>..... +[05D0] F1 15 FD BB DA EE 06 A9 20 6A 38 DC 46 06 27 D9 ........ j8.F.'. +[05E0] A2 9D 2D 1F FD 0D 7D 8A BB 0A 7C E8 47 17 BC 7B ..-...}. ..|.G..{ +[05F0] 70 E4 51 6A BA 51 68 62 28 4A 1E 51 D1 0D CD 02 p.Qj.Qhb (J.Q.... +[0600] 55 75 44 8A B9 C2 84 F4 17 34 92 9B 31 85 9E 43 UuD..... .4..1..C +[0610] C1 0C 3A B2 69 7F 20 1A 18 1F 65 4F C0 20 C9 B5 ..:.i. . ..eO. .. +[0620] AF E1 61 8C 90 10 63 26 A6 5D 05 3C CD 29 BB 7B ..a...c& .].<.).{ +[0630] 74 D5 8F 2C 7F 4B E8 84 24 57 37 8A C6 F7 91 FD t..,.K.. $W7..... +[0640] 22 9A A5 0D E9 4A 78 93 36 FC A8 8C 8A 27 8A C6 "....Jx. 6....'.. +[0650] 28 4B 7B DA 11 42 BC 09 10 81 82 14 0F 9C B8 48 (K{..B.. .......H +[0660] 26 91 78 A8 DD 97 6C 24 A1 D2 E8 85 19 B3 D3 85 &.x...l$ ........ +[0670] 4D 38 C7 7D 49 55 8E 85 46 E1 EE 7B BA 11 62 63 M8.}IU.. F..{..bc +[0680] 53 C5 16 4A 0C 1C 99 7C 0E FB 45 1D B4 98 58 67 S..J...| ..E...Xg +[0690] 7E 40 65 4B 48 E2 89 9C 8B C2 B8 39 D1 04 C0 A8 ~@eKH... ...9.... +[06A0] 56 E8 A1 04 7A 7A C9 60 18 A0 29 E2 DC 82 4C 8F V...zz.` ..)...L. +[06B0] 18 CE 2F 14 F0 18 5B 6C FF 85 45 88 73 CB A4 55 ../...[l ..E.s..U +[06C0] 08 FC BF C7 9F 51 0A DB 2C C1 E3 3C DD F6 F0 A3 .....Q.. ,..<.... +[06D0] 2D F1 3B A0 12 1D FC 2A 67 F5 1A 7F E5 7C 6C FB -.;....* g....|l. +[06E0] 8A 18 BD D1 5D E5 5E 68 30 AA 58 9E 10 13 E0 26 ....].^h 0.X....& +[06F0] 7E 7D C4 E1 A5 B6 86 0F 1C 0F 13 A4 5E 5E 6A ED ~}...... ....^^j. +[0700] 42 79 31 BB B3 5F 3A 3F DD CB 63 82 FB 06 AE 12 By1.._:? ..c..... +[0710] 36 C9 1E 06 7D 41 82 2E D2 FA 26 EC 17 50 5E D0 6...}A.. ..&..P^. +[0720] DE 26 85 30 71 BC 45 3B DA 2E 08 8D B2 2A 3C E0 .&.0q.E; .....*<. +[0730] 79 8F 77 4C 01 69 7A 09 C7 88 E1 D1 DC FF 78 DB y.wL.iz. ......x. +[0740] 25 7B B1 3C BB 22 27 80 0D 75 96 18 B6 40 95 6D %{.<."'. .u...@.m +[0750] C8 AB 04 05 41 A1 C4 25 71 C4 53 3A A6 9C B2 4D ....A..% q.S:...M +[0760] E6 15 2C B2 47 6C DA A8 7D CC A3 89 8B C9 1E 21 ..,.Gl.. }......! +[0770] F5 E9 B2 42 95 68 28 AF C6 37 22 BA 30 8D 53 FA ...B.h(. .7".0.S. +[0780] 08 0D CE CA 81 61 0D 84 A5 2D 75 BD 41 85 4C 88 .....a.. .-u.A.L. +[0790] 56 72 C6 B6 10 F8 34 CD B2 F4 5C 94 FA 80 90 82 Vr....4. ..\..... +[07A0] A0 BD 68 EC 08 32 C3 B6 51 1E 3F 67 CB 7B EB 70 ..h..2.. Q.?g.{.p +[07B0] 83 84 D4 CB 52 55 36 61 1E 60 90 5B 6F FE 9A 62 ....RU6a .`.[o..b +[07C0] 05 CF 26 8E 65 E2 60 4B ED 63 B4 C4 E6 44 B4 2F ..&.e.`K .c...D./ +[07D0] B0 B8 07 FE BE 0D 50 E4 56 A4 2E 0D 25 76 0B 0F ......P. V...%v.. +[07E0] 44 09 20 80 E5 C4 94 63 E0 54 46 1D AB 5E 0B 09 D. ....c .TF..^.. +[07F0] 93 B1 30 31 7B 04 DC 23 43 3B DB 7D 39 67 FE 9A ..01{..# C;.}9g.. +[0800] 1F C1 08 AF 34 24 F6 74 E4 14 DA 34 8F 61 57 6A ....4$.t ...4.aWj +[0810] 7F 1D 4A 88 0A 90 78 93 F1 86 54 DB 22 86 D6 69 ..J...x. ..T."..i +[0820] 0F DF 44 7C D3 6B 9D 41 63 50 98 3A 97 B9 7B 4C ..D|.k.A cP.:..{L +[0830] 53 E3 85 73 9A C9 08 A0 75 12 50 02 87 B0 CF CC S..s.... u.P..... +[0840] 84 84 D9 BC FC 94 79 AF 6A A6 08 FF 19 7E E9 22 ......y. j....~." +[0850] 9B EC 5C C1 6B 1D A4 B4 55 32 5E 23 C3 C0 D4 8B ..\.k... U2^#.... +[0860] 80 E6 67 B1 59 EB 9D 5D 9B AD C6 0E 7D E2 FE B1 ..g.Y..] ....}... +[0870] 24 8A B1 37 1E 60 7F 83 35 48 32 F7 03 E8 12 E6 $..7.`.. 5H2..... +[0880] 21 7C 3D 21 7F 6B 14 31 9C 1A A3 4C 2B 1C 5E EC !|=!.k.1 ...L+.^. +[0890] 34 C1 2D DA 19 6C E6 6D 8D 60 D7 55 9E E6 D0 B5 4.-..l.m .`.U.... +[08A0] 07 06 72 C0 E9 4E 91 94 6B 3E 0B F1 0A 75 4D E8 ..r..N.. k>...uM. +[08B0] CB 53 6B 34 A4 2F 96 A5 39 1A 18 6E 27 00 6D 41 .Sk4./.. 9..n'.mA +[08C0] B7 D8 F5 9A E5 01 FC 0B A8 97 56 EE 98 04 1D 98 ........ ..V..... +[08D0] 84 5E 82 C8 E8 EC 17 D5 FA 96 00 3B E1 98 1C D8 .^...... ...;.... +[08E0] FA 66 A0 DC 32 60 F6 03 46 08 3C E5 16 6F F2 8B .f..2`.. F.<..o.. +[08F0] 4D 72 9F 0F E0 A9 71 6E 7C AE AA FB A3 4D F1 A1 Mr....qn |....M.. +[0900] B6 1B 9F 62 71 E1 2C 82 9B AE E3 07 9B 79 90 F1 ...bq.,. .....y.. +[0910] C2 69 E5 7E CB 57 E6 C9 1C 4E A8 C7 12 EA 4F 4C .i.~.W.. .N....OL +[0920] 52 17 03 AB D4 FD 34 60 F4 7C BE 9E 36 30 37 88 R.....4` .|..607. +[0930] 95 61 2E CF 70 AF 22 70 DB E8 AA 6E 3D 30 F7 4D .a..p."p ...n=0.M +[0940] 84 D5 00 00 00 00 00 00 00 01 00 00 00 01 00 00 ........ ........ +[0950] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[0960] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D AMPLE.CO M....adm +[0970] 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 inistrat or...... +[0980] 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[0990] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 A.EXAMPL E.COM... +[09A0] 04 63 69 66 73 00 00 00 0B 6C 6F 63 61 6C 6B 74 .cifs... .localkt +[09B0] 65 73 74 36 00 17 00 00 00 10 00 6E A1 B2 31 6D est6.... ...n..1m +[09C0] 48 C7 90 72 3A 0C 4B 8B 83 8C 4D 99 4F 6A 4D 99 H..r:.K. ..M.OjM. +[09D0] 50 85 7D 44 0B 68 00 00 00 00 00 40 28 00 00 00 P.}D.h.. ...@(... +[09E0] 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 ........ ...a...0 +[09F0] 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 ........ ....KTES +[0A00] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0A10] 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 COM..0.. ......0. +[0A20] 1B 04 63 69 66 73 1B 0B 6C 6F 63 61 6C 6B 74 65 ..cifs.. localkte +[0A30] 73 74 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 st6....0 ........ +[0A40] A1 03 02 01 02 A2 82 03 9C 04 82 03 98 C6 BB 64 ........ .......d +[0A50] A8 31 00 FC 5E 51 3C 87 F8 34 47 3B D0 6F 6F FD .1..^Q<. .4G;.oo. +[0A60] 9E A6 91 12 74 2D 44 BB AA 91 A0 2D 46 3E 9E FB ....t-D. ...-F>.. +[0A70] FB C4 FB F1 15 FD BB DA EE 06 A9 20 6A 38 DC 46 ........ ... j8.F +[0A80] 06 27 D9 A2 9D 2D 1F FD 0D 7D 8A BB 0A 7C E8 47 .'...-.. .}...|.G +[0A90] 17 BC 7B 70 E4 51 6A BA 51 68 62 28 4A 1E 51 D1 ..{p.Qj. Qhb(J.Q. +[0AA0] 0D CD 02 55 75 44 8A B9 C2 84 F4 17 34 92 9B 31 ...UuD.. ....4..1 +[0AB0] 85 9E 43 C1 0C 3A B2 69 7F 20 1A 18 1F 65 4F C0 ..C..:.i . ...eO. +[0AC0] 20 C9 B5 AF E1 61 8C 90 10 63 26 A6 5D 05 3C CD ....a.. .c&.].<. +[0AD0] 29 BB 7B 74 D5 8F 2C 7F 4B E8 84 24 57 37 8A C6 ).{t..,. K..$W7.. +[0AE0] F7 91 FD 22 9A A5 0D E9 4A 78 93 36 FC A8 8C 8A ...".... Jx.6.... +[0AF0] 27 8A C6 28 4B 7B DA 11 42 BC 09 10 81 82 14 0F '..(K{.. B....... +[0B00] 9C B8 48 26 91 78 A8 DD 97 6C 24 A1 D2 E8 85 19 ..H&.x.. .l$..... +[0B10] B3 D3 85 4D 38 C7 7D 49 55 8E 85 46 E1 EE 7B BA ...M8.}I U..F..{. +[0B20] 11 62 63 53 C5 16 4A 0C 1C 99 7C 0E FB 45 1D B4 .bcS..J. ..|..E.. +[0B30] 98 58 67 7E 40 65 4B 48 E2 89 9C 8B C2 B8 39 D1 .Xg~@eKH ......9. +[0B40] 04 C0 A8 56 E8 A1 04 7A 7A C9 60 18 A0 29 E2 DC ...V...z z.`..).. +[0B50] 82 4C 8F 18 CE 2F 14 F0 18 5B 6C FF 85 45 88 73 .L.../.. .[l..E.s +[0B60] CB A4 55 08 FC BF C7 9F 51 0A DB 2C C1 E3 3C DD ..U..... Q..,..<. +[0B70] F6 F0 A3 2D F1 3B A0 12 1D FC 2A 67 F5 1A 7F E5 ...-.;.. ..*g.... +[0B80] 7C 6C FB 8A 18 BD D1 5D E5 5E 68 30 AA 58 9E 10 |l.....] .^h0.X.. +[0B90] 13 E0 26 7E 7D C4 E1 A5 B6 86 0F 1C 0F 13 A4 5E ..&~}... .......^ +[0BA0] 5E 6A ED 42 79 31 BB B3 5F 3A 3F DD CB 63 82 FB ^j.By1.. _:?..c.. +[0BB0] 06 AE 12 36 C9 1E 06 7D 41 82 2E D2 FA 26 EC 17 ...6...} A....&.. +[0BC0] 50 5E D0 DE 26 85 30 71 BC 45 3B DA 2E 08 8D B2 P^..&.0q .E;..... +[0BD0] 2A 3C E0 79 8F 77 4C 01 69 7A 09 C7 88 E1 D1 DC *<.y.wL. iz...... +[0BE0] FF 78 DB 25 7B B1 3C BB 22 27 80 0D 75 96 18 B6 .x.%{.<. "'..u... +[0BF0] 40 95 6D C8 AB 04 05 41 A1 C4 25 71 C4 53 3A A6 @.m....A ..%q.S:. +[0C00] 9C B2 4D E6 15 2C B2 47 6C DA A8 7D CC A3 89 8B ..M..,.G l..}.... +[0C10] C9 1E 21 F5 E9 B2 42 95 68 28 AF C6 37 22 BA 30 ..!...B. h(..7".0 +[0C20] 8D 53 FA 08 0D CE CA 81 61 0D 84 A5 2D 75 BD 41 .S...... a...-u.A +[0C30] 85 4C 88 56 72 C6 B6 10 F8 34 CD B2 F4 5C 94 FA .L.Vr... .4...\.. +[0C40] 80 90 82 A0 BD 68 EC 08 32 C3 B6 51 1E 3F 67 CB .....h.. 2..Q.?g. +[0C50] 7B EB 70 83 84 D4 CB 52 55 36 61 1E 60 90 5B 6F {.p....R U6a.`.[o +[0C60] FE 9A 62 05 CF 26 8E 65 E2 60 4B ED 63 B4 C4 E6 ..b..&.e .`K.c... +[0C70] 44 B4 2F B0 B8 07 FE BE 0D 50 E4 56 A4 2E 0D 25 D./..... .P.V...% +[0C80] 76 0B 0F 44 09 20 80 E5 C4 94 63 E0 54 46 1D AB v..D. .. ..c.TF.. +[0C90] 5E 0B 09 93 B1 30 31 7B 04 DC 23 43 3B DB 7D 39 ^....01{ ..#C;.}9 +[0CA0] 67 FE 9A 1F C1 08 AF 34 24 F6 74 E4 14 DA 34 8F g......4 $.t...4. +[0CB0] 61 57 6A 7F 1D 4A 88 0A 90 78 93 F1 86 54 DB 22 aWj..J.. .x...T." +[0CC0] 86 D6 69 0F DF 44 7C D3 6B 9D 41 63 50 98 3A 97 ..i..D|. k.AcP.:. +[0CD0] B9 7B 4C 53 E3 85 73 9A C9 08 A0 75 12 50 02 87 .{LS..s. ...u.P.. +[0CE0] B0 CF CC 84 84 D9 BC FC 94 79 AF 6A A6 08 FF 19 ........ .y.j.... +[0CF0] 7E E9 22 9B EC 5C C1 6B 1D A4 B4 55 32 5E 23 C3 ~."..\.k ...U2^#. +[0D00] C0 D4 8B 80 E6 67 B1 59 EB 9D 5D 9B AD C6 0E 7D .....g.Y ..]....} +[0D10] E2 FE B1 24 8A B1 37 1E 60 7F 83 35 48 32 F7 03 ...$..7. `..5H2.. +[0D20] E8 12 E6 21 7C 3D 21 7F 6B 14 31 9C 1A A3 4C 2B ...!|=!. k.1...L+ +[0D30] 1C 5E EC 34 C1 2D DA 19 6C E6 6D 8D 60 D7 55 9E .^.4.-.. l.m.`.U. +[0D40] E6 D0 B5 07 06 72 C0 E9 4E 91 94 6B 3E 0B F1 0A .....r.. N..k>... +[0D50] 75 4D E8 CB 53 6B 34 A4 2F 96 A5 39 1A 18 6E 27 uM..Sk4. /..9..n' +[0D60] 00 6D 41 B7 D8 F5 9A E5 01 FC 0B A8 97 56 EE 98 .mA..... .....V.. +[0D70] 04 1D 98 84 5E 82 C8 E8 EC 17 D5 FA 96 00 3B E1 ....^... ......;. +[0D80] 98 1C D8 FA 66 A0 DC 32 60 F6 03 46 08 3C E5 16 ....f..2 `..F.<.. +[0D90] 6F F2 8B 4D 72 9F 0F E0 A9 71 6E 7C AE AA FB A3 o..Mr... .qn|.... +[0DA0] 4D F1 A1 B6 1B 9F 62 71 E1 2C 82 9B AE E3 07 9B M.....bq .,...... +[0DB0] 79 90 F1 C2 69 E5 7E CB 57 E6 C9 1C 4E A8 C7 12 y...i.~. W...N... +[0DC0] EA 4F 4C 52 17 03 AB D4 FD 34 60 F4 7C BE 9E 36 .OLR.... .4`.|..6 +[0DD0] 30 37 88 95 61 2E CF 70 AF 22 70 DB E8 AA 6E 3D 07..a..p ."p...n= +[0DE0] 30 F7 4D 84 D5 00 00 00 00 00 00 00 01 00 00 00 0.M..... ........ +[0DF0] 01 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[0E00] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D .EXAMPLE .COM.... +[0E10] 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 administ rator... +[0E20] 01 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0E30] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0E40] 00 00 00 04 63 69 66 73 00 00 00 0B 4C 4F 43 41 ....cifs ....LOCA +[0E50] 4C 4B 54 45 53 54 36 00 17 00 00 00 10 1D C8 5E LKTEST6. .......^ +[0E60] 46 48 82 F9 29 DB C6 A6 F1 72 6D 8D E9 4D 99 4F FH..)... .rm..M.O +[0E70] 6A 4D 99 85 09 7D 44 0B 68 00 00 00 00 00 40 28 jM...}D. h.....@( +[0E80] 00 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 ........ ......a. +[0E90] 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B ..0..... .......K +[0EA0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0EB0] 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 LE.COM.. 0....... +[0EC0] 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F 43 41 4C .0...cif s..LOCAL +[0ED0] 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 KTEST6.. ..0..... +[0EE0] 02 01 17 A1 03 02 01 02 A2 82 03 9C 04 82 03 98 ........ ........ +[0EF0] 66 D8 19 46 FA CB 73 2D CF 88 FD 4A EE 07 48 DA f..F..s- ...J..H. +[0F00] 0E BC 58 30 43 40 A4 9C 00 0F 3B 17 C1 2D F5 9C ..X0C@.. ..;..-.. +[0F10] 3E D9 2F 1D CA 01 9B D7 2E EC D7 70 ED 8B 8B 1B >./..... ...p.... +[0F20] 5E F2 4E EE DD 0F C0 8D 61 E5 D7 0A 56 00 32 B1 ^.N..... a...V.2. +[0F30] DB 91 37 29 0F 2F 85 EE A8 43 BA A5 B8 D4 19 74 ..7)./.. .C.....t +[0F40] 33 F0 69 52 E1 58 98 83 D6 16 0B 44 A9 63 9B D4 3.iR.X.. ...D.c.. +[0F50] 4E 6E A7 3E CD 9A 96 4D C4 96 F5 07 6D 29 B6 ED Nn.>...M ....m).. +[0F60] 2A 62 3D 53 22 33 D1 95 E9 DF 74 4C 2A E2 29 AF *b=S"3.. ..tL*.). +[0F70] 5B 69 B0 48 2D AD 94 FD A5 1D 54 D8 E2 5E C1 68 [i.H-... ..T..^.h +[0F80] 6F BA 02 01 79 C3 C9 97 0B 76 66 45 E2 3B 10 17 o...y... .vfE.;.. +[0F90] 95 40 46 E4 85 B9 87 BB CF CF 19 8C 3A C0 EA 38 .@F..... ....:..8 +[0FA0] 3B B9 E9 4B 05 89 E5 27 8C 62 95 BC 0D 65 F0 D2 ;..K...' .b...e.. +[0FB0] C0 5E BC 65 01 D5 0B CB 17 31 0F 06 49 4F A2 4A .^.e.... .1..IO.J +[0FC0] 70 77 DB BD 92 5B 37 5C EC 06 DF C5 E2 31 C8 40 pw...[7\ .....1.@ +[0FD0] 09 11 68 14 E7 7D CE 54 4F 52 61 31 2C 1C 53 52 ..h..}.T ORa1,.SR +[0FE0] DB BE D8 95 39 EE 7D C6 CE C8 22 95 92 97 97 3D ....9.}. .."....= +[0FF0] 5E 66 0F AD DC C2 4E 2E 2B 9F 63 20 30 DF B7 C1 ^f....N. +.c 0... +[1000] D4 65 AA 6F 2D 10 24 07 20 8D 88 6E 4B 09 04 31 .e.o-.$. ..nK..1 +[1010] B6 A3 EB F7 37 32 0E 0C 73 C6 F6 B8 4D D9 0C 4C ....72.. s...M..L +[1020] 5B EC 10 6A 51 19 EA 3F FF 46 E7 73 16 A7 1F 33 [..jQ..? .F.s...3 +[1030] 98 7C 9B AD 5A 23 A9 40 7C 0F DF EE 0F AA C7 E8 .|..Z#.@ |....... +[1040] 63 07 98 3A 4A 0D 18 62 01 21 B2 AE A5 69 B0 C1 c..:J..b .!...i.. +[1050] 15 51 BA 97 D2 C5 42 5B C5 30 38 18 A9 48 AB D7 .Q....B[ .08..H.. +[1060] FC A1 BC 9F 71 E7 EA 18 54 42 DA D6 A4 FC C1 DC ....q... TB...... +[1070] F3 12 30 62 AC 98 E1 7D 2B 34 1E 52 4C 26 67 32 ..0b...} +4.RL&g2 +[1080] D9 44 1A 08 27 0E DA D0 FC 84 66 35 81 D6 EB 98 .D..'... ..f5.... +[1090] 46 6F 1E 47 E0 14 31 BE 47 80 65 AA 0B 20 D6 33 Fo.G..1. G.e.. .3 +[10A0] 36 3B 0D 40 2F 5A 2E 0E 01 BE 00 EB 33 3E 4B 32 6;.@/Z.. ....3>K2 +[10B0] 91 F4 22 96 E5 5F D4 D5 92 94 CC 5B 59 6A 3E D2 ..".._.. ...[Yj>. +[10C0] FB A0 4F 99 C4 07 8B 6F 2B 14 37 CD 37 44 C0 1F ..O....o +.7.7D.. +[10D0] 80 9C 43 46 F2 5E F4 FE D3 39 70 61 BE 72 5B 3A ..CF.^.. .9pa.r[: +[10E0] 8F 37 95 78 1E AB D9 E7 E9 DA FC 47 09 81 A0 0D .7.x.... ...G.... +[10F0] 62 E1 F9 34 36 D1 DB E6 98 D8 F4 3E 77 5A 4D E2 b..46... ...>wZM. +[1100] 5F 20 70 3D 3D 5B 34 D9 FD A8 31 F7 D9 59 F7 A3 _ p==[4. ..1..Y.. +[1110] F0 66 F7 D9 AD 1C CD D5 85 33 A0 87 22 31 D4 F3 .f...... .3.."1.. +[1120] 67 80 68 20 A2 90 72 7A 6F 64 FD 68 82 9E 91 B8 g.h ..rz od.h.... +[1130] E3 F7 6D 6C 38 74 F0 96 A2 F6 25 D7 92 58 14 60 ..ml8t.. ..%..X.` +[1140] 9F AE 01 4C 0C 09 67 3E 35 67 71 1E 2A 86 21 D3 ...L..g> 5gq.*.!. +[1150] 60 61 98 16 94 67 0B 52 76 63 93 BD A3 3B A9 F0 `a...g.R vc...;.. +[1160] A2 6A B7 E6 0F 35 64 DA 6A EA 20 A6 3D 94 71 59 .j...5d. j. .=.qY +[1170] 5E CB B2 D3 F9 4D FE 1B 4B D8 64 C8 3B 7A A8 E6 ^....M.. K.d.;z.. +[1180] D2 D5 76 71 26 D4 5C DA 1A 55 17 F2 16 C9 2F 77 ..vq&.\. .U..../w +[1190] DB 95 19 48 A5 AC D0 C3 31 9C 0A CC 1B 44 11 6B ...H.... 1....D.k +[11A0] 7C 88 7A 5D CF 6E 12 DA EF C5 C7 34 1D F4 CC EA |.z].n.. ...4.... +[11B0] 37 24 4B B3 0F C1 A3 F2 29 A0 D8 93 39 C6 16 57 7$K..... )...9..W +[11C0] D5 BF 57 BF 6C 7E F7 90 E0 EB A3 8B 07 56 9C EC ..W.l~.. .....V.. +[11D0] 15 3E 21 DA A5 7C 00 3C F9 D2 A7 1C 6F 16 25 31 .>!..|.< ....o.%1 +[11E0] C5 28 A7 EA F3 47 31 50 DD E1 ED 0A 93 DB 85 CC .(...G1P ........ +[11F0] 6B 4B 2C 7F E8 F8 2D A9 6D 1D 0A 87 F2 10 8C 82 kK,...-. m....... +[1200] 2F 9B D4 9B 92 8C 77 40 50 42 1E 42 C4 0A 4F E3 /.....w@ PB.B..O. +[1210] 6C 6C DC 81 C4 1E BB F0 7D CF 3C 73 22 5B C3 1A ll...... }..x K....%J. +[1240] 1E 6C 8F 01 D6 59 D7 CF 2E A0 CC 98 F6 75 28 2F .l...Y.. .....u(/ +[1250] F7 2A 70 28 A9 45 1F 75 C2 4E 62 ED D8 C4 A0 8D .*p(.E.u .Nb..... +[1260] 55 B2 84 1C A4 CE 87 EF 24 EE BC CE 40 09 EB 05 U....... $...@... +[1270] 0B D1 14 31 50 32 2F B6 A8 97 17 4B A7 95 01 50 ...1P2/. ...K...P +[1280] 6E 0E 23 49 9C 72 21 91 00 00 00 00 00 00 00 01 n.#I.r!. ........ +[1290] 00 00 00 01 00 00 00 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[12A0] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 MBA.EXAM PLE.COM. +[12B0] 00 00 0D 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 ...admin istrator +[12C0] 00 00 00 01 00 00 00 02 00 00 00 17 4B 54 45 53 ........ ....KTES +[12D0] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[12E0] 43 4F 4D 00 00 00 04 63 69 66 73 00 00 00 0B 4C COM....c ifs....L +[12F0] 4F 43 41 4C 4B 54 45 53 54 36 00 17 00 00 00 10 OCALKTES T6...... +[1300] 1D C8 5E 46 48 82 F9 29 DB C6 A6 F1 72 6D 8D E9 ..^FH..) ....rm.. +[1310] 4D 99 4F 6A 4D 99 85 09 7D 44 0B 68 00 00 00 00 M.OjM... }D.h.... +[1320] 00 40 28 00 00 00 00 00 00 00 00 00 00 00 00 03 .@(..... ........ +[1330] FA 61 82 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 .a...0.. ........ +[1340] 1B 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[1350] 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 AMPLE.CO M..0.... +[1360] 01 01 A1 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F ....0... cifs..LO +[1370] 43 41 4C 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 CALKTEST 6....0.. +[1380] AA A0 03 02 01 17 A1 03 02 01 02 A2 82 03 9C 04 ........ ........ +[1390] 82 03 98 66 D8 19 46 FA CB 73 2D CF 88 FD 4A EE ...f..F. .s-...J. +[13A0] 07 48 DA 0E BC 58 30 43 40 A4 9C 00 0F 3B 17 C1 .H...X0C @....;.. +[13B0] 2D F5 9C 3E D9 2F 1D CA 01 9B D7 2E EC D7 70 ED -..>./.. ......p. +[13C0] 8B 8B 1B 5E F2 4E EE DD 0F C0 8D 61 E5 D7 0A 56 ...^.N.. ...a...V +[13D0] 00 32 B1 DB 91 37 29 0F 2F 85 EE A8 43 BA A5 B8 .2...7). /...C... +[13E0] D4 19 74 33 F0 69 52 E1 58 98 83 D6 16 0B 44 A9 ..t3.iR. X.....D. +[13F0] 63 9B D4 4E 6E A7 3E CD 9A 96 4D C4 96 F5 07 6D c..Nn.>. ..M....m +[1400] 29 B6 ED 2A 62 3D 53 22 33 D1 95 E9 DF 74 4C 2A )..*b=S" 3....tL* +[1410] E2 29 AF 5B 69 B0 48 2D AD 94 FD A5 1D 54 D8 E2 .).[i.H- .....T.. +[1420] 5E C1 68 6F BA 02 01 79 C3 C9 97 0B 76 66 45 E2 ^.ho...y ....vfE. +[1430] 3B 10 17 95 40 46 E4 85 B9 87 BB CF CF 19 8C 3A ;...@F.. .......: +[1440] C0 EA 38 3B B9 E9 4B 05 89 E5 27 8C 62 95 BC 0D ..8;..K. ..'.b... +[1450] 65 F0 D2 C0 5E BC 65 01 D5 0B CB 17 31 0F 06 49 e...^.e. ....1..I +[1460] 4F A2 4A 70 77 DB BD 92 5B 37 5C EC 06 DF C5 E2 O.Jpw... [7\..... +[1470] 31 C8 40 09 11 68 14 E7 7D CE 54 4F 52 61 31 2C 1.@..h.. }.TORa1, +[1480] 1C 53 52 DB BE D8 95 39 EE 7D C6 CE C8 22 95 92 .SR....9 .}...".. +[1490] 97 97 3D 5E 66 0F AD DC C2 4E 2E 2B 9F 63 20 30 ..=^f... .N.+.c 0 +[14A0] DF B7 C1 D4 65 AA 6F 2D 10 24 07 20 8D 88 6E 4B ....e.o- .$. ..nK +[14B0] 09 04 31 B6 A3 EB F7 37 32 0E 0C 73 C6 F6 B8 4D ..1....7 2..s...M +[14C0] D9 0C 4C 5B EC 10 6A 51 19 EA 3F FF 46 E7 73 16 ..L[..jQ ..?.F.s. +[14D0] A7 1F 33 98 7C 9B AD 5A 23 A9 40 7C 0F DF EE 0F ..3.|..Z #.@|.... +[14E0] AA C7 E8 63 07 98 3A 4A 0D 18 62 01 21 B2 AE A5 ...c..:J ..b.!... +[14F0] 69 B0 C1 15 51 BA 97 D2 C5 42 5B C5 30 38 18 A9 i...Q... .B[.08.. +[1500] 48 AB D7 FC A1 BC 9F 71 E7 EA 18 54 42 DA D6 A4 H......q ...TB... +[1510] FC C1 DC F3 12 30 62 AC 98 E1 7D 2B 34 1E 52 4C .....0b. ..}+4.RL +[1520] 26 67 32 D9 44 1A 08 27 0E DA D0 FC 84 66 35 81 &g2.D..' .....f5. +[1530] D6 EB 98 46 6F 1E 47 E0 14 31 BE 47 80 65 AA 0B ...Fo.G. .1.G.e.. +[1540] 20 D6 33 36 3B 0D 40 2F 5A 2E 0E 01 BE 00 EB 33 .36;.@/ Z......3 +[1550] 3E 4B 32 91 F4 22 96 E5 5F D4 D5 92 94 CC 5B 59 >K2..".. _.....[Y +[1560] 6A 3E D2 FB A0 4F 99 C4 07 8B 6F 2B 14 37 CD 37 j>...O.. ..o+.7.7 +[1570] 44 C0 1F 80 9C 43 46 F2 5E F4 FE D3 39 70 61 BE D....CF. ^...9pa. +[1580] 72 5B 3A 8F 37 95 78 1E AB D9 E7 E9 DA FC 47 09 r[:.7.x. ......G. +[1590] 81 A0 0D 62 E1 F9 34 36 D1 DB E6 98 D8 F4 3E 77 ...b..46 ......>w +[15A0] 5A 4D E2 5F 20 70 3D 3D 5B 34 D9 FD A8 31 F7 D9 ZM._ p== [4...1.. +[15B0] 59 F7 A3 F0 66 F7 D9 AD 1C CD D5 85 33 A0 87 22 Y...f... ....3.." +[15C0] 31 D4 F3 67 80 68 20 A2 90 72 7A 6F 64 FD 68 82 1..g.h . .rzod.h. +[15D0] 9E 91 B8 E3 F7 6D 6C 38 74 F0 96 A2 F6 25 D7 92 .....ml8 t....%.. +[15E0] 58 14 60 9F AE 01 4C 0C 09 67 3E 35 67 71 1E 2A X.`...L. .g>5gq.* +[15F0] 86 21 D3 60 61 98 16 94 67 0B 52 76 63 93 BD A3 .!.`a... g.Rvc... +[1600] 3B A9 F0 A2 6A B7 E6 0F 35 64 DA 6A EA 20 A6 3D ;...j... 5d.j. .= +[1610] 94 71 59 5E CB B2 D3 F9 4D FE 1B 4B D8 64 C8 3B .qY^.... M..K.d.; +[1620] 7A A8 E6 D2 D5 76 71 26 D4 5C DA 1A 55 17 F2 16 z....vq& .\..U... +[1630] C9 2F 77 DB 95 19 48 A5 AC D0 C3 31 9C 0A CC 1B ./w...H. ...1.... +[1640] 44 11 6B 7C 88 7A 5D CF 6E 12 DA EF C5 C7 34 1D D.k|.z]. n.....4. +[1650] F4 CC EA 37 24 4B B3 0F C1 A3 F2 29 A0 D8 93 39 ...7$K.. ...)...9 +[1660] C6 16 57 D5 BF 57 BF 6C 7E F7 90 E0 EB A3 8B 07 ..W..W.l ~....... +[1670] 56 9C EC 15 3E 21 DA A5 7C 00 3C F9 D2 A7 1C 6F V...>!.. |.<....o +[1680] 16 25 31 C5 28 A7 EA F3 47 31 50 DD E1 ED 0A 93 .%1.(... G1P..... +[1690] DB 85 CC 6B 4B 2C 7F E8 F8 2D A9 6D 1D 0A 87 F2 ...kK,.. .-.m.... +[16A0] 10 8C 82 2F 9B D4 9B 92 8C 77 40 50 42 1E 42 C4 .../.... .w@PB.B. +[16B0] 0A 4F E3 6C 6C DC 81 C4 1E BB F0 7D CF 3C 73 22 .O.ll... ...}..xK.... +[16E0] 25 4A 92 1E 6C 8F 01 D6 59 D7 CF 2E A0 CC 98 F6 %J..l... Y....... +[16F0] 75 28 2F F7 2A 70 28 A9 45 1F 75 C2 4E 62 ED D8 u(/.*p(. E.u.Nb.. +[1700] C4 A0 8D 55 B2 84 1C A4 CE 87 EF 24 EE BC CE 40 ...U.... ...$...@ +[1710] 09 EB 05 0B D1 14 31 50 32 2F B6 A8 97 17 4B A7 ......1P 2/....K. +[1720] 95 01 50 6E 0E 23 49 9C 72 21 91 00 00 00 00 00 ..Pn.#I. r!...... +[1730] 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 54 ........ ...KTEST +[1740] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[1750] 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 61 OM....ad ministra +[1760] 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 4B tor..... .......K +[1770] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[1780] 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 73 00 00 LE.COM.. ..cifs.. +[1790] 00 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 00 17 00 ..LOCALK TEST6... +[17A0] 00 00 10 1D C8 5E 46 48 82 F9 29 DB C6 A6 F1 72 .....^FH ..)....r +[17B0] 6D 8D E9 4D 99 4F 6A 4D 99 85 09 7D 44 0B 68 00 m..M.OjM ...}D.h. +[17C0] 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 00 ....@(.. ........ +[17D0] 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 01 ....a... 0....... +[17E0] 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[17F0] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 1C .EXAMPLE .COM..0. +[1800] A0 03 02 01 01 A1 15 30 13 1B 04 63 69 66 73 1B .......0 ...cifs. +[1810] 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 A3 82 03 AE .LOCALKT EST6.... +[1820] 30 82 03 AA A0 03 02 01 17 A1 03 02 01 02 A2 82 0....... ........ +[1830] 03 9C 04 82 03 98 66 D8 19 46 FA CB 73 2D CF 88 ......f. .F..s-.. +[1840] FD 4A EE 07 48 DA 0E BC 58 30 43 40 A4 9C 00 0F .J..H... X0C@.... +[1850] 3B 17 C1 2D F5 9C 3E D9 2F 1D CA 01 9B D7 2E EC ;..-..>. /....... +[1860] D7 70 ED 8B 8B 1B 5E F2 4E EE DD 0F C0 8D 61 E5 .p....^. N.....a. +[1870] D7 0A 56 00 32 B1 DB 91 37 29 0F 2F 85 EE A8 43 ..V.2... 7)./...C +[1880] BA A5 B8 D4 19 74 33 F0 69 52 E1 58 98 83 D6 16 .....t3. iR.X.... +[1890] 0B 44 A9 63 9B D4 4E 6E A7 3E CD 9A 96 4D C4 96 .D.c..Nn .>...M.. +[18A0] F5 07 6D 29 B6 ED 2A 62 3D 53 22 33 D1 95 E9 DF ..m)..*b =S"3.... +[18B0] 74 4C 2A E2 29 AF 5B 69 B0 48 2D AD 94 FD A5 1D tL*.).[i .H-..... +[18C0] 54 D8 E2 5E C1 68 6F BA 02 01 79 C3 C9 97 0B 76 T..^.ho. ..y....v +[18D0] 66 45 E2 3B 10 17 95 40 46 E4 85 B9 87 BB CF CF fE.;...@ F....... +[18E0] 19 8C 3A C0 EA 38 3B B9 E9 4B 05 89 E5 27 8C 62 ..:..8;. .K...'.b +[18F0] 95 BC 0D 65 F0 D2 C0 5E BC 65 01 D5 0B CB 17 31 ...e...^ .e.....1 +[1900] 0F 06 49 4F A2 4A 70 77 DB BD 92 5B 37 5C EC 06 ..IO.Jpw ...[7\.. +[1910] DF C5 E2 31 C8 40 09 11 68 14 E7 7D CE 54 4F 52 ...1.@.. h..}.TOR +[1920] 61 31 2C 1C 53 52 DB BE D8 95 39 EE 7D C6 CE C8 a1,.SR.. ..9.}... +[1930] 22 95 92 97 97 3D 5E 66 0F AD DC C2 4E 2E 2B 9F "....=^f ....N.+. +[1940] 63 20 30 DF B7 C1 D4 65 AA 6F 2D 10 24 07 20 8D c 0....e .o-.$. . +[1950] 88 6E 4B 09 04 31 B6 A3 EB F7 37 32 0E 0C 73 C6 .nK..1.. ..72..s. +[1960] F6 B8 4D D9 0C 4C 5B EC 10 6A 51 19 EA 3F FF 46 ..M..L[. .jQ..?.F +[1970] E7 73 16 A7 1F 33 98 7C 9B AD 5A 23 A9 40 7C 0F .s...3.| ..Z#.@|. +[1980] DF EE 0F AA C7 E8 63 07 98 3A 4A 0D 18 62 01 21 ......c. .:J..b.! +[1990] B2 AE A5 69 B0 C1 15 51 BA 97 D2 C5 42 5B C5 30 ...i...Q ....B[.0 +[19A0] 38 18 A9 48 AB D7 FC A1 BC 9F 71 E7 EA 18 54 42 8..H.... ..q...TB +[19B0] DA D6 A4 FC C1 DC F3 12 30 62 AC 98 E1 7D 2B 34 ........ 0b...}+4 +[19C0] 1E 52 4C 26 67 32 D9 44 1A 08 27 0E DA D0 FC 84 .RL&g2.D ..'..... +[19D0] 66 35 81 D6 EB 98 46 6F 1E 47 E0 14 31 BE 47 80 f5....Fo .G..1.G. +[19E0] 65 AA 0B 20 D6 33 36 3B 0D 40 2F 5A 2E 0E 01 BE e.. .36; .@/Z.... +[19F0] 00 EB 33 3E 4B 32 91 F4 22 96 E5 5F D4 D5 92 94 ..3>K2.. ".._.... +[1A00] CC 5B 59 6A 3E D2 FB A0 4F 99 C4 07 8B 6F 2B 14 .[Yj>... O....o+. +[1A10] 37 CD 37 44 C0 1F 80 9C 43 46 F2 5E F4 FE D3 39 7.7D.... CF.^...9 +[1A20] 70 61 BE 72 5B 3A 8F 37 95 78 1E AB D9 E7 E9 DA pa.r[:.7 .x...... +[1A30] FC 47 09 81 A0 0D 62 E1 F9 34 36 D1 DB E6 98 D8 .G....b. .46..... +[1A40] F4 3E 77 5A 4D E2 5F 20 70 3D 3D 5B 34 D9 FD A8 .>wZM._ p==[4... +[1A50] 31 F7 D9 59 F7 A3 F0 66 F7 D9 AD 1C CD D5 85 33 1..Y...f .......3 +[1A60] A0 87 22 31 D4 F3 67 80 68 20 A2 90 72 7A 6F 64 .."1..g. h ..rzod +[1A70] FD 68 82 9E 91 B8 E3 F7 6D 6C 38 74 F0 96 A2 F6 .h...... ml8t.... +[1A80] 25 D7 92 58 14 60 9F AE 01 4C 0C 09 67 3E 35 67 %..X.`.. .L..g>5g +[1A90] 71 1E 2A 86 21 D3 60 61 98 16 94 67 0B 52 76 63 q.*.!.`a ...g.Rvc +[1AA0] 93 BD A3 3B A9 F0 A2 6A B7 E6 0F 35 64 DA 6A EA ...;...j ...5d.j. +[1AB0] 20 A6 3D 94 71 59 5E CB B2 D3 F9 4D FE 1B 4B D8 .=.qY^. ...M..K. +[1AC0] 64 C8 3B 7A A8 E6 D2 D5 76 71 26 D4 5C DA 1A 55 d.;z.... vq&.\..U +[1AD0] 17 F2 16 C9 2F 77 DB 95 19 48 A5 AC D0 C3 31 9C ..../w.. .H....1. +[1AE0] 0A CC 1B 44 11 6B 7C 88 7A 5D CF 6E 12 DA EF C5 ...D.k|. z].n.... +[1AF0] C7 34 1D F4 CC EA 37 24 4B B3 0F C1 A3 F2 29 A0 .4....7$ K.....). +[1B00] D8 93 39 C6 16 57 D5 BF 57 BF 6C 7E F7 90 E0 EB ..9..W.. W.l~.... +[1B10] A3 8B 07 56 9C EC 15 3E 21 DA A5 7C 00 3C F9 D2 ...V...> !..|.<.. +[1B20] A7 1C 6F 16 25 31 C5 28 A7 EA F3 47 31 50 DD E1 ..o.%1.( ...G1P.. +[1B30] ED 0A 93 DB 85 CC 6B 4B 2C 7F E8 F8 2D A9 6D 1D ......kK ,...-.m. +[1B40] 0A 87 F2 10 8C 82 2F 9B D4 9B 92 8C 77 40 50 42 ....../. ....w@PB +[1B50] 1E 42 C4 0A 4F E3 6C 6C DC 81 C4 1E BB F0 7D CF .B..O.ll ......}. +[1B60] 3C 73 22 5B C3 1A 97 35 EE 3A CD 6D F3 68 A3 C5 .xK. +[1B80] 18 9F A5 25 4A 92 1E 6C 8F 01 D6 59 D7 CF 2E A0 ...%J..l ...Y.... +[1B90] CC 98 F6 75 28 2F F7 2A 70 28 A9 45 1F 75 C2 4E ...u(/.* p(.E.u.N +[1BA0] 62 ED D8 C4 A0 8D 55 B2 84 1C A4 CE 87 EF 24 EE b.....U. ......$. +[1BB0] BC CE 40 09 EB 05 0B D1 14 31 50 32 2F B6 A8 97 ..@..... .1P2/... +[1BC0] 17 4B A7 95 01 50 6E 0E 23 49 9C 72 21 91 00 00 .K...Pn. #I.r!... +[1BD0] 00 00 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 ........ ......KT +[1BE0] 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C EST.SAMB A.EXAMPL +[1BF0] 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 E.COM... .adminis +[1C00] 74 72 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 trator.. ........ +[1C10] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[1C20] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 AMPLE.CO M....cif +[1C30] 73 00 00 00 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 s....LOC ALKTEST6 +[1C40] 00 17 00 00 00 10 1D C8 5E 46 48 82 F9 29 DB C6 ........ ^FH..).. +[1C50] A6 F1 72 6D 8D E9 4D 99 4F 6A 4D 99 85 09 7D 44 ..rm..M. OjM...}D +[1C60] 0B 68 00 00 00 00 00 40 28 00 00 00 00 00 00 00 .h.....@ (....... +[1C70] 00 00 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 .......a ...0.... +[1C80] 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[1C90] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 MBA.EXAM PLE.COM. +[1CA0] 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 69 .0...... ..0...ci +[1CB0] 66 73 1B 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 A3 fs..LOCA LKTEST6. +[1CC0] 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 ...0.... ........ +[1CD0] 02 A2 82 03 9C 04 82 03 98 66 D8 19 46 FA CB 73 ........ .f..F..s +[1CE0] 2D CF 88 FD 4A EE 07 48 DA 0E BC 58 30 43 40 A4 -...J..H ...X0C@. +[1CF0] 9C 00 0F 3B 17 C1 2D F5 9C 3E D9 2F 1D CA 01 9B ...;..-. .>./.... +[1D00] D7 2E EC D7 70 ED 8B 8B 1B 5E F2 4E EE DD 0F C0 ....p... .^.N.... +[1D10] 8D 61 E5 D7 0A 56 00 32 B1 DB 91 37 29 0F 2F 85 .a...V.2 ...7)./. +[1D20] EE A8 43 BA A5 B8 D4 19 74 33 F0 69 52 E1 58 98 ..C..... t3.iR.X. +[1D30] 83 D6 16 0B 44 A9 63 9B D4 4E 6E A7 3E CD 9A 96 ....D.c. .Nn.>... +[1D40] 4D C4 96 F5 07 6D 29 B6 ED 2A 62 3D 53 22 33 D1 M....m). .*b=S"3. +[1D50] 95 E9 DF 74 4C 2A E2 29 AF 5B 69 B0 48 2D AD 94 ...tL*.) .[i.H-.. +[1D60] FD A5 1D 54 D8 E2 5E C1 68 6F BA 02 01 79 C3 C9 ...T..^. ho...y.. +[1D70] 97 0B 76 66 45 E2 3B 10 17 95 40 46 E4 85 B9 87 ..vfE.;. ..@F.... +[1D80] BB CF CF 19 8C 3A C0 EA 38 3B B9 E9 4B 05 89 E5 .....:.. 8;..K... +[1D90] 27 8C 62 95 BC 0D 65 F0 D2 C0 5E BC 65 01 D5 0B '.b...e. ..^.e... +[1DA0] CB 17 31 0F 06 49 4F A2 4A 70 77 DB BD 92 5B 37 ..1..IO. Jpw...[7 +[1DB0] 5C EC 06 DF C5 E2 31 C8 40 09 11 68 14 E7 7D CE \.....1. @..h..}. +[1DC0] 54 4F 52 61 31 2C 1C 53 52 DB BE D8 95 39 EE 7D TORa1,.S R....9.} +[1DD0] C6 CE C8 22 95 92 97 97 3D 5E 66 0F AD DC C2 4E ...".... =^f....N +[1DE0] 2E 2B 9F 63 20 30 DF B7 C1 D4 65 AA 6F 2D 10 24 .+.c 0.. ..e.o-.$ +[1DF0] 07 20 8D 88 6E 4B 09 04 31 B6 A3 EB F7 37 32 0E . ..nK.. 1....72. +[1E00] 0C 73 C6 F6 B8 4D D9 0C 4C 5B EC 10 6A 51 19 EA .s...M.. L[..jQ.. +[1E10] 3F FF 46 E7 73 16 A7 1F 33 98 7C 9B AD 5A 23 A9 ?.F.s... 3.|..Z#. +[1E20] 40 7C 0F DF EE 0F AA C7 E8 63 07 98 3A 4A 0D 18 @|...... .c..:J.. +[1E30] 62 01 21 B2 AE A5 69 B0 C1 15 51 BA 97 D2 C5 42 b.!...i. ..Q....B +[1E40] 5B C5 30 38 18 A9 48 AB D7 FC A1 BC 9F 71 E7 EA [.08..H. .....q.. +[1E50] 18 54 42 DA D6 A4 FC C1 DC F3 12 30 62 AC 98 E1 .TB..... ...0b... +[1E60] 7D 2B 34 1E 52 4C 26 67 32 D9 44 1A 08 27 0E DA }+4.RL&g 2.D..'.. +[1E70] D0 FC 84 66 35 81 D6 EB 98 46 6F 1E 47 E0 14 31 ...f5... .Fo.G..1 +[1E80] BE 47 80 65 AA 0B 20 D6 33 36 3B 0D 40 2F 5A 2E .G.e.. . 36;.@/Z. +[1E90] 0E 01 BE 00 EB 33 3E 4B 32 91 F4 22 96 E5 5F D4 .....3>K 2..".._. +[1EA0] D5 92 94 CC 5B 59 6A 3E D2 FB A0 4F 99 C4 07 8B ....[Yj> ...O.... +[1EB0] 6F 2B 14 37 CD 37 44 C0 1F 80 9C 43 46 F2 5E F4 o+.7.7D. ...CF.^. +[1EC0] FE D3 39 70 61 BE 72 5B 3A 8F 37 95 78 1E AB D9 ..9pa.r[ :.7.x... +[1ED0] E7 E9 DA FC 47 09 81 A0 0D 62 E1 F9 34 36 D1 DB ....G... .b..46.. +[1EE0] E6 98 D8 F4 3E 77 5A 4D E2 5F 20 70 3D 3D 5B 34 ....>wZM ._ p==[4 +[1EF0] D9 FD A8 31 F7 D9 59 F7 A3 F0 66 F7 D9 AD 1C CD ...1..Y. ..f..... +[1F00] D5 85 33 A0 87 22 31 D4 F3 67 80 68 20 A2 90 72 ..3.."1. .g.h ..r +[1F10] 7A 6F 64 FD 68 82 9E 91 B8 E3 F7 6D 6C 38 74 F0 zod.h... ...ml8t. +[1F20] 96 A2 F6 25 D7 92 58 14 60 9F AE 01 4C 0C 09 67 ...%..X. `...L..g +[1F30] 3E 35 67 71 1E 2A 86 21 D3 60 61 98 16 94 67 0B >5gq.*.! .`a...g. +[1F40] 52 76 63 93 BD A3 3B A9 F0 A2 6A B7 E6 0F 35 64 Rvc...;. ..j...5d +[1F50] DA 6A EA 20 A6 3D 94 71 59 5E CB B2 D3 F9 4D FE .j. .=.q Y^....M. +[1F60] 1B 4B D8 64 C8 3B 7A A8 E6 D2 D5 76 71 26 D4 5C .K.d.;z. ...vq&.\ +[1F70] DA 1A 55 17 F2 16 C9 2F 77 DB 95 19 48 A5 AC D0 ..U..../ w...H... +[1F80] C3 31 9C 0A CC 1B 44 11 6B 7C 88 7A 5D CF 6E 12 .1....D. k|.z].n. +[1F90] DA EF C5 C7 34 1D F4 CC EA 37 24 4B B3 0F C1 A3 ....4... .7$K.... +[1FA0] F2 29 A0 D8 93 39 C6 16 57 D5 BF 57 BF 6C 7E F7 .)...9.. W..W.l~. +[1FB0] 90 E0 EB A3 8B 07 56 9C EC 15 3E 21 DA A5 7C 00 ......V. ..>!..|. +[1FC0] 3C F9 D2 A7 1C 6F 16 25 31 C5 28 A7 EA F3 47 31 <....o.% 1.(...G1 +[1FD0] 50 DD E1 ED 0A 93 DB 85 CC 6B 4B 2C 7F E8 F8 2D P....... .kK,...- +[1FE0] A9 6D 1D 0A 87 F2 10 8C 82 2F 9B D4 9B 92 8C 77 .m...... ./.....w +[1FF0] 40 50 42 1E 42 C4 0A 4F E3 6C 6C DC 81 C4 1E BB @PB.B..O .ll..... +[2000] F0 7D CF 3C 73 22 5B C3 1A 97 35 EE 3A CD 6D F3 .}.. +[2020] 78 4B BF 18 9F A5 25 4A 92 1E 6C 8F 01 D6 59 D7 xK....%J ..l...Y. +[2030] CF 2E A0 CC 98 F6 75 28 2F F7 2A 70 28 A9 45 1F ......u( /.*p(.E. +[2040] 75 C2 4E 62 ED D8 C4 A0 8D 55 B2 84 1C A4 CE 87 u.Nb.... .U...... +[2050] EF 24 EE BC CE 40 09 EB 05 0B D1 14 31 50 32 2F .$...@.. ....1P2/ +[2060] B6 A8 97 17 4B A7 95 01 50 6E 0E 23 49 9C 72 21 ....K... Pn.#I.r! +[2070] 91 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ........ ........ +[2080] 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 .KTEST.S AMBA.EXA +[2090] 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 MPLE.COM ....admi +[20A0] 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 00 nistrato r....... +[20B0] 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[20C0] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 .EXAMPLE .COM.... +[20D0] 68 6F 73 74 00 00 00 0B 6C 6F 63 61 6C 6B 74 65 host.... localkte +[20E0] 73 74 36 00 17 00 00 00 10 72 47 04 38 B6 E6 F0 st6..... .rG.8... +[20F0] 44 9E 9F 27 66 E1 69 9C 9A 4D 99 4F 6A 4D 99 90 D..'f.i. .M.OjM.. +[2100] F5 7D 44 0B 68 00 00 00 00 00 40 28 00 00 00 00 .}D.h... ..@(.... +[2110] 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 82 ........ ..a...0. +[2120] 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 ........ ...KTEST +[2130] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[2140] 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B OM..0... .....0.. +[2150] 04 68 6F 73 74 1B 0B 6C 6F 63 61 6C 6B 74 65 73 .host..l ocalktes +[2160] 74 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 t6....0. ........ +[2170] 03 02 01 02 A2 82 03 9C 04 82 03 98 58 95 95 EB ........ ....X... +[2180] CB 8F 68 D4 77 43 0F 3B 44 B4 15 DA 40 6D FD E9 ..h.wC.; D...@m.. +[2190] 85 D3 2F CD B5 1E 96 CD F6 E9 67 91 36 08 9E B4 ../..... ..g.6... +[21A0] B3 47 70 7A B3 4E 82 5A 4F 8E 4B F5 8D 04 E4 5C .Gpz.N.Z O.K....\ +[21B0] C4 D8 0C AF 08 25 F9 C1 64 B2 3A 35 26 E9 B2 72 .....%.. d.:5&..r +[21C0] 66 B5 E9 81 FC BE 12 1B CC 8A A5 82 31 F6 7F C3 f....... ....1... +[21D0] 5A 19 A3 31 F2 99 14 1E 64 E4 41 E8 C7 C3 F3 DF Z..1.... d.A..... +[21E0] F5 65 7D B0 9F DC 5D 25 1D 1A A8 EA AA 88 6D F4 .e}...]% ......m. +[21F0] 7C 25 9F 53 F6 A6 8F B1 24 AF 98 FE 53 7B 35 3C |%.S.... $...S{5< +[2200] DB EC 7F 09 74 E9 C4 8D 20 B4 47 08 0E 32 B8 C9 ....t... .G..2.. +[2210] 45 27 12 F9 8E F5 D6 C2 DD 1A 96 0E 68 5F 39 65 E'...... ....h_9e +[2220] 72 C7 BD 8E 04 0E 13 E1 03 27 AC 50 80 76 E6 7A r....... .'.P.v.z +[2230] 8E F4 C2 72 4F 68 B3 34 00 A9 54 41 DA FD 96 94 ...rOh.4 ..TA.... +[2240] 29 A1 59 15 2F DB 6C 94 85 49 C5 D0 6D 48 B0 C4 ).Y./.l. .I..mH.. +[2250] 65 D0 95 1D DB 3D 25 D0 75 50 D4 CF FA 2F 71 57 e....=%. uP.../qW +[2260] BD 6C 1C 59 E1 C3 5B C7 24 95 FF B0 20 EF 6A DB .l.Y..[. $... .j. +[2270] 79 87 67 91 94 E9 16 E2 BB 74 7A 08 E1 6A 36 5F y.g..... .tz..j6_ +[2280] DF 11 AB 35 9B 3E 32 48 83 89 41 4E 06 BF F9 BB ...5.>2H ..AN.... +[2290] EC E4 D7 6D 77 C4 55 22 DF F7 91 4D CB C5 01 A5 ...mw.U" ...M.... +[22A0] BA 2D 1E 92 76 04 E8 02 2F 5E AF 1C B3 B7 A6 FB .-..v... /^...... +[22B0] 3A 9F D9 7C 6D DA B4 8F 31 00 A5 30 F2 76 72 9B :..|m... 1..0.vr. +[22C0] 62 97 E0 56 E5 E4 C7 6B 8B FC 84 75 57 66 6E D7 b..V...k ...uWfn. +[22D0] B7 41 6F 61 F4 5B 0F 87 68 F6 54 02 26 1B 1F B7 .Aoa.[.. h.T.&... +[22E0] 60 D6 E7 FA 4F C7 DB 35 58 EC 13 21 D4 C6 A1 27 `...O..5 X..!...' +[22F0] BA E7 82 DF 29 FB 9D 5D E8 35 28 C9 9C 4E D7 BE ....)..] .5(..N.. +[2300] 2F 6D F1 E8 0B 5A 74 C9 93 9F AD 42 24 4B B7 3B /m...Zt. ...B$K.; +[2310] 38 2A 11 CF F0 BD 85 40 48 D8 9D E7 6B 65 70 42 8*.....@ H...kepB +[2320] 60 DA 9B 65 CB C8 C5 D7 40 3A 12 DC 64 AF 82 54 `..e.... @:..d..T +[2330] 34 05 38 4F C6 FB 38 E2 73 A9 89 B7 FC 33 15 85 4.8O..8. s....3.. +[2340] 9E CA E9 E0 89 18 18 84 02 65 B4 74 5B D4 A1 6F ........ .e.t[..o +[2350] 5F 79 20 CB D7 36 C8 6D 5B 1E 5E 0C 82 16 9F CC _y ..6.m [.^..... +[2360] 5A 1E 57 C1 B6 94 51 87 A1 3D 12 D4 8B FE 0F 93 Z.W...Q. .=...... +[2370] ED 53 A3 F4 88 3C 35 05 89 FE AF 0B 36 62 E3 2F .S...<5. ....6b./ +[2380] 5C 4A 0E 07 67 39 A3 8E C0 45 07 7F 73 32 BC DE \J..g9.. .E..s2.. +[2390] 2D 00 8B 47 79 3D 1C A1 90 AE B6 8F 83 B2 1B 31 -..Gy=.. .......1 +[23A0] EE E4 F2 C5 C1 4A E2 4A 2F 28 F0 AA 19 43 6A 14 .....J.J /(...Cj. +[23B0] B1 42 61 90 34 2E EE 3D 16 9F 5D 9F 7A A2 01 7A .Ba.4..= ..].z..z +[23C0] 4B 96 FA 4D C9 85 1A 75 27 B7 6B FD 4D 7D 9C 65 K..M...u '.k.M}.e +[23D0] 97 DB 05 CC 76 68 EA 05 5D 5D BB BD 51 4B 5B F2 ....vh.. ]]..QK[. +[23E0] 48 59 BD 1E AD 56 D4 69 A5 75 CD ED EC B1 3E AB HY...V.i .u....>. +[23F0] FA B7 F8 8D 4F BE 95 63 38 1C 4C 70 26 C4 3A 21 ....O..c 8.Lp&.:! +[2400] 80 61 05 3A D4 E2 28 2C 85 01 5A DA FC 10 60 F3 .a.:..(, ..Z...`. +[2410] 74 0C FD DB 2F 5B 25 4B 14 E4 7D 8A DB 85 12 D2 t.../[%K ..}..... +[2420] D7 69 CD B5 B1 93 CE E5 E6 4D 57 D3 C2 D3 2E A0 .i...... .MW..... +[2430] 08 37 09 CD 19 99 09 FA 33 68 4A E0 92 46 21 0C .7...... 3hJ..F!. +[2440] 99 9F DA 05 15 20 8B 3D 7C 7B CA D6 81 AC AA 83 ..... .= |{...... +[2450] 48 C8 24 4C C8 FC A5 14 2C BC 49 1A 1C 49 61 1D H.$L.... ,.I..Ia. +[2460] 24 86 42 B1 37 6A C8 3A AC 18 CC C0 50 84 12 48 $.B.7j.: ....P..H +[2470] 8B 29 0A 49 26 A4 E2 B9 E5 96 E7 37 C3 DE 4C 23 .).I&... ...7..L# +[2480] D2 D4 62 14 8F 1E 72 39 CF 03 BC A3 00 C7 63 51 ..b...r9 ......cQ +[2490] A9 6B E4 3E B2 65 A1 A2 BB EC 06 41 85 50 22 02 .k.>.e.. ...A.P". +[24A0] 46 2F 72 2B 32 1A A4 2D 85 94 02 47 69 8D AD 6D F/r+2..- ...Gi..m +[24B0] 66 AB D4 E4 29 C8 C7 DA F4 18 31 2A DF 50 6A 05 f...)... ..1*.Pj. +[24C0] D6 47 26 C4 F9 87 0F 35 24 6E 72 D6 23 7D 3A 94 .G&....5 $nr.#}:. +[24D0] 14 8D E8 57 AA BA D7 CF A9 2D E7 4C 10 7C D8 0D ...W.... .-.L.|.. +[24E0] 51 30 1F E1 FB E5 E2 6C EE AA 65 2F D8 22 05 67 Q0.....l ..e/.".g +[24F0] 87 4D 4D D2 11 3D B4 1E AA 20 3F 76 E3 94 93 6D .MM..=.. . ?v...m +[2500] AC 10 05 AF 09 BD 67 86 C5 83 93 D6 1C D3 81 D9 ......g. ........ +[2510] B1 3B E1 76 00 00 00 00 00 00 00 01 00 00 00 01 .;.v.... ........ +[2520] 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E ....KTES T.SAMBA. +[2530] 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 EXAMPLE. COM....a +[2540] 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 dministr ator.... +[2550] 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[2560] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 MBA.EXAM PLE.COM. +[2570] 00 00 04 68 6F 73 74 00 00 00 0B 4C 4F 43 41 4C ...host. ...LOCAL +[2580] 4B 54 45 53 54 36 00 17 00 00 00 10 55 6E 3E FC KTEST6.. ....Un>. +[2590] E2 F4 40 51 19 E6 6E EB 23 4C 48 8E 4D 99 4F 6A ..@Q..n. #LH.M.Oj +[25A0] 4D 99 90 FC 7D 44 0B 68 00 00 00 00 00 40 28 00 M...}D.h .....@(. +[25B0] 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 ........ .....a.. +[25C0] F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 .0...... ......KT +[25D0] 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C EST.SAMB A.EXAMPL +[25E0] 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 E.COM..0 ........ +[25F0] 30 13 1B 04 68 6F 73 74 1B 0B 4C 4F 43 41 4C 4B 0...host ..LOCALK +[2600] 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 02 TEST6... .0...... +[2610] 01 17 A1 03 02 01 02 A2 82 03 9C 04 82 03 98 6E ........ .......n +[2620] 87 B7 7B 3A 7E EF 4A 1B 29 C9 E3 C4 1F 42 4F 0E ..{:~.J. )....BO. +[2630] C8 AC AC 4E A2 77 1D DA 93 37 F1 AF DA A3 75 2D ...N.w.. .7....u- +[2640] 12 8B 40 34 23 0E 8E A9 90 58 46 42 42 39 31 D6 ..@4#... .XFBB91. +[2650] 03 9E 5D 81 D9 E8 F6 08 2B D9 96 88 8A 2F F1 CC ..]..... +..../.. +[2660] F2 EA 9E 9A 4B 31 B6 04 2D 3D 4C 7F 92 DE 3B 04 ....K1.. -=L...;. +[2670] 19 EE 28 D0 83 81 C3 46 CD 74 23 4C 14 34 DE 62 ..(....F .t#L.4.b +[2680] 0A AC E5 12 16 75 E9 A8 4B 32 78 CC 8D AE A2 E5 .....u.. K2x..... +[2690] 6D E8 09 70 76 52 F5 E5 18 F7 E7 91 15 6A 69 AB m..pvR.. .....ji. +[26A0] B8 62 DD 80 F5 28 6D DF ED 10 DA AC FB 92 27 CF .b...(m. ......'. +[26B0] 98 B5 77 9D A5 96 E6 9A CC B9 C3 91 78 22 35 9C ..w..... ....x"5. +[26C0] A1 13 A3 20 28 D1 16 E5 3E 4A 85 1E 12 0B CA 4D ... (... >J.....M +[26D0] C6 C8 03 C8 28 2C D8 29 5D 9A 76 4A 92 13 43 56 ....(,.) ].vJ..CV +[26E0] AF F7 C1 71 25 72 5C 38 75 1C 07 F1 5E 86 05 72 ...q%r\8 u...^..r +[26F0] 6F 69 95 42 B6 F2 DA A9 91 06 9F B9 54 20 33 A5 oi.B.... ....T 3. +[2700] 31 60 3B 54 DC 3A 95 34 96 26 07 52 6B 0E 1D 3B 1`;T.:.4 .&.Rk..; +[2710] D9 F8 48 20 AC CD 05 3B 99 F8 EE DB 83 28 CD C7 ..H ...; .....(.. +[2720] 2F 45 00 7E 2F 0A 65 7A D1 9E 95 4B EE C3 34 93 /E.~/.ez ...K..4. +[2730] A8 C7 DF 03 8B 14 D0 FC CE 56 90 AC EE 93 C5 D3 ........ .V...... +[2740] F7 12 24 69 0B 20 8D A2 65 87 55 26 2A F9 9A 88 ..$i. .. e.U&*... +[2750] D7 0D 86 61 D6 92 B6 FE E5 D1 66 F9 1F 9D F4 04 ...a.... ..f..... +[2760] 48 A6 39 BC 54 20 EA 10 21 E9 6D 30 46 1D C2 1C H.9.T .. !.m0F... +[2770] A4 E8 B4 63 85 37 27 25 80 52 41 60 C7 A1 32 21 ...c.7'% .RA`..2! +[2780] 43 90 02 E6 5F 5A E9 4E AF F9 B5 13 BD 42 BD A3 C..._Z.N .....B.. +[2790] A5 4D 10 45 83 4D 92 18 1F C9 CF FB 84 29 89 23 .M.E.M.. .....).# +[27A0] AC 71 4B 89 1B 52 E5 06 8C 3E 7C 88 CB D3 B3 CF .qK..R.. .>|..... +[27B0] B9 7A 67 D6 24 F4 AC 00 A6 AD 91 30 9A 95 53 F1 .zg.$... ...0..S. +[27C0] 48 06 A6 39 DB CF DC 9D C9 55 76 26 5E C1 DB 5D H..9.... .Uv&^..] +[27D0] B3 5B 3E AE 1A A0 10 BA 82 21 83 44 02 E0 99 33 .[>..... .!.D...3 +[27E0] 40 BA 29 9E 28 E5 73 4C 23 94 A2 4F BF 07 ED 4F @.).(.sL #..O...O +[27F0] 7C 45 9B 30 C8 41 6B 0A 55 13 6E F5 AD 7A 0C B2 |E.0.Ak. U.n..z.. +[2800] EA FF D0 06 13 4D F3 24 82 7F F6 51 2F 4A 4F 0D .....M.$ ...Q/JO. +[2810] 37 F8 14 6B E9 E4 82 BB 3A 75 63 63 12 E8 78 6F 7..k.... :ucc..xo +[2820] 6F FC 6C D3 4B A6 F1 CC 2A F1 7D EB 82 26 2F D0 o.l.K... *.}..&/. +[2830] A1 8B 3E 9A 71 D7 91 D3 08 E6 FD 62 1B 84 13 2D ..>.q... ...b...- +[2840] 8E A0 A0 C3 85 78 2F 0D F8 E7 10 FC CB 05 A7 B9 .....x/. ........ +[2850] 9A 33 90 B5 9B 26 E3 23 98 B0 91 4B EB 32 37 D6 .3...&.# ...K.27. +[2860] F4 ED 61 08 D8 75 CC 03 83 2C 3C CF 21 63 9C F6 ..a..u.. .,<.!c.. +[2870] AF 5B 4F 12 07 74 17 CD 98 BB E7 5E C7 17 2D C4 .[O..t.. ...^..-. +[2880] 87 A4 74 6D 5E CE DB A3 01 B9 AD 20 73 38 78 22 ..tm^... ... s8x" +[2890] 3D 45 F5 51 77 C6 47 63 45 61 81 D9 FF 31 90 C4 =E.Qw.Gc Ea...1.. +[28A0] 6F 5A F8 FE 6A 56 5B D4 EE EC 49 C7 A7 51 AE 5C oZ..jV[. ..I..Q.\ +[28B0] 85 53 70 3D 1A 49 83 59 CF 65 58 B3 48 7E 04 9E .Sp=.I.Y .eX.H~.. +[28C0] C7 64 8A 05 73 E3 DC 1A 65 5D 4F 41 01 56 73 90 .d..s... e]OA.Vs. +[28D0] 61 F3 84 1F FF CF 46 B2 06 46 56 97 93 B9 DB 32 a.....F. .FV....2 +[28E0] 2A 64 8A 48 02 05 84 E9 FA 76 8B 94 96 89 A0 73 *d.H.... .v.....s +[28F0] 20 75 4D 52 1D 23 13 D1 83 D7 5D 59 23 6A 87 C1 uMR.#.. ..]Y#j.. +[2900] 09 3E 01 3A 28 65 42 8C 35 F1 91 EA 6A 1F 83 0D .>.:(eB. 5...j... +[2910] 8F 57 69 81 D4 A2 D2 EA 0C BF AF 95 A3 F4 90 15 .Wi..... ........ +[2920] 61 34 F2 6C 8B D0 DA B5 1E 43 AC CE C7 8A 1B 2B a4.l.... .C.....+ +[2930] 29 2B 89 1C C5 53 C8 04 F7 1E 46 72 F3 A8 CE F7 )+...S.. ..Fr.... +[2940] 59 76 55 E7 53 1C A2 9F D8 23 F7 EA 71 B0 74 83 YvU.S... .#..q.t. +[2950] 71 95 3E DC A6 FA 2D A4 42 13 93 8B 2B FA A2 70 q.>...-. B...+..p +[2960] 25 21 2D F6 E1 26 56 DF 58 79 25 16 E8 C9 03 EC %!-..&V. Xy%..... +[2970] 72 5F 35 CF 59 6B E1 AD 85 85 7B AB 78 F2 0D AC r_5.Yk.. ..{.x... +[2980] AB 89 F2 DA 85 E7 DE 09 77 99 EC 7C F3 97 1F 71 ........ w..|...q +[2990] 3C DB 09 44 7A 3C 69 E5 03 B0 6D 4D 3B 6B 4C D5 <..Dz....... +[0150] 1A 69 EE 8C 4E A4 D8 55 A5 0B 23 0F D0 89 48 C4 .i..N..U ..#...H. +[0160] 51 FE 32 FD CC F6 71 E1 95 2D CC 1D 0A 0C 8A A2 Q.2...q. .-...... +[0170] 69 58 3B 65 88 53 EC D0 2E E1 C6 CC 6B BC 09 E5 iX;e.S.. ....k... +[0180] B9 15 27 8B E4 B2 24 18 61 42 BB 8B 09 1B 8A 7B ..'...$. aB.....{ +[0190] 13 D8 51 E1 0B 79 12 48 DE A9 54 04 00 6D DD E6 ..Q..y.H ..T..m.. +[01A0] 5E 03 91 FF C7 6D 0B 7C 91 44 E1 0F C0 7E 32 34 ^....m.| .D...~24 +[01B0] 82 86 94 F7 CD 53 EC 52 38 18 AA ED FF FC 5C 01 .....S.R 8.....\. +[01C0] D2 EE 99 45 8E 5B E6 B3 46 B0 F6 3B 22 29 EC 11 ...E.[.. F..;").. +[01D0] 30 6A F6 A1 1F 9E AE 71 E3 A6 E7 3F F3 7D 2B 75 0j.....q ...?.}+u +[01E0] 70 4D 63 47 5C 18 2C 8B B1 1A 69 B6 C5 46 01 17 pMcG\.,. ..i..F.. +[01F0] 8E 64 3D 47 88 20 1C AA D7 60 32 28 11 60 EA 28 .d=G. .. .`2(.`.( +[0200] 66 99 4C B1 2A 28 96 BF 18 2A 3E F4 D6 84 E5 A0 f.L.*(.. .*>..... +[0210] F4 4E E7 F9 54 95 22 96 2A 87 01 CC 3E A7 FF 42 .N..T.". *...>..B +[0220] 6A A4 4A 3A B9 24 10 65 99 53 58 2A 4E 72 E7 1F j.J:.$.e .SX*Nr.. +[0230] 82 BC BD 3C 6C 9D 33 3A CE C6 6E 72 A2 81 B3 84 ........ +[0280] AB F0 D0 93 08 42 E5 37 19 24 4E C1 AF FC 92 A9 .....B.7 .$N..... +[0290] B1 27 B1 9A 2A 62 34 F1 DC C0 6B 83 AE C3 74 E8 .'..*b4. ..k...t. +[02A0] A3 05 DD 82 DD A3 D7 90 A8 E3 9C EB 64 16 23 06 ........ ....d.#. +[02B0] 5D FB E4 35 7C 22 29 78 E3 3B 75 92 91 0C 9D A1 ]..5|")x .;u..... +[02C0] 87 7C 2E 82 AE 49 9D 4A 50 A9 C2 D5 85 B0 16 5D .|...I.J P......] +[02D0] A2 CD B0 DD 29 3F 6F 66 C9 C1 9F 5C F0 B6 FC D2 ....)?of ...\.... +[02E0] 52 BE 7B F0 1F 26 AF 8A FC C3 A6 24 8C C0 10 06 R.{..&.. ...$.... +[02F0] 73 1E 17 9E 6E 6F 32 44 6A DF 82 5D D0 6B 74 CE s...no2D j..].kt. +[0300] 58 0B 4C 7B EB A1 13 44 B1 3E D8 F8 BA F4 4E 55 X.L{...D .>....NU +[0310] 71 3D C1 09 D9 E7 97 9A 14 5C 54 7E 57 81 5F 6B q=...... .\T~W._k +[0320] 30 BE 9A E1 98 29 47 D4 C0 8F 63 0A F8 27 1F CE 0....)G. ..c..'.. +[0330] ED D9 BB 7B 12 24 D0 34 2A 7C F0 F7 77 F4 F1 1D ...{.$.4 *|..w... +[0340] 4C 5D 75 2D 6B 0D 80 35 82 CC D8 7A 6B FA A0 55 L]u-k..5 ...zk..U +[0350] 34 CD 87 15 61 38 78 D4 69 0F AA 72 D6 AC FA 99 4...a8x. i..r.... +[0360] BC 70 39 27 A7 25 2E 1B 6F 36 01 FD E9 B4 9A 79 .p9'.%.. o6.....y +[0370] 6C 19 DD A6 8C 78 B0 40 92 60 58 F0 28 AD 08 78 l....x.@ .`X.(..x +[0380] 4A 29 06 2C 82 2B 1A E3 91 0B 5F EE D6 B8 66 47 J).,.+.. .._...fG +[0390] 31 9B A3 DF 9F 79 D7 BB 0E 2C FA 0E C9 66 84 8D 1....y.. .,...f.. +[03A0] FF BA BB 21 27 9E AD 86 84 55 8D 4C 4C 47 D9 5F ...!'... .U.LLG._ +[03B0] B2 7D 26 CA B7 49 3C 9D 1B 67 71 11 3A 8A EB EA .}&..I<. .gq.:... +[03C0] 0F 15 EB F0 1E 46 F7 A4 34 04 D7 E3 50 67 47 D3 .....F.. 4...PgG. +[03D0] 66 21 17 77 51 A7 1F 1D 84 3B 7C B1 5D 4E B8 D4 f!.wQ... .;|.]N.. +[03E0] F9 C5 75 06 AA 19 45 1C E9 06 9E AD 23 26 6B 10 ..u...E. ....#&k. +[03F0] 53 A0 36 D3 58 9F 5E 8C CB A5 F6 BC C9 30 3C BC S.6.X.^. .....0<. +[0400] AD FF 7C 92 F0 C6 9A 02 ..|..... + second_ticket : DATA_BLOB length=0 + further_creds : DATA_BLOB length=10683 +[0000] 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 ........ ....KTES +[0010] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0020] 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 COM....a dministr +[0030] 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 ator.... ........ +[0040] 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D KTEST.SA MBA.EXAM +[0050] 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 73 00 PLE.COM. ...cifs. +[0060] 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 00 17 ...local ktest6.. +[0070] 00 00 00 10 00 6E A1 B2 31 6D 48 C7 90 72 3A 0C .....n.. 1mH..r:. +[0080] 4B 8B 83 8C 4D 99 4F 6A 4D 99 50 85 7D 44 0B 68 K...M.Oj M.P.}D.h +[0090] 00 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 .....@(. ........ +[00A0] 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 .....a.. .0...... +[00B0] 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[00C0] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 A.EXAMPL E.COM..0 +[00D0] 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 69 66 73 ........ 0...cifs +[00E0] 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 A3 82 03 ..localk test6... +[00F0] AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 02 A2 .0...... ........ +[0100] 82 03 9C 04 82 03 98 C6 BB 64 A8 31 00 FC 5E 51 ........ .d.1..^Q +[0110] 3C 87 F8 34 47 3B D0 6F 6F FD 9E A6 91 12 74 2D <..4G;.o o.....t- +[0120] 44 BB AA 91 A0 2D 46 3E 9E FB FB C4 FB F1 15 FD D....-F> ........ +[0130] BB DA EE 06 A9 20 6A 38 DC 46 06 27 D9 A2 9D 2D ..... j8 .F.'...- +[0140] 1F FD 0D 7D 8A BB 0A 7C E8 47 17 BC 7B 70 E4 51 ...}...| .G..{p.Q +[0150] 6A BA 51 68 62 28 4A 1E 51 D1 0D CD 02 55 75 44 j.Qhb(J. Q....UuD +[0160] 8A B9 C2 84 F4 17 34 92 9B 31 85 9E 43 C1 0C 3A ......4. .1..C..: +[0170] B2 69 7F 20 1A 18 1F 65 4F C0 20 C9 B5 AF E1 61 .i. ...e O. ....a +[0180] 8C 90 10 63 26 A6 5D 05 3C CD 29 BB 7B 74 D5 8F ...c&.]. <.).{t.. +[0190] 2C 7F 4B E8 84 24 57 37 8A C6 F7 91 FD 22 9A A5 ,.K..$W7 .....".. +[01A0] 0D E9 4A 78 93 36 FC A8 8C 8A 27 8A C6 28 4B 7B ..Jx.6.. ..'..(K{ +[01B0] DA 11 42 BC 09 10 81 82 14 0F 9C B8 48 26 91 78 ..B..... ....H&.x +[01C0] A8 DD 97 6C 24 A1 D2 E8 85 19 B3 D3 85 4D 38 C7 ...l$... .....M8. +[01D0] 7D 49 55 8E 85 46 E1 EE 7B BA 11 62 63 53 C5 16 }IU..F.. {..bcS.. +[01E0] 4A 0C 1C 99 7C 0E FB 45 1D B4 98 58 67 7E 40 65 J...|..E ...Xg~@e +[01F0] 4B 48 E2 89 9C 8B C2 B8 39 D1 04 C0 A8 56 E8 A1 KH...... 9....V.. +[0200] 04 7A 7A C9 60 18 A0 29 E2 DC 82 4C 8F 18 CE 2F .zz.`..) ...L.../ +[0210] 14 F0 18 5B 6C FF 85 45 88 73 CB A4 55 08 FC BF ...[l..E .s..U... +[0220] C7 9F 51 0A DB 2C C1 E3 3C DD F6 F0 A3 2D F1 3B ..Q..,.. <....-.; +[0230] A0 12 1D FC 2A 67 F5 1A 7F E5 7C 6C FB 8A 18 BD ....*g.. ..|l.... +[0240] D1 5D E5 5E 68 30 AA 58 9E 10 13 E0 26 7E 7D C4 .].^h0.X ....&~}. +[0250] E1 A5 B6 86 0F 1C 0F 13 A4 5E 5E 6A ED 42 79 31 ........ .^^j.By1 +[0260] BB B3 5F 3A 3F DD CB 63 82 FB 06 AE 12 36 C9 1E .._:?..c .....6.. +[0270] 06 7D 41 82 2E D2 FA 26 EC 17 50 5E D0 DE 26 85 .}A....& ..P^..&. +[0280] 30 71 BC 45 3B DA 2E 08 8D B2 2A 3C E0 79 8F 77 0q.E;... ..*<.y.w +[0290] 4C 01 69 7A 09 C7 88 E1 D1 DC FF 78 DB 25 7B B1 L.iz.... ...x.%{. +[02A0] 3C BB 22 27 80 0D 75 96 18 B6 40 95 6D C8 AB 04 <."'..u. ..@.m... +[02B0] 05 41 A1 C4 25 71 C4 53 3A A6 9C B2 4D E6 15 2C .A..%q.S :...M.., +[02C0] B2 47 6C DA A8 7D CC A3 89 8B C9 1E 21 F5 E9 B2 .Gl..}.. ....!... +[02D0] 42 95 68 28 AF C6 37 22 BA 30 8D 53 FA 08 0D CE B.h(..7" .0.S.... +[02E0] CA 81 61 0D 84 A5 2D 75 BD 41 85 4C 88 56 72 C6 ..a...-u .A.L.Vr. +[02F0] B6 10 F8 34 CD B2 F4 5C 94 FA 80 90 82 A0 BD 68 ...4...\ .......h +[0300] EC 08 32 C3 B6 51 1E 3F 67 CB 7B EB 70 83 84 D4 ..2..Q.? g.{.p... +[0310] CB 52 55 36 61 1E 60 90 5B 6F FE 9A 62 05 CF 26 .RU6a.`. [o..b..& +[0320] 8E 65 E2 60 4B ED 63 B4 C4 E6 44 B4 2F B0 B8 07 .e.`K.c. ..D./... +[0330] FE BE 0D 50 E4 56 A4 2E 0D 25 76 0B 0F 44 09 20 ...P.V.. .%v..D. +[0340] 80 E5 C4 94 63 E0 54 46 1D AB 5E 0B 09 93 B1 30 ....c.TF ..^....0 +[0350] 31 7B 04 DC 23 43 3B DB 7D 39 67 FE 9A 1F C1 08 1{..#C;. }9g..... +[0360] AF 34 24 F6 74 E4 14 DA 34 8F 61 57 6A 7F 1D 4A .4$.t... 4.aWj..J +[0370] 88 0A 90 78 93 F1 86 54 DB 22 86 D6 69 0F DF 44 ...x...T ."..i..D +[0380] 7C D3 6B 9D 41 63 50 98 3A 97 B9 7B 4C 53 E3 85 |.k.AcP. :..{LS.. +[0390] 73 9A C9 08 A0 75 12 50 02 87 B0 CF CC 84 84 D9 s....u.P ........ +[03A0] BC FC 94 79 AF 6A A6 08 FF 19 7E E9 22 9B EC 5C ...y.j.. ..~."..\ +[03B0] C1 6B 1D A4 B4 55 32 5E 23 C3 C0 D4 8B 80 E6 67 .k...U2^ #......g +[03C0] B1 59 EB 9D 5D 9B AD C6 0E 7D E2 FE B1 24 8A B1 .Y..]... .}...$.. +[03D0] 37 1E 60 7F 83 35 48 32 F7 03 E8 12 E6 21 7C 3D 7.`..5H2 .....!|= +[03E0] 21 7F 6B 14 31 9C 1A A3 4C 2B 1C 5E EC 34 C1 2D !.k.1... L+.^.4.- +[03F0] DA 19 6C E6 6D 8D 60 D7 55 9E E6 D0 B5 07 06 72 ..l.m.`. U......r +[0400] C0 E9 4E 91 94 6B 3E 0B F1 0A 75 4D E8 CB 53 6B ..N..k>. ..uM..Sk +[0410] 34 A4 2F 96 A5 39 1A 18 6E 27 00 6D 41 B7 D8 F5 4./..9.. n'.mA... +[0420] 9A E5 01 FC 0B A8 97 56 EE 98 04 1D 98 84 5E 82 .......V ......^. +[0430] C8 E8 EC 17 D5 FA 96 00 3B E1 98 1C D8 FA 66 A0 ........ ;.....f. +[0440] DC 32 60 F6 03 46 08 3C E5 16 6F F2 8B 4D 72 9F .2`..F.< ..o..Mr. +[0450] 0F E0 A9 71 6E 7C AE AA FB A3 4D F1 A1 B6 1B 9F ...qn|.. ..M..... +[0460] 62 71 E1 2C 82 9B AE E3 07 9B 79 90 F1 C2 69 E5 bq.,.... ..y...i. +[0470] 7E CB 57 E6 C9 1C 4E A8 C7 12 EA 4F 4C 52 17 03 ~.W...N. ...OLR.. +[0480] AB D4 FD 34 60 F4 7C BE 9E 36 30 37 88 95 61 2E ...4`.|. .607..a. +[0490] CF 70 AF 22 70 DB E8 AA 6E 3D 30 F7 4D 84 D5 00 .p."p... n=0.M... +[04A0] 00 00 00 00 00 00 01 00 00 00 01 00 00 00 17 4B ........ .......K +[04B0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[04C0] 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 LE.COM.. ..admini +[04D0] 73 74 72 61 74 6F 72 00 00 00 01 00 00 00 02 00 strator. ........ +[04E0] 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 ...KTEST .SAMBA.E +[04F0] 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 XAMPLE.C OM....ci +[0500] 66 73 00 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 fs....lo calktest +[0510] 36 00 17 00 00 00 10 00 6E A1 B2 31 6D 48 C7 90 6....... n..1mH.. +[0520] 72 3A 0C 4B 8B 83 8C 4D 99 4F 6A 4D 99 50 85 7D r:.K...M .OjM.P.} +[0530] 44 0B 68 00 00 00 00 00 40 28 00 00 00 00 00 00 D.h..... @(...... +[0540] 00 00 00 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 ........ a...0... +[0550] A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0560] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0570] A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 ..0..... ...0...c +[0580] 69 66 73 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 ifs..loc alktest6 +[0590] A3 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 03 02 ....0... ........ +[05A0] 01 02 A2 82 03 9C 04 82 03 98 C6 BB 64 A8 31 00 ........ ....d.1. +[05B0] FC 5E 51 3C 87 F8 34 47 3B D0 6F 6F FD 9E A6 91 .^Q<..4G ;.oo.... +[05C0] 12 74 2D 44 BB AA 91 A0 2D 46 3E 9E FB FB C4 FB .t-D.... -F>..... +[05D0] F1 15 FD BB DA EE 06 A9 20 6A 38 DC 46 06 27 D9 ........ j8.F.'. +[05E0] A2 9D 2D 1F FD 0D 7D 8A BB 0A 7C E8 47 17 BC 7B ..-...}. ..|.G..{ +[05F0] 70 E4 51 6A BA 51 68 62 28 4A 1E 51 D1 0D CD 02 p.Qj.Qhb (J.Q.... +[0600] 55 75 44 8A B9 C2 84 F4 17 34 92 9B 31 85 9E 43 UuD..... .4..1..C +[0610] C1 0C 3A B2 69 7F 20 1A 18 1F 65 4F C0 20 C9 B5 ..:.i. . ..eO. .. +[0620] AF E1 61 8C 90 10 63 26 A6 5D 05 3C CD 29 BB 7B ..a...c& .].<.).{ +[0630] 74 D5 8F 2C 7F 4B E8 84 24 57 37 8A C6 F7 91 FD t..,.K.. $W7..... +[0640] 22 9A A5 0D E9 4A 78 93 36 FC A8 8C 8A 27 8A C6 "....Jx. 6....'.. +[0650] 28 4B 7B DA 11 42 BC 09 10 81 82 14 0F 9C B8 48 (K{..B.. .......H +[0660] 26 91 78 A8 DD 97 6C 24 A1 D2 E8 85 19 B3 D3 85 &.x...l$ ........ +[0670] 4D 38 C7 7D 49 55 8E 85 46 E1 EE 7B BA 11 62 63 M8.}IU.. F..{..bc +[0680] 53 C5 16 4A 0C 1C 99 7C 0E FB 45 1D B4 98 58 67 S..J...| ..E...Xg +[0690] 7E 40 65 4B 48 E2 89 9C 8B C2 B8 39 D1 04 C0 A8 ~@eKH... ...9.... +[06A0] 56 E8 A1 04 7A 7A C9 60 18 A0 29 E2 DC 82 4C 8F V...zz.` ..)...L. +[06B0] 18 CE 2F 14 F0 18 5B 6C FF 85 45 88 73 CB A4 55 ../...[l ..E.s..U +[06C0] 08 FC BF C7 9F 51 0A DB 2C C1 E3 3C DD F6 F0 A3 .....Q.. ,..<.... +[06D0] 2D F1 3B A0 12 1D FC 2A 67 F5 1A 7F E5 7C 6C FB -.;....* g....|l. +[06E0] 8A 18 BD D1 5D E5 5E 68 30 AA 58 9E 10 13 E0 26 ....].^h 0.X....& +[06F0] 7E 7D C4 E1 A5 B6 86 0F 1C 0F 13 A4 5E 5E 6A ED ~}...... ....^^j. +[0700] 42 79 31 BB B3 5F 3A 3F DD CB 63 82 FB 06 AE 12 By1.._:? ..c..... +[0710] 36 C9 1E 06 7D 41 82 2E D2 FA 26 EC 17 50 5E D0 6...}A.. ..&..P^. +[0720] DE 26 85 30 71 BC 45 3B DA 2E 08 8D B2 2A 3C E0 .&.0q.E; .....*<. +[0730] 79 8F 77 4C 01 69 7A 09 C7 88 E1 D1 DC FF 78 DB y.wL.iz. ......x. +[0740] 25 7B B1 3C BB 22 27 80 0D 75 96 18 B6 40 95 6D %{.<."'. .u...@.m +[0750] C8 AB 04 05 41 A1 C4 25 71 C4 53 3A A6 9C B2 4D ....A..% q.S:...M +[0760] E6 15 2C B2 47 6C DA A8 7D CC A3 89 8B C9 1E 21 ..,.Gl.. }......! +[0770] F5 E9 B2 42 95 68 28 AF C6 37 22 BA 30 8D 53 FA ...B.h(. .7".0.S. +[0780] 08 0D CE CA 81 61 0D 84 A5 2D 75 BD 41 85 4C 88 .....a.. .-u.A.L. +[0790] 56 72 C6 B6 10 F8 34 CD B2 F4 5C 94 FA 80 90 82 Vr....4. ..\..... +[07A0] A0 BD 68 EC 08 32 C3 B6 51 1E 3F 67 CB 7B EB 70 ..h..2.. Q.?g.{.p +[07B0] 83 84 D4 CB 52 55 36 61 1E 60 90 5B 6F FE 9A 62 ....RU6a .`.[o..b +[07C0] 05 CF 26 8E 65 E2 60 4B ED 63 B4 C4 E6 44 B4 2F ..&.e.`K .c...D./ +[07D0] B0 B8 07 FE BE 0D 50 E4 56 A4 2E 0D 25 76 0B 0F ......P. V...%v.. +[07E0] 44 09 20 80 E5 C4 94 63 E0 54 46 1D AB 5E 0B 09 D. ....c .TF..^.. +[07F0] 93 B1 30 31 7B 04 DC 23 43 3B DB 7D 39 67 FE 9A ..01{..# C;.}9g.. +[0800] 1F C1 08 AF 34 24 F6 74 E4 14 DA 34 8F 61 57 6A ....4$.t ...4.aWj +[0810] 7F 1D 4A 88 0A 90 78 93 F1 86 54 DB 22 86 D6 69 ..J...x. ..T."..i +[0820] 0F DF 44 7C D3 6B 9D 41 63 50 98 3A 97 B9 7B 4C ..D|.k.A cP.:..{L +[0830] 53 E3 85 73 9A C9 08 A0 75 12 50 02 87 B0 CF CC S..s.... u.P..... +[0840] 84 84 D9 BC FC 94 79 AF 6A A6 08 FF 19 7E E9 22 ......y. j....~." +[0850] 9B EC 5C C1 6B 1D A4 B4 55 32 5E 23 C3 C0 D4 8B ..\.k... U2^#.... +[0860] 80 E6 67 B1 59 EB 9D 5D 9B AD C6 0E 7D E2 FE B1 ..g.Y..] ....}... +[0870] 24 8A B1 37 1E 60 7F 83 35 48 32 F7 03 E8 12 E6 $..7.`.. 5H2..... +[0880] 21 7C 3D 21 7F 6B 14 31 9C 1A A3 4C 2B 1C 5E EC !|=!.k.1 ...L+.^. +[0890] 34 C1 2D DA 19 6C E6 6D 8D 60 D7 55 9E E6 D0 B5 4.-..l.m .`.U.... +[08A0] 07 06 72 C0 E9 4E 91 94 6B 3E 0B F1 0A 75 4D E8 ..r..N.. k>...uM. +[08B0] CB 53 6B 34 A4 2F 96 A5 39 1A 18 6E 27 00 6D 41 .Sk4./.. 9..n'.mA +[08C0] B7 D8 F5 9A E5 01 FC 0B A8 97 56 EE 98 04 1D 98 ........ ..V..... +[08D0] 84 5E 82 C8 E8 EC 17 D5 FA 96 00 3B E1 98 1C D8 .^...... ...;.... +[08E0] FA 66 A0 DC 32 60 F6 03 46 08 3C E5 16 6F F2 8B .f..2`.. F.<..o.. +[08F0] 4D 72 9F 0F E0 A9 71 6E 7C AE AA FB A3 4D F1 A1 Mr....qn |....M.. +[0900] B6 1B 9F 62 71 E1 2C 82 9B AE E3 07 9B 79 90 F1 ...bq.,. .....y.. +[0910] C2 69 E5 7E CB 57 E6 C9 1C 4E A8 C7 12 EA 4F 4C .i.~.W.. .N....OL +[0920] 52 17 03 AB D4 FD 34 60 F4 7C BE 9E 36 30 37 88 R.....4` .|..607. +[0930] 95 61 2E CF 70 AF 22 70 DB E8 AA 6E 3D 30 F7 4D .a..p."p ...n=0.M +[0940] 84 D5 00 00 00 00 00 00 00 01 00 00 00 01 00 00 ........ ........ +[0950] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[0960] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D AMPLE.CO M....adm +[0970] 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 inistrat or...... +[0980] 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[0990] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 A.EXAMPL E.COM... +[09A0] 04 63 69 66 73 00 00 00 0B 6C 6F 63 61 6C 6B 74 .cifs... .localkt +[09B0] 65 73 74 36 00 17 00 00 00 10 00 6E A1 B2 31 6D est6.... ...n..1m +[09C0] 48 C7 90 72 3A 0C 4B 8B 83 8C 4D 99 4F 6A 4D 99 H..r:.K. ..M.OjM. +[09D0] 50 85 7D 44 0B 68 00 00 00 00 00 40 28 00 00 00 P.}D.h.. ...@(... +[09E0] 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 ........ ...a...0 +[09F0] 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 ........ ....KTES +[0A00] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0A10] 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 COM..0.. ......0. +[0A20] 1B 04 63 69 66 73 1B 0B 6C 6F 63 61 6C 6B 74 65 ..cifs.. localkte +[0A30] 73 74 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 st6....0 ........ +[0A40] A1 03 02 01 02 A2 82 03 9C 04 82 03 98 C6 BB 64 ........ .......d +[0A50] A8 31 00 FC 5E 51 3C 87 F8 34 47 3B D0 6F 6F FD .1..^Q<. .4G;.oo. +[0A60] 9E A6 91 12 74 2D 44 BB AA 91 A0 2D 46 3E 9E FB ....t-D. ...-F>.. +[0A70] FB C4 FB F1 15 FD BB DA EE 06 A9 20 6A 38 DC 46 ........ ... j8.F +[0A80] 06 27 D9 A2 9D 2D 1F FD 0D 7D 8A BB 0A 7C E8 47 .'...-.. .}...|.G +[0A90] 17 BC 7B 70 E4 51 6A BA 51 68 62 28 4A 1E 51 D1 ..{p.Qj. Qhb(J.Q. +[0AA0] 0D CD 02 55 75 44 8A B9 C2 84 F4 17 34 92 9B 31 ...UuD.. ....4..1 +[0AB0] 85 9E 43 C1 0C 3A B2 69 7F 20 1A 18 1F 65 4F C0 ..C..:.i . ...eO. +[0AC0] 20 C9 B5 AF E1 61 8C 90 10 63 26 A6 5D 05 3C CD ....a.. .c&.].<. +[0AD0] 29 BB 7B 74 D5 8F 2C 7F 4B E8 84 24 57 37 8A C6 ).{t..,. K..$W7.. +[0AE0] F7 91 FD 22 9A A5 0D E9 4A 78 93 36 FC A8 8C 8A ...".... Jx.6.... +[0AF0] 27 8A C6 28 4B 7B DA 11 42 BC 09 10 81 82 14 0F '..(K{.. B....... +[0B00] 9C B8 48 26 91 78 A8 DD 97 6C 24 A1 D2 E8 85 19 ..H&.x.. .l$..... +[0B10] B3 D3 85 4D 38 C7 7D 49 55 8E 85 46 E1 EE 7B BA ...M8.}I U..F..{. +[0B20] 11 62 63 53 C5 16 4A 0C 1C 99 7C 0E FB 45 1D B4 .bcS..J. ..|..E.. +[0B30] 98 58 67 7E 40 65 4B 48 E2 89 9C 8B C2 B8 39 D1 .Xg~@eKH ......9. +[0B40] 04 C0 A8 56 E8 A1 04 7A 7A C9 60 18 A0 29 E2 DC ...V...z z.`..).. +[0B50] 82 4C 8F 18 CE 2F 14 F0 18 5B 6C FF 85 45 88 73 .L.../.. .[l..E.s +[0B60] CB A4 55 08 FC BF C7 9F 51 0A DB 2C C1 E3 3C DD ..U..... Q..,..<. +[0B70] F6 F0 A3 2D F1 3B A0 12 1D FC 2A 67 F5 1A 7F E5 ...-.;.. ..*g.... +[0B80] 7C 6C FB 8A 18 BD D1 5D E5 5E 68 30 AA 58 9E 10 |l.....] .^h0.X.. +[0B90] 13 E0 26 7E 7D C4 E1 A5 B6 86 0F 1C 0F 13 A4 5E ..&~}... .......^ +[0BA0] 5E 6A ED 42 79 31 BB B3 5F 3A 3F DD CB 63 82 FB ^j.By1.. _:?..c.. +[0BB0] 06 AE 12 36 C9 1E 06 7D 41 82 2E D2 FA 26 EC 17 ...6...} A....&.. +[0BC0] 50 5E D0 DE 26 85 30 71 BC 45 3B DA 2E 08 8D B2 P^..&.0q .E;..... +[0BD0] 2A 3C E0 79 8F 77 4C 01 69 7A 09 C7 88 E1 D1 DC *<.y.wL. iz...... +[0BE0] FF 78 DB 25 7B B1 3C BB 22 27 80 0D 75 96 18 B6 .x.%{.<. "'..u... +[0BF0] 40 95 6D C8 AB 04 05 41 A1 C4 25 71 C4 53 3A A6 @.m....A ..%q.S:. +[0C00] 9C B2 4D E6 15 2C B2 47 6C DA A8 7D CC A3 89 8B ..M..,.G l..}.... +[0C10] C9 1E 21 F5 E9 B2 42 95 68 28 AF C6 37 22 BA 30 ..!...B. h(..7".0 +[0C20] 8D 53 FA 08 0D CE CA 81 61 0D 84 A5 2D 75 BD 41 .S...... a...-u.A +[0C30] 85 4C 88 56 72 C6 B6 10 F8 34 CD B2 F4 5C 94 FA .L.Vr... .4...\.. +[0C40] 80 90 82 A0 BD 68 EC 08 32 C3 B6 51 1E 3F 67 CB .....h.. 2..Q.?g. +[0C50] 7B EB 70 83 84 D4 CB 52 55 36 61 1E 60 90 5B 6F {.p....R U6a.`.[o +[0C60] FE 9A 62 05 CF 26 8E 65 E2 60 4B ED 63 B4 C4 E6 ..b..&.e .`K.c... +[0C70] 44 B4 2F B0 B8 07 FE BE 0D 50 E4 56 A4 2E 0D 25 D./..... .P.V...% +[0C80] 76 0B 0F 44 09 20 80 E5 C4 94 63 E0 54 46 1D AB v..D. .. ..c.TF.. +[0C90] 5E 0B 09 93 B1 30 31 7B 04 DC 23 43 3B DB 7D 39 ^....01{ ..#C;.}9 +[0CA0] 67 FE 9A 1F C1 08 AF 34 24 F6 74 E4 14 DA 34 8F g......4 $.t...4. +[0CB0] 61 57 6A 7F 1D 4A 88 0A 90 78 93 F1 86 54 DB 22 aWj..J.. .x...T." +[0CC0] 86 D6 69 0F DF 44 7C D3 6B 9D 41 63 50 98 3A 97 ..i..D|. k.AcP.:. +[0CD0] B9 7B 4C 53 E3 85 73 9A C9 08 A0 75 12 50 02 87 .{LS..s. ...u.P.. +[0CE0] B0 CF CC 84 84 D9 BC FC 94 79 AF 6A A6 08 FF 19 ........ .y.j.... +[0CF0] 7E E9 22 9B EC 5C C1 6B 1D A4 B4 55 32 5E 23 C3 ~."..\.k ...U2^#. +[0D00] C0 D4 8B 80 E6 67 B1 59 EB 9D 5D 9B AD C6 0E 7D .....g.Y ..]....} +[0D10] E2 FE B1 24 8A B1 37 1E 60 7F 83 35 48 32 F7 03 ...$..7. `..5H2.. +[0D20] E8 12 E6 21 7C 3D 21 7F 6B 14 31 9C 1A A3 4C 2B ...!|=!. k.1...L+ +[0D30] 1C 5E EC 34 C1 2D DA 19 6C E6 6D 8D 60 D7 55 9E .^.4.-.. l.m.`.U. +[0D40] E6 D0 B5 07 06 72 C0 E9 4E 91 94 6B 3E 0B F1 0A .....r.. N..k>... +[0D50] 75 4D E8 CB 53 6B 34 A4 2F 96 A5 39 1A 18 6E 27 uM..Sk4. /..9..n' +[0D60] 00 6D 41 B7 D8 F5 9A E5 01 FC 0B A8 97 56 EE 98 .mA..... .....V.. +[0D70] 04 1D 98 84 5E 82 C8 E8 EC 17 D5 FA 96 00 3B E1 ....^... ......;. +[0D80] 98 1C D8 FA 66 A0 DC 32 60 F6 03 46 08 3C E5 16 ....f..2 `..F.<.. +[0D90] 6F F2 8B 4D 72 9F 0F E0 A9 71 6E 7C AE AA FB A3 o..Mr... .qn|.... +[0DA0] 4D F1 A1 B6 1B 9F 62 71 E1 2C 82 9B AE E3 07 9B M.....bq .,...... +[0DB0] 79 90 F1 C2 69 E5 7E CB 57 E6 C9 1C 4E A8 C7 12 y...i.~. W...N... +[0DC0] EA 4F 4C 52 17 03 AB D4 FD 34 60 F4 7C BE 9E 36 .OLR.... .4`.|..6 +[0DD0] 30 37 88 95 61 2E CF 70 AF 22 70 DB E8 AA 6E 3D 07..a..p ."p...n= +[0DE0] 30 F7 4D 84 D5 00 00 00 00 00 00 00 01 00 00 00 0.M..... ........ +[0DF0] 01 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[0E00] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D .EXAMPLE .COM.... +[0E10] 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 administ rator... +[0E20] 01 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0E30] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0E40] 00 00 00 04 63 69 66 73 00 00 00 0B 4C 4F 43 41 ....cifs ....LOCA +[0E50] 4C 4B 54 45 53 54 36 00 17 00 00 00 10 1D C8 5E LKTEST6. .......^ +[0E60] 46 48 82 F9 29 DB C6 A6 F1 72 6D 8D E9 4D 99 4F FH..)... .rm..M.O +[0E70] 6A 4D 99 85 09 7D 44 0B 68 00 00 00 00 00 40 28 jM...}D. h.....@( +[0E80] 00 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 ........ ......a. +[0E90] 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B ..0..... .......K +[0EA0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0EB0] 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 LE.COM.. 0....... +[0EC0] 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F 43 41 4C .0...cif s..LOCAL +[0ED0] 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 KTEST6.. ..0..... +[0EE0] 02 01 17 A1 03 02 01 02 A2 82 03 9C 04 82 03 98 ........ ........ +[0EF0] 66 D8 19 46 FA CB 73 2D CF 88 FD 4A EE 07 48 DA f..F..s- ...J..H. +[0F00] 0E BC 58 30 43 40 A4 9C 00 0F 3B 17 C1 2D F5 9C ..X0C@.. ..;..-.. +[0F10] 3E D9 2F 1D CA 01 9B D7 2E EC D7 70 ED 8B 8B 1B >./..... ...p.... +[0F20] 5E F2 4E EE DD 0F C0 8D 61 E5 D7 0A 56 00 32 B1 ^.N..... a...V.2. +[0F30] DB 91 37 29 0F 2F 85 EE A8 43 BA A5 B8 D4 19 74 ..7)./.. .C.....t +[0F40] 33 F0 69 52 E1 58 98 83 D6 16 0B 44 A9 63 9B D4 3.iR.X.. ...D.c.. +[0F50] 4E 6E A7 3E CD 9A 96 4D C4 96 F5 07 6D 29 B6 ED Nn.>...M ....m).. +[0F60] 2A 62 3D 53 22 33 D1 95 E9 DF 74 4C 2A E2 29 AF *b=S"3.. ..tL*.). +[0F70] 5B 69 B0 48 2D AD 94 FD A5 1D 54 D8 E2 5E C1 68 [i.H-... ..T..^.h +[0F80] 6F BA 02 01 79 C3 C9 97 0B 76 66 45 E2 3B 10 17 o...y... .vfE.;.. +[0F90] 95 40 46 E4 85 B9 87 BB CF CF 19 8C 3A C0 EA 38 .@F..... ....:..8 +[0FA0] 3B B9 E9 4B 05 89 E5 27 8C 62 95 BC 0D 65 F0 D2 ;..K...' .b...e.. +[0FB0] C0 5E BC 65 01 D5 0B CB 17 31 0F 06 49 4F A2 4A .^.e.... .1..IO.J +[0FC0] 70 77 DB BD 92 5B 37 5C EC 06 DF C5 E2 31 C8 40 pw...[7\ .....1.@ +[0FD0] 09 11 68 14 E7 7D CE 54 4F 52 61 31 2C 1C 53 52 ..h..}.T ORa1,.SR +[0FE0] DB BE D8 95 39 EE 7D C6 CE C8 22 95 92 97 97 3D ....9.}. .."....= +[0FF0] 5E 66 0F AD DC C2 4E 2E 2B 9F 63 20 30 DF B7 C1 ^f....N. +.c 0... +[1000] D4 65 AA 6F 2D 10 24 07 20 8D 88 6E 4B 09 04 31 .e.o-.$. ..nK..1 +[1010] B6 A3 EB F7 37 32 0E 0C 73 C6 F6 B8 4D D9 0C 4C ....72.. s...M..L +[1020] 5B EC 10 6A 51 19 EA 3F FF 46 E7 73 16 A7 1F 33 [..jQ..? .F.s...3 +[1030] 98 7C 9B AD 5A 23 A9 40 7C 0F DF EE 0F AA C7 E8 .|..Z#.@ |....... +[1040] 63 07 98 3A 4A 0D 18 62 01 21 B2 AE A5 69 B0 C1 c..:J..b .!...i.. +[1050] 15 51 BA 97 D2 C5 42 5B C5 30 38 18 A9 48 AB D7 .Q....B[ .08..H.. +[1060] FC A1 BC 9F 71 E7 EA 18 54 42 DA D6 A4 FC C1 DC ....q... TB...... +[1070] F3 12 30 62 AC 98 E1 7D 2B 34 1E 52 4C 26 67 32 ..0b...} +4.RL&g2 +[1080] D9 44 1A 08 27 0E DA D0 FC 84 66 35 81 D6 EB 98 .D..'... ..f5.... +[1090] 46 6F 1E 47 E0 14 31 BE 47 80 65 AA 0B 20 D6 33 Fo.G..1. G.e.. .3 +[10A0] 36 3B 0D 40 2F 5A 2E 0E 01 BE 00 EB 33 3E 4B 32 6;.@/Z.. ....3>K2 +[10B0] 91 F4 22 96 E5 5F D4 D5 92 94 CC 5B 59 6A 3E D2 ..".._.. ...[Yj>. +[10C0] FB A0 4F 99 C4 07 8B 6F 2B 14 37 CD 37 44 C0 1F ..O....o +.7.7D.. +[10D0] 80 9C 43 46 F2 5E F4 FE D3 39 70 61 BE 72 5B 3A ..CF.^.. .9pa.r[: +[10E0] 8F 37 95 78 1E AB D9 E7 E9 DA FC 47 09 81 A0 0D .7.x.... ...G.... +[10F0] 62 E1 F9 34 36 D1 DB E6 98 D8 F4 3E 77 5A 4D E2 b..46... ...>wZM. +[1100] 5F 20 70 3D 3D 5B 34 D9 FD A8 31 F7 D9 59 F7 A3 _ p==[4. ..1..Y.. +[1110] F0 66 F7 D9 AD 1C CD D5 85 33 A0 87 22 31 D4 F3 .f...... .3.."1.. +[1120] 67 80 68 20 A2 90 72 7A 6F 64 FD 68 82 9E 91 B8 g.h ..rz od.h.... +[1130] E3 F7 6D 6C 38 74 F0 96 A2 F6 25 D7 92 58 14 60 ..ml8t.. ..%..X.` +[1140] 9F AE 01 4C 0C 09 67 3E 35 67 71 1E 2A 86 21 D3 ...L..g> 5gq.*.!. +[1150] 60 61 98 16 94 67 0B 52 76 63 93 BD A3 3B A9 F0 `a...g.R vc...;.. +[1160] A2 6A B7 E6 0F 35 64 DA 6A EA 20 A6 3D 94 71 59 .j...5d. j. .=.qY +[1170] 5E CB B2 D3 F9 4D FE 1B 4B D8 64 C8 3B 7A A8 E6 ^....M.. K.d.;z.. +[1180] D2 D5 76 71 26 D4 5C DA 1A 55 17 F2 16 C9 2F 77 ..vq&.\. .U..../w +[1190] DB 95 19 48 A5 AC D0 C3 31 9C 0A CC 1B 44 11 6B ...H.... 1....D.k +[11A0] 7C 88 7A 5D CF 6E 12 DA EF C5 C7 34 1D F4 CC EA |.z].n.. ...4.... +[11B0] 37 24 4B B3 0F C1 A3 F2 29 A0 D8 93 39 C6 16 57 7$K..... )...9..W +[11C0] D5 BF 57 BF 6C 7E F7 90 E0 EB A3 8B 07 56 9C EC ..W.l~.. .....V.. +[11D0] 15 3E 21 DA A5 7C 00 3C F9 D2 A7 1C 6F 16 25 31 .>!..|.< ....o.%1 +[11E0] C5 28 A7 EA F3 47 31 50 DD E1 ED 0A 93 DB 85 CC .(...G1P ........ +[11F0] 6B 4B 2C 7F E8 F8 2D A9 6D 1D 0A 87 F2 10 8C 82 kK,...-. m....... +[1200] 2F 9B D4 9B 92 8C 77 40 50 42 1E 42 C4 0A 4F E3 /.....w@ PB.B..O. +[1210] 6C 6C DC 81 C4 1E BB F0 7D CF 3C 73 22 5B C3 1A ll...... }..x K....%J. +[1240] 1E 6C 8F 01 D6 59 D7 CF 2E A0 CC 98 F6 75 28 2F .l...Y.. .....u(/ +[1250] F7 2A 70 28 A9 45 1F 75 C2 4E 62 ED D8 C4 A0 8D .*p(.E.u .Nb..... +[1260] 55 B2 84 1C A4 CE 87 EF 24 EE BC CE 40 09 EB 05 U....... $...@... +[1270] 0B D1 14 31 50 32 2F B6 A8 97 17 4B A7 95 01 50 ...1P2/. ...K...P +[1280] 6E 0E 23 49 9C 72 21 91 00 00 00 00 00 00 00 01 n.#I.r!. ........ +[1290] 00 00 00 01 00 00 00 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[12A0] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 MBA.EXAM PLE.COM. +[12B0] 00 00 0D 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 ...admin istrator +[12C0] 00 00 00 01 00 00 00 02 00 00 00 17 4B 54 45 53 ........ ....KTES +[12D0] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[12E0] 43 4F 4D 00 00 00 04 63 69 66 73 00 00 00 0B 4C COM....c ifs....L +[12F0] 4F 43 41 4C 4B 54 45 53 54 36 00 17 00 00 00 10 OCALKTES T6...... +[1300] 1D C8 5E 46 48 82 F9 29 DB C6 A6 F1 72 6D 8D E9 ..^FH..) ....rm.. +[1310] 4D 99 4F 6A 4D 99 85 09 7D 44 0B 68 00 00 00 00 M.OjM... }D.h.... +[1320] 00 40 28 00 00 00 00 00 00 00 00 00 00 00 00 03 .@(..... ........ +[1330] FA 61 82 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 .a...0.. ........ +[1340] 1B 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[1350] 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 AMPLE.CO M..0.... +[1360] 01 01 A1 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F ....0... cifs..LO +[1370] 43 41 4C 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 CALKTEST 6....0.. +[1380] AA A0 03 02 01 17 A1 03 02 01 02 A2 82 03 9C 04 ........ ........ +[1390] 82 03 98 66 D8 19 46 FA CB 73 2D CF 88 FD 4A EE ...f..F. .s-...J. +[13A0] 07 48 DA 0E BC 58 30 43 40 A4 9C 00 0F 3B 17 C1 .H...X0C @....;.. +[13B0] 2D F5 9C 3E D9 2F 1D CA 01 9B D7 2E EC D7 70 ED -..>./.. ......p. +[13C0] 8B 8B 1B 5E F2 4E EE DD 0F C0 8D 61 E5 D7 0A 56 ...^.N.. ...a...V +[13D0] 00 32 B1 DB 91 37 29 0F 2F 85 EE A8 43 BA A5 B8 .2...7). /...C... +[13E0] D4 19 74 33 F0 69 52 E1 58 98 83 D6 16 0B 44 A9 ..t3.iR. X.....D. +[13F0] 63 9B D4 4E 6E A7 3E CD 9A 96 4D C4 96 F5 07 6D c..Nn.>. ..M....m +[1400] 29 B6 ED 2A 62 3D 53 22 33 D1 95 E9 DF 74 4C 2A )..*b=S" 3....tL* +[1410] E2 29 AF 5B 69 B0 48 2D AD 94 FD A5 1D 54 D8 E2 .).[i.H- .....T.. +[1420] 5E C1 68 6F BA 02 01 79 C3 C9 97 0B 76 66 45 E2 ^.ho...y ....vfE. +[1430] 3B 10 17 95 40 46 E4 85 B9 87 BB CF CF 19 8C 3A ;...@F.. .......: +[1440] C0 EA 38 3B B9 E9 4B 05 89 E5 27 8C 62 95 BC 0D ..8;..K. ..'.b... +[1450] 65 F0 D2 C0 5E BC 65 01 D5 0B CB 17 31 0F 06 49 e...^.e. ....1..I +[1460] 4F A2 4A 70 77 DB BD 92 5B 37 5C EC 06 DF C5 E2 O.Jpw... [7\..... +[1470] 31 C8 40 09 11 68 14 E7 7D CE 54 4F 52 61 31 2C 1.@..h.. }.TORa1, +[1480] 1C 53 52 DB BE D8 95 39 EE 7D C6 CE C8 22 95 92 .SR....9 .}...".. +[1490] 97 97 3D 5E 66 0F AD DC C2 4E 2E 2B 9F 63 20 30 ..=^f... .N.+.c 0 +[14A0] DF B7 C1 D4 65 AA 6F 2D 10 24 07 20 8D 88 6E 4B ....e.o- .$. ..nK +[14B0] 09 04 31 B6 A3 EB F7 37 32 0E 0C 73 C6 F6 B8 4D ..1....7 2..s...M +[14C0] D9 0C 4C 5B EC 10 6A 51 19 EA 3F FF 46 E7 73 16 ..L[..jQ ..?.F.s. +[14D0] A7 1F 33 98 7C 9B AD 5A 23 A9 40 7C 0F DF EE 0F ..3.|..Z #.@|.... +[14E0] AA C7 E8 63 07 98 3A 4A 0D 18 62 01 21 B2 AE A5 ...c..:J ..b.!... +[14F0] 69 B0 C1 15 51 BA 97 D2 C5 42 5B C5 30 38 18 A9 i...Q... .B[.08.. +[1500] 48 AB D7 FC A1 BC 9F 71 E7 EA 18 54 42 DA D6 A4 H......q ...TB... +[1510] FC C1 DC F3 12 30 62 AC 98 E1 7D 2B 34 1E 52 4C .....0b. ..}+4.RL +[1520] 26 67 32 D9 44 1A 08 27 0E DA D0 FC 84 66 35 81 &g2.D..' .....f5. +[1530] D6 EB 98 46 6F 1E 47 E0 14 31 BE 47 80 65 AA 0B ...Fo.G. .1.G.e.. +[1540] 20 D6 33 36 3B 0D 40 2F 5A 2E 0E 01 BE 00 EB 33 .36;.@/ Z......3 +[1550] 3E 4B 32 91 F4 22 96 E5 5F D4 D5 92 94 CC 5B 59 >K2..".. _.....[Y +[1560] 6A 3E D2 FB A0 4F 99 C4 07 8B 6F 2B 14 37 CD 37 j>...O.. ..o+.7.7 +[1570] 44 C0 1F 80 9C 43 46 F2 5E F4 FE D3 39 70 61 BE D....CF. ^...9pa. +[1580] 72 5B 3A 8F 37 95 78 1E AB D9 E7 E9 DA FC 47 09 r[:.7.x. ......G. +[1590] 81 A0 0D 62 E1 F9 34 36 D1 DB E6 98 D8 F4 3E 77 ...b..46 ......>w +[15A0] 5A 4D E2 5F 20 70 3D 3D 5B 34 D9 FD A8 31 F7 D9 ZM._ p== [4...1.. +[15B0] 59 F7 A3 F0 66 F7 D9 AD 1C CD D5 85 33 A0 87 22 Y...f... ....3.." +[15C0] 31 D4 F3 67 80 68 20 A2 90 72 7A 6F 64 FD 68 82 1..g.h . .rzod.h. +[15D0] 9E 91 B8 E3 F7 6D 6C 38 74 F0 96 A2 F6 25 D7 92 .....ml8 t....%.. +[15E0] 58 14 60 9F AE 01 4C 0C 09 67 3E 35 67 71 1E 2A X.`...L. .g>5gq.* +[15F0] 86 21 D3 60 61 98 16 94 67 0B 52 76 63 93 BD A3 .!.`a... g.Rvc... +[1600] 3B A9 F0 A2 6A B7 E6 0F 35 64 DA 6A EA 20 A6 3D ;...j... 5d.j. .= +[1610] 94 71 59 5E CB B2 D3 F9 4D FE 1B 4B D8 64 C8 3B .qY^.... M..K.d.; +[1620] 7A A8 E6 D2 D5 76 71 26 D4 5C DA 1A 55 17 F2 16 z....vq& .\..U... +[1630] C9 2F 77 DB 95 19 48 A5 AC D0 C3 31 9C 0A CC 1B ./w...H. ...1.... +[1640] 44 11 6B 7C 88 7A 5D CF 6E 12 DA EF C5 C7 34 1D D.k|.z]. n.....4. +[1650] F4 CC EA 37 24 4B B3 0F C1 A3 F2 29 A0 D8 93 39 ...7$K.. ...)...9 +[1660] C6 16 57 D5 BF 57 BF 6C 7E F7 90 E0 EB A3 8B 07 ..W..W.l ~....... +[1670] 56 9C EC 15 3E 21 DA A5 7C 00 3C F9 D2 A7 1C 6F V...>!.. |.<....o +[1680] 16 25 31 C5 28 A7 EA F3 47 31 50 DD E1 ED 0A 93 .%1.(... G1P..... +[1690] DB 85 CC 6B 4B 2C 7F E8 F8 2D A9 6D 1D 0A 87 F2 ...kK,.. .-.m.... +[16A0] 10 8C 82 2F 9B D4 9B 92 8C 77 40 50 42 1E 42 C4 .../.... .w@PB.B. +[16B0] 0A 4F E3 6C 6C DC 81 C4 1E BB F0 7D CF 3C 73 22 .O.ll... ...}..xK.... +[16E0] 25 4A 92 1E 6C 8F 01 D6 59 D7 CF 2E A0 CC 98 F6 %J..l... Y....... +[16F0] 75 28 2F F7 2A 70 28 A9 45 1F 75 C2 4E 62 ED D8 u(/.*p(. E.u.Nb.. +[1700] C4 A0 8D 55 B2 84 1C A4 CE 87 EF 24 EE BC CE 40 ...U.... ...$...@ +[1710] 09 EB 05 0B D1 14 31 50 32 2F B6 A8 97 17 4B A7 ......1P 2/....K. +[1720] 95 01 50 6E 0E 23 49 9C 72 21 91 00 00 00 00 00 ..Pn.#I. r!...... +[1730] 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 54 ........ ...KTEST +[1740] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[1750] 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 61 OM....ad ministra +[1760] 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 4B tor..... .......K +[1770] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[1780] 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 73 00 00 LE.COM.. ..cifs.. +[1790] 00 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 00 17 00 ..LOCALK TEST6... +[17A0] 00 00 10 1D C8 5E 46 48 82 F9 29 DB C6 A6 F1 72 .....^FH ..)....r +[17B0] 6D 8D E9 4D 99 4F 6A 4D 99 85 09 7D 44 0B 68 00 m..M.OjM ...}D.h. +[17C0] 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 00 ....@(.. ........ +[17D0] 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 01 ....a... 0....... +[17E0] 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[17F0] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 1C .EXAMPLE .COM..0. +[1800] A0 03 02 01 01 A1 15 30 13 1B 04 63 69 66 73 1B .......0 ...cifs. +[1810] 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 A3 82 03 AE .LOCALKT EST6.... +[1820] 30 82 03 AA A0 03 02 01 17 A1 03 02 01 02 A2 82 0....... ........ +[1830] 03 9C 04 82 03 98 66 D8 19 46 FA CB 73 2D CF 88 ......f. .F..s-.. +[1840] FD 4A EE 07 48 DA 0E BC 58 30 43 40 A4 9C 00 0F .J..H... X0C@.... +[1850] 3B 17 C1 2D F5 9C 3E D9 2F 1D CA 01 9B D7 2E EC ;..-..>. /....... +[1860] D7 70 ED 8B 8B 1B 5E F2 4E EE DD 0F C0 8D 61 E5 .p....^. N.....a. +[1870] D7 0A 56 00 32 B1 DB 91 37 29 0F 2F 85 EE A8 43 ..V.2... 7)./...C +[1880] BA A5 B8 D4 19 74 33 F0 69 52 E1 58 98 83 D6 16 .....t3. iR.X.... +[1890] 0B 44 A9 63 9B D4 4E 6E A7 3E CD 9A 96 4D C4 96 .D.c..Nn .>...M.. +[18A0] F5 07 6D 29 B6 ED 2A 62 3D 53 22 33 D1 95 E9 DF ..m)..*b =S"3.... +[18B0] 74 4C 2A E2 29 AF 5B 69 B0 48 2D AD 94 FD A5 1D tL*.).[i .H-..... +[18C0] 54 D8 E2 5E C1 68 6F BA 02 01 79 C3 C9 97 0B 76 T..^.ho. ..y....v +[18D0] 66 45 E2 3B 10 17 95 40 46 E4 85 B9 87 BB CF CF fE.;...@ F....... +[18E0] 19 8C 3A C0 EA 38 3B B9 E9 4B 05 89 E5 27 8C 62 ..:..8;. .K...'.b +[18F0] 95 BC 0D 65 F0 D2 C0 5E BC 65 01 D5 0B CB 17 31 ...e...^ .e.....1 +[1900] 0F 06 49 4F A2 4A 70 77 DB BD 92 5B 37 5C EC 06 ..IO.Jpw ...[7\.. +[1910] DF C5 E2 31 C8 40 09 11 68 14 E7 7D CE 54 4F 52 ...1.@.. h..}.TOR +[1920] 61 31 2C 1C 53 52 DB BE D8 95 39 EE 7D C6 CE C8 a1,.SR.. ..9.}... +[1930] 22 95 92 97 97 3D 5E 66 0F AD DC C2 4E 2E 2B 9F "....=^f ....N.+. +[1940] 63 20 30 DF B7 C1 D4 65 AA 6F 2D 10 24 07 20 8D c 0....e .o-.$. . +[1950] 88 6E 4B 09 04 31 B6 A3 EB F7 37 32 0E 0C 73 C6 .nK..1.. ..72..s. +[1960] F6 B8 4D D9 0C 4C 5B EC 10 6A 51 19 EA 3F FF 46 ..M..L[. .jQ..?.F +[1970] E7 73 16 A7 1F 33 98 7C 9B AD 5A 23 A9 40 7C 0F .s...3.| ..Z#.@|. +[1980] DF EE 0F AA C7 E8 63 07 98 3A 4A 0D 18 62 01 21 ......c. .:J..b.! +[1990] B2 AE A5 69 B0 C1 15 51 BA 97 D2 C5 42 5B C5 30 ...i...Q ....B[.0 +[19A0] 38 18 A9 48 AB D7 FC A1 BC 9F 71 E7 EA 18 54 42 8..H.... ..q...TB +[19B0] DA D6 A4 FC C1 DC F3 12 30 62 AC 98 E1 7D 2B 34 ........ 0b...}+4 +[19C0] 1E 52 4C 26 67 32 D9 44 1A 08 27 0E DA D0 FC 84 .RL&g2.D ..'..... +[19D0] 66 35 81 D6 EB 98 46 6F 1E 47 E0 14 31 BE 47 80 f5....Fo .G..1.G. +[19E0] 65 AA 0B 20 D6 33 36 3B 0D 40 2F 5A 2E 0E 01 BE e.. .36; .@/Z.... +[19F0] 00 EB 33 3E 4B 32 91 F4 22 96 E5 5F D4 D5 92 94 ..3>K2.. ".._.... +[1A00] CC 5B 59 6A 3E D2 FB A0 4F 99 C4 07 8B 6F 2B 14 .[Yj>... O....o+. +[1A10] 37 CD 37 44 C0 1F 80 9C 43 46 F2 5E F4 FE D3 39 7.7D.... CF.^...9 +[1A20] 70 61 BE 72 5B 3A 8F 37 95 78 1E AB D9 E7 E9 DA pa.r[:.7 .x...... +[1A30] FC 47 09 81 A0 0D 62 E1 F9 34 36 D1 DB E6 98 D8 .G....b. .46..... +[1A40] F4 3E 77 5A 4D E2 5F 20 70 3D 3D 5B 34 D9 FD A8 .>wZM._ p==[4... +[1A50] 31 F7 D9 59 F7 A3 F0 66 F7 D9 AD 1C CD D5 85 33 1..Y...f .......3 +[1A60] A0 87 22 31 D4 F3 67 80 68 20 A2 90 72 7A 6F 64 .."1..g. h ..rzod +[1A70] FD 68 82 9E 91 B8 E3 F7 6D 6C 38 74 F0 96 A2 F6 .h...... ml8t.... +[1A80] 25 D7 92 58 14 60 9F AE 01 4C 0C 09 67 3E 35 67 %..X.`.. .L..g>5g +[1A90] 71 1E 2A 86 21 D3 60 61 98 16 94 67 0B 52 76 63 q.*.!.`a ...g.Rvc +[1AA0] 93 BD A3 3B A9 F0 A2 6A B7 E6 0F 35 64 DA 6A EA ...;...j ...5d.j. +[1AB0] 20 A6 3D 94 71 59 5E CB B2 D3 F9 4D FE 1B 4B D8 .=.qY^. ...M..K. +[1AC0] 64 C8 3B 7A A8 E6 D2 D5 76 71 26 D4 5C DA 1A 55 d.;z.... vq&.\..U +[1AD0] 17 F2 16 C9 2F 77 DB 95 19 48 A5 AC D0 C3 31 9C ..../w.. .H....1. +[1AE0] 0A CC 1B 44 11 6B 7C 88 7A 5D CF 6E 12 DA EF C5 ...D.k|. z].n.... +[1AF0] C7 34 1D F4 CC EA 37 24 4B B3 0F C1 A3 F2 29 A0 .4....7$ K.....). +[1B00] D8 93 39 C6 16 57 D5 BF 57 BF 6C 7E F7 90 E0 EB ..9..W.. W.l~.... +[1B10] A3 8B 07 56 9C EC 15 3E 21 DA A5 7C 00 3C F9 D2 ...V...> !..|.<.. +[1B20] A7 1C 6F 16 25 31 C5 28 A7 EA F3 47 31 50 DD E1 ..o.%1.( ...G1P.. +[1B30] ED 0A 93 DB 85 CC 6B 4B 2C 7F E8 F8 2D A9 6D 1D ......kK ,...-.m. +[1B40] 0A 87 F2 10 8C 82 2F 9B D4 9B 92 8C 77 40 50 42 ....../. ....w@PB +[1B50] 1E 42 C4 0A 4F E3 6C 6C DC 81 C4 1E BB F0 7D CF .B..O.ll ......}. +[1B60] 3C 73 22 5B C3 1A 97 35 EE 3A CD 6D F3 68 A3 C5 .xK. +[1B80] 18 9F A5 25 4A 92 1E 6C 8F 01 D6 59 D7 CF 2E A0 ...%J..l ...Y.... +[1B90] CC 98 F6 75 28 2F F7 2A 70 28 A9 45 1F 75 C2 4E ...u(/.* p(.E.u.N +[1BA0] 62 ED D8 C4 A0 8D 55 B2 84 1C A4 CE 87 EF 24 EE b.....U. ......$. +[1BB0] BC CE 40 09 EB 05 0B D1 14 31 50 32 2F B6 A8 97 ..@..... .1P2/... +[1BC0] 17 4B A7 95 01 50 6E 0E 23 49 9C 72 21 91 00 00 .K...Pn. #I.r!... +[1BD0] 00 00 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 ........ ......KT +[1BE0] 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C EST.SAMB A.EXAMPL +[1BF0] 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 E.COM... .adminis +[1C00] 74 72 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 trator.. ........ +[1C10] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[1C20] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 63 69 66 AMPLE.CO M....cif +[1C30] 73 00 00 00 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 s....LOC ALKTEST6 +[1C40] 00 17 00 00 00 10 1D C8 5E 46 48 82 F9 29 DB C6 ........ ^FH..).. +[1C50] A6 F1 72 6D 8D E9 4D 99 4F 6A 4D 99 85 09 7D 44 ..rm..M. OjM...}D +[1C60] 0B 68 00 00 00 00 00 40 28 00 00 00 00 00 00 00 .h.....@ (....... +[1C70] 00 00 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 .......a ...0.... +[1C80] 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[1C90] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 MBA.EXAM PLE.COM. +[1CA0] 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B 04 63 69 .0...... ..0...ci +[1CB0] 66 73 1B 0B 4C 4F 43 41 4C 4B 54 45 53 54 36 A3 fs..LOCA LKTEST6. +[1CC0] 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 ...0.... ........ +[1CD0] 02 A2 82 03 9C 04 82 03 98 66 D8 19 46 FA CB 73 ........ .f..F..s +[1CE0] 2D CF 88 FD 4A EE 07 48 DA 0E BC 58 30 43 40 A4 -...J..H ...X0C@. +[1CF0] 9C 00 0F 3B 17 C1 2D F5 9C 3E D9 2F 1D CA 01 9B ...;..-. .>./.... +[1D00] D7 2E EC D7 70 ED 8B 8B 1B 5E F2 4E EE DD 0F C0 ....p... .^.N.... +[1D10] 8D 61 E5 D7 0A 56 00 32 B1 DB 91 37 29 0F 2F 85 .a...V.2 ...7)./. +[1D20] EE A8 43 BA A5 B8 D4 19 74 33 F0 69 52 E1 58 98 ..C..... t3.iR.X. +[1D30] 83 D6 16 0B 44 A9 63 9B D4 4E 6E A7 3E CD 9A 96 ....D.c. .Nn.>... +[1D40] 4D C4 96 F5 07 6D 29 B6 ED 2A 62 3D 53 22 33 D1 M....m). .*b=S"3. +[1D50] 95 E9 DF 74 4C 2A E2 29 AF 5B 69 B0 48 2D AD 94 ...tL*.) .[i.H-.. +[1D60] FD A5 1D 54 D8 E2 5E C1 68 6F BA 02 01 79 C3 C9 ...T..^. ho...y.. +[1D70] 97 0B 76 66 45 E2 3B 10 17 95 40 46 E4 85 B9 87 ..vfE.;. ..@F.... +[1D80] BB CF CF 19 8C 3A C0 EA 38 3B B9 E9 4B 05 89 E5 .....:.. 8;..K... +[1D90] 27 8C 62 95 BC 0D 65 F0 D2 C0 5E BC 65 01 D5 0B '.b...e. ..^.e... +[1DA0] CB 17 31 0F 06 49 4F A2 4A 70 77 DB BD 92 5B 37 ..1..IO. Jpw...[7 +[1DB0] 5C EC 06 DF C5 E2 31 C8 40 09 11 68 14 E7 7D CE \.....1. @..h..}. +[1DC0] 54 4F 52 61 31 2C 1C 53 52 DB BE D8 95 39 EE 7D TORa1,.S R....9.} +[1DD0] C6 CE C8 22 95 92 97 97 3D 5E 66 0F AD DC C2 4E ...".... =^f....N +[1DE0] 2E 2B 9F 63 20 30 DF B7 C1 D4 65 AA 6F 2D 10 24 .+.c 0.. ..e.o-.$ +[1DF0] 07 20 8D 88 6E 4B 09 04 31 B6 A3 EB F7 37 32 0E . ..nK.. 1....72. +[1E00] 0C 73 C6 F6 B8 4D D9 0C 4C 5B EC 10 6A 51 19 EA .s...M.. L[..jQ.. +[1E10] 3F FF 46 E7 73 16 A7 1F 33 98 7C 9B AD 5A 23 A9 ?.F.s... 3.|..Z#. +[1E20] 40 7C 0F DF EE 0F AA C7 E8 63 07 98 3A 4A 0D 18 @|...... .c..:J.. +[1E30] 62 01 21 B2 AE A5 69 B0 C1 15 51 BA 97 D2 C5 42 b.!...i. ..Q....B +[1E40] 5B C5 30 38 18 A9 48 AB D7 FC A1 BC 9F 71 E7 EA [.08..H. .....q.. +[1E50] 18 54 42 DA D6 A4 FC C1 DC F3 12 30 62 AC 98 E1 .TB..... ...0b... +[1E60] 7D 2B 34 1E 52 4C 26 67 32 D9 44 1A 08 27 0E DA }+4.RL&g 2.D..'.. +[1E70] D0 FC 84 66 35 81 D6 EB 98 46 6F 1E 47 E0 14 31 ...f5... .Fo.G..1 +[1E80] BE 47 80 65 AA 0B 20 D6 33 36 3B 0D 40 2F 5A 2E .G.e.. . 36;.@/Z. +[1E90] 0E 01 BE 00 EB 33 3E 4B 32 91 F4 22 96 E5 5F D4 .....3>K 2..".._. +[1EA0] D5 92 94 CC 5B 59 6A 3E D2 FB A0 4F 99 C4 07 8B ....[Yj> ...O.... +[1EB0] 6F 2B 14 37 CD 37 44 C0 1F 80 9C 43 46 F2 5E F4 o+.7.7D. ...CF.^. +[1EC0] FE D3 39 70 61 BE 72 5B 3A 8F 37 95 78 1E AB D9 ..9pa.r[ :.7.x... +[1ED0] E7 E9 DA FC 47 09 81 A0 0D 62 E1 F9 34 36 D1 DB ....G... .b..46.. +[1EE0] E6 98 D8 F4 3E 77 5A 4D E2 5F 20 70 3D 3D 5B 34 ....>wZM ._ p==[4 +[1EF0] D9 FD A8 31 F7 D9 59 F7 A3 F0 66 F7 D9 AD 1C CD ...1..Y. ..f..... +[1F00] D5 85 33 A0 87 22 31 D4 F3 67 80 68 20 A2 90 72 ..3.."1. .g.h ..r +[1F10] 7A 6F 64 FD 68 82 9E 91 B8 E3 F7 6D 6C 38 74 F0 zod.h... ...ml8t. +[1F20] 96 A2 F6 25 D7 92 58 14 60 9F AE 01 4C 0C 09 67 ...%..X. `...L..g +[1F30] 3E 35 67 71 1E 2A 86 21 D3 60 61 98 16 94 67 0B >5gq.*.! .`a...g. +[1F40] 52 76 63 93 BD A3 3B A9 F0 A2 6A B7 E6 0F 35 64 Rvc...;. ..j...5d +[1F50] DA 6A EA 20 A6 3D 94 71 59 5E CB B2 D3 F9 4D FE .j. .=.q Y^....M. +[1F60] 1B 4B D8 64 C8 3B 7A A8 E6 D2 D5 76 71 26 D4 5C .K.d.;z. ...vq&.\ +[1F70] DA 1A 55 17 F2 16 C9 2F 77 DB 95 19 48 A5 AC D0 ..U..../ w...H... +[1F80] C3 31 9C 0A CC 1B 44 11 6B 7C 88 7A 5D CF 6E 12 .1....D. k|.z].n. +[1F90] DA EF C5 C7 34 1D F4 CC EA 37 24 4B B3 0F C1 A3 ....4... .7$K.... +[1FA0] F2 29 A0 D8 93 39 C6 16 57 D5 BF 57 BF 6C 7E F7 .)...9.. W..W.l~. +[1FB0] 90 E0 EB A3 8B 07 56 9C EC 15 3E 21 DA A5 7C 00 ......V. ..>!..|. +[1FC0] 3C F9 D2 A7 1C 6F 16 25 31 C5 28 A7 EA F3 47 31 <....o.% 1.(...G1 +[1FD0] 50 DD E1 ED 0A 93 DB 85 CC 6B 4B 2C 7F E8 F8 2D P....... .kK,...- +[1FE0] A9 6D 1D 0A 87 F2 10 8C 82 2F 9B D4 9B 92 8C 77 .m...... ./.....w +[1FF0] 40 50 42 1E 42 C4 0A 4F E3 6C 6C DC 81 C4 1E BB @PB.B..O .ll..... +[2000] F0 7D CF 3C 73 22 5B C3 1A 97 35 EE 3A CD 6D F3 .}.. +[2020] 78 4B BF 18 9F A5 25 4A 92 1E 6C 8F 01 D6 59 D7 xK....%J ..l...Y. +[2030] CF 2E A0 CC 98 F6 75 28 2F F7 2A 70 28 A9 45 1F ......u( /.*p(.E. +[2040] 75 C2 4E 62 ED D8 C4 A0 8D 55 B2 84 1C A4 CE 87 u.Nb.... .U...... +[2050] EF 24 EE BC CE 40 09 EB 05 0B D1 14 31 50 32 2F .$...@.. ....1P2/ +[2060] B6 A8 97 17 4B A7 95 01 50 6E 0E 23 49 9C 72 21 ....K... Pn.#I.r! +[2070] 91 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ........ ........ +[2080] 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 .KTEST.S AMBA.EXA +[2090] 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D 69 MPLE.COM ....admi +[20A0] 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 00 nistrato r....... +[20B0] 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[20C0] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 04 .EXAMPLE .COM.... +[20D0] 68 6F 73 74 00 00 00 0B 6C 6F 63 61 6C 6B 74 65 host.... localkte +[20E0] 73 74 36 00 17 00 00 00 10 72 47 04 38 B6 E6 F0 st6..... .rG.8... +[20F0] 44 9E 9F 27 66 E1 69 9C 9A 4D 99 4F 6A 4D 99 90 D..'f.i. .M.OjM.. +[2100] F5 7D 44 0B 68 00 00 00 00 00 40 28 00 00 00 00 .}D.h... ..@(.... +[2110] 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 82 ........ ..a...0. +[2120] 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 54 ........ ...KTEST +[2130] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[2140] 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 1B OM..0... .....0.. +[2150] 04 68 6F 73 74 1B 0B 6C 6F 63 61 6C 6B 74 65 73 .host..l ocalktes +[2160] 74 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 A1 t6....0. ........ +[2170] 03 02 01 02 A2 82 03 9C 04 82 03 98 58 95 95 EB ........ ....X... +[2180] CB 8F 68 D4 77 43 0F 3B 44 B4 15 DA 40 6D FD E9 ..h.wC.; D...@m.. +[2190] 85 D3 2F CD B5 1E 96 CD F6 E9 67 91 36 08 9E B4 ../..... ..g.6... +[21A0] B3 47 70 7A B3 4E 82 5A 4F 8E 4B F5 8D 04 E4 5C .Gpz.N.Z O.K....\ +[21B0] C4 D8 0C AF 08 25 F9 C1 64 B2 3A 35 26 E9 B2 72 .....%.. d.:5&..r +[21C0] 66 B5 E9 81 FC BE 12 1B CC 8A A5 82 31 F6 7F C3 f....... ....1... +[21D0] 5A 19 A3 31 F2 99 14 1E 64 E4 41 E8 C7 C3 F3 DF Z..1.... d.A..... +[21E0] F5 65 7D B0 9F DC 5D 25 1D 1A A8 EA AA 88 6D F4 .e}...]% ......m. +[21F0] 7C 25 9F 53 F6 A6 8F B1 24 AF 98 FE 53 7B 35 3C |%.S.... $...S{5< +[2200] DB EC 7F 09 74 E9 C4 8D 20 B4 47 08 0E 32 B8 C9 ....t... .G..2.. +[2210] 45 27 12 F9 8E F5 D6 C2 DD 1A 96 0E 68 5F 39 65 E'...... ....h_9e +[2220] 72 C7 BD 8E 04 0E 13 E1 03 27 AC 50 80 76 E6 7A r....... .'.P.v.z +[2230] 8E F4 C2 72 4F 68 B3 34 00 A9 54 41 DA FD 96 94 ...rOh.4 ..TA.... +[2240] 29 A1 59 15 2F DB 6C 94 85 49 C5 D0 6D 48 B0 C4 ).Y./.l. .I..mH.. +[2250] 65 D0 95 1D DB 3D 25 D0 75 50 D4 CF FA 2F 71 57 e....=%. uP.../qW +[2260] BD 6C 1C 59 E1 C3 5B C7 24 95 FF B0 20 EF 6A DB .l.Y..[. $... .j. +[2270] 79 87 67 91 94 E9 16 E2 BB 74 7A 08 E1 6A 36 5F y.g..... .tz..j6_ +[2280] DF 11 AB 35 9B 3E 32 48 83 89 41 4E 06 BF F9 BB ...5.>2H ..AN.... +[2290] EC E4 D7 6D 77 C4 55 22 DF F7 91 4D CB C5 01 A5 ...mw.U" ...M.... +[22A0] BA 2D 1E 92 76 04 E8 02 2F 5E AF 1C B3 B7 A6 FB .-..v... /^...... +[22B0] 3A 9F D9 7C 6D DA B4 8F 31 00 A5 30 F2 76 72 9B :..|m... 1..0.vr. +[22C0] 62 97 E0 56 E5 E4 C7 6B 8B FC 84 75 57 66 6E D7 b..V...k ...uWfn. +[22D0] B7 41 6F 61 F4 5B 0F 87 68 F6 54 02 26 1B 1F B7 .Aoa.[.. h.T.&... +[22E0] 60 D6 E7 FA 4F C7 DB 35 58 EC 13 21 D4 C6 A1 27 `...O..5 X..!...' +[22F0] BA E7 82 DF 29 FB 9D 5D E8 35 28 C9 9C 4E D7 BE ....)..] .5(..N.. +[2300] 2F 6D F1 E8 0B 5A 74 C9 93 9F AD 42 24 4B B7 3B /m...Zt. ...B$K.; +[2310] 38 2A 11 CF F0 BD 85 40 48 D8 9D E7 6B 65 70 42 8*.....@ H...kepB +[2320] 60 DA 9B 65 CB C8 C5 D7 40 3A 12 DC 64 AF 82 54 `..e.... @:..d..T +[2330] 34 05 38 4F C6 FB 38 E2 73 A9 89 B7 FC 33 15 85 4.8O..8. s....3.. +[2340] 9E CA E9 E0 89 18 18 84 02 65 B4 74 5B D4 A1 6F ........ .e.t[..o +[2350] 5F 79 20 CB D7 36 C8 6D 5B 1E 5E 0C 82 16 9F CC _y ..6.m [.^..... +[2360] 5A 1E 57 C1 B6 94 51 87 A1 3D 12 D4 8B FE 0F 93 Z.W...Q. .=...... +[2370] ED 53 A3 F4 88 3C 35 05 89 FE AF 0B 36 62 E3 2F .S...<5. ....6b./ +[2380] 5C 4A 0E 07 67 39 A3 8E C0 45 07 7F 73 32 BC DE \J..g9.. .E..s2.. +[2390] 2D 00 8B 47 79 3D 1C A1 90 AE B6 8F 83 B2 1B 31 -..Gy=.. .......1 +[23A0] EE E4 F2 C5 C1 4A E2 4A 2F 28 F0 AA 19 43 6A 14 .....J.J /(...Cj. +[23B0] B1 42 61 90 34 2E EE 3D 16 9F 5D 9F 7A A2 01 7A .Ba.4..= ..].z..z +[23C0] 4B 96 FA 4D C9 85 1A 75 27 B7 6B FD 4D 7D 9C 65 K..M...u '.k.M}.e +[23D0] 97 DB 05 CC 76 68 EA 05 5D 5D BB BD 51 4B 5B F2 ....vh.. ]]..QK[. +[23E0] 48 59 BD 1E AD 56 D4 69 A5 75 CD ED EC B1 3E AB HY...V.i .u....>. +[23F0] FA B7 F8 8D 4F BE 95 63 38 1C 4C 70 26 C4 3A 21 ....O..c 8.Lp&.:! +[2400] 80 61 05 3A D4 E2 28 2C 85 01 5A DA FC 10 60 F3 .a.:..(, ..Z...`. +[2410] 74 0C FD DB 2F 5B 25 4B 14 E4 7D 8A DB 85 12 D2 t.../[%K ..}..... +[2420] D7 69 CD B5 B1 93 CE E5 E6 4D 57 D3 C2 D3 2E A0 .i...... .MW..... +[2430] 08 37 09 CD 19 99 09 FA 33 68 4A E0 92 46 21 0C .7...... 3hJ..F!. +[2440] 99 9F DA 05 15 20 8B 3D 7C 7B CA D6 81 AC AA 83 ..... .= |{...... +[2450] 48 C8 24 4C C8 FC A5 14 2C BC 49 1A 1C 49 61 1D H.$L.... ,.I..Ia. +[2460] 24 86 42 B1 37 6A C8 3A AC 18 CC C0 50 84 12 48 $.B.7j.: ....P..H +[2470] 8B 29 0A 49 26 A4 E2 B9 E5 96 E7 37 C3 DE 4C 23 .).I&... ...7..L# +[2480] D2 D4 62 14 8F 1E 72 39 CF 03 BC A3 00 C7 63 51 ..b...r9 ......cQ +[2490] A9 6B E4 3E B2 65 A1 A2 BB EC 06 41 85 50 22 02 .k.>.e.. ...A.P". +[24A0] 46 2F 72 2B 32 1A A4 2D 85 94 02 47 69 8D AD 6D F/r+2..- ...Gi..m +[24B0] 66 AB D4 E4 29 C8 C7 DA F4 18 31 2A DF 50 6A 05 f...)... ..1*.Pj. +[24C0] D6 47 26 C4 F9 87 0F 35 24 6E 72 D6 23 7D 3A 94 .G&....5 $nr.#}:. +[24D0] 14 8D E8 57 AA BA D7 CF A9 2D E7 4C 10 7C D8 0D ...W.... .-.L.|.. +[24E0] 51 30 1F E1 FB E5 E2 6C EE AA 65 2F D8 22 05 67 Q0.....l ..e/.".g +[24F0] 87 4D 4D D2 11 3D B4 1E AA 20 3F 76 E3 94 93 6D .MM..=.. . ?v...m +[2500] AC 10 05 AF 09 BD 67 86 C5 83 93 D6 1C D3 81 D9 ......g. ........ +[2510] B1 3B E1 76 00 00 00 00 00 00 00 01 00 00 00 01 .;.v.... ........ +[2520] 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E ....KTES T.SAMBA. +[2530] 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 EXAMPLE. COM....a +[2540] 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 dministr ator.... +[2550] 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 ........ KTEST.SA +[2560] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 MBA.EXAM PLE.COM. +[2570] 00 00 04 68 6F 73 74 00 00 00 0B 4C 4F 43 41 4C ...host. ...LOCAL +[2580] 4B 54 45 53 54 36 00 17 00 00 00 10 55 6E 3E FC KTEST6.. ....Un>. +[2590] E2 F4 40 51 19 E6 6E EB 23 4C 48 8E 4D 99 4F 6A ..@Q..n. #LH.M.Oj +[25A0] 4D 99 90 FC 7D 44 0B 68 00 00 00 00 00 40 28 00 M...}D.h .....@(. +[25B0] 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 ........ .....a.. +[25C0] F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 .0...... ......KT +[25D0] 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C EST.SAMB A.EXAMPL +[25E0] 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 E.COM..0 ........ +[25F0] 30 13 1B 04 68 6F 73 74 1B 0B 4C 4F 43 41 4C 4B 0...host ..LOCALK +[2600] 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 02 TEST6... .0...... +[2610] 01 17 A1 03 02 01 02 A2 82 03 9C 04 82 03 98 6E ........ .......n +[2620] 87 B7 7B 3A 7E EF 4A 1B 29 C9 E3 C4 1F 42 4F 0E ..{:~.J. )....BO. +[2630] C8 AC AC 4E A2 77 1D DA 93 37 F1 AF DA A3 75 2D ...N.w.. .7....u- +[2640] 12 8B 40 34 23 0E 8E A9 90 58 46 42 42 39 31 D6 ..@4#... .XFBB91. +[2650] 03 9E 5D 81 D9 E8 F6 08 2B D9 96 88 8A 2F F1 CC ..]..... +..../.. +[2660] F2 EA 9E 9A 4B 31 B6 04 2D 3D 4C 7F 92 DE 3B 04 ....K1.. -=L...;. +[2670] 19 EE 28 D0 83 81 C3 46 CD 74 23 4C 14 34 DE 62 ..(....F .t#L.4.b +[2680] 0A AC E5 12 16 75 E9 A8 4B 32 78 CC 8D AE A2 E5 .....u.. K2x..... +[2690] 6D E8 09 70 76 52 F5 E5 18 F7 E7 91 15 6A 69 AB m..pvR.. .....ji. +[26A0] B8 62 DD 80 F5 28 6D DF ED 10 DA AC FB 92 27 CF .b...(m. ......'. +[26B0] 98 B5 77 9D A5 96 E6 9A CC B9 C3 91 78 22 35 9C ..w..... ....x"5. +[26C0] A1 13 A3 20 28 D1 16 E5 3E 4A 85 1E 12 0B CA 4D ... (... >J.....M +[26D0] C6 C8 03 C8 28 2C D8 29 5D 9A 76 4A 92 13 43 56 ....(,.) ].vJ..CV +[26E0] AF F7 C1 71 25 72 5C 38 75 1C 07 F1 5E 86 05 72 ...q%r\8 u...^..r +[26F0] 6F 69 95 42 B6 F2 DA A9 91 06 9F B9 54 20 33 A5 oi.B.... ....T 3. +[2700] 31 60 3B 54 DC 3A 95 34 96 26 07 52 6B 0E 1D 3B 1`;T.:.4 .&.Rk..; +[2710] D9 F8 48 20 AC CD 05 3B 99 F8 EE DB 83 28 CD C7 ..H ...; .....(.. +[2720] 2F 45 00 7E 2F 0A 65 7A D1 9E 95 4B EE C3 34 93 /E.~/.ez ...K..4. +[2730] A8 C7 DF 03 8B 14 D0 FC CE 56 90 AC EE 93 C5 D3 ........ .V...... +[2740] F7 12 24 69 0B 20 8D A2 65 87 55 26 2A F9 9A 88 ..$i. .. e.U&*... +[2750] D7 0D 86 61 D6 92 B6 FE E5 D1 66 F9 1F 9D F4 04 ...a.... ..f..... +[2760] 48 A6 39 BC 54 20 EA 10 21 E9 6D 30 46 1D C2 1C H.9.T .. !.m0F... +[2770] A4 E8 B4 63 85 37 27 25 80 52 41 60 C7 A1 32 21 ...c.7'% .RA`..2! +[2780] 43 90 02 E6 5F 5A E9 4E AF F9 B5 13 BD 42 BD A3 C..._Z.N .....B.. +[2790] A5 4D 10 45 83 4D 92 18 1F C9 CF FB 84 29 89 23 .M.E.M.. .....).# +[27A0] AC 71 4B 89 1B 52 E5 06 8C 3E 7C 88 CB D3 B3 CF .qK..R.. .>|..... +[27B0] B9 7A 67 D6 24 F4 AC 00 A6 AD 91 30 9A 95 53 F1 .zg.$... ...0..S. +[27C0] 48 06 A6 39 DB CF DC 9D C9 55 76 26 5E C1 DB 5D H..9.... .Uv&^..] +[27D0] B3 5B 3E AE 1A A0 10 BA 82 21 83 44 02 E0 99 33 .[>..... .!.D...3 +[27E0] 40 BA 29 9E 28 E5 73 4C 23 94 A2 4F BF 07 ED 4F @.).(.sL #..O...O +[27F0] 7C 45 9B 30 C8 41 6B 0A 55 13 6E F5 AD 7A 0C B2 |E.0.Ak. U.n..z.. +[2800] EA FF D0 06 13 4D F3 24 82 7F F6 51 2F 4A 4F 0D .....M.$ ...Q/JO. +[2810] 37 F8 14 6B E9 E4 82 BB 3A 75 63 63 12 E8 78 6F 7..k.... :ucc..xo +[2820] 6F FC 6C D3 4B A6 F1 CC 2A F1 7D EB 82 26 2F D0 o.l.K... *.}..&/. +[2830] A1 8B 3E 9A 71 D7 91 D3 08 E6 FD 62 1B 84 13 2D ..>.q... ...b...- +[2840] 8E A0 A0 C3 85 78 2F 0D F8 E7 10 FC CB 05 A7 B9 .....x/. ........ +[2850] 9A 33 90 B5 9B 26 E3 23 98 B0 91 4B EB 32 37 D6 .3...&.# ...K.27. +[2860] F4 ED 61 08 D8 75 CC 03 83 2C 3C CF 21 63 9C F6 ..a..u.. .,<.!c.. +[2870] AF 5B 4F 12 07 74 17 CD 98 BB E7 5E C7 17 2D C4 .[O..t.. ...^..-. +[2880] 87 A4 74 6D 5E CE DB A3 01 B9 AD 20 73 38 78 22 ..tm^... ... s8x" +[2890] 3D 45 F5 51 77 C6 47 63 45 61 81 D9 FF 31 90 C4 =E.Qw.Gc Ea...1.. +[28A0] 6F 5A F8 FE 6A 56 5B D4 EE EC 49 C7 A7 51 AE 5C oZ..jV[. ..I..Q.\ +[28B0] 85 53 70 3D 1A 49 83 59 CF 65 58 B3 48 7E 04 9E .Sp=.I.Y .eX.H~.. +[28C0] C7 64 8A 05 73 E3 DC 1A 65 5D 4F 41 01 56 73 90 .d..s... e]OA.Vs. +[28D0] 61 F3 84 1F FF CF 46 B2 06 46 56 97 93 B9 DB 32 a.....F. .FV....2 +[28E0] 2A 64 8A 48 02 05 84 E9 FA 76 8B 94 96 89 A0 73 *d.H.... .v.....s +[28F0] 20 75 4D 52 1D 23 13 D1 83 D7 5D 59 23 6A 87 C1 uMR.#.. ..]Y#j.. +[2900] 09 3E 01 3A 28 65 42 8C 35 F1 91 EA 6A 1F 83 0D .>.:(eB. 5...j... +[2910] 8F 57 69 81 D4 A2 D2 EA 0C BF AF 95 A3 F4 90 15 .Wi..... ........ +[2920] 61 34 F2 6C 8B D0 DA B5 1E 43 AC CE C7 8A 1B 2B a4.l.... .C.....+ +[2930] 29 2B 89 1C C5 53 C8 04 F7 1E 46 72 F3 A8 CE F7 )+...S.. ..Fr.... +[2940] 59 76 55 E7 53 1C A2 9F D8 23 F7 EA 71 B0 74 83 YvU.S... .#..q.t. +[2950] 71 95 3E DC A6 FA 2D A4 42 13 93 8B 2B FA A2 70 q.>...-. B...+..p +[2960] 25 21 2D F6 E1 26 56 DF 58 79 25 16 E8 C9 03 EC %!-..&V. Xy%..... +[2970] 72 5F 35 CF 59 6B E1 AD 85 85 7B AB 78 F2 0D AC r_5.Yk.. ..{.x... +[2980] AB 89 F2 DA 85 E7 DE 09 77 99 EC 7C F3 97 1F 71 ........ w..|...q +[2990] 3C DB 09 44 7A 3C 69 E5 03 B0 6D 4D 3B 6B 4C D5 <..Dz.B].]} +[00E0] 0B 1F C3 88 2A 93 40 F9 E9 18 7D 3F 73 DA AC 1F ....*.@. ..}?s... +[00F0] E7 7B C3 B8 14 56 C3 63 86 5B AF C9 C3 21 9F 94 .{...V.c .[...!.. +[0100] B4 67 06 60 7F 56 2D F4 C7 22 CD B4 1C 14 B7 5B .g.`.V-. .".....[ +[0110] 26 67 9D 18 28 B5 5D C2 FC 13 B6 CA 9F AB CD 32 &g..(.]. .......2 +[0120] 71 D5 51 5F A2 11 5A 5D 4A B3 3B 1D D1 6B 4F 7D q.Q_..Z] J.;..kO} +[0130] E9 54 F0 B4 AC 80 DE 27 80 C5 64 3C 0B 22 79 1C .T.....' ..d<."y. +[0140] 9E D1 58 A1 3E 20 5A 9F E3 34 49 D8 16 C6 6B 2D ..X.> Z. .4I...k- +[0150] 36 0E E2 C2 3F 44 DE 63 32 DB EB 78 50 A2 6F 37 6...?D.c 2..xP.o7 +[0160] 05 2B 13 D4 31 07 D4 2A C0 53 B1 30 39 79 C3 D8 .+..1..* .S.09y.. +[0170] C4 4C 30 97 E8 F9 DA ED 10 B0 D0 21 71 8B 56 F3 .L0..... ...!q.V. +[0180] 0F 3A 2D 26 A2 3D AD 70 27 82 95 59 0A D7 7D 4E .:-&.=.p '..Y..}N +[0190] 2D 76 96 4D 94 70 2A BB 26 3B 7E FC E1 59 5A 55 -v.M.p*. &;~..YZU +[01A0] 04 A2 DA 27 AD 46 70 45 43 C0 FB C1 42 7F F0 CB ...'.FpE C...B... +[01B0] 21 D2 CD 54 35 7C 60 13 EE BB BB 60 6B 91 2B BE !..T5|`. ...`k.+. +[01C0] 91 8A CF 49 29 F8 60 D1 AB A5 51 B5 5E 4B B2 3A ...I).`. ..Q.^K.: +[01D0] F4 56 3A 89 2D 88 D0 73 08 A6 FB D8 6E B3 B1 4E .V:.-..s ....n..N +[01E0] D8 90 27 58 D2 53 40 B2 A0 3C 40 4D E9 21 C6 83 ..'X.S@. .<@M.!.. +[01F0] FC 15 14 F0 8C 08 46 C5 29 14 E3 84 CC 2C 56 C9 ......F. )....,V. +[0200] 20 53 45 34 D0 BE E0 CC F7 F1 15 D4 D4 B1 3C 43 SE4.... .......BT.Ba +[03A0] C5 22 B7 AE 51 76 8F 12 83 7F E1 9F 97 D8 31 38 ."..Qv.. ......18 +[03B0] A6 B9 11 B4 E1 BA 19 5B E4 A5 A3 6F 4B B3 03 93 .......[ ...oK... +[03C0] 4C D6 1E 08 FC 94 D1 C5 7C AA 95 EB 9C 7A C2 57 L....... |....z.W +[03D0] 60 CA 17 FF 8E 66 80 76 CB 35 46 26 C3 BD CA 83 `....f.v .5F&.... +[03E0] F0 04 08 0D 4C 5D B2 E4 7C 1C 82 28 D7 2C 42 B1 ....L].. |..(.,B. +[03F0] 36 72 60 5E 26 4A 79 D0 41 94 3C 2C 65 0E 32 18 6r`^&Jy. A.<,e.2. +[0400] B8 56 26 9D D3 84 78 BB .V&...x. + second_ticket : DATA_BLOB length=0 + further_creds : DATA_BLOB length=4748 +[0000] 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 ........ ....KTES +[0010] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0020] 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 COM....a dministr +[0030] 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 ator.... ........ +[0040] 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D KTEST.SA MBA.EXAM +[0050] 50 4C 45 2E 43 4F 4D 00 00 00 04 68 6F 73 74 00 PLE.COM. ...host. +[0060] 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 00 17 ...local ktest6.. +[0070] 00 00 00 10 EA 0D 3A 24 41 21 F7 7D 7D A3 C5 BB ......:$ A!.}}... +[0080] A4 88 F6 17 4D 9B 90 45 4D 9B 90 52 7D 46 4C 43 ....M..E M..R}FLC +[0090] 00 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 .....@(. ........ +[00A0] 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 .....a.. .0...... +[00B0] 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[00C0] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 A.EXAMPL E.COM..0 +[00D0] 1C A0 03 02 01 01 A1 15 30 13 1B 04 68 6F 73 74 ........ 0...host +[00E0] 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 A3 82 03 ..localk test6... +[00F0] AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 03 A2 .0...... ........ +[0100] 82 03 9C 04 82 03 98 44 8B C4 7D BA 9F FE 59 F6 .......D ..}...Y. +[0110] C1 DF 62 89 02 A4 55 54 AB D6 D6 2E 8B 5E 35 3D ..b...UT .....^5= +[0120] D9 46 9D 8B 49 93 A6 66 5F 1A 8B 81 AD 09 19 E9 .F..I..f _....... +[0130] 59 CE 58 18 50 63 4A A6 7D 6F 71 21 51 4A 41 C2 Y.X.PcJ. }oq!QJA. +[0140] A1 FE B0 D5 0A 3D 38 9F E5 3B 72 A2 7A 59 22 A4 .....=8. .;r.zY". +[0150] B7 1C A3 8D DB EA 5D A5 E2 D3 1D AE 42 D0 7F 75 ......]. ....B..u +[0160] B5 E9 ED B5 04 7B 67 1E 28 90 7D 3D 1A 3E F6 62 .....{g. (.}=.>.b +[0170] D0 A1 56 89 28 76 5C 19 1A FD 66 E5 F2 86 E7 58 ..V.(v\. ..f....X +[0180] 93 31 90 C5 CD F8 71 96 56 21 15 13 F0 EA C2 CC .1....q. V!...... +[0190] 48 4C B4 50 EF F9 81 44 29 8A 75 C4 31 75 D1 BA HL.P...D ).u.1u.. +[01A0] E2 0B 05 B2 E0 EA 64 3A 11 45 84 3D 69 55 FF E6 ......d: .E.=iU.. +[01B0] 32 7E C9 CA C4 28 E8 40 B6 5E F9 26 0F 09 12 1F 2~...(.@ .^.&.... +[01C0] 1F D4 9C 9A 50 E8 B7 6D F8 4F 55 6E 2A D4 AC 6A ....P..m .OUn*..j +[01D0] 79 D1 C2 2A 88 99 F8 39 75 36 F1 2D C7 89 0A C6 y..*...9 u6.-.... +[01E0] B4 C7 A1 7B F1 BF 22 87 A4 B2 93 22 54 A1 72 25 ...{..". ..."T.r% +[01F0] AF 67 FE 20 D5 C8 29 47 28 FF 51 FB F9 4E 2C 17 .g. ..)G (.Q..N,. +[0200] 10 BE 2E 13 8B 18 BE 3C A3 BE 50 49 A7 65 DD 2E .......< ..PI.e.. +[0210] CC EB D6 0F 47 4E DB 7E 08 D5 F0 37 79 36 8F 24 ....GN.~ ...7y6.$ +[0220] 34 28 86 89 EC A3 84 7F 44 4E 37 03 B5 D8 89 1C 4(...... DN7..... +[0230] C7 AA AC 42 70 5F 96 73 35 8B 83 D1 16 24 27 C1 ...Bp_.s 5....$'. +[0240] EC 0E AE 83 59 5A C2 EB C1 91 B6 3D BB 8D 21 49 ....YZ.. ...=..!I +[0250] 63 41 3C 91 1D E9 01 C2 4F A9 E4 42 C1 FD 54 E3 cA<..... O..B..T. +[0260] 7B 3B DF 24 3D 98 E9 84 F8 1D 8D CE 4D 85 AC 8A {;.$=... ....M... +[0270] 12 15 48 C4 DA 1B 3C B8 FC A3 0B AF E2 4D 71 E9 ..H...<. .....Mq. +[0280] 0A 28 53 DC 4E 6C 23 2C 73 26 50 FE 37 03 BF D1 .(S.Nl#, s&P.7... +[0290] 5F 8A 39 4F 04 2E 4A CE 3C 90 11 0C DA 84 5C C3 _.9O..J. <.....\. +[02A0] F8 BE C7 74 ED F4 CF 7E B2 AE 9B 47 D6 2A 1D 93 ...t...~ ...G.*.. +[02B0] 3F A8 8B 51 E9 A3 A0 59 55 DB E3 52 67 E3 DE FF ?..Q...Y U..Rg... +[02C0] B1 56 74 A0 87 21 99 23 8C 8E D1 92 A6 3D 93 D6 .Vt..!.# .....=.. +[02D0] 4D 5B 84 2B B1 8D DD E4 F7 01 A6 6C 4A DF 3C 6E M[.+.... ...lJ....+... +[0330] 4B 6D 22 B3 41 DE 85 35 2D 19 09 E5 68 8E 1F 98 Km".A..5 -...h... +[0340] 1B F2 73 F2 D4 91 08 89 42 0C 05 8B 42 77 6B CC ..s..... B...Bwk. +[0350] 18 78 43 1A 73 C2 7C E7 C2 23 28 56 F7 A0 19 B3 .xC.s.|. .#(V.... +[0360] 99 A6 25 4F C3 5E 70 EC 78 BB 30 15 36 77 B3 A6 ..%O.^p. x.0.6w.. +[0370] 89 98 B6 A0 85 CC 8F E7 41 40 B5 E0 89 93 25 04 ........ A@....%. +[0380] B8 1D 0B 06 31 1D C7 30 52 E1 64 29 8C 64 B9 89 ....1..0 R.d).d.. +[0390] 1F 86 5A AD 74 15 1C C8 AF 37 7B 27 E0 C0 DB 73 ..Z.t... .7{'...s +[03A0] 30 72 65 D3 C0 A5 07 61 E9 0C 07 A1 27 18 8F 50 0re....a ....'..P +[03B0] DB CE FB 4C DD 75 98 F2 28 D2 76 FF F2 41 9F D5 ...L.u.. (.v..A.. +[03C0] 74 22 8A 03 73 B1 A8 B3 B8 80 93 E5 E2 CD 4B F2 t"..s... ......K. +[03D0] 6B 99 DF 5B 5B C7 22 69 81 2A 8A CD 2A F9 9D 08 k..[[."i .*..*... +[03E0] B8 B0 40 77 D3 43 8B AF 40 DD 0C CB 45 E3 88 CB ..@w.C.. @...E... +[03F0] 06 AA 63 38 EB DD 72 89 03 0E DC 3E 97 3F 16 D4 ..c8..r. ...>.?.. +[0400] 1A 21 40 D8 30 BD B0 B4 04 C2 7A 22 43 15 A2 D8 .!@.0... ..z"C... +[0410] 2F 08 28 3B 63 26 AA B3 1C B6 FC E4 0B 2A CD 0E /.(;c&.. .....*.. +[0420] A8 7C E8 11 33 03 D3 C5 6C 35 6A 5D 3C 5A 80 1A .|..3... l5j];J +[0680] 60 25 3D 11 E4 F9 16 02 3E 55 8F CE D2 E9 95 E7 `%=..... >U...... +[0690] B1 C4 8F C4 0B 3E 3C 14 15 28 1A 21 49 15 CE 8E .....><. .(.!I... +[06A0] 91 5E 98 71 00 1F 29 D3 12 C8 D0 11 4F E7 14 E3 .^.q..). ....O... +[06B0] 72 1B 61 6D 7B 8A 00 A6 5E 01 01 50 C2 CF 1A A9 r.am{... ^..P.... +[06C0] 34 8C BA 33 9E 62 C5 69 97 6A 24 3D E0 C6 3F C6 4..3.b.i .j$=..?. +[06D0] F4 36 B1 80 D6 5C 44 19 5B 65 C7 CA 47 DE 4B 65 .6...\D. [e..G.Ke +[06E0] 41 29 9F F8 EA E8 E0 3B E2 C6 98 9D 58 A4 6C 62 A).....; ....X.lb +[06F0] EF 25 12 C9 0E 97 CE 9D F0 D8 08 AD 13 73 A6 82 .%...... .....s.. +[0700] C5 54 23 F4 A4 CB 91 35 91 BD 10 B4 04 DD 55 7E .T#....5 ......U~ +[0710] C9 DE AE CB B0 8F C0 D8 28 AE BD 78 64 91 6C AB ........ (..xd.l. +[0720] CA 36 EA 0E 0E 97 DC 40 ED 26 1D 09 17 28 30 D3 .6.....@ .&...(0. +[0730] 78 DC F7 D2 9C 78 DA 6F 6F 57 00 B3 FD 8E 75 A1 x....x.o oW....u. +[0740] 56 98 5C 4B D8 61 A6 0A 89 27 CD 11 BF 7F 79 53 V.\K.a.. .'....yS +[0750] D9 50 9A 8D EC DD DB BB B8 23 27 0D 20 5B 53 51 .P...... .#'. [SQ +[0760] 07 C4 26 31 3B D4 DF ED 3C 40 B4 1C 8B 46 E2 A6 ..&1;... <@...F.. +[0770] B7 0F 97 D2 B3 1D 19 FD 13 60 7B 38 E6 37 0C 59 ........ .`{8.7.Y +[0780] B0 A8 47 5D 32 A5 0C 57 76 EF 2C ED 40 9F BF 4B ..G]2..W v.,.@..K +[0790] 43 99 3C 68 C4 DE 84 9C A1 36 8C CA CB 2A 08 36 C..%p.4 ...>..-. +[0930] 72 8E DA 4D 2D 55 EC 49 66 5E 01 96 E4 C1 0C 23 r..M-U.I f^.....# +[0940] 57 91 00 00 00 00 00 00 00 01 00 00 00 01 00 00 W....... ........ +[0950] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[0960] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D AMPLE.CO M....adm +[0970] 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 inistrat or...... +[0980] 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[0990] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 A.EXAMPL E.COM... +[09A0] 04 68 6F 73 74 00 00 00 0B 4C 4F 43 41 4C 4B 54 .host... .LOCALKT +[09B0] 45 53 54 36 00 17 00 00 00 10 9D AE 06 BE 29 E0 EST6.... ......). +[09C0] F7 9A 46 97 29 E0 69 8E 5A F0 4D 9B 90 45 4D 9B ..F.).i. Z.M..EM. +[09D0] 90 61 7D 46 4C 43 00 00 00 00 00 40 28 00 00 00 .a}FLC.. ...@(... +[09E0] 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 ........ ...a...0 +[09F0] 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 ........ ....KTES +[0A00] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0A10] 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 COM..0.. ......0. +[0A20] 1B 04 68 6F 73 74 1B 0B 4C 4F 43 41 4C 4B 54 45 ..host.. LOCALKTE +[0A30] 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 ST6....0 ........ +[0A40] A1 03 02 01 03 A2 82 03 9C 04 82 03 98 B9 C5 6E ........ .......n +[0A50] 77 F9 59 6D 19 F0 A6 56 2F 14 B3 9A A3 17 06 A6 w.Ym...V /....... +[0A60] AD F5 92 38 6A 1E EA 3D 53 BF 5E 95 13 FF 5D BB ...8j..= S.^...]. +[0A70] 43 4F 51 AE FB 12 3B 06 67 36 91 B9 E0 C4 C4 F3 COQ...;. g6...... +[0A80] 45 A0 48 E6 DC 49 E8 EA 6F 55 D2 3F 79 57 54 FF E.H..I.. oU.?yWT. +[0A90] 10 8D 89 4A A4 E2 B2 80 FD EE 36 C5 D5 4C D0 97 ...J.... ..6..L.. +[0AA0] B3 EC 96 8B E8 5A 05 F0 13 39 8B 1B B3 C4 32 2A .....Z.. .9....2* +[0AB0] 9B BB EF 06 C4 1C 53 2F 0A F6 A8 C6 BE 09 57 26 ......S/ ......W& +[0AC0] B9 39 7B 7B 50 13 2D 6C 52 FF C4 B5 83 28 A8 47 .9{{P.-l R....(.G +[0AD0] 5A CD 1C DD A7 65 FD 8A 84 2A 10 E7 44 E6 83 E7 Z....e.. .*..D... +[0AE0] E7 AA B8 E5 0A 8B 7E E1 87 7B 3D C4 9F 68 BD 19 ......~. .{=..h.. +[0AF0] 2B 59 5E 5A 45 0D B5 71 CC A6 C7 03 3C B3 17 D3 +Y^ZE..q ....<... +[0B00] AF 99 F6 A2 52 A0 99 F7 39 56 B4 33 B4 C5 F4 CC ....R... 9V.3.... +[0B10] 74 34 4C 00 76 26 10 D1 3A 87 6E 6A 52 9B 7A BF t4L.v&.. :.njR.z. +[0B20] 4E 59 36 32 C5 41 29 CF E1 BF 14 E0 54 BF 4A 25 NY62.A). ....T.J% +[0B30] 1F 0B 6E 9A 8C 0E 5D 47 A9 64 1B A4 9D 99 A9 09 ..n...]G .d...... +[0B40] 39 14 E7 41 22 98 8C 62 CC E2 B5 91 8E C1 31 EB 9..A"..b ......1. +[0B50] B2 70 A6 3B 86 FC DD 19 0B 3F 5D C9 B5 1A 95 73 .p.;.... .?]....s +[0B60] EB 97 89 BE 14 87 85 17 BE 40 F6 80 14 23 4D 66 ........ .@...#Mf +[0B70] E4 B0 E5 51 46 34 DA 1C C8 CB FF C6 84 A3 DF D2 ...QF4.. ........ +[0B80] DC 00 AF 7B 27 C8 78 44 CB 6E 7B CC 5C 94 1E 7A ...{'.xD .n{.\..z +[0B90] 95 29 19 F4 14 BE 5C 23 C3 B9 A4 2C 5D 4D F3 61 .)....\# ...,]M.a +[0BA0] 63 1F D4 FE 37 EE 44 14 06 B7 14 50 B6 74 37 75 c...7.D. ...P.t7u +[0BB0] 2C AB 06 F0 93 F9 93 34 75 63 44 7E 12 48 D1 F1 ,......4 ucD~.H.. +[0BC0] 06 55 14 11 B9 23 43 CE 01 16 3E 6B A3 BD 23 55 .U...#C. ..>k..#U +[0BD0] DE 48 5D AF E1 2B 89 E8 E7 C2 E2 34 25 A2 09 4A .H]..+.. ...4%..J +[0BE0] 1F BE 05 AA DE 4B 08 65 27 4C 9B C7 54 96 C2 FB .....K.e 'L..T... +[0BF0] E2 CE 53 4A 32 93 8D 0B 44 77 8C D3 65 54 F9 0E ..SJ2... Dw..eT.. +[0C00] 7F 74 1E FE 3D 74 83 0F 2F E7 9F BC A2 B0 2B 25 .t..=t.. /.....+% +[0C10] BB D2 6F A8 49 C1 3E 9E B5 93 67 74 39 A4 FE 84 ..o.I.>. ..gt9... +[0C20] 4C 45 5F 30 74 E0 CA 5F F6 46 EC 89 B5 2D C8 14 LE_0t.._ .F...-.. +[0C30] 69 76 BC 93 15 F4 60 30 5F AB EB 02 DD 12 4C 62 iv....`0 _.....Lb +[0C40] F9 73 F7 01 E1 7F 2A 6F 09 05 BF 3A 3A 7E 69 A3 .s....*o ...::~i. +[0C50] 7B FC 20 2B D6 CE C0 74 4F BB 29 E4 BE CE 04 9D {. +...t O.)..... +[0C60] 24 D4 98 4A ED 94 A8 81 CD 26 A0 63 EA 09 57 42 $..J.... .&.c..WB +[0C70] 26 B7 B5 4E B5 CB 45 35 A7 84 D8 74 CA C3 9F FF &..N..E5 ...t.... +[0C80] C8 1E 2A 75 34 01 C5 A7 B4 9D 6F A3 E1 BB 2B F8 ..*u4... ..o...+. +[0C90] F0 21 D6 77 57 74 2E 80 DB 76 53 01 86 33 17 32 .!.wWt.. .vS..3.2 +[0CA0] 2E 16 E1 8D 89 3A B2 67 ED A3 ED 39 82 87 26 A6 .....:.g ...9..&. +[0CB0] DB CE 59 84 E4 0A A6 CA 7E 07 98 F7 02 91 6E 56 ..Y..... ~.....nV +[0CC0] 9F 60 03 D3 88 B0 FF EB 20 CA 9E 5B 37 26 67 00 .`...... ..[7&g. +[0CD0] CC BD 9D 53 15 31 53 14 FD 9C E1 28 08 CB C4 0B ...S.1S. ...(.... +[0CE0] E3 50 D9 DB 0C E2 E4 F9 44 50 E9 28 6E 01 96 AA .P...... DP.(n... +[0CF0] C1 D2 4E B2 DE 38 A2 F8 94 32 79 AE 49 64 FB 57 ..N..8.. .2y.Id.W +[0D00] 50 F6 73 E8 98 43 C6 DD 67 3C 91 AC 97 C9 2E 8C P.s..C.. g<...... +[0D10] 06 59 A1 FC 49 EC 2F BF 6F 64 21 63 ED C8 6C CE .Y..I./. od!c..l. +[0D20] 37 28 7B 80 7F 5F 85 F6 98 93 C0 66 A8 D6 F1 2C 7({.._.. ...f..., +[0D30] D8 01 68 B1 C8 EA 82 0D 5B 9B 35 4F 3D B3 47 19 ..h..... [.5O=.G. +[0D40] 54 7A C6 9F AD D7 54 CF B0 DB 3E 18 BA 2A 39 08 Tz....T. ..>..*9. +[0D50] 0C C4 98 4B 43 DE 53 68 25 B1 83 93 1D E1 6C BF ...KC.Sh %.....l. +[0D60] F5 B4 A9 83 17 34 64 8C 2F 91 80 97 4A 48 EC 90 .....4d. /...JH.. +[0D70] BB FA 92 2C 01 80 E4 99 91 0E 67 88 D5 75 AB 7C ...,.... ..g..u.| +[0D80] 98 59 98 45 C9 11 A9 8C 02 98 91 DE AB A0 FF 45 .Y.E.... .......E +[0D90] 11 66 6F C5 DE 61 6D C6 DB C9 CA A3 A0 2B B1 73 .fo..am. .....+.s +[0DA0] 05 85 37 BF AB CA 43 7A 6F 38 C8 BE ED CE 12 49 ..7...Cz o8.....I +[0DB0] 93 C7 7C 1A 33 60 52 7A 67 67 AA 60 57 7E C8 FF ..|.3`Rz gg.`W~.. +[0DC0] DF 91 91 18 45 74 C0 9E 36 19 BC 42 F9 46 CC 84 ....Et.. 6..B.F.. +[0DD0] 09 2E 8C 59 1A E3 65 51 F4 87 6F 4C 3E 29 38 E6 ...Y..eQ ..oL>)8. +[0DE0] 77 E8 A9 B7 FA 00 00 00 00 00 00 00 01 00 00 00 w....... ........ +[0DF0] 01 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[0E00] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D .EXAMPLE .COM.... +[0E10] 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 administ rator... +[0E20] 01 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0E30] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0E40] 00 00 00 04 63 69 66 73 00 00 00 0B 4C 4F 43 41 ....cifs ....LOCA +[0E50] 4C 4B 54 45 53 54 36 00 17 00 00 00 10 01 78 D0 LKTEST6. ......x. +[0E60] 3B 9B FF F0 88 86 4B 3B FE 41 A9 6B 00 4D 9B 90 ;.....K; .A.k.M.. +[0E70] 45 4D 9B 90 6B 7D 46 4C 43 00 00 00 00 00 40 28 EM..k}FL C.....@( +[0E80] 00 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 ........ ......a. +[0E90] 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B ..0..... .......K +[0EA0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0EB0] 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 LE.COM.. 0....... +[0EC0] 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F 43 41 4C .0...cif s..LOCAL +[0ED0] 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 KTEST6.. ..0..... +[0EE0] 02 01 17 A1 03 02 01 03 A2 82 03 9C 04 82 03 98 ........ ........ +[0EF0] CA EA 4D 46 2D D1 E9 58 5D 25 8D 9F DF EA C9 01 ..MF-..X ]%...... +[0F00] B6 08 27 CD 14 85 02 DC 20 C6 51 AA F9 6A B1 CE ..'..... .Q..j.. +[0F10] F5 77 84 BF 9A AC 6B A7 B2 F2 1F 60 BF CB C6 FC .w....k. ...`.... +[0F20] C7 14 B7 41 1C A8 C9 70 7B 86 BC 8E 70 2B 65 4B ...A...p {...p+eK +[0F30] DC F5 B9 23 F8 08 BF 96 C9 A8 77 F4 54 67 25 F8 ...#.... ..w.Tg%. +[0F40] 0F A8 C5 D6 D1 BB 46 5E A0 7E D2 98 9C CD AF E0 ......F^ .~...... +[0F50] 82 62 ED 39 D2 FB F2 E8 9B 1B EE E5 B4 1B C9 0A .b.9.... ........ +[0F60] 86 27 52 6E 11 8B D7 AD B4 54 F9 C6 69 8D E0 F1 .'Rn.... .T..i... +[0F70] CD 63 1C 89 7C 8F B6 A0 71 53 A6 DA B1 66 D2 9D .c..|... qS...f.. +[0F80] D3 4C A8 FB C6 9D 81 74 10 8E 84 D2 3D D8 1C BE .L.....t ....=... +[0F90] BB 3F F7 BF 91 3E 89 66 43 A1 E0 90 1B 1A 97 FF .?...>.f C....... +[0FA0] EF CC 35 75 14 62 4F 67 3A 29 F4 F9 C5 2E BE C5 ..5u.bOg :)...... +[0FB0] C2 2B A8 35 22 D9 92 31 1D 49 2A A5 19 AA 08 0F .+.5"..1 .I*..... +[0FC0] A8 22 0B 68 D2 A2 D7 07 7B 37 1E A3 AC 9B 4F 0A .".h.... {7....O. +[0FD0] A4 FA 7F 37 6F 3E 35 79 4E 00 4B B6 28 A3 6A E4 ...7o>5y N.K.(.j. +[0FE0] 0C 95 53 BA E8 41 07 DA BE E9 08 B9 51 24 91 49 ..S..A.. ....Q$.I +[0FF0] 78 5D 44 12 BC 85 63 81 B8 E0 88 D5 95 0C D3 A8 x]D...c. ........ +[1000] 1D 32 4B E4 A0 C8 A7 7D 3C 97 EE D8 59 AC 3A 21 .2K....} <...Y.:! +[1010] 09 F2 7A CC D0 4A F3 50 10 DC FC 26 BB C2 6A 8E ..z..J.P ...&..j. +[1020] 8B 14 2B 2D 50 2E B3 1E 9B D2 69 56 22 F2 48 BD ..+-P... ..iV".H. +[1030] E9 2E 2F 28 DE 77 67 5F 68 AA 29 05 4B 36 58 40 ../(.wg_ h.).K6X@ +[1040] E5 54 11 C5 4D 68 96 49 9D 53 37 87 5F D2 3A 9B .T..Mh.I .S7._.:. +[1050] E9 8E 79 BE AE 11 B4 6B AB FD DB 8A F5 A0 9B 29 ..y....k .......) +[1060] D9 F5 ED CA FA 3F FE 35 FC F4 69 7E E4 D0 44 29 .....?.5 ..i~..D) +[1070] 48 FF 82 61 26 FC D3 E2 10 EE 14 F7 4A E3 CD F2 H..a&... ....J... +[1080] 8B BC 8B 43 64 2C DE 40 6E BB E1 56 C0 B6 2C D0 ...Cd,.@ n..V..,. +[1090] E5 1E E9 B3 FB 38 48 66 ED AF D2 25 D1 35 5C C6 .....8Hf ...%.5\. +[10A0] F0 4D 36 19 0B EC 33 07 34 D0 27 8D 14 DC 01 45 .M6...3. 4.'....E +[10B0] DE F8 73 A6 A0 F4 C1 91 9D BD 05 E3 70 25 E1 10 ..s..... ....p%.. +[10C0] 44 F6 4B 46 F7 24 84 BF 20 96 AD 6A 96 94 81 58 D.KF.$.. ..j...X +[10D0] 80 95 06 92 F5 7F 17 39 3B 32 47 B2 C5 CE 7B 73 .......9 ;2G...{s +[10E0] CF 53 AE FA D1 9A 60 5A 98 EC 8C FA BD C0 CE 8D .S....`Z ........ +[10F0] C5 27 E6 17 1A 4D 47 D8 3F 5D A9 7C FB 2C B3 05 .'...MG. ?].|.,.. +[1100] 0C 69 20 48 99 80 11 DC 48 AB A7 EA 5B 98 C1 15 .i H.... H...[... +[1110] 27 AE FA 3E 1E 1E E0 E1 F8 32 C0 54 13 D6 30 34 '..>.... .2.T..04 +[1120] 71 98 26 61 6C 1C C4 C7 4E C4 A6 7E FE A8 B8 89 q.&al... N..~.... +[1130] 2A 70 3C 19 58 8D 57 45 55 83 0A C2 B5 F7 89 0E *p<.X.WE U....... +[1140] 7B 7A 17 0C CF 6E 08 A5 F7 21 4A 62 81 4F 49 CA {z...n.. .!Jb.OI. +[1150] E2 ED C2 B4 C7 33 5C BC A1 A0 DE 4E 09 37 BE 24 .....3\. ...N.7.$ +[1160] 62 22 94 55 75 AA 53 DE E0 74 5A B0 B8 E9 BF 2B b".Uu.S. .tZ....+ +[1170] 12 65 2F 90 6B 84 ED 11 AD F7 CE 19 A1 96 E4 1E .e/.k... ........ +[1180] 8C EA C8 81 1B 47 4F 5F B1 5D A5 8B E3 0D 5A 80 .....GO_ .]....Z. +[1190] 89 EC 4B D9 CE ED E8 67 7F 96 FC 1B EF 65 C2 68 ..K....g .....e.h +[11A0] 40 F7 20 36 83 58 62 F4 CA 02 F4 5C 0D 46 B1 CB @. 6.Xb. ...\.F.. +[11B0] 50 D2 D8 3D B7 9A 96 48 8C CF EB E6 8C F4 B2 B4 P..=...H ........ +[11C0] 47 C9 34 C9 DC 14 F1 33 1B 6F 9E 65 27 D7 9D 46 G.4....3 .o.e'..F +[11D0] 1E 91 FF 2E FB 8E 97 5D 17 8F 48 54 7C 3C A0 11 .......] ..HT|<.. +[11E0] 9C AA 77 E9 79 DE 26 D1 F0 7C EA 24 73 BE EC 60 ..w.y.&. .|.$s..` +[11F0] B4 EE BD ED 0D 0A AB 74 60 6E 46 C0 35 5B 65 1A .......t `nF.5[e. +[1200] A4 4A 5C 22 AC B9 CD B7 56 06 88 09 FC 48 68 55 .J\".... V....HhU +[1210] B7 5E 39 72 DF 8A 4C CD 79 74 B0 84 0B 78 DA B2 .^9r..L. yt...x.. +[1220] 55 F8 06 0B 5C 27 06 B3 CA 10 65 6B 04 A3 64 11 U...\'.. ..ek..d. +[1230] 04 09 DC DF 67 00 70 B1 16 DF 24 E9 27 85 11 91 ....g.p. ..$.'... +[1240] 31 CB 92 95 50 18 91 08 C2 A1 A3 76 C7 1A FC 64 1...P... ...v...d +[1250] 9E 2C 3A E7 30 F4 16 0D A0 56 C0 BC D2 FE 2D A0 .,:.0... .V....-. +[1260] 20 A4 E2 82 AD F0 C5 12 71 09 23 E1 66 52 53 D0 ....... q.#.fRS. +[1270] 89 30 E7 BE B7 C2 89 F2 1C 7A F6 8E D7 28 F0 A4 .0...... .z...(.. +[1280] 33 46 7C A2 79 66 DE 26 00 00 00 00 3F|.yf.& .... +push returned Success +pull returned Success + CCACHE: struct CCACHE + pvno : 0x05 (5) + version : 0x04 (4) + optional_header : union OPTIONAL_HEADER(case 0x4) + v4header: struct V4HEADER + v4tags: struct V4TAGS + tag: struct V4TAG + tag : 0x0001 (1) + field : union FIELD(case 0x1) + deltatime_tag: struct DELTATIME_TAG + kdc_sec_offset : 0 + kdc_usec_offset : 0 + further_tags : DATA_BLOB length=0 + principal: struct PRINCIPAL + name_type : 0x00000001 (1) + component_count : 0x00000001 (1) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(1) + components : 'administrator' + cred: struct CREDENTIAL + client: struct PRINCIPAL + name_type : 0x00000001 (1) + component_count : 0x00000001 (1) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(1) + components : 'administrator' + server: struct PRINCIPAL + name_type : 0x00000000 (0) + component_count : 0x00000002 (2) + realm : 'KTEST.SAMBA.EXAMPLE.COM' + components: ARRAY(2) + components : 'krbtgt' + components : 'KTEST.SAMBA.EXAMPLE.COM' + keyblock: struct KEYBLOCK + enctype : 0x0017 (23) + data : DATA_BLOB length=16 +[0000] E5 E4 15 C8 A8 0F 4D 95 F9 1B E3 B9 98 CA A1 7F ......M. ........ + authtime : 0x4d9b9045 (1302040645) + starttime : 0x4d9b9045 (1302040645) + endtime : 0x7d464c43 (2101759043) + renew_till : 0x7d464c43 (2101759043) + is_skey : 0x00 (0) + ticket_flags : 0x40e00000 (1088421888) + addresses: struct ADDRESSES + count : 0x00000000 (0) + data: ARRAY(0) + authdata: struct AUTHDATA + count : 0x00000000 (0) + data: ARRAY(0) + ticket : DATA_BLOB length=1032 +[0000] 61 82 04 04 30 82 04 00 A0 03 02 01 05 A1 19 1B a...0... ........ +[0010] 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 .KTEST.S AMBA.EXA +[0020] 4D 50 4C 45 2E 43 4F 4D A2 2C 30 2A A0 03 02 01 MPLE.COM .,0*.... +[0030] 00 A1 23 30 21 1B 06 6B 72 62 74 67 74 1B 17 4B ..#0!..k rbtgt..K +[0040] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0050] 4C 45 2E 43 4F 4D A3 82 03 AE 30 82 03 AA A0 03 LE.COM.. ..0..... +[0060] 02 01 17 A1 03 02 01 01 A2 82 03 9C 04 82 03 98 ........ ........ +[0070] 01 40 48 A6 B8 F0 DA 43 54 A5 18 CF B0 15 CB 68 .@H....C T......h +[0080] 9F A0 69 44 87 A9 FF 06 25 B9 29 48 59 64 26 48 ..iD.... %.)HYd&H +[0090] 96 7C 46 6A 79 E5 F0 77 DB 46 6C 20 A1 59 D9 F8 .|Fjy..w .Fl .Y.. +[00A0] 6A 8A 2D B5 D9 EF A4 54 DE 19 20 C0 7B 93 D4 3D j.-....T .. .{..= +[00B0] ED 72 35 AF 9D 87 75 9E 44 01 A4 6C D9 EA 94 A3 .r5...u. D..l.... +[00C0] 18 C6 42 75 E3 0A 0C 76 9A AE 75 BC A3 02 91 BC ..Bu...v ..u..... +[00D0] 2D BB 3C 23 73 A6 1A A7 8A 3E 85 42 5D 1F 5D 7D -.<#s... .>.B].]} +[00E0] 0B 1F C3 88 2A 93 40 F9 E9 18 7D 3F 73 DA AC 1F ....*.@. ..}?s... +[00F0] E7 7B C3 B8 14 56 C3 63 86 5B AF C9 C3 21 9F 94 .{...V.c .[...!.. +[0100] B4 67 06 60 7F 56 2D F4 C7 22 CD B4 1C 14 B7 5B .g.`.V-. .".....[ +[0110] 26 67 9D 18 28 B5 5D C2 FC 13 B6 CA 9F AB CD 32 &g..(.]. .......2 +[0120] 71 D5 51 5F A2 11 5A 5D 4A B3 3B 1D D1 6B 4F 7D q.Q_..Z] J.;..kO} +[0130] E9 54 F0 B4 AC 80 DE 27 80 C5 64 3C 0B 22 79 1C .T.....' ..d<."y. +[0140] 9E D1 58 A1 3E 20 5A 9F E3 34 49 D8 16 C6 6B 2D ..X.> Z. .4I...k- +[0150] 36 0E E2 C2 3F 44 DE 63 32 DB EB 78 50 A2 6F 37 6...?D.c 2..xP.o7 +[0160] 05 2B 13 D4 31 07 D4 2A C0 53 B1 30 39 79 C3 D8 .+..1..* .S.09y.. +[0170] C4 4C 30 97 E8 F9 DA ED 10 B0 D0 21 71 8B 56 F3 .L0..... ...!q.V. +[0180] 0F 3A 2D 26 A2 3D AD 70 27 82 95 59 0A D7 7D 4E .:-&.=.p '..Y..}N +[0190] 2D 76 96 4D 94 70 2A BB 26 3B 7E FC E1 59 5A 55 -v.M.p*. &;~..YZU +[01A0] 04 A2 DA 27 AD 46 70 45 43 C0 FB C1 42 7F F0 CB ...'.FpE C...B... +[01B0] 21 D2 CD 54 35 7C 60 13 EE BB BB 60 6B 91 2B BE !..T5|`. ...`k.+. +[01C0] 91 8A CF 49 29 F8 60 D1 AB A5 51 B5 5E 4B B2 3A ...I).`. ..Q.^K.: +[01D0] F4 56 3A 89 2D 88 D0 73 08 A6 FB D8 6E B3 B1 4E .V:.-..s ....n..N +[01E0] D8 90 27 58 D2 53 40 B2 A0 3C 40 4D E9 21 C6 83 ..'X.S@. .<@M.!.. +[01F0] FC 15 14 F0 8C 08 46 C5 29 14 E3 84 CC 2C 56 C9 ......F. )....,V. +[0200] 20 53 45 34 D0 BE E0 CC F7 F1 15 D4 D4 B1 3C 43 SE4.... .......BT.Ba +[03A0] C5 22 B7 AE 51 76 8F 12 83 7F E1 9F 97 D8 31 38 ."..Qv.. ......18 +[03B0] A6 B9 11 B4 E1 BA 19 5B E4 A5 A3 6F 4B B3 03 93 .......[ ...oK... +[03C0] 4C D6 1E 08 FC 94 D1 C5 7C AA 95 EB 9C 7A C2 57 L....... |....z.W +[03D0] 60 CA 17 FF 8E 66 80 76 CB 35 46 26 C3 BD CA 83 `....f.v .5F&.... +[03E0] F0 04 08 0D 4C 5D B2 E4 7C 1C 82 28 D7 2C 42 B1 ....L].. |..(.,B. +[03F0] 36 72 60 5E 26 4A 79 D0 41 94 3C 2C 65 0E 32 18 6r`^&Jy. A.<,e.2. +[0400] B8 56 26 9D D3 84 78 BB .V&...x. + second_ticket : DATA_BLOB length=0 + further_creds : DATA_BLOB length=4748 +[0000] 00 00 00 01 00 00 00 01 00 00 00 17 4B 54 45 53 ........ ....KTES +[0010] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0020] 43 4F 4D 00 00 00 0D 61 64 6D 69 6E 69 73 74 72 COM....a dministr +[0030] 61 74 6F 72 00 00 00 01 00 00 00 02 00 00 00 17 ator.... ........ +[0040] 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D KTEST.SA MBA.EXAM +[0050] 50 4C 45 2E 43 4F 4D 00 00 00 04 68 6F 73 74 00 PLE.COM. ...host. +[0060] 00 00 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 00 17 ...local ktest6.. +[0070] 00 00 00 10 EA 0D 3A 24 41 21 F7 7D 7D A3 C5 BB ......:$ A!.}}... +[0080] A4 88 F6 17 4D 9B 90 45 4D 9B 90 52 7D 46 4C 43 ....M..E M..R}FLC +[0090] 00 00 00 00 00 40 28 00 00 00 00 00 00 00 00 00 .....@(. ........ +[00A0] 00 00 00 03 FA 61 82 03 F6 30 82 03 F2 A0 03 02 .....a.. .0...... +[00B0] 01 05 A1 19 1B 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[00C0] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D A2 1E 30 A.EXAMPL E.COM..0 +[00D0] 1C A0 03 02 01 01 A1 15 30 13 1B 04 68 6F 73 74 ........ 0...host +[00E0] 1B 0B 6C 6F 63 61 6C 6B 74 65 73 74 36 A3 82 03 ..localk test6... +[00F0] AE 30 82 03 AA A0 03 02 01 17 A1 03 02 01 03 A2 .0...... ........ +[0100] 82 03 9C 04 82 03 98 44 8B C4 7D BA 9F FE 59 F6 .......D ..}...Y. +[0110] C1 DF 62 89 02 A4 55 54 AB D6 D6 2E 8B 5E 35 3D ..b...UT .....^5= +[0120] D9 46 9D 8B 49 93 A6 66 5F 1A 8B 81 AD 09 19 E9 .F..I..f _....... +[0130] 59 CE 58 18 50 63 4A A6 7D 6F 71 21 51 4A 41 C2 Y.X.PcJ. }oq!QJA. +[0140] A1 FE B0 D5 0A 3D 38 9F E5 3B 72 A2 7A 59 22 A4 .....=8. .;r.zY". +[0150] B7 1C A3 8D DB EA 5D A5 E2 D3 1D AE 42 D0 7F 75 ......]. ....B..u +[0160] B5 E9 ED B5 04 7B 67 1E 28 90 7D 3D 1A 3E F6 62 .....{g. (.}=.>.b +[0170] D0 A1 56 89 28 76 5C 19 1A FD 66 E5 F2 86 E7 58 ..V.(v\. ..f....X +[0180] 93 31 90 C5 CD F8 71 96 56 21 15 13 F0 EA C2 CC .1....q. V!...... +[0190] 48 4C B4 50 EF F9 81 44 29 8A 75 C4 31 75 D1 BA HL.P...D ).u.1u.. +[01A0] E2 0B 05 B2 E0 EA 64 3A 11 45 84 3D 69 55 FF E6 ......d: .E.=iU.. +[01B0] 32 7E C9 CA C4 28 E8 40 B6 5E F9 26 0F 09 12 1F 2~...(.@ .^.&.... +[01C0] 1F D4 9C 9A 50 E8 B7 6D F8 4F 55 6E 2A D4 AC 6A ....P..m .OUn*..j +[01D0] 79 D1 C2 2A 88 99 F8 39 75 36 F1 2D C7 89 0A C6 y..*...9 u6.-.... +[01E0] B4 C7 A1 7B F1 BF 22 87 A4 B2 93 22 54 A1 72 25 ...{..". ..."T.r% +[01F0] AF 67 FE 20 D5 C8 29 47 28 FF 51 FB F9 4E 2C 17 .g. ..)G (.Q..N,. +[0200] 10 BE 2E 13 8B 18 BE 3C A3 BE 50 49 A7 65 DD 2E .......< ..PI.e.. +[0210] CC EB D6 0F 47 4E DB 7E 08 D5 F0 37 79 36 8F 24 ....GN.~ ...7y6.$ +[0220] 34 28 86 89 EC A3 84 7F 44 4E 37 03 B5 D8 89 1C 4(...... DN7..... +[0230] C7 AA AC 42 70 5F 96 73 35 8B 83 D1 16 24 27 C1 ...Bp_.s 5....$'. +[0240] EC 0E AE 83 59 5A C2 EB C1 91 B6 3D BB 8D 21 49 ....YZ.. ...=..!I +[0250] 63 41 3C 91 1D E9 01 C2 4F A9 E4 42 C1 FD 54 E3 cA<..... O..B..T. +[0260] 7B 3B DF 24 3D 98 E9 84 F8 1D 8D CE 4D 85 AC 8A {;.$=... ....M... +[0270] 12 15 48 C4 DA 1B 3C B8 FC A3 0B AF E2 4D 71 E9 ..H...<. .....Mq. +[0280] 0A 28 53 DC 4E 6C 23 2C 73 26 50 FE 37 03 BF D1 .(S.Nl#, s&P.7... +[0290] 5F 8A 39 4F 04 2E 4A CE 3C 90 11 0C DA 84 5C C3 _.9O..J. <.....\. +[02A0] F8 BE C7 74 ED F4 CF 7E B2 AE 9B 47 D6 2A 1D 93 ...t...~ ...G.*.. +[02B0] 3F A8 8B 51 E9 A3 A0 59 55 DB E3 52 67 E3 DE FF ?..Q...Y U..Rg... +[02C0] B1 56 74 A0 87 21 99 23 8C 8E D1 92 A6 3D 93 D6 .Vt..!.# .....=.. +[02D0] 4D 5B 84 2B B1 8D DD E4 F7 01 A6 6C 4A DF 3C 6E M[.+.... ...lJ....+... +[0330] 4B 6D 22 B3 41 DE 85 35 2D 19 09 E5 68 8E 1F 98 Km".A..5 -...h... +[0340] 1B F2 73 F2 D4 91 08 89 42 0C 05 8B 42 77 6B CC ..s..... B...Bwk. +[0350] 18 78 43 1A 73 C2 7C E7 C2 23 28 56 F7 A0 19 B3 .xC.s.|. .#(V.... +[0360] 99 A6 25 4F C3 5E 70 EC 78 BB 30 15 36 77 B3 A6 ..%O.^p. x.0.6w.. +[0370] 89 98 B6 A0 85 CC 8F E7 41 40 B5 E0 89 93 25 04 ........ A@....%. +[0380] B8 1D 0B 06 31 1D C7 30 52 E1 64 29 8C 64 B9 89 ....1..0 R.d).d.. +[0390] 1F 86 5A AD 74 15 1C C8 AF 37 7B 27 E0 C0 DB 73 ..Z.t... .7{'...s +[03A0] 30 72 65 D3 C0 A5 07 61 E9 0C 07 A1 27 18 8F 50 0re....a ....'..P +[03B0] DB CE FB 4C DD 75 98 F2 28 D2 76 FF F2 41 9F D5 ...L.u.. (.v..A.. +[03C0] 74 22 8A 03 73 B1 A8 B3 B8 80 93 E5 E2 CD 4B F2 t"..s... ......K. +[03D0] 6B 99 DF 5B 5B C7 22 69 81 2A 8A CD 2A F9 9D 08 k..[[."i .*..*... +[03E0] B8 B0 40 77 D3 43 8B AF 40 DD 0C CB 45 E3 88 CB ..@w.C.. @...E... +[03F0] 06 AA 63 38 EB DD 72 89 03 0E DC 3E 97 3F 16 D4 ..c8..r. ...>.?.. +[0400] 1A 21 40 D8 30 BD B0 B4 04 C2 7A 22 43 15 A2 D8 .!@.0... ..z"C... +[0410] 2F 08 28 3B 63 26 AA B3 1C B6 FC E4 0B 2A CD 0E /.(;c&.. .....*.. +[0420] A8 7C E8 11 33 03 D3 C5 6C 35 6A 5D 3C 5A 80 1A .|..3... l5j];J +[0680] 60 25 3D 11 E4 F9 16 02 3E 55 8F CE D2 E9 95 E7 `%=..... >U...... +[0690] B1 C4 8F C4 0B 3E 3C 14 15 28 1A 21 49 15 CE 8E .....><. .(.!I... +[06A0] 91 5E 98 71 00 1F 29 D3 12 C8 D0 11 4F E7 14 E3 .^.q..). ....O... +[06B0] 72 1B 61 6D 7B 8A 00 A6 5E 01 01 50 C2 CF 1A A9 r.am{... ^..P.... +[06C0] 34 8C BA 33 9E 62 C5 69 97 6A 24 3D E0 C6 3F C6 4..3.b.i .j$=..?. +[06D0] F4 36 B1 80 D6 5C 44 19 5B 65 C7 CA 47 DE 4B 65 .6...\D. [e..G.Ke +[06E0] 41 29 9F F8 EA E8 E0 3B E2 C6 98 9D 58 A4 6C 62 A).....; ....X.lb +[06F0] EF 25 12 C9 0E 97 CE 9D F0 D8 08 AD 13 73 A6 82 .%...... .....s.. +[0700] C5 54 23 F4 A4 CB 91 35 91 BD 10 B4 04 DD 55 7E .T#....5 ......U~ +[0710] C9 DE AE CB B0 8F C0 D8 28 AE BD 78 64 91 6C AB ........ (..xd.l. +[0720] CA 36 EA 0E 0E 97 DC 40 ED 26 1D 09 17 28 30 D3 .6.....@ .&...(0. +[0730] 78 DC F7 D2 9C 78 DA 6F 6F 57 00 B3 FD 8E 75 A1 x....x.o oW....u. +[0740] 56 98 5C 4B D8 61 A6 0A 89 27 CD 11 BF 7F 79 53 V.\K.a.. .'....yS +[0750] D9 50 9A 8D EC DD DB BB B8 23 27 0D 20 5B 53 51 .P...... .#'. [SQ +[0760] 07 C4 26 31 3B D4 DF ED 3C 40 B4 1C 8B 46 E2 A6 ..&1;... <@...F.. +[0770] B7 0F 97 D2 B3 1D 19 FD 13 60 7B 38 E6 37 0C 59 ........ .`{8.7.Y +[0780] B0 A8 47 5D 32 A5 0C 57 76 EF 2C ED 40 9F BF 4B ..G]2..W v.,.@..K +[0790] 43 99 3C 68 C4 DE 84 9C A1 36 8C CA CB 2A 08 36 C..%p.4 ...>..-. +[0930] 72 8E DA 4D 2D 55 EC 49 66 5E 01 96 E4 C1 0C 23 r..M-U.I f^.....# +[0940] 57 91 00 00 00 00 00 00 00 01 00 00 00 01 00 00 W....... ........ +[0950] 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 ..KTEST. SAMBA.EX +[0960] 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D 61 64 6D AMPLE.CO M....adm +[0970] 69 6E 69 73 74 72 61 74 6F 72 00 00 00 01 00 00 inistrat or...... +[0980] 00 02 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 ......KT EST.SAMB +[0990] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 A.EXAMPL E.COM... +[09A0] 04 68 6F 73 74 00 00 00 0B 4C 4F 43 41 4C 4B 54 .host... .LOCALKT +[09B0] 45 53 54 36 00 17 00 00 00 10 9D AE 06 BE 29 E0 EST6.... ......). +[09C0] F7 9A 46 97 29 E0 69 8E 5A F0 4D 9B 90 45 4D 9B ..F.).i. Z.M..EM. +[09D0] 90 61 7D 46 4C 43 00 00 00 00 00 40 28 00 00 00 .a}FLC.. ...@(... +[09E0] 00 00 00 00 00 00 00 00 00 03 FA 61 82 03 F6 30 ........ ...a...0 +[09F0] 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B 54 45 53 ........ ....KTES +[0A00] 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E T.SAMBA. EXAMPLE. +[0A10] 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 15 30 13 COM..0.. ......0. +[0A20] 1B 04 68 6F 73 74 1B 0B 4C 4F 43 41 4C 4B 54 45 ..host.. LOCALKTE +[0A30] 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 02 01 17 ST6....0 ........ +[0A40] A1 03 02 01 03 A2 82 03 9C 04 82 03 98 B9 C5 6E ........ .......n +[0A50] 77 F9 59 6D 19 F0 A6 56 2F 14 B3 9A A3 17 06 A6 w.Ym...V /....... +[0A60] AD F5 92 38 6A 1E EA 3D 53 BF 5E 95 13 FF 5D BB ...8j..= S.^...]. +[0A70] 43 4F 51 AE FB 12 3B 06 67 36 91 B9 E0 C4 C4 F3 COQ...;. g6...... +[0A80] 45 A0 48 E6 DC 49 E8 EA 6F 55 D2 3F 79 57 54 FF E.H..I.. oU.?yWT. +[0A90] 10 8D 89 4A A4 E2 B2 80 FD EE 36 C5 D5 4C D0 97 ...J.... ..6..L.. +[0AA0] B3 EC 96 8B E8 5A 05 F0 13 39 8B 1B B3 C4 32 2A .....Z.. .9....2* +[0AB0] 9B BB EF 06 C4 1C 53 2F 0A F6 A8 C6 BE 09 57 26 ......S/ ......W& +[0AC0] B9 39 7B 7B 50 13 2D 6C 52 FF C4 B5 83 28 A8 47 .9{{P.-l R....(.G +[0AD0] 5A CD 1C DD A7 65 FD 8A 84 2A 10 E7 44 E6 83 E7 Z....e.. .*..D... +[0AE0] E7 AA B8 E5 0A 8B 7E E1 87 7B 3D C4 9F 68 BD 19 ......~. .{=..h.. +[0AF0] 2B 59 5E 5A 45 0D B5 71 CC A6 C7 03 3C B3 17 D3 +Y^ZE..q ....<... +[0B00] AF 99 F6 A2 52 A0 99 F7 39 56 B4 33 B4 C5 F4 CC ....R... 9V.3.... +[0B10] 74 34 4C 00 76 26 10 D1 3A 87 6E 6A 52 9B 7A BF t4L.v&.. :.njR.z. +[0B20] 4E 59 36 32 C5 41 29 CF E1 BF 14 E0 54 BF 4A 25 NY62.A). ....T.J% +[0B30] 1F 0B 6E 9A 8C 0E 5D 47 A9 64 1B A4 9D 99 A9 09 ..n...]G .d...... +[0B40] 39 14 E7 41 22 98 8C 62 CC E2 B5 91 8E C1 31 EB 9..A"..b ......1. +[0B50] B2 70 A6 3B 86 FC DD 19 0B 3F 5D C9 B5 1A 95 73 .p.;.... .?]....s +[0B60] EB 97 89 BE 14 87 85 17 BE 40 F6 80 14 23 4D 66 ........ .@...#Mf +[0B70] E4 B0 E5 51 46 34 DA 1C C8 CB FF C6 84 A3 DF D2 ...QF4.. ........ +[0B80] DC 00 AF 7B 27 C8 78 44 CB 6E 7B CC 5C 94 1E 7A ...{'.xD .n{.\..z +[0B90] 95 29 19 F4 14 BE 5C 23 C3 B9 A4 2C 5D 4D F3 61 .)....\# ...,]M.a +[0BA0] 63 1F D4 FE 37 EE 44 14 06 B7 14 50 B6 74 37 75 c...7.D. ...P.t7u +[0BB0] 2C AB 06 F0 93 F9 93 34 75 63 44 7E 12 48 D1 F1 ,......4 ucD~.H.. +[0BC0] 06 55 14 11 B9 23 43 CE 01 16 3E 6B A3 BD 23 55 .U...#C. ..>k..#U +[0BD0] DE 48 5D AF E1 2B 89 E8 E7 C2 E2 34 25 A2 09 4A .H]..+.. ...4%..J +[0BE0] 1F BE 05 AA DE 4B 08 65 27 4C 9B C7 54 96 C2 FB .....K.e 'L..T... +[0BF0] E2 CE 53 4A 32 93 8D 0B 44 77 8C D3 65 54 F9 0E ..SJ2... Dw..eT.. +[0C00] 7F 74 1E FE 3D 74 83 0F 2F E7 9F BC A2 B0 2B 25 .t..=t.. /.....+% +[0C10] BB D2 6F A8 49 C1 3E 9E B5 93 67 74 39 A4 FE 84 ..o.I.>. ..gt9... +[0C20] 4C 45 5F 30 74 E0 CA 5F F6 46 EC 89 B5 2D C8 14 LE_0t.._ .F...-.. +[0C30] 69 76 BC 93 15 F4 60 30 5F AB EB 02 DD 12 4C 62 iv....`0 _.....Lb +[0C40] F9 73 F7 01 E1 7F 2A 6F 09 05 BF 3A 3A 7E 69 A3 .s....*o ...::~i. +[0C50] 7B FC 20 2B D6 CE C0 74 4F BB 29 E4 BE CE 04 9D {. +...t O.)..... +[0C60] 24 D4 98 4A ED 94 A8 81 CD 26 A0 63 EA 09 57 42 $..J.... .&.c..WB +[0C70] 26 B7 B5 4E B5 CB 45 35 A7 84 D8 74 CA C3 9F FF &..N..E5 ...t.... +[0C80] C8 1E 2A 75 34 01 C5 A7 B4 9D 6F A3 E1 BB 2B F8 ..*u4... ..o...+. +[0C90] F0 21 D6 77 57 74 2E 80 DB 76 53 01 86 33 17 32 .!.wWt.. .vS..3.2 +[0CA0] 2E 16 E1 8D 89 3A B2 67 ED A3 ED 39 82 87 26 A6 .....:.g ...9..&. +[0CB0] DB CE 59 84 E4 0A A6 CA 7E 07 98 F7 02 91 6E 56 ..Y..... ~.....nV +[0CC0] 9F 60 03 D3 88 B0 FF EB 20 CA 9E 5B 37 26 67 00 .`...... ..[7&g. +[0CD0] CC BD 9D 53 15 31 53 14 FD 9C E1 28 08 CB C4 0B ...S.1S. ...(.... +[0CE0] E3 50 D9 DB 0C E2 E4 F9 44 50 E9 28 6E 01 96 AA .P...... DP.(n... +[0CF0] C1 D2 4E B2 DE 38 A2 F8 94 32 79 AE 49 64 FB 57 ..N..8.. .2y.Id.W +[0D00] 50 F6 73 E8 98 43 C6 DD 67 3C 91 AC 97 C9 2E 8C P.s..C.. g<...... +[0D10] 06 59 A1 FC 49 EC 2F BF 6F 64 21 63 ED C8 6C CE .Y..I./. od!c..l. +[0D20] 37 28 7B 80 7F 5F 85 F6 98 93 C0 66 A8 D6 F1 2C 7({.._.. ...f..., +[0D30] D8 01 68 B1 C8 EA 82 0D 5B 9B 35 4F 3D B3 47 19 ..h..... [.5O=.G. +[0D40] 54 7A C6 9F AD D7 54 CF B0 DB 3E 18 BA 2A 39 08 Tz....T. ..>..*9. +[0D50] 0C C4 98 4B 43 DE 53 68 25 B1 83 93 1D E1 6C BF ...KC.Sh %.....l. +[0D60] F5 B4 A9 83 17 34 64 8C 2F 91 80 97 4A 48 EC 90 .....4d. /...JH.. +[0D70] BB FA 92 2C 01 80 E4 99 91 0E 67 88 D5 75 AB 7C ...,.... ..g..u.| +[0D80] 98 59 98 45 C9 11 A9 8C 02 98 91 DE AB A0 FF 45 .Y.E.... .......E +[0D90] 11 66 6F C5 DE 61 6D C6 DB C9 CA A3 A0 2B B1 73 .fo..am. .....+.s +[0DA0] 05 85 37 BF AB CA 43 7A 6F 38 C8 BE ED CE 12 49 ..7...Cz o8.....I +[0DB0] 93 C7 7C 1A 33 60 52 7A 67 67 AA 60 57 7E C8 FF ..|.3`Rz gg.`W~.. +[0DC0] DF 91 91 18 45 74 C0 9E 36 19 BC 42 F9 46 CC 84 ....Et.. 6..B.F.. +[0DD0] 09 2E 8C 59 1A E3 65 51 F4 87 6F 4C 3E 29 38 E6 ...Y..eQ ..oL>)8. +[0DE0] 77 E8 A9 B7 FA 00 00 00 00 00 00 00 01 00 00 00 w....... ........ +[0DF0] 01 00 00 00 17 4B 54 45 53 54 2E 53 41 4D 42 41 .....KTE ST.SAMBA +[0E00] 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 00 00 0D .EXAMPLE .COM.... +[0E10] 61 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 00 00 administ rator... +[0E20] 01 00 00 00 02 00 00 00 17 4B 54 45 53 54 2E 53 ........ .KTEST.S +[0E30] 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D AMBA.EXA MPLE.COM +[0E40] 00 00 00 04 63 69 66 73 00 00 00 0B 4C 4F 43 41 ....cifs ....LOCA +[0E50] 4C 4B 54 45 53 54 36 00 17 00 00 00 10 01 78 D0 LKTEST6. ......x. +[0E60] 3B 9B FF F0 88 86 4B 3B FE 41 A9 6B 00 4D 9B 90 ;.....K; .A.k.M.. +[0E70] 45 4D 9B 90 6B 7D 46 4C 43 00 00 00 00 00 40 28 EM..k}FL C.....@( +[0E80] 00 00 00 00 00 00 00 00 00 00 00 00 03 FA 61 82 ........ ......a. +[0E90] 03 F6 30 82 03 F2 A0 03 02 01 05 A1 19 1B 17 4B ..0..... .......K +[0EA0] 54 45 53 54 2E 53 41 4D 42 41 2E 45 58 41 4D 50 TEST.SAM BA.EXAMP +[0EB0] 4C 45 2E 43 4F 4D A2 1E 30 1C A0 03 02 01 01 A1 LE.COM.. 0....... +[0EC0] 15 30 13 1B 04 63 69 66 73 1B 0B 4C 4F 43 41 4C .0...cif s..LOCAL +[0ED0] 4B 54 45 53 54 36 A3 82 03 AE 30 82 03 AA A0 03 KTEST6.. ..0..... +[0EE0] 02 01 17 A1 03 02 01 03 A2 82 03 9C 04 82 03 98 ........ ........ +[0EF0] CA EA 4D 46 2D D1 E9 58 5D 25 8D 9F DF EA C9 01 ..MF-..X ]%...... +[0F00] B6 08 27 CD 14 85 02 DC 20 C6 51 AA F9 6A B1 CE ..'..... .Q..j.. +[0F10] F5 77 84 BF 9A AC 6B A7 B2 F2 1F 60 BF CB C6 FC .w....k. ...`.... +[0F20] C7 14 B7 41 1C A8 C9 70 7B 86 BC 8E 70 2B 65 4B ...A...p {...p+eK +[0F30] DC F5 B9 23 F8 08 BF 96 C9 A8 77 F4 54 67 25 F8 ...#.... ..w.Tg%. +[0F40] 0F A8 C5 D6 D1 BB 46 5E A0 7E D2 98 9C CD AF E0 ......F^ .~...... +[0F50] 82 62 ED 39 D2 FB F2 E8 9B 1B EE E5 B4 1B C9 0A .b.9.... ........ +[0F60] 86 27 52 6E 11 8B D7 AD B4 54 F9 C6 69 8D E0 F1 .'Rn.... .T..i... +[0F70] CD 63 1C 89 7C 8F B6 A0 71 53 A6 DA B1 66 D2 9D .c..|... qS...f.. +[0F80] D3 4C A8 FB C6 9D 81 74 10 8E 84 D2 3D D8 1C BE .L.....t ....=... +[0F90] BB 3F F7 BF 91 3E 89 66 43 A1 E0 90 1B 1A 97 FF .?...>.f C....... +[0FA0] EF CC 35 75 14 62 4F 67 3A 29 F4 F9 C5 2E BE C5 ..5u.bOg :)...... +[0FB0] C2 2B A8 35 22 D9 92 31 1D 49 2A A5 19 AA 08 0F .+.5"..1 .I*..... +[0FC0] A8 22 0B 68 D2 A2 D7 07 7B 37 1E A3 AC 9B 4F 0A .".h.... {7....O. +[0FD0] A4 FA 7F 37 6F 3E 35 79 4E 00 4B B6 28 A3 6A E4 ...7o>5y N.K.(.j. +[0FE0] 0C 95 53 BA E8 41 07 DA BE E9 08 B9 51 24 91 49 ..S..A.. ....Q$.I +[0FF0] 78 5D 44 12 BC 85 63 81 B8 E0 88 D5 95 0C D3 A8 x]D...c. ........ +[1000] 1D 32 4B E4 A0 C8 A7 7D 3C 97 EE D8 59 AC 3A 21 .2K....} <...Y.:! +[1010] 09 F2 7A CC D0 4A F3 50 10 DC FC 26 BB C2 6A 8E ..z..J.P ...&..j. +[1020] 8B 14 2B 2D 50 2E B3 1E 9B D2 69 56 22 F2 48 BD ..+-P... ..iV".H. +[1030] E9 2E 2F 28 DE 77 67 5F 68 AA 29 05 4B 36 58 40 ../(.wg_ h.).K6X@ +[1040] E5 54 11 C5 4D 68 96 49 9D 53 37 87 5F D2 3A 9B .T..Mh.I .S7._.:. +[1050] E9 8E 79 BE AE 11 B4 6B AB FD DB 8A F5 A0 9B 29 ..y....k .......) +[1060] D9 F5 ED CA FA 3F FE 35 FC F4 69 7E E4 D0 44 29 .....?.5 ..i~..D) +[1070] 48 FF 82 61 26 FC D3 E2 10 EE 14 F7 4A E3 CD F2 H..a&... ....J... +[1080] 8B BC 8B 43 64 2C DE 40 6E BB E1 56 C0 B6 2C D0 ...Cd,.@ n..V..,. +[1090] E5 1E E9 B3 FB 38 48 66 ED AF D2 25 D1 35 5C C6 .....8Hf ...%.5\. +[10A0] F0 4D 36 19 0B EC 33 07 34 D0 27 8D 14 DC 01 45 .M6...3. 4.'....E +[10B0] DE F8 73 A6 A0 F4 C1 91 9D BD 05 E3 70 25 E1 10 ..s..... ....p%.. +[10C0] 44 F6 4B 46 F7 24 84 BF 20 96 AD 6A 96 94 81 58 D.KF.$.. ..j...X +[10D0] 80 95 06 92 F5 7F 17 39 3B 32 47 B2 C5 CE 7B 73 .......9 ;2G...{s +[10E0] CF 53 AE FA D1 9A 60 5A 98 EC 8C FA BD C0 CE 8D .S....`Z ........ +[10F0] C5 27 E6 17 1A 4D 47 D8 3F 5D A9 7C FB 2C B3 05 .'...MG. ?].|.,.. +[1100] 0C 69 20 48 99 80 11 DC 48 AB A7 EA 5B 98 C1 15 .i H.... H...[... +[1110] 27 AE FA 3E 1E 1E E0 E1 F8 32 C0 54 13 D6 30 34 '..>.... .2.T..04 +[1120] 71 98 26 61 6C 1C C4 C7 4E C4 A6 7E FE A8 B8 89 q.&al... N..~.... +[1130] 2A 70 3C 19 58 8D 57 45 55 83 0A C2 B5 F7 89 0E *p<.X.WE U....... +[1140] 7B 7A 17 0C CF 6E 08 A5 F7 21 4A 62 81 4F 49 CA {z...n.. .!Jb.OI. +[1150] E2 ED C2 B4 C7 33 5C BC A1 A0 DE 4E 09 37 BE 24 .....3\. ...N.7.$ +[1160] 62 22 94 55 75 AA 53 DE E0 74 5A B0 B8 E9 BF 2B b".Uu.S. .tZ....+ +[1170] 12 65 2F 90 6B 84 ED 11 AD F7 CE 19 A1 96 E4 1E .e/.k... ........ +[1180] 8C EA C8 81 1B 47 4F 5F B1 5D A5 8B E3 0D 5A 80 .....GO_ .]....Z. +[1190] 89 EC 4B D9 CE ED E8 67 7F 96 FC 1B EF 65 C2 68 ..K....g .....e.h +[11A0] 40 F7 20 36 83 58 62 F4 CA 02 F4 5C 0D 46 B1 CB @. 6.Xb. ...\.F.. +[11B0] 50 D2 D8 3D B7 9A 96 48 8C CF EB E6 8C F4 B2 B4 P..=...H ........ +[11C0] 47 C9 34 C9 DC 14 F1 33 1B 6F 9E 65 27 D7 9D 46 G.4....3 .o.e'..F +[11D0] 1E 91 FF 2E FB 8E 97 5D 17 8F 48 54 7C 3C A0 11 .......] ..HT|<.. +[11E0] 9C AA 77 E9 79 DE 26 D1 F0 7C EA 24 73 BE EC 60 ..w.y.&. .|.$s..` +[11F0] B4 EE BD ED 0D 0A AB 74 60 6E 46 C0 35 5B 65 1A .......t `nF.5[e. +[1200] A4 4A 5C 22 AC B9 CD B7 56 06 88 09 FC 48 68 55 .J\".... V....HhU +[1210] B7 5E 39 72 DF 8A 4C CD 79 74 B0 84 0B 78 DA B2 .^9r..L. yt...x.. +[1220] 55 F8 06 0B 5C 27 06 B3 CA 10 65 6B 04 A3 64 11 U...\'.. ..ek..d. +[1230] 04 09 DC DF 67 00 70 B1 16 DF 24 E9 27 85 11 91 ....g.p. ..$.'... +[1240] 31 CB 92 95 50 18 91 08 C2 A1 A3 76 C7 1A FC 64 1...P... ...v...d +[1250] 9E 2C 3A E7 30 F4 16 0D A0 56 C0 BC D2 FE 2D A0 .,:.0... .V....-. +[1260] 20 A4 E2 82 AD F0 C5 12 71 09 23 E1 66 52 53 D0 ....... q.#.fRS. +[1270] 89 30 E7 BE B7 C2 89 F2 1C 7A F6 8E D7 28 F0 A4 .0...... .z...(.. +[1280] 33 46 7C A2 79 66 DE 26 00 00 00 00 3F|.yf.& .... +dump OK -- 2.25.1 From 722c46e13c61c5a08f49ee7975a3ebafaf356a1c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 11:02:47 +1200 Subject: [PATCH 069/645] krb5: Add Python functions to create a credentials cache containing a service ticket This is a FILE: format credentials cache readable by the MIT/Heimdal Kerberos libraries. This allows us to glue the Python ASN1 Kerberos system to the MIT/Heimdal one. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2d88a6ff3dbcf650b09ef9c8c37170ca6663b533) --- python/samba/tests/krb5/kdc_base_test.py | 167 ++++++++++++++++++++++- 1 file changed, 163 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1c7f05dda6d..d8193ae9cdc 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1,6 +1,6 @@ # Unix SMB/CIFS implementation. # Copyright (C) Stefan Metzmacher 2020 -# Copyright (C) 2020 Catalyst.Net Ltd +# Copyright (C) 2020-2021 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 @@ -18,6 +18,8 @@ import sys import os +from datetime import datetime +import tempfile sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" @@ -26,10 +28,10 @@ import ldb from ldb import SCOPE_BASE from samba import generate_random_password from samba.auth import system_session -from samba.credentials import Credentials -from samba.dcerpc import krb5pac +from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS +from samba.dcerpc import krb5pac, krb5ccache from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_NORMAL_ACCOUNT -from samba.ndr import ndr_unpack +from samba.ndr import ndr_pack, ndr_unpack from samba.samdb import SamDB from samba.tests import delete_force @@ -38,6 +40,8 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( AD_IF_RELEVANT, AD_WIN2K_PAC, + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, KDC_ERR_PREAUTH_REQUIRED, KRB_AS_REP, KRB_TGS_REP, @@ -46,6 +50,8 @@ from samba.tests.krb5.rfc4120_constants import ( KU_PA_ENC_TIMESTAMP, KU_TGS_REP_ENC_PART_SUB_KEY, KU_TICKET, + NT_PRINCIPAL, + NT_SRV_HST, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO2, ) @@ -445,3 +451,156 @@ class KDCBaseTest(RawKerberosTest): msg = ldb.Message(dn) msg[name] = ldb.MessageElement(values, flag, name) self.ldb.modify(msg) + + def create_ccache(self, cname, ticket, enc_part): + """ Lay out a version 4 on-disk credentials cache, to be read using the + FILE: protocol. + """ + + field = krb5ccache.DELTATIME_TAG() + field.kdc_sec_offset = 0 + field.kdc_usec_offset = 0 + + v4tag = krb5ccache.V4TAG() + v4tag.tag = 1 + v4tag.field = field + + v4tags = krb5ccache.V4TAGS() + v4tags.tag = v4tag + v4tags.further_tags = b'' + + optional_header = krb5ccache.V4HEADER() + optional_header.v4tags = v4tags + + cname_string = cname['name-string'] + + cprincipal = krb5ccache.PRINCIPAL() + cprincipal.name_type = cname['name-type'] + cprincipal.component_count = len(cname_string) + cprincipal.realm = ticket['realm'] + cprincipal.components = cname_string + + sname = ticket['sname'] + sname_string = sname['name-string'] + + sprincipal = krb5ccache.PRINCIPAL() + sprincipal.name_type = sname['name-type'] + sprincipal.component_count = len(sname_string) + sprincipal.realm = ticket['realm'] + sprincipal.components = sname_string + + key = self.EncryptionKey_import(enc_part['key']) + + key_data = key.export_obj() + keyblock = krb5ccache.KEYBLOCK() + keyblock.enctype = key_data['keytype'] + keyblock.data = key_data['keyvalue'] + + addresses = krb5ccache.ADDRESSES() + addresses.count = 0 + addresses.data = [] + + authdata = krb5ccache.AUTHDATA() + authdata.count = 0 + authdata.data = [] + + # Re-encode the ticket, since it was decoded by another layer. + ticket_data = self.der_encode(ticket, asn1Spec=krb5_asn1.Ticket()) + + authtime = enc_part['authtime'] + try: + starttime = enc_part['starttime'] + except KeyError: + starttime = authtime + endtime = enc_part['endtime'] + + cred = krb5ccache.CREDENTIAL() + cred.client = cprincipal + cred.server = sprincipal + cred.keyblock = keyblock + cred.authtime = int(datetime.strptime(authtime.decode(), + "%Y%m%d%H%M%SZ").timestamp()) + cred.starttime = int(datetime.strptime(starttime.decode(), + "%Y%m%d%H%M%SZ").timestamp()) + cred.endtime = int(datetime.strptime(endtime.decode(), + "%Y%m%d%H%M%SZ").timestamp()) + cred.renew_till = cred.endtime + cred.is_skey = 0 + cred.ticket_flags = int(enc_part['flags'], 2) + cred.addresses = addresses + cred.authdata = authdata + cred.ticket = ticket_data + cred.second_ticket = b'' + + ccache = krb5ccache.CCACHE() + ccache.pvno = 5 + ccache.version = 4 + ccache.optional_header = optional_header + ccache.principal = cprincipal + ccache.cred = cred + + # Serialise the credentials cache structure. + result = ndr_pack(ccache) + + # Create a temporary file and write the credentials. + cachefile = tempfile.NamedTemporaryFile(dir=self.tempdir, delete=False) + cachefile.write(result) + cachefile.close() + + return cachefile + + def create_ccache_with_user(self, user_credentials, mach_name, + service="host"): + # Obtain a service ticket authorising the user and place it into a + # newly created credentials cache file. + + user_name = user_credentials.get_username() + realm = user_credentials.get_realm() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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_HST, + names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(user_credentials, rep) + key = self.get_as_rep_key(user_credentials, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part['key']) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create(name_type=NT_SRV_HST, + names=[service, mach_name]) + + (rep, enc_part) = self.tgs_req( + cname, sname, realm, ticket, key, etype) + self.check_tgs_reply(rep) + key = self.EncryptionKey_import(enc_part['key']) + + # Check the contents of the pac, and the ticket + ticket = rep['ticket'] + + # Write the ticket into a credentials cache file that can be ingested + # by the main credentials code. + cachefile = self.create_ccache(cname, ticket, enc_part) + + # Create a credentials object to reference the credentials cache. + creds = Credentials() + creds.set_kerberos_state(MUST_USE_KERBEROS) + creds.set_username(user_name, SPECIFIED) + creds.set_realm(realm) + creds.set_named_ccache(cachefile.name, SPECIFIED, self.lp) + + # Return the credentials along with the cache file. + return (creds, cachefile) -- 2.25.1 From ffbd4d841e90df64a9ed50503a347a0708d80fce Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 11:06:33 +1200 Subject: [PATCH 070/645] python: Add credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service using the normal credentials system backed on to MIT/Heimdal Kerberos 5 libraries. This will allow us to validate the output of the MIT/Heimdal libraries in the future. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit c15f26ec40860782b22e862f9bdf665745387718) --- python/samba/tests/krb5/raw_testcase.py | 8 +- python/samba/tests/krb5/rfc4120_constants.py | 1 + python/samba/tests/krb5/test_ccache.py | 127 +++++++++++++++++++ python/samba/tests/usage.py | 1 + source4/selftest/tests.py | 2 + 5 files changed, 135 insertions(+), 4 deletions(-) create mode 100755 python/samba/tests/krb5/test_ccache.py diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 82e68ee7019..27ab89ecf99 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -25,7 +25,7 @@ import random import samba.tests from samba.credentials import Credentials -from samba.tests import TestCase +from samba.tests import TestCaseInTempDir import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 import samba.tests.krb5.kcrypto as kcrypto @@ -178,11 +178,11 @@ class Krb5EncryptionKey(object): return EncryptionKey_obj -class RawKerberosTest(TestCase): +class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" def setUp(self): - super(RawKerberosTest, self).setUp() + super().setUp() self.do_asn1_print = False self.do_hexdump = False @@ -192,7 +192,7 @@ class RawKerberosTest(TestCase): def tearDown(self): self._disconnect("tearDown") - super(TestCase, self).tearDown() + super().tearDown() def _disconnect(self, reason): if self.s is None: diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 5bbf1229d09..702f6084217 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -46,6 +46,7 @@ KDC_ERR_SKEW = 37 # Name types NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) +NT_SRV_HST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-HST')) NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues( 'kRB5-NT-ENTERPRISE-PRINCIPAL')) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py new file mode 100755 index 00000000000..e0998a4c43f --- /dev/null +++ b/python/samba/tests/krb5/test_ccache.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 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 sys +import os + +from ldb import SCOPE_SUBTREE +from samba import gensec +from samba.auth import AuthContext +from samba.dcerpc import security +from samba.ndr import ndr_unpack + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class CcacheTests(KDCBaseTest): + """Test for authentication using Kerberos credentials stored in a + credentials cache file. + """ + + def test_ccache(self): + # Create a user account and a machine account, along with a Kerberos + # credentials cache file where the service ticket authenticating the + # user are stored. + + user_name = "ccacheusr" + mach_name = "ccachemac" + + # Create the user account. + (user_credentials, _) = self.create_account(user_name) + + # Create the machine account. + (mach_credentials, _) = self.create_account(mach_name, + machine_account=True) + + # 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 + # ticket, to ensure that the krbtgt ticket doesn't also need to be + # stored. + (creds, cachefile) = self.create_ccache_with_user(user_credentials, + mach_name) + + # Authenticate in-process to the machine account using the user's + # cached credentials. + + settings = {} + settings["lp_ctx"] = self.lp + settings["target_hostname"] = mach_name + + gensec_client = gensec.Security.start_client(settings) + gensec_client.set_credentials(creds) + gensec_client.want_feature(gensec.FEATURE_SEAL) + gensec_client.start_mech_by_sasl_name("GSSAPI") + + auth_context = AuthContext(lp_ctx=self.lp, ldb=self.ldb, methods=[]) + + gensec_server = gensec.Security.start_server(settings, auth_context) + gensec_server.set_credentials(mach_credentials) + + gensec_server.start_mech_by_sasl_name("GSSAPI") + + client_finished = False + server_finished = False + server_to_client = b'' + + # Operate as both the client and the server to verify the user's + # credentials. + while not client_finished or not server_finished: + if not client_finished: + print("running client gensec_update") + (client_finished, client_to_server) = gensec_client.update( + server_to_client) + if not server_finished: + print("running server gensec_update") + (server_finished, server_to_client) = gensec_server.update( + client_to_server) + + # Ensure that the first SID contained within the obtained security + # token is the SID of the user we created. + + # Retrieve the user account's SID. + ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) + self.assertEqual(1, len(ldb_res)) + sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + + # Retrieve the SIDs from the security token. + session = gensec_server.session_info() + token = session.security_token + token_sids = token.sids + self.assertGreater(len(token_sids), 0) + + # Ensure that they match. + self.assertEqual(sid, token_sids[0]) + + # Remove the cached credentials file. + os.remove(cachefile.name) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 1b22461c735..2ca1e0215ce 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -95,6 +95,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/kdc_tests.py', 'python/samba/tests/krb5/kdc_base_test.py', 'python/samba/tests/krb5/kdc_tgs_tests.py', + 'python/samba/tests/krb5/test_ccache.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', } diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 9bb2ff2e1ed..d5b51ad3a3a 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -752,6 +752,8 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache") + for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite(env + ":local", "samba.tests.ntacls_backup", -- 2.25.1 From 31d3ac2bcb162869c6932f0c2e49e002c3ab009c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Apr 2021 20:58:11 +1200 Subject: [PATCH 071/645] python: Add LDAP credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through LDAP. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 7663b5c37fa3413f7c67c018107322494e4a6fd9) --- python/samba/tests/krb5/test_ldap.py | 94 ++++++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + source4/selftest/tests.py | 1 + 3 files changed, 96 insertions(+) create mode 100755 python/samba/tests/krb5/test_ldap.py diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py new file mode 100755 index 00000000000..6a4bf52d77f --- /dev/null +++ b/python/samba/tests/krb5/test_ldap.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 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 sys +import os + +from ldb import SCOPE_BASE, SCOPE_SUBTREE +from samba.dcerpc import security +from samba.ndr import ndr_unpack +from samba.samdb import SamDB + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class LdapTests(KDCBaseTest): + """Test for LDAP authentication using Kerberos credentials stored in a + credentials cache file. + """ + + def test_ldap(self): + # Create a user account and a machine account, along with a Kerberos + # credentials cache file where the service ticket authenticating the + # user are stored. + + user_name = "ldapusr" + mach_name = self.dns_host_name + service = "ldap" + + # Create the user account. + (user_credentials, _) = self.create_account(user_name) + + # 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 + # ticket, to ensure that the krbtgt ticket doesn't also need to be + # stored. + (creds, cachefile) = self.create_ccache_with_user(user_credentials, + mach_name, + service) + + # Authenticate in-process to the machine account using the user's + # cached credentials. + + # Retrieve the user account's SID. + ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) + self.assertEqual(1, len(ldb_res)) + sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + + # Connect to the machine account and retrieve the user SID. + ldb_as_user = SamDB(url="ldap://%s" % mach_name, + credentials=creds, + lp=self.lp) + ldb_res = ldb_as_user.search('', + scope=SCOPE_BASE, + attrs=["tokenGroups"]) + self.assertEqual(1, len(ldb_res)) + + token_sid = ndr_unpack(security.dom_sid, ldb_res[0]["tokenGroups"][0]) + + # Ensure that they match. + self.assertEqual(sid, token_sid) + + # Remove the cached credentials file. + os.remove(cachefile.name) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 2ca1e0215ce..45636f3d3a3 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -96,6 +96,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/kdc_base_test.py', 'python/samba/tests/krb5/kdc_tgs_tests.py', 'python/samba/tests/krb5/test_ccache.py', + 'python/samba/tests/krb5/test_ldap.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', } diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index d5b51ad3a3a..83fe47cbc20 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -753,6 +753,7 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache") +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap") for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From 13cfa898cc5ec314710eca97631320d5df53b9aa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Apr 2021 21:04:25 +1200 Subject: [PATCH 072/645] python: Add RPC credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through RPC. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 072451a033da07c0cdaa005dd1020ef1c7951e99) --- python/samba/tests/krb5/test_rpc.py | 77 +++++++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + source4/selftest/tests.py | 1 + 3 files changed, 79 insertions(+) create mode 100755 python/samba/tests/krb5/test_rpc.py diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py new file mode 100755 index 00000000000..da1c4eb88ac --- /dev/null +++ b/python/samba/tests/krb5/test_rpc.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 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 sys +import os + +from samba.dcerpc import lsa + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class RpcTests(KDCBaseTest): + """Test for RPC authentication using Kerberos credentials stored in a + credentials cache file. + """ + + def test_rpc(self): + # Create a user account and a machine account, along with a Kerberos + # credentials cache file where the service ticket authenticating the + # user are stored. + + user_name = "rpcusr" + mach_name = self.dns_host_name + service = "cifs" + + # Create the user account. + (user_credentials, _) = self.create_account(user_name) + + # 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 + # ticket, to ensure that the krbtgt ticket doesn't also need to be + # stored. + (creds, cachefile) = self.create_ccache_with_user(user_credentials, + mach_name, + service) + + # Authenticate in-process to the machine account using the user's + # cached credentials. + + binding_str = "ncacn_np:%s[\\pipe\\lsarpc]" % mach_name + conn = lsa.lsarpc(binding_str, self.lp, creds) + + (account_name, _) = conn.GetUserName(None, None, None) + + self.assertEqual(user_name, account_name.string) + + # Remove the cached credentials file. + os.remove(cachefile.name) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 45636f3d3a3..eb7c003b48b 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -97,6 +97,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/kdc_tgs_tests.py', 'python/samba/tests/krb5/test_ccache.py', 'python/samba/tests/krb5/test_ldap.py', + 'python/samba/tests/krb5/test_rpc.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', } diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 83fe47cbc20..5acbeda6bbe 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -754,6 +754,7 @@ planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap") +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc") for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From 4f807efdad0d00d3c3a52d29234a8107cf8d6ff0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 15:48:43 +1200 Subject: [PATCH 073/645] Revert "libsmb: Use sid_parse()" This reverts commit afd5d34f5e1d13ba88448b3b94d353aa8361d1a9. This code originally used ndr_pull_struct_blob() to pull one SID from a buffer potentially containing multiple SIDs. When this was changed to use sid_parse(), it was now attempting to parse the whole buffer as a single SID with ndr_pull_struct_blob_all(), which would cause it to fail if more than one SID was present. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2b487890d946df88abce67c3d07d74559f70f069) --- source3/libsmb/clifsinfo.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 1c140ebbd59..09c0d9535f1 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -29,7 +29,6 @@ #include "../libcli/smb/smbXcli_base.h" #include "auth/credentials/credentials.h" #include "../librpc/gen_ndr/ndr_security.h" -#include "libcli/security/dom_sid.h" /**************************************************************************** Get UNIX extensions version info. @@ -686,9 +685,23 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) num_rdata -= (p - rdata); for (i = 0; i < state->num_sids; i++) { - ssize_t sid_size = sid_parse(p, num_rdata, &state->sids[i]); + size_t sid_size; + DATA_BLOB in = data_blob_const(p, num_rdata); + enum ndr_err_code ndr_err; - if ((sid_size == -1) || (sid_size > num_rdata)) { + ndr_err = ndr_pull_struct_blob(&in, + state, + &state->sids[i], + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + tevent_req_nterror(req, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + sid_size = ndr_size_dom_sid(&state->sids[i], 0); + + if (sid_size > num_rdata) { tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; -- 2.25.1 From 468548531aeb4cbe225541ad4654669e56992f0e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 15:55:01 +1200 Subject: [PATCH 074/645] libsmb: Remove overflow check Pointer overflow is undefined, so this check does not accomplish anything. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit db5b34c7682e36630908356cf674fddd18d8fa1f) --- source3/libsmb/clifsinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 09c0d9535f1..cc9f7382d49 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -650,7 +650,7 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) * parsing network packets in C. */ - if (num_rdata < 40 || rdata + num_rdata < rdata) { + if (num_rdata < 40) { tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } -- 2.25.1 From 88e0b2d428c3ea3fe3a3c5d9aab510ac2619cc50 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 16:16:51 +1200 Subject: [PATCH 075/645] libsmb: Avoid undefined behaviour when parsing whoami state If num_gids is such that the gids array would overflow the rdata buffer, 'p + 8' could produce a result pointing outside the buffer, and thus result in undefined behaviour. To avoid this, we check num_gids against the size of the buffer beforehand. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 9d8aeed33d8edf7a5dc96dbe35e4e164e2baeeeb) --- source3/libsmb/clifsinfo.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index cc9f7382d49..aca559d153b 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -661,6 +661,13 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) state->num_gids = IVAL(rdata, 24); state->num_sids = IVAL(rdata, 28); + /* Ensure the gid array doesn't overflow */ + if (state->num_gids > (num_rdata - 40) / sizeof(uint64_t)) { + tevent_req_nterror(req, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + state->gids = talloc_array(state, uint64_t, state->num_gids); if (tevent_req_nomem(state->gids, req)) { return; @@ -673,11 +680,6 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) p = rdata + 40; for (i = 0; i < state->num_gids; i++) { - if (p + 8 > rdata + num_rdata) { - tevent_req_nterror(req, - NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } state->gids[i] = BVAL(p, 0); p += 8; } -- 2.25.1 From 1d830b72140fa95a708cf08443e3abc6efb7c546 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 16:22:43 +1200 Subject: [PATCH 076/645] libsmb: Check to see that whoami is not receiving more data than it requested Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 9e414233c84d2f2fa4a9415be9ee975eca8b9bfd) --- source3/libsmb/clifsinfo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index aca559d153b..6f3c07a8a7e 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -570,6 +570,8 @@ struct posix_whoami_state { static void cli_posix_whoami_done(struct tevent_req *subreq); +static const uint32_t posix_whoami_max_rdata = 62*1024; + struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli) @@ -586,7 +588,7 @@ struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx, SSVAL(state->setup, 0, TRANSACT2_QFSINFO); SSVAL(state->param, 0, SMB_QUERY_POSIX_WHOAMI); - state->max_rdata = 62*1024; + state->max_rdata = posix_whoami_max_rdata; subreq = cli_trans_send(state, /* mem ctx. */ ev, /* event ctx. */ @@ -650,7 +652,7 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) * parsing network packets in C. */ - if (num_rdata < 40) { + if (num_rdata < 40 || num_rdata > posix_whoami_max_rdata) { tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } -- 2.25.1 From c9d13bc9d0f368858b4e04f4fd6ec326b101a9ce Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 16:24:42 +1200 Subject: [PATCH 077/645] libsmb: Ensure that whoami parses all the data provided to it Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 9b96ebea5c6966b096cf1100a0895a9c41f2aa1d) --- source3/libsmb/clifsinfo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 6f3c07a8a7e..f09428bdbcb 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -714,6 +714,13 @@ static void cli_posix_whoami_done(struct tevent_req *subreq) p += sid_size; num_rdata -= sid_size; } + + if (num_rdata != 0) { + tevent_req_nterror(req, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + tevent_req_done(req); } -- 2.25.1 From a4df60363edb107d0a1287b394ace2f7fccbaea6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 30 Apr 2021 12:49:24 +1200 Subject: [PATCH 078/645] pylibsmb: Add posix_whoami() Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 [abartlet@samba.org backport from commit 482559436f12a85adb3409433aac3ab06baa82b1 as the 4.13 backport doesn't have ealier pylibsmb changes including 752a8f870de2bb087802a1287d7fb6c7624ac631 (s3:pylibsmb: remove unused SECINFO_DEFAULT_FLAGS)] --- source3/libsmb/pylibsmb.c | 138 +++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index c09df917251..a882fe2f2a7 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -43,6 +43,8 @@ SECINFO_DACL | SECINFO_PROTECTED_DACL | SECINFO_UNPROTECTED_DACL | \ SECINFO_SACL | SECINFO_PROTECTED_SACL | SECINFO_UNPROTECTED_SACL) +static PyTypeObject *dom_sid_Type = NULL; + static PyTypeObject *get_pytype(const char *module, const char *type) { PyObject *mod; @@ -1357,6 +1359,123 @@ static PyObject *py_smb_mkdir(struct py_cli_state *self, PyObject *args) Py_RETURN_NONE; } +/* + * Does a whoami call + */ +static PyObject *py_smb_posix_whoami(struct py_cli_state *self, + PyObject *Py_UNUSED(ignored)) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + struct tevent_req *req = NULL; + uint64_t uid; + uint64_t gid; + uint32_t num_gids; + uint64_t *gids = NULL; + uint32_t num_sids; + struct dom_sid *sids = NULL; + bool guest; + PyObject *py_gids = NULL; + PyObject *py_sids = NULL; + PyObject *py_guest = NULL; + PyObject *py_ret = NULL; + Py_ssize_t i; + + req = cli_posix_whoami_send(frame, self->ev, self->cli); + if (!py_tevent_req_wait_exc(self, req)) { + goto fail; + } + status = cli_posix_whoami_recv(req, + frame, + &uid, + &gid, + &num_gids, + &gids, + &num_sids, + &sids, + &guest); + if (!NT_STATUS_IS_OK(status)) { + PyErr_SetNTSTATUS(status); + goto fail; + } + if (num_gids > PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, "posix_whoami: Too many GIDs"); + goto fail; + } + if (num_sids > PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, "posix_whoami: Too many SIDs"); + goto fail; + } + + py_gids = PyList_New(num_gids); + if (!py_gids) { + goto fail; + } + for (i = 0; i < num_gids; ++i) { + int ret; + PyObject *py_item = PyLong_FromUnsignedLongLong(gids[i]); + if (!py_item) { + goto fail2; + } + + ret = PyList_SetItem(py_gids, i, py_item); + if (ret) { + goto fail2; + } + } + py_sids = PyList_New(num_sids); + if (!py_sids) { + goto fail2; + } + for (i = 0; i < num_sids; ++i) { + int ret; + struct dom_sid *sid; + PyObject *py_item; + + sid = dom_sid_dup(frame, &sids[i]); + if (!sid) { + PyErr_NoMemory(); + goto fail3; + } + + py_item = pytalloc_steal(dom_sid_Type, sid); + if (!py_item) { + PyErr_NoMemory(); + goto fail3; + } + + ret = PyList_SetItem(py_sids, i, py_item); + if (ret) { + goto fail3; + } + } + + py_guest = guest ? Py_True : Py_False; + + py_ret = Py_BuildValue("KKNNO", + uid, + gid, + py_gids, + py_sids, + py_guest); + if (!py_ret) { + goto fail3; + } + + TALLOC_FREE(frame); + return py_ret; + +fail3: + Py_CLEAR(py_sids); + +fail2: + Py_CLEAR(py_gids); + +fail: + TALLOC_FREE(frame); + return NULL; +} + /* * Checks existence of a directory */ @@ -1618,6 +1737,8 @@ static PyMethodDef py_cli_state_methods[] = { "unlink(path) -> None\n\n \t\tDelete a file." }, { "mkdir", (PyCFunction)py_smb_mkdir, METH_VARARGS, "mkdir(path) -> None\n\n \t\tCreate a directory." }, + { "posix_whoami", (PyCFunction)py_smb_posix_whoami, METH_NOARGS, + "posix_whoami() -> (uid, gid, gids, sids, guest)" }, { "rmdir", (PyCFunction)py_smb_rmdir, METH_VARARGS, "rmdir(path) -> None\n\n \t\tDelete a directory." }, { "chkpath", (PyCFunction)py_smb_chkpath, METH_VARARGS, @@ -1670,16 +1791,31 @@ static struct PyModuleDef moduledef = { MODULE_INIT_FUNC(libsmb_samba_internal) { PyObject *m = NULL; + PyObject *mod = NULL; talloc_stackframe(); + if (PyType_Ready(&py_cli_state_type) < 0) { + return NULL; + } + m = PyModule_Create(&moduledef); if (m == NULL) { return m; } - if (PyType_Ready(&py_cli_state_type) < 0) { + + /* Import dom_sid type from dcerpc.security */ + mod = PyImport_ImportModule("samba.dcerpc.security"); + if (mod == NULL) { return NULL; } + + dom_sid_Type = (PyTypeObject *)PyObject_GetAttrString(mod, "dom_sid"); + if (dom_sid_Type == NULL) { + Py_DECREF(mod); + return NULL; + } + Py_INCREF(&py_cli_state_type); PyModule_AddObject(m, "Conn", (PyObject *)&py_cli_state_type); -- 2.25.1 From b1467c9533ce11aa5c3436564780764974648a1b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 30 Apr 2021 08:58:11 +1200 Subject: [PATCH 079/645] python: Add SMB credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through SMB. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 78a0b57b51642df07deed8aeb6e39e608fafda60) --- python/samba/tests/krb5/test_smb.py | 108 ++++++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + source4/selftest/tests.py | 1 + 3 files changed, 110 insertions(+) create mode 100755 python/samba/tests/krb5/test_smb.py diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py new file mode 100755 index 00000000000..0262a37ebb5 --- /dev/null +++ b/python/samba/tests/krb5/test_smb.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 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 sys +import os + +from ldb import SCOPE_SUBTREE +from samba.dcerpc import security +from samba.ndr import ndr_unpack +from samba.samba3 import libsmb_samba_internal as libsmb +from samba.samba3 import param as s3param + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class SmbTests(KDCBaseTest): + """Test for SMB authentication using Kerberos credentials stored in a + credentials cache file. + """ + + def test_smb(self): + # Create a user account and a machine account, along with a Kerberos + # credentials cache file where the service ticket authenticating the + # user are stored. + + user_name = "smbusr" + mach_name = self.dns_host_name + service = "cifs" + share = "tmp" + + # Create the user account. + (user_credentials, _) = self.create_account(user_name) + + # 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 + # ticket, to ensure that the krbtgt ticket doesn't also need to be + # stored. + (creds, cachefile) = self.create_ccache_with_user(user_credentials, + mach_name, + service) + + # Set the Kerberos 5 credentials cache environment variable. This is + # required because the codepath that gets run (gse_krb5) looks for it + # in here and not in the credentials object. + krb5_ccname = os.environ.get("KRB5CCNAME", "") + self.addCleanup(os.environ.__setitem__, "KRB5CCNAME", krb5_ccname) + os.environ["KRB5CCNAME"] = "FILE:" + cachefile.name + + # Authenticate in-process to the machine account using the user's + # cached credentials. + + # Retrieve the user account's SID. + ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) + self.assertEqual(1, len(ldb_res)) + sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + + # Connect to a share and retrieve the user SID. + s3_lp = s3param.get_context() + s3_lp.load(self.lp.configfile) + + min_protocol = s3_lp.get("client min protocol") + self.addCleanup(s3_lp.set, "client min protocol", min_protocol) + s3_lp.set("client min protocol", "NT1") + + max_protocol = s3_lp.get("client max protocol") + self.addCleanup(s3_lp.set, "client max protocol", max_protocol) + s3_lp.set("client max protocol", "NT1") + + conn = libsmb.Conn(mach_name, share, lp=s3_lp, creds=creds) + + (uid, gid, gids, sids, guest) = conn.posix_whoami() + + # Ensure that they match. + self.assertEqual(sid, sids[0]) + + # Remove the cached credentials file. + os.remove(cachefile.name) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index eb7c003b48b..e8eda7d6896 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -98,6 +98,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/test_ccache.py', 'python/samba/tests/krb5/test_ldap.py', 'python/samba/tests/krb5/test_rpc.py', + 'python/samba/tests/krb5/test_smb.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', } diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 5acbeda6bbe..f26bdc2bf6f 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -755,6 +755,7 @@ planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc") +planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb") for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From b42676c2d97e77b7ec107a949af52d68fa771ac0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 14:42:10 +1200 Subject: [PATCH 080/645] python: Ensure reference counts are properly incremented Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 290c1dc0975867a71c02e911708323d1f38b6f96) --- lib/talloc/pytalloc.c | 4 ++-- libgpo/pygpo.c | 2 +- source4/auth/gensec/pygensec.c | 4 ++-- source4/librpc/ndr/py_security.c | 2 +- source4/ntvfs/posix/python/pyposix_eadb.c | 2 +- source4/ntvfs/posix/python/pyxattr_native.c | 4 ++-- source4/ntvfs/posix/python/pyxattr_tdb.c | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c index 12c7325fcac..700e0f7f2af 100644 --- a/lib/talloc/pytalloc.c +++ b/lib/talloc/pytalloc.c @@ -37,7 +37,7 @@ static PyObject *pytalloc_report_full(PyObject *self, PyObject *args) } else { talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout); } - return Py_None; + Py_RETURN_NONE; } /* enable null tracking */ @@ -45,7 +45,7 @@ static PyObject *pytalloc_enable_null_tracking(PyObject *self, PyObject *Py_UNUSED(ignored)) { talloc_enable_null_tracking(); - return Py_None; + Py_RETURN_NONE; } /* return the number of talloc blocks */ diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index 97bbb3ec528..ddfb5c76ef9 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -41,7 +41,7 @@ static PyObject* GPO_get_##ATTR(PyObject *self, void *closure) \ if (gpo_ptr->ATTR) \ return PyUnicode_FromString(gpo_ptr->ATTR); \ else \ - return Py_None; \ + Py_RETURN_NONE; \ } GPO_getter(ds_path) GPO_getter(file_sys_path) diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index 35b3307ab8f..35095344168 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -426,9 +426,9 @@ static PyObject *py_gensec_have_feature(PyObject *self, PyObject *args) return NULL; if (gensec_have_feature(security, feature)) { - return Py_True; + Py_RETURN_TRUE; } - return Py_False; + Py_RETURN_FALSE; } static PyObject *py_gensec_set_max_update_size(PyObject *self, PyObject *args) diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index 0b8a1c66b7a..fc0aea99c3b 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -342,7 +342,7 @@ static PyObject *py_descriptor_richcmp( break; } - return Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } static void py_descriptor_patch(PyTypeObject *type) diff --git a/source4/ntvfs/posix/python/pyposix_eadb.c b/source4/ntvfs/posix/python/pyposix_eadb.c index ef4db0e867a..14979b95a58 100644 --- a/source4/ntvfs/posix/python/pyposix_eadb.c +++ b/source4/ntvfs/posix/python/pyposix_eadb.c @@ -32,7 +32,7 @@ static PyObject *py_is_xattr_supported(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return Py_True; + Py_RETURN_TRUE; } static PyObject *py_wrap_setxattr(PyObject *self, PyObject *args) diff --git a/source4/ntvfs/posix/python/pyxattr_native.c b/source4/ntvfs/posix/python/pyxattr_native.c index 7d5bee0c37c..c479be66a65 100644 --- a/source4/ntvfs/posix/python/pyxattr_native.c +++ b/source4/ntvfs/posix/python/pyxattr_native.c @@ -29,9 +29,9 @@ static PyObject *py_is_xattr_supported(PyObject *self, PyObject *Py_UNUSED(ignored)) { #if !defined(HAVE_XATTR_SUPPORT) - return Py_False; + Py_RETURN_FALSE; #else - return Py_True; + Py_RETURN_TRUE; #endif } diff --git a/source4/ntvfs/posix/python/pyxattr_tdb.c b/source4/ntvfs/posix/python/pyxattr_tdb.c index 397cae77bc9..133c7089d5f 100644 --- a/source4/ntvfs/posix/python/pyxattr_tdb.c +++ b/source4/ntvfs/posix/python/pyxattr_tdb.c @@ -36,7 +36,7 @@ static PyObject *py_is_xattr_supported(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return Py_True; + Py_RETURN_TRUE; } static PyObject *py_wrap_setxattr(PyObject *self, PyObject *args) -- 2.25.1 From 683872460d45cd18327e40d475f4245cd7b6f3d8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 3 May 2021 14:43:04 +1200 Subject: [PATCH 081/645] python: Fix erroneous increments of reference counts Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 66695f0f94775c4db24fb625fe78ff44d964b5ad) --- source3/passdb/py_passdb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source3/passdb/py_passdb.c b/source3/passdb/py_passdb.c index f7e80c47397..c323adf2969 100644 --- a/source3/passdb/py_passdb.c +++ b/source3/passdb/py_passdb.c @@ -2075,8 +2075,6 @@ static PyObject *py_pdb_enum_group_mapping(PyObject *self, PyObject *args) PyObject *py_gmap_list, *py_group_map; int i; - Py_INCREF(Py_None); - if (!PyArg_ParseTuple(args, "|O!ii:enum_group_mapping", dom_sid_Type, &py_domain_sid, &lsa_sidtype_value, &unix_only)) { talloc_free(frame); @@ -2816,8 +2814,6 @@ static PyObject *py_pdb_search_aliases(PyObject *self, PyObject *args) PyObject *py_domain_sid = Py_None; struct dom_sid *domain_sid = NULL; - Py_INCREF(Py_None); - if (!PyArg_ParseTuple(args, "|O!:search_aliases", dom_sid_Type, &py_domain_sid)) { talloc_free(frame); return NULL; -- 2.25.1 From c10f2a41b0d6b22d39af2095b9881ea97b18f8dd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 10 May 2021 16:43:03 +1200 Subject: [PATCH 082/645] python: Fix ticket timestamp conversion when local timezone is not UTC Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b9006f33343ba8bb82ef8ffe1fd90c780961b41e) --- python/samba/tests/krb5/kdc_base_test.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index d8193ae9cdc..e345f739e1c 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -18,7 +18,7 @@ import sys import os -from datetime import datetime +from datetime import datetime, timezone import tempfile sys.path.insert(0, "bin/python") @@ -519,11 +519,26 @@ class KDCBaseTest(RawKerberosTest): cred.server = sprincipal cred.keyblock = keyblock cred.authtime = int(datetime.strptime(authtime.decode(), - "%Y%m%d%H%M%SZ").timestamp()) + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) cred.starttime = int(datetime.strptime(starttime.decode(), - "%Y%m%d%H%M%SZ").timestamp()) + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) cred.endtime = int(datetime.strptime(endtime.decode(), - "%Y%m%d%H%M%SZ").timestamp()) + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) + + # Account for clock skew of up to five minutes. + self.assertLess(cred.authtime - 5*60, + datetime.now(timezone.utc).timestamp(), + "Ticket not yet valid - clocks may be out of sync.") + self.assertLess(cred.starttime - 5*60, + datetime.now(timezone.utc).timestamp(), + "Ticket not yet valid - clocks may be out of sync.") + self.assertGreater(cred.endtime - 60*60, + datetime.now(timezone.utc).timestamp(), + "Ticket already expired/about to expire - clocks may be out of sync.") + cred.renew_till = cred.endtime cred.is_skey = 0 cred.ticket_flags = int(enc_part['flags'], 2) -- 2.25.1 From 391b4538fa0c2064a32f3f4dba61b4b8fc419bf3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 10 May 2021 15:06:06 +1200 Subject: [PATCH 083/645] python: Make credentials cache test run against Windows Windows, unlike Samba, requires the service principal name to be set when requesting a ticket to that service. Additionally, default_realm from the libdefaults section of krb5.conf should be set so that the correct realm is used. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed May 19 02:22:01 UTC 2021 on sn-devel-184 (cherry picked from commit 7791acb074b84ec7b571a81f15b56d33e2214ce9) --- python/samba/tests/krb5/test_ccache.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index e0998a4c43f..32c9e3cce6b 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -47,13 +47,16 @@ class CcacheTests(KDCBaseTest): user_name = "ccacheusr" mach_name = "ccachemac" + service = "host" # Create the user account. (user_credentials, _) = self.create_account(user_name) # Create the machine account. (mach_credentials, _) = self.create_account(mach_name, - machine_account=True) + machine_account=True, + spn="%s/%s" % (service, + mach_name)) # 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 -- 2.25.1 From b3fe7ab0c493db72c38318d828e067045232abd9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Apr 2020 21:04:44 +0200 Subject: [PATCH 084/645] auth/credentials: allow credentials.Credentials to act as base class In tests it's useful to add more details. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1f413b2b2977687884781ca2399dadf6611ab461) --- auth/credentials/pycredentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 314f0eba894..ad39fe13925 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1221,7 +1221,7 @@ static struct PyModuleDef moduledef = { PyTypeObject PyCredentials = { .tp_name = "credentials.Credentials", .tp_new = py_creds_new, - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_methods = py_creds_methods, }; -- 2.25.1 From 9ccd5f89d624a4a7dacac79e5b42f8afb851b6f6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Apr 2020 16:50:55 +0200 Subject: [PATCH 085/645] Rename python/samba/tests/krb5/{rfc4120_pyasn1_regen.sh => pyasn1_regen.sh} This is a clearer name for the script Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit fef08add9ec324fb0c3902e96c2a91c07646d499) --- .../samba/tests/krb5/{rfc4120_pyasn1_regen.sh => pyasn1_regen.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/samba/tests/krb5/{rfc4120_pyasn1_regen.sh => pyasn1_regen.sh} (100%) diff --git a/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh b/python/samba/tests/krb5/pyasn1_regen.sh similarity index 100% rename from python/samba/tests/krb5/rfc4120_pyasn1_regen.sh rename to python/samba/tests/krb5/pyasn1_regen.sh -- 2.25.1 From f0a34678d518b488b9f21c9c5d11265a31b737a4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Apr 2020 11:10:11 +0200 Subject: [PATCH 086/645] tests/krb5/rfc4120.asn1: Improve definitions to allow expanded testing Update and re-generate the ASN.1 to allow an improved testsuite. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d4492a8aaaf70cbe81af7e6703b4ea9fc1f24162) --- python/samba/tests/krb5/rfc4120.asn1 | 70 ++++++++++- python/samba/tests/krb5/rfc4120_pyasn1.py | 134 +++++++++++++++++++++- 2 files changed, 199 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index 654f9788ca7..d81d06ad6f7 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -386,14 +386,14 @@ PA-ENC-TS-ENC ::= SEQUENCE { } ETYPE-INFO-ENTRY ::= SEQUENCE { - etype [0] Int32, + etype [0] EncryptionType, --Int32 EncryptionType -- salt [1] OCTET STRING OPTIONAL } ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY ETYPE-INFO2-ENTRY ::= SEQUENCE { - etype [0] Int32, + etype [0] EncryptionType, --Int32 EncryptionType -- salt [1] KerberosString OPTIONAL, s2kparams [2] OCTET STRING OPTIONAL } @@ -425,9 +425,48 @@ PA-S4U2Self ::= SEQUENCE { auth [3] KerberosString } +-- +-- +-- MS-KILE Start + +KERB-ERROR-DATA ::= SEQUENCE { + data-type [1] KerbErrorDataType, + data-value [2] OCTET STRING OPTIONAL +} + +KerbErrorDataType ::= INTEGER + +KERB-PA-PAC-REQUEST ::= SEQUENCE { + include-pac[0] BOOLEAN --If TRUE, and no pac present, include PAC. + --If FALSE, and PAC present, remove PAC +} + +KERB-LOCAL ::= OCTET STRING -- Implementation-specific data which MUST be + -- ignored if Kerberos client is not local. + +KERB-AD-RESTRICTION-ENTRY ::= SEQUENCE { + restriction-type [0] Int32, + restriction [1] OCTET STRING -- LSAP_TOKEN_INFO_INTEGRITY structure +} + +PA-SUPPORTED-ENCTYPES ::= Int32 -- Supported Encryption Types Bit Field -- +PACOptionFlags ::= KerberosFlags -- Claims (0) + -- Branch Aware (1) + -- Forward to Full DC (2) + -- Resource Based Constrained Delegation (3) +PA-PAC-OPTIONS ::= SEQUENCE { + options [0] PACOptionFlags +} +-- Note: KerberosFlags ::= BIT STRING (SIZE (32..MAX)) +-- minimum number of bits shall be sent, but no fewer than 32 +KERB-KEY-LIST-REQ ::= SEQUENCE OF EncryptionType -- Int32 encryption type -- +KERB-KEY-LIST-REP ::= SEQUENCE OF EncryptionKey +-- MS-KILE End +-- +-- -- -- @@ -504,6 +543,15 @@ KDCOptionsSequence ::= SEQUENCE { dummy [0] KDCOptionsValues } +APOptionsValues ::= BIT STRING { -- KerberosFlags + reserved(0), + use-session-key(1), + mutual-required(2) +} +APOptionsSequence ::= SEQUENCE { + dummy [0] APOptionsValues +} + MessageTypeValues ::= INTEGER { krb-as-req(10), -- Request for initial authentication krb-as-rep(11), -- Response to KRB_AS_REQ request @@ -669,4 +717,22 @@ EncryptionTypeSequence ::= SEQUENCE { dummy [0] EncryptionTypeValues } +KerbErrorDataTypeValues ::= INTEGER { + kERB-AP-ERR-TYPE-SKEW-RECOVERY(2), + kERB-ERR-TYPE-EXTENDED(3) +} +KerbErrorDataTypeSequence ::= SEQUENCE { + dummy [0] KerbErrorDataTypeValues +} + +PACOptionFlagsValues ::= BIT STRING { -- KerberosFlags + claims(0), + branch-aware(1), + forward-to-full-dc(2), + resource-based-constrained-delegation(3) +} +PACOptionFlagsSequence ::= SEQUENCE { + dummy [0] PACOptionFlagsValues +} + END diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index 1d89f94adf1..56fe02a68f0 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/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 2020-11-06 11:30:42.476808) +# (last modified on 2021-06-16 08:54:13.969508) # KerberosV5Spec2 from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful @@ -175,6 +175,26 @@ AP_REQ.componentType = namedtype.NamedTypes( ) +class APOptionsValues(univ.BitString): + pass + + +APOptionsValues.namedValues = namedval.NamedValues( + ('reserved', 0), + ('use-session-key', 1), + ('mutual-required', 2) +) + + +class APOptionsSequence(univ.Sequence): + pass + + +APOptionsSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', APOptionsValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + class PADataType(Int32): pass @@ -384,7 +404,7 @@ class ETYPE_INFO_ENTRY(univ.Sequence): ETYPE_INFO_ENTRY.componentType = namedtype.NamedTypes( - namedtype.NamedType('etype', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('etype', EncryptionType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), namedtype.OptionalNamedType('salt', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) ) @@ -401,7 +421,7 @@ class ETYPE_INFO2_ENTRY(univ.Sequence): ETYPE_INFO2_ENTRY.componentType = namedtype.NamedTypes( - namedtype.NamedType('etype', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('etype', EncryptionType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), namedtype.OptionalNamedType('salt', KerberosString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), namedtype.OptionalNamedType('s2kparams', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) ) @@ -636,6 +656,57 @@ KDCOptionsSequence.componentType = namedtype.NamedTypes( ) +class KERB_AD_RESTRICTION_ENTRY(univ.Sequence): + pass + + +KERB_AD_RESTRICTION_ENTRY.componentType = namedtype.NamedTypes( + namedtype.NamedType('restriction-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('restriction', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class KerbErrorDataType(univ.Integer): + pass + + +class KERB_ERROR_DATA(univ.Sequence): + pass + + +KERB_ERROR_DATA.componentType = namedtype.NamedTypes( + namedtype.NamedType('data-type', KerbErrorDataType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('data-value', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class KERB_KEY_LIST_REP(univ.SequenceOf): + pass + + +KERB_KEY_LIST_REP.componentType = EncryptionKey() + + +class KERB_KEY_LIST_REQ(univ.SequenceOf): + pass + + +KERB_KEY_LIST_REQ.componentType = EncryptionType() + + +class KERB_LOCAL(univ.OctetString): + pass + + +class KERB_PA_PAC_REQUEST(univ.Sequence): + pass + + +KERB_PA_PAC_REQUEST.componentType = namedtype.NamedTypes( + namedtype.NamedType('include-pac', univ.Boolean().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + class KRB_CRED(univ.Sequence): pass @@ -710,6 +781,25 @@ KRB_SAFE.componentType = namedtype.NamedTypes( ) +class KerbErrorDataTypeValues(univ.Integer): + pass + + +KerbErrorDataTypeValues.namedValues = namedval.NamedValues( + ('kERB-AP-ERR-TYPE-SKEW-RECOVERY', 2), + ('kERB-ERR-TYPE-EXTENDED', 3) +) + + +class KerbErrorDataTypeSequence(univ.Sequence): + pass + + +KerbErrorDataTypeSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', KerbErrorDataTypeValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + class MessageTypeValues(univ.Integer): pass @@ -781,6 +871,19 @@ PA_ENC_TS_ENC.componentType = namedtype.NamedTypes( ) +class PACOptionFlags(KerberosFlags): + pass + + +class PA_PAC_OPTIONS(univ.Sequence): + pass + + +PA_PAC_OPTIONS.componentType = namedtype.NamedTypes( + namedtype.NamedType('options', PACOptionFlags().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + class PA_S4U2Self(univ.Sequence): pass @@ -793,6 +896,31 @@ PA_S4U2Self.componentType = namedtype.NamedTypes( ) +class PA_SUPPORTED_ENCTYPES(Int32): + pass + + +class PACOptionFlagsValues(univ.BitString): + pass + + +PACOptionFlagsValues.namedValues = namedval.NamedValues( + ('claims', 0), + ('branch-aware', 1), + ('forward-to-full-dc', 2), + ('resource-based-constrained-delegation', 3) +) + + +class PACOptionFlagsSequence(univ.Sequence): + pass + + +PACOptionFlagsSequence.componentType = namedtype.NamedTypes( + namedtype.NamedType('dummy', PACOptionFlagsValues().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + class PADataTypeValues(univ.Integer): pass -- 2.25.1 From 1bc06fdf8758e3a70d70cdd2048550eea2a0deae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Apr 2020 10:55:28 +0200 Subject: [PATCH 087/645] tests/krb5/raw_testcase.py: Add get_{client,server,krbtgt}_creds() These helpful functions allow us to build the various credentials that we will use in validating the KDC responses in this test. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit c3222870b92db7f867557c2896b7bf39915d469a) --- python/samba/tests/krb5/raw_testcase.py | 199 +++++++++++++++++++++--- python/samba/tests/krb5/simple_tests.py | 6 +- 2 files changed, 183 insertions(+), 22 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 27ab89ecf99..b28939f0388 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -22,10 +22,12 @@ import struct import time import datetime import random +import binascii import samba.tests from samba.credentials import Credentials from samba.tests import TestCaseInTempDir +from samba.dcerpc import security import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 import samba.tests.krb5.kcrypto as kcrypto @@ -177,6 +179,81 @@ class Krb5EncryptionKey(object): } return EncryptionKey_obj +class KerberosCredentials(Credentials): + def __init__(self): + super(KerberosCredentials, self).__init__() + all_enc_types = 0 + all_enc_types |= security.KERB_ENCTYPE_RC4_HMAC_MD5 + all_enc_types |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + all_enc_types |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 + + self.as_supported_enctypes = all_enc_types + self.tgs_supported_enctypes = all_enc_types + self.ap_supported_enctypes = all_enc_types + + self.kvno = None + self.forced_keys = {} + + self.forced_salt = None + return + + def set_as_supported_enctypes(self, value): + self.as_supported_enctypes = int(value) + return + + def set_tgs_supported_enctypes(self, value): + self.tgs_supported_enctypes = int(value) + return + + def set_ap_supported_enctypes(self, value): + self.ap_supported_enctypes = int(value) + return + + def _get_krb5_etypes(self, supported_enctypes): + etypes = () + + if supported_enctypes & security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96: + etypes += (kcrypto.Enctype.AES256,) + if supported_enctypes & security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96: + etypes += (kcrypto.Enctype.AES128,) + if supported_enctypes & security.KERB_ENCTYPE_RC4_HMAC_MD5: + etypes += (kcrypto.Enctype.RC4,) + + return etypes + + def get_as_krb5_etypes(self): + return self._get_krb5_etypes(self.as_supported_enctypes) + + def get_tgs_krb5_etypes(self): + return self._get_krb5_etypes(self.tgs_supported_enctypes) + + def get_ap_krb5_etypes(self): + return self._get_krb5_etypes(self.ap_supported_enctypes) + + def set_kvno(self, kvno): + self.kvno = kvno + + def get_kvno(self): + return self.kvno + + def set_forced_key(self, etype, hexkey): + etype = int(etype) + contents = binascii.a2b_hex(hexkey) + key = kcrypto.Key(etype, contents) + self.forced_keys[etype] = Krb5EncryptionKey(key, self.kvno) + + def get_forced_key(self, etype): + etype = int(etype) + if etype in self.forced_keys: + return self.forced_keys[etype] + return None + + def set_forced_salt(self, salt): + self.forced_salt = bytes(salt) + return + + def get_forced_salt(self): + return self.forced_salt class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" @@ -229,33 +306,113 @@ class RawKerberosTest(TestCaseInTempDir): sys.stderr.write("connected[%s]\n" % self.host) return - def get_user_creds(self): - c = Credentials() + def _get_krb5_creds(self, prefix, + default_username=None, + allow_missing_password=False, + require_strongest_key=False): + c = KerberosCredentials() c.guess() - domain = samba.tests.env_get_var_value('DOMAIN') - realm = samba.tests.env_get_var_value('REALM') - username = samba.tests.env_get_var_value('USERNAME') - password = samba.tests.env_get_var_value('PASSWORD') - c.set_domain(domain) - c.set_realm(realm) - c.set_username(username) - c.set_password(password) - return c - def get_service_creds(self, allow_missing_password=False): - c = Credentials() - c.guess() - domain = samba.tests.env_get_var_value('DOMAIN') - realm = samba.tests.env_get_var_value('REALM') - username = samba.tests.env_get_var_value('SERVICE_USERNAME') - password = samba.tests.env_get_var_value( - 'SERVICE_PASSWORD', - allow_missing=allow_missing_password) + def env_get_var(varname, prefix, fallback_default=True, allow_missing=False): + val = None + if prefix is not None: + allow_missing_prefix = allow_missing + if fallback_default: + allow_missing_prefix = True + val = samba.tests.env_get_var_value('%s_%s' % (prefix, varname), + allow_missing=allow_missing_prefix) + else: + fallback_default = True + if val is None and fallback_default: + val = samba.tests.env_get_var_value(varname, + allow_missing=allow_missing) + return val + + domain = env_get_var('DOMAIN', prefix) + realm = env_get_var('REALM', prefix) + allow_missing_username = False + if default_username is not None: + allow_missing_username = True + username = env_get_var('USERNAME', prefix, + fallback_default=False, + allow_missing=allow_missing_username) + if username is None: + username = default_username + password = env_get_var('PASSWORD', prefix, + fallback_default=False, + allow_missing=allow_missing_password) c.set_domain(domain) c.set_realm(realm) c.set_username(username) if password is not None: c.set_password(password) + as_supported_enctypes = env_get_var('AS_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) + if as_supported_enctypes is not None: + c.set_as_supported_enctypes(as_supported_enctypes) + tgs_supported_enctypes = env_get_var('TGS_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) + if tgs_supported_enctypes is not None: + c.set_tgs_supported_enctypes(tgs_supported_enctypes) + ap_supported_enctypes = env_get_var('AP_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) + if ap_supported_enctypes is not None: + c.set_ap_supported_enctypes(ap_supported_enctypes) + + if require_strongest_key: + kvno_allow_missing = False + if password is None: + aes256_allow_missing = False + else: + aes256_allow_missing = True + else: + kvno_allow_missing = True + aes256_allow_missing = True + kvno = env_get_var('KVNO', prefix, + fallback_default=False, + allow_missing=kvno_allow_missing) + if kvno is not None: + c.set_kvno(kvno) + aes256_key = env_get_var('AES256_KEY_HEX', prefix, + fallback_default=False, + allow_missing=aes256_allow_missing) + if aes256_key is not None: + c.set_forced_key(kcrypto.Enctype.AES256, aes256_key) + aes128_key = env_get_var('AES128_KEY_HEX', prefix, + fallback_default=False, allow_missing=True) + if aes128_key is not None: + c.set_forced_key(kcrypto.Enctype.AES128, aes128_key) + rc4_key = env_get_var('RC4_KEY_HEX', prefix, + fallback_default=False, allow_missing=True) + if rc4_key is not None: + c.set_forced_key(kcrypto.Enctype.RC4, rc4_key) + return c + + def get_user_creds(self, allow_missing_password=False): + c = self._get_krb5_creds(prefix=None, + allow_missing_password=allow_missing_password) + return c + + def get_service_creds(self, allow_missing_password=False): + c = self._get_krb5_creds(prefix='SERVICE', + allow_missing_password=allow_missing_password) + return c + + def get_client_creds(self, allow_missing_password=False): + c = self._get_krb5_creds(prefix='CLIENT', + allow_missing_password=allow_missing_password) + return c + + def get_server_creds(self, allow_missing_password=False): + c = self._get_krb5_creds(prefix='SERVER', + allow_missing_password=allow_missing_password) + return c + + def get_krbtgt_creds(self, require_strongest_key=False): + c = self._get_krb5_creds(prefix='KRBTGT', + default_username='krbtgt', + allow_missing_password=True, + require_strongest_key=require_strongest_key) return c def get_anon_creds(self): @@ -473,6 +630,8 @@ class RawKerberosTest(TestCaseInTempDir): return Krb5EncryptionKey(key, kvno) def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None): + self.assertIsNotNone(pwd) + self.assertIsNotNone(salt) key = kcrypto.string_to_key(etype, pwd, salt) return Krb5EncryptionKey(key, kvno) diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 889b91a9bf0..2da76a3cf5e 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -44,10 +44,12 @@ class SimpleKerberosTests(RawKerberosTest): def test_simple(self): user_creds = self.get_user_creds() user = user_creds.get_username() - realm = user_creds.get_realm() + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_account = krbtgt_creds.get_username() + realm = krbtgt_creds.get_realm() cname = self.PrincipalName_create(name_type=1, names=[user]) - sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) + sname = self.PrincipalName_create(name_type=2, names=[krbtgt_account, realm]) till = self.get_KerberosTime(offset=36000) -- 2.25.1 From fdb3ce889cb3aa4a654672f92276b339bbecb899 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Apr 2020 22:28:32 +0200 Subject: [PATCH 088/645] tests/krb5/raw_testcase.py: introduce STRICT_CHECKING=0 in order to relax the checks in future We should write tests as strict as possible in order to let them run against Windows servers. But at the same time we want to allow tests to be useful for Samba too... Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit dff611976d6a067614e37add99edae214815a68b) --- python/samba/tests/krb5/raw_testcase.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b28939f0388..333aab70c8e 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -263,6 +263,11 @@ class RawKerberosTest(TestCaseInTempDir): self.do_asn1_print = False self.do_hexdump = False + strict_checking = samba.tests.env_get_var_value('STRICT_CHECKING', allow_missing=True) + if strict_checking is None: + strict_checking = '1' + self.strict_checking = bool(int(strict_checking)) + self.host = samba.tests.env_get_var_value('SERVER') self.s = None -- 2.25.1 From 8b374617205234af3f72dd4c864848d1a96533a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Apr 2020 13:49:52 +0200 Subject: [PATCH 089/645] tests/krb5/raw_testcase.py: add assertElement*() These helper functions make writing subsequent Kerberos test clearer. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 61e1b179812e48797146584998afc5bd0168beae) --- python/samba/tests/krb5/raw_testcase.py | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 333aab70c8e..eb294a75a95 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -605,6 +605,36 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(value) return + def getElementValue(self, obj, elem): + v = None + try: + v = obj[elem] + except KeyError: + pass + return v + + def assertElementMissing(self, obj, elem): + v = self.getElementValue(obj, elem) + self.assertIsNone(v) + return + + def assertElementPresent(self, obj, elem): + v = self.getElementValue(obj, elem) + self.assertIsNotNone(v) + return + + def assertElementEqual(self, obj, elem, value): + v = self.getElementValue(obj, elem) + self.assertIsNotNone(v) + self.assertEqual(v, value) + return + + def assertElementEqualUTF8(self, obj, elem, value): + v = self.getElementValue(obj, elem) + self.assertIsNotNone(v) + self.assertEqual(v, bytes(value, 'utf8')) + return + def assertPrincipalEqual(self, princ1, princ2): self.assertEqual(princ1['name-type'], princ2['name-type']) self.assertEqual( @@ -618,6 +648,30 @@ class RawKerberosTest(TestCaseInTempDir): msg="princ1=%s != princ2=%s" % (princ1, princ2)) return + def assertElementEqualPrincipal(self, obj, elem, value): + v = self.getElementValue(obj, elem) + self.assertIsNotNone(v) + v = pyasn1_native_decode(v, asn1Spec=krb5_asn1.PrincipalName()) + self.assertPrincipalEqual(v, value) + return + + def assertElementKVNO(self, obj, elem, value): + v = self.getElementValue(obj, elem) + if value == "autodetect": + value = v + if value is not None: + self.assertIsNotNone(v) + # The value on the wire should never be 0 + self.assertNotEqual(v, 0) + # value == 0 means we don't know the kvno + # but enforce at any value != 0 is present + value = int(value) + if value != 0: + self.assertEqual(v, value) + else: + self.assertIsNone(v) + return + def get_KerberosTimeWithUsec(self, epoch=None, offset=None): if epoch is None: epoch = time.time() -- 2.25.1 From c73566933c23b1ce7ff57c1d5678b7a1155bd4b4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Apr 2020 17:50:00 +0200 Subject: [PATCH 090/645] tests/krb5/raw_testcase.py: Allow prettyPrint of more RFC-defined values By setting krb5_asn1.APOptions.prettyPrint = BitString_NamedValues_prettyPrint we allow the BitString_NamedValues_prettyPrint() routine to show more named values. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 34e079ce9a232a765fb3a2b25441434df35df54c) --- python/samba/tests/krb5/raw_testcase.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index eb294a75a95..29745fa4089 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -111,6 +111,12 @@ krb5_asn1.KDCOptions.namedValues =\ krb5_asn1.KDCOptionsValues.namedValues krb5_asn1.KDCOptions.prettyPrint =\ BitString_NamedValues_prettyPrint +krb5_asn1.APOptions.prettyPrintNamedValues =\ + krb5_asn1.APOptionsValues.namedValues +krb5_asn1.APOptions.namedValues =\ + krb5_asn1.APOptionsValues.namedValues +krb5_asn1.APOptions.prettyPrint =\ + BitString_NamedValues_prettyPrint def Integer_NamedValues_prettyPrint(self, scope=0): -- 2.25.1 From 026f7a75b40b469a9990281e61813e6a37346cc5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Apr 2020 17:57:37 +0200 Subject: [PATCH 091/645] tests/krb5/raw_testcase.py: Allow prettyPrint of more MS-KILE-defined values By setting krb5_asn1.APOptions.prettyPrint = BitString_NamedValues_prettyPrint we allow the BitString_NamedValues_prettyPrint() routine to show more named values. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 3abb3b41368666535a216a98c3e7d15a5d498f7e) --- python/samba/tests/krb5/raw_testcase.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 29745fa4089..1ef15db9f8c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -117,6 +117,12 @@ krb5_asn1.APOptions.namedValues =\ krb5_asn1.APOptionsValues.namedValues krb5_asn1.APOptions.prettyPrint =\ BitString_NamedValues_prettyPrint +krb5_asn1.PACOptionFlags.prettyPrintNamedValues =\ + krb5_asn1.PACOptionFlagsValues.namedValues +krb5_asn1.PACOptionFlags.namedValues =\ + krb5_asn1.PACOptionFlagsValues.namedValues +krb5_asn1.PACOptionFlags.prettyPrint =\ + BitString_NamedValues_prettyPrint def Integer_NamedValues_prettyPrint(self, scope=0): @@ -149,6 +155,10 @@ krb5_asn1.ChecksumType.prettyPrintNamedValues =\ krb5_asn1.ChecksumTypeValues.namedValues krb5_asn1.ChecksumType.prettyPrint =\ Integer_NamedValues_prettyPrint +krb5_asn1.KerbErrorDataType.prettyPrintNamedValues =\ + krb5_asn1.KerbErrorDataTypeValues.namedValues +krb5_asn1.KerbErrorDataType.prettyPrint =\ + Integer_NamedValues_prettyPrint class Krb5EncryptionKey(object): -- 2.25.1 From f3c559f4d276a1e56a70aae8ee8f146c52172ff2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Apr 2020 14:45:01 +0200 Subject: [PATCH 092/645] tests/krb5/raw_testcase.py: split KDC_REQ_BODY_create() from KDC_REQ_create() This allows us to reuse body in future and calculate checksums on it. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b03fcfeb6c005936818ce50d511e9f9cc75aa9fb) --- python/samba/tests/krb5/raw_testcase.py | 81 +++++++------------------ 1 file changed, 23 insertions(+), 58 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 1ef15db9f8c..71a4753717f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -872,19 +872,7 @@ class RawKerberosTest(TestCaseInTempDir): def KDC_REQ_create(self, msg_type, padata, - kdc_options, - cname, - realm, - sname, - from_time, - till_time, - renew_time, - nonce, - etypes, - addresses, - EncAuthorizationData, - EncAuthorizationData_key, - additional_tickets, + req_body, asn1Spec=None, asn1_print=None, hexdump=None): @@ -897,25 +885,10 @@ class RawKerberosTest(TestCaseInTempDir): # req-body [4] KDC-REQ-BODY # } # - KDC_REQ_BODY_obj = self.KDC_REQ_BODY_create(kdc_options, - cname, - realm, - sname, - from_time, - till_time, - renew_time, - nonce, - etypes, - addresses, - EncAuthorizationData, - EncAuthorizationData_key, - additional_tickets, - asn1_print=asn1_print, - hexdump=hexdump) KDC_REQ_obj = { 'pvno': 5, 'msg-type': msg_type, - 'req-body': KDC_REQ_BODY_obj, + 'req-body': req_body, } if padata is not None: KDC_REQ_obj['padata'] = padata @@ -974,22 +947,26 @@ class RawKerberosTest(TestCaseInTempDir): # additional-tickets [11] SEQUENCE OF Ticket OPTIONAL # -- NOTE: not empty # } + KDC_REQ_BODY_obj = self.KDC_REQ_BODY_create( + kdc_options, + cname, + realm, + sname, + from_time, + till_time, + renew_time, + nonce, + etypes, + addresses, + EncAuthorizationData, + EncAuthorizationData_key, + additional_tickets, + asn1_print=asn1_print, + hexdump=hexdump) obj, decoded = self.KDC_REQ_create( msg_type=10, padata=padata, - kdc_options=kdc_options, - cname=cname, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets, + req_body=KDC_REQ_BODY_obj, asn1Spec=krb5_asn1.AS_REQ(), asn1_print=asn1_print, hexdump=hexdump) @@ -1115,11 +1092,11 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData=EncAuthorizationData, EncAuthorizationData_key=EncAuthorizationData_key, additional_tickets=additional_tickets) - req_body = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), - asn1_print=asn1_print, hexdump=hexdump) + req_body_blob = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), + asn1_print=asn1_print, hexdump=hexdump) req_body_checksum = self.Checksum_create( - ticket_session_key, 6, req_body, ctype=body_checksum_type) + ticket_session_key, 6, req_body_blob, ctype=body_checksum_type) subkey_obj = None if authenticator_subkey is not None: @@ -1158,19 +1135,7 @@ class RawKerberosTest(TestCaseInTempDir): obj, decoded = self.KDC_REQ_create( msg_type=12, padata=padata, - kdc_options=kdc_options, - cname=None, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets, + req_body=req_body, asn1Spec=krb5_asn1.TGS_REQ(), asn1_print=asn1_print, hexdump=hexdump) -- 2.25.1 From 351483fc139e648bbc7cab25d1584c1cf377e087 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Apr 2020 10:43:54 +0200 Subject: [PATCH 093/645] tests/krb5/raw_testcase.py: add KERB_PA_PAC_REQUEST_create() This allows building the pre-authentication data that encodes the request for the KDC (or more likely a request not to include) the KRB5 PAC in the resulting ticket. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ee2ac2b8ccafe3e6d560d893a4135a28e393914d) --- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 71a4753717f..f341911ef53 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -799,6 +799,21 @@ class RawKerberosTest(TestCaseInTempDir): } return PA_ENC_TS_ENC_obj + def KERB_PA_PAC_REQUEST_create(self, include_pac, pa_data_create=True): + #KERB-PA-PAC-REQUEST ::= SEQUENCE { + # include-pac[0] BOOLEAN --If TRUE, and no pac present, include PAC. + # --If FALSE, and PAC present, remove PAC + #} + KERB_PA_PAC_REQUEST_obj = { + 'include-pac': include_pac, + } + if not pa_data_create: + return KERB_PA_PAC_REQUEST_obj + pa_pac = self.der_encode(KERB_PA_PAC_REQUEST_obj, + asn1Spec=krb5_asn1.KERB_PA_PAC_REQUEST()) + pa_data = self.PA_DATA_create(128, pa_pac) # PA-PAC-REQUEST + return pa_data + def KDC_REQ_BODY_create(self, kdc_options, cname, -- 2.25.1 From d1fb21b58e7be6f7b60f1be702c968ab9961a916 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 20 Apr 2020 20:02:52 +0200 Subject: [PATCH 094/645] tests/krb5/raw_testcase.py: add methods to iterate over etype permutations It's often useful to run tests over a lot of input parameter permutations. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit e3905035847a5268c1a65366830cc739280ae437) --- python/samba/tests/krb5/raw_testcase.py | 58 +++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f341911ef53..a002a442d03 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -23,6 +23,7 @@ import time import datetime import random import binascii +import itertools import samba.tests from samba.credentials import Credentials @@ -274,6 +275,63 @@ class KerberosCredentials(Credentials): class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" + etypes_to_test = ( + { "value": -1111, "name": "dummy", }, + { "value": kcrypto.Enctype.AES256, "name": "aes128", }, + { "value": kcrypto.Enctype.AES128, "name": "aes256", }, + { "value": kcrypto.Enctype.RC4, "name": "rc4", }, + ) + + setup_etype_test_permutations_done = False + + @classmethod + def setup_etype_test_permutations(cls): + if cls.setup_etype_test_permutations_done: + return + + res = [] + + num_idxs = len(cls.etypes_to_test) + permutations = [] + for num in range(1, num_idxs+1): + chunk = list(itertools.permutations(range(num_idxs), num)) + for e in chunk: + el = list(e) + permutations.append(el) + + for p in permutations: + name = None + etypes = () + for idx in p: + n = cls.etypes_to_test[idx]["name"] + if name is None: + name = n + else: + name += "_%s" % n + etypes += (cls.etypes_to_test[idx]["value"],) + + r = { "name": name, "etypes": etypes, } + res.append(r) + + cls.etype_test_permutations = res + cls.setup_etype_test_permutations_done = True + return + + @classmethod + def etype_test_permutation_name_idx(cls): + cls.setup_etype_test_permutations() + res = [] + idx = 0 + for e in cls.etype_test_permutations: + r = (e['name'], idx) + idx += 1 + res.append(r) + return res + + def etype_test_permutation_by_idx(self, idx): + e = self.etype_test_permutations[idx] + return (e['name'], e['etypes']) + def setUp(self): super().setUp() self.do_asn1_print = False -- 2.25.1 From f59be60ee4ef250e98398907a596506e21439f61 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Apr 2020 17:13:35 +0200 Subject: [PATCH 095/645] tests/krb5/raw_testcase.py: Add TicketDecryptionKey_from_creds() This will allow building test_as_req_enc_timestamp() It also introduces ways to specify keys in hex formated environment variables ${PREFIX}_{AES256,AES128,RC4}_KEY_HEX. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 69ce2a6408f78d41eb865b89726021ad7643b065) --- python/samba/tests/krb5/raw_testcase.py | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a002a442d03..7d0dc9c9609 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -784,6 +784,35 @@ class RawKerberosTest(TestCaseInTempDir): return self.PasswordKey_create( etype=e, pwd=password, salt=salt, kvno=kvno) + def TicketDecryptionKey_from_creds(self, creds, etype=None): + + if etype is None: + etypes = creds.get_tgs_krb5_etypes() + etype = etypes[0] + + forced_key = creds.get_forced_key(etype) + if forced_key is not None: + return forced_key + + kvno = creds.get_kvno() + + fail_msg = ("%s has no fixed key for etype[%s] kvno[%s] " + "nor a password specified, " % ( + creds.get_username(), etype, kvno)) + + if etype == kcrypto.Enctype.RC4: + nthash = creds.get_nt_hash() + self.assertIsNotNone(nthash, msg=fail_msg) + return self.SessionKey_create(etype=etype, contents=nthash, kvno=kvno) + + password = creds.get_password() + self.assertIsNotNone(password, msg=fail_msg) + salt = creds.get_forced_salt() + if salt is None: + salt = bytes("%s%s" % (creds.get_realm(), creds.get_username()), + encoding='utf-8') + return self.PasswordKey_create(etype=etype, pwd=password, salt=salt, kvno=kvno) + def RandomKey(self, etype): e = kcrypto._get_enctype_profile(etype) contents = samba.generate_random_bytes(e.keysize) -- 2.25.1 From d11a7b65038870d0d38129f6601a0fc3ae303f6f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Apr 2020 11:07:45 +0200 Subject: [PATCH 096/645] tests/krb5/raw_testcase.py: introduce a _generic_kdc_exchange() infrastructure This will allow us to write tests, which will all cross check almost every aspect of the KDC response (including encrypted parts). Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 6e2f2adc8e825634780077e24a9e437bdc68155a) --- python/samba/tests/krb5/raw_testcase.py | 634 +++++++++++++++++++ python/samba/tests/krb5/rfc4120_constants.py | 11 + 2 files changed, 645 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 7d0dc9c9609..8c8926b0ad2 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -30,6 +30,27 @@ from samba.credentials import Credentials from samba.tests import TestCaseInTempDir from samba.dcerpc import security import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_ETYPE_NOSUPP, + KDC_ERR_PREAUTH_REQUIRED, + KRB_AS_REP, + KRB_AS_REQ, + KRB_ERROR, + KRB_TGS_REP, + KRB_TGS_REQ, + KU_AS_REP_ENC_PART, + KU_TGS_REP_ENC_PART_SESSION, + KU_TGS_REP_ENC_PART_SUB_KEY, + KU_TGS_REQ_AUTH, + KU_TGS_REQ_AUTH_CKSUM, + KU_TICKET, + PADATA_ENC_TIMESTAMP, + PADATA_ETYPE_INFO, + PADATA_ETYPE_INFO2, + PADATA_KDC_REQ, + PADATA_PK_AS_REQ, + PADATA_PK_AS_REP_19 +) import samba.tests.krb5.kcrypto as kcrypto from pyasn1.codec.der.decoder import decode as pyasn1_der_decode @@ -272,6 +293,24 @@ class KerberosCredentials(Credentials): def get_forced_salt(self): return self.forced_salt +class KerberosTicketCreds(object): + def __init__(self, ticket, session_key, + crealm=None, cname=None, + srealm=None, sname=None, + decryption_key=None, + ticket_private=None, + encpart_private=None): + self.ticket = ticket + self.session_key = session_key + self.crealm = crealm + self.cname = cname + self.srealm = srealm + self.sname = sname + self.decryption_key = decryption_key + self.ticket_private = ticket_private + self.encpart_private = encpart_private + return + class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" @@ -758,6 +797,12 @@ class RawKerberosTest(TestCaseInTempDir): (s, _) = self.get_KerberosTimeWithUsec(epoch=epoch, offset=offset) return s + def get_Nonce(self): + nonce_min=0x7f000000 + nonce_max=0x7fffffff + v = random.randint(nonce_min, nonce_max) + return v + def SessionKey_create(self, etype, contents, kvno=None): key = kcrypto.Key(etype, contents) return Krb5EncryptionKey(key, kvno) @@ -1268,3 +1313,592 @@ class RawKerberosTest(TestCaseInTempDir): pa_s4u2self = self.der_encode( PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) return self.PA_DATA_create(129, pa_s4u2self) + + def _generic_kdc_exchange(self, + kdc_exchange_dict, # required + kdc_options=None, # required + cname=None, # optional + realm=None, # required + sname=None, # optional + from_time=None, # optional + till_time=None, # required + renew_time=None, # optional + nonce=None, # required + etypes=None, # required + addresses=None, # optional + EncAuthorizationData=None, # optional + EncAuthorizationData_key=None, # optional + additional_tickets=None): # optional + + check_error_fn = kdc_exchange_dict['check_error_fn'] + check_rep_fn = kdc_exchange_dict['check_rep_fn'] + generate_padata_fn = kdc_exchange_dict['generate_padata_fn'] + callback_dict = kdc_exchange_dict['callback_dict'] + req_msg_type = kdc_exchange_dict['req_msg_type'] + req_asn1Spec = kdc_exchange_dict['req_asn1Spec'] + rep_msg_type = kdc_exchange_dict['rep_msg_type'] + + if till_time is None: + till_time = self.get_KerberosTime(offset=36000) + if nonce is None: + nonce = self.get_Nonce() + + req_body = self.KDC_REQ_BODY_create(kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets) + if generate_padata_fn is not None: + # This can alter req_body... + padata, req_body = generate_padata_fn(kdc_exchange_dict, + callback_dict, + req_body) + else: + padata = None + + kdc_exchange_dict['req_padata'] = padata + kdc_exchange_dict['req_body'] = req_body + + req_obj,req_decoded = self.KDC_REQ_create(msg_type=req_msg_type, + padata=padata, + req_body=req_body, + asn1Spec=req_asn1Spec()) + + rep = self.send_recv_transaction(req_decoded) + self.assertIsNotNone(rep) + + msg_type = self.getElementValue(rep, 'msg-type') + self.assertIsNotNone(msg_type) + + allowed_msg_types = () + if check_error_fn is not None: + allowed_msg_types = (KRB_ERROR,) + if check_rep_fn is not None: + allowed_msg_types += (rep_msg_type,) + self.assertIn(msg_type, allowed_msg_types) + + if msg_type == KRB_ERROR: + return check_error_fn(kdc_exchange_dict, + callback_dict, + rep) + + return check_rep_fn(kdc_exchange_dict, callback_dict, rep) + + def as_exchange_dict(self, + expected_crealm=None, + expected_cname=None, + expected_srealm=None, + expected_sname=None, + ticket_decryption_key=None, + generate_padata_fn=None, + check_error_fn=None, + check_rep_fn=None, + check_padata_fn=None, + check_kdc_private_fn=None, + callback_dict=dict(), + expected_error_mode=None, + client_as_etypes=None, + expected_salt=None): + kdc_exchange_dict = { + 'req_msg_type': KRB_AS_REQ, + 'req_asn1Spec': krb5_asn1.AS_REQ, + 'rep_msg_type': KRB_AS_REP, + 'rep_asn1Spec': krb5_asn1.AS_REP, + 'rep_encpart_asn1Spec': krb5_asn1.EncASRepPart, + 'expected_crealm': expected_crealm, + 'expected_cname': expected_cname, + 'expected_srealm': expected_srealm, + 'expected_sname': expected_sname, + 'ticket_decryption_key': ticket_decryption_key, + 'generate_padata_fn': generate_padata_fn, + 'check_error_fn': check_error_fn, + 'check_rep_fn': check_rep_fn, + 'check_padata_fn': check_padata_fn, + 'check_kdc_private_fn': check_kdc_private_fn, + 'callback_dict': callback_dict, + 'expected_error_mode': expected_error_mode, + 'client_as_etypes': client_as_etypes, + 'expected_salt': expected_salt, + } + return kdc_exchange_dict + + def tgs_exchange_dict(self, + expected_crealm=None, + expected_cname=None, + expected_srealm=None, + expected_sname=None, + ticket_decryption_key=None, + generate_padata_fn=None, + check_error_fn=None, + check_rep_fn=None, + check_padata_fn=None, + check_kdc_private_fn=None, + callback_dict=dict(), + tgt=None, + authenticator_subkey=None, + body_checksum_type=None): + kdc_exchange_dict = { + 'req_msg_type': KRB_TGS_REQ, + 'req_asn1Spec': krb5_asn1.TGS_REQ, + 'rep_msg_type': KRB_TGS_REP, + 'rep_asn1Spec': krb5_asn1.TGS_REP, + 'rep_encpart_asn1Spec': krb5_asn1.EncTGSRepPart, + 'expected_crealm': expected_crealm, + 'expected_cname': expected_cname, + 'expected_srealm': expected_srealm, + 'expected_sname': expected_sname, + 'ticket_decryption_key': ticket_decryption_key, + 'generate_padata_fn': generate_padata_fn, + 'check_error_fn': check_error_fn, + 'check_rep_fn': check_rep_fn, + 'check_padata_fn': check_padata_fn, + 'check_kdc_private_fn': check_kdc_private_fn, + 'callback_dict': callback_dict, + 'tgt': tgt, + 'body_checksum_type': body_checksum_type, + 'authenticator_subkey': authenticator_subkey, + } + return kdc_exchange_dict + + def generic_check_kdc_rep(self, + kdc_exchange_dict, + callback_dict, + rep): + + expected_crealm = kdc_exchange_dict['expected_crealm'] + expected_cname = kdc_exchange_dict['expected_cname'] + expected_srealm = kdc_exchange_dict['expected_srealm'] + expected_sname = kdc_exchange_dict['expected_sname'] + ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] + check_padata_fn = kdc_exchange_dict['check_padata_fn'] + check_kdc_private_fn = kdc_exchange_dict['check_kdc_private_fn'] + rep_encpart_asn1Spec = kdc_exchange_dict['rep_encpart_asn1Spec'] + msg_type = kdc_exchange_dict['rep_msg_type'] + + self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP + padata = self.getElementValue(rep, 'padata') + self.assertElementEqualUTF8(rep, 'crealm', expected_crealm) + self.assertElementEqualPrincipal(rep, 'cname', expected_cname) + self.assertElementPresent(rep, 'ticket') + ticket = self.getElementValue(rep, 'ticket') + ticket_encpart = None + ticket_cipher = None + if ticket is not None: # Never None, but gives indentation + self.assertElementPresent(ticket, 'tkt-vno') + self.assertElementEqualUTF8(ticket, 'realm', expected_srealm) + self.assertElementEqualPrincipal(ticket, 'sname', expected_sname) + self.assertElementPresent(ticket, 'enc-part') + ticket_encpart = self.getElementValue(ticket, 'enc-part') + if ticket_encpart is not None: # Never None, but gives indentation + self.assertElementPresent(ticket_encpart, 'etype') + # 0 means present, with any value != 0 + self.assertElementKVNO(ticket_encpart, 'kvno', 0) + self.assertElementPresent(ticket_encpart, 'cipher') + ticket_cipher = self.getElementValue(ticket_encpart, 'cipher') + self.assertElementPresent(rep, 'enc-part') + encpart = self.getElementValue(rep, 'enc-part') + encpart_cipher = None + if encpart is not None: # Never None, but gives indentation + self.assertElementPresent(encpart, 'etype') + self.assertElementKVNO(ticket_encpart, 'kvno', 'autodetect') + self.assertElementPresent(encpart, 'cipher') + encpart_cipher = self.getElementValue(encpart, 'cipher') + + encpart_decryption_key = None + if check_padata_fn is not None: + # See if get the decryption key from the preauth phase + encpart_decryption_key,encpart_decryption_usage = \ + check_padata_fn(kdc_exchange_dict, callback_dict, + rep, padata) + + ticket_private = None + if ticket_decryption_key is not None: + self.assertElementEqual(ticket_encpart, 'etype', ticket_decryption_key.etype) + self.assertElementKVNO(ticket_encpart, 'kvno', ticket_decryption_key.kvno) + ticket_decpart = ticket_decryption_key.decrypt(KU_TICKET, ticket_cipher) + ticket_private = self.der_decode(ticket_decpart, asn1Spec=krb5_asn1.EncTicketPart()) + + encpart_private = None + if encpart_decryption_key is not None: + self.assertElementEqual(encpart, 'etype', encpart_decryption_key.etype) + self.assertElementKVNO(encpart, 'kvno', encpart_decryption_key.kvno) + rep_decpart = encpart_decryption_key.decrypt(encpart_decryption_usage, encpart_cipher) + encpart_private = self.der_decode(rep_decpart, asn1Spec=rep_encpart_asn1Spec()) + + if check_kdc_private_fn is not None: + check_kdc_private_fn(kdc_exchange_dict, callback_dict, + rep, ticket_private, encpart_private) + + return rep + + def generic_check_kdc_private(self, + kdc_exchange_dict, + callback_dict, + rep, + ticket_private, + encpart_private): + + expected_crealm = kdc_exchange_dict['expected_crealm'] + expected_cname = kdc_exchange_dict['expected_cname'] + expected_srealm = kdc_exchange_dict['expected_srealm'] + expected_sname = kdc_exchange_dict['expected_sname'] + ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] + + ticket = self.getElementValue(rep, 'ticket') + + ticket_session_key = None + if ticket_private is not None: + self.assertElementPresent(ticket_private, 'flags') + self.assertElementPresent(ticket_private, 'key') + ticket_key = self.getElementValue(ticket_private, 'key') + if ticket_key is not None: # Never None, but gives indentation + self.assertElementPresent(ticket_key, 'keytype') + self.assertElementPresent(ticket_key, 'keyvalue') + ticket_session_key = self.EncryptionKey_import(ticket_key) + self.assertElementEqualUTF8(ticket_private, 'crealm', expected_crealm) + self.assertElementEqualPrincipal(ticket_private, 'cname', expected_cname) + self.assertElementPresent(ticket_private, 'transited') + self.assertElementPresent(ticket_private, 'authtime') + if self.strict_checking: + self.assertElementPresent(ticket_private, 'starttime') + self.assertElementPresent(ticket_private, 'endtime') + # TODO self.assertElementPresent(ticket_private, 'renew-till') + # TODO self.assertElementMissing(ticket_private, 'caddr') + self.assertElementPresent(ticket_private, 'authorization-data') + + encpart_session_key = None + if encpart_private is not None: + self.assertElementPresent(encpart_private, 'key') + encpart_key = self.getElementValue(encpart_private, 'key') + if encpart_key is not None: # Never None, but gives indentation + self.assertElementPresent(encpart_key, 'keytype') + self.assertElementPresent(encpart_key, 'keyvalue') + encpart_session_key = self.EncryptionKey_import(encpart_key) + self.assertElementPresent(encpart_private, 'last-req') + self.assertElementPresent(encpart_private, 'nonce') + # TODO self.assertElementPresent(encpart_private, 'key-expiration') + self.assertElementPresent(encpart_private, 'flags') + self.assertElementPresent(encpart_private, 'authtime') + if self.strict_checking: + self.assertElementPresent(encpart_private, 'starttime') + self.assertElementPresent(encpart_private, 'endtime') + # TODO self.assertElementPresent(encpart_private, 'renew-till') + self.assertElementEqualUTF8(encpart_private, 'srealm', expected_srealm) + self.assertElementEqualPrincipal(encpart_private, 'sname', expected_sname) + # TODO self.assertElementMissing(encpart_private, 'caddr') + + if ticket_session_key is not None and encpart_session_key is not None: + self.assertEqual(ticket_session_key.etype, encpart_session_key.etype) + self.assertEqual(ticket_session_key.key.contents, encpart_session_key.key.contents) + if encpart_session_key is not None: + session_key = encpart_session_key + else: + session_key = ticket_session_key + ticket_creds = KerberosTicketCreds(ticket, + session_key, + crealm=expected_crealm, + cname=expected_cname, + srealm=expected_srealm, + sname=expected_sname, + decryption_key=ticket_decryption_key, + ticket_private=ticket_private, + encpart_private=encpart_private) + + kdc_exchange_dict['rep_ticket_creds'] = ticket_creds + return + + def generic_check_as_error(self, + kdc_exchange_dict, + callback_dict, + rep): + + expected_crealm = kdc_exchange_dict['expected_crealm'] + expected_cname = kdc_exchange_dict['expected_cname'] + expected_srealm = kdc_exchange_dict['expected_srealm'] + expected_sname = kdc_exchange_dict['expected_sname'] + expected_salt = kdc_exchange_dict['expected_salt'] + client_as_etypes = kdc_exchange_dict['client_as_etypes'] + expected_error_mode = kdc_exchange_dict['expected_error_mode'] + req_body = kdc_exchange_dict['req_body'] + proposed_etypes = req_body['etype'] + + kdc_exchange_dict['preauth_etype_info2'] = None + + 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: + expect_etype_info = True + for etype in proposed_etypes: + if etype in (kcrypto.Enctype.AES256,kcrypto.Enctype.AES128): + expect_etype_info = False + if etype not in client_as_etypes: + continue + if etype in (kcrypto.Enctype.AES256,kcrypto.Enctype.AES128): + if etype > expected_aes_type: + expected_aes_type = etype + if etype in (kcrypto.Enctype.RC4,): + unexpect_etype_info = False + if etype > expected_rc4_type: + expected_rc4_type = etype + + if expected_aes_type != 0: + expect_etype_info2 += (expected_aes_type,) + if expected_rc4_type != 0: + expect_etype_info2 += (expected_rc4_type,) + + expected_error = KDC_ERR_ETYPE_NOSUPP + expected_patypes = () + if expect_etype_info: + self.assertGreater(len(expect_etype_info2), 0) + expected_patypes += (PADATA_ETYPE_INFO,) + if len(expect_etype_info2) != 0: + expected_error = KDC_ERR_PREAUTH_REQUIRED + expected_patypes += (PADATA_ETYPE_INFO2,) + + expected_patypes += (PADATA_ENC_TIMESTAMP,) + expected_patypes += (PADATA_PK_AS_REQ,) + expected_patypes += (PADATA_PK_AS_REP_19,) + + self.assertElementEqual(rep, 'msg-type', KRB_ERROR) + self.assertElementEqual(rep, 'error-code', expected_error) + self.assertElementMissing(rep, 'ctime') + self.assertElementMissing(rep, 'cusec') + self.assertElementPresent(rep, 'stime') + self.assertElementPresent(rep, 'susec') + # error-code checked above + if self.strict_checking: + self.assertElementMissing(rep, 'crealm') + self.assertElementMissing(rep, 'cname') + self.assertElementEqualUTF8(rep, 'realm', expected_srealm) + self.assertElementEqualPrincipal(rep, 'sname', expected_sname) + if self.strict_checking: + self.assertElementMissing(rep, 'e-text') + if expected_error_mode != KDC_ERR_PREAUTH_REQUIRED: + self.assertElementMissing(rep, 'e-data') + return + edata = self.getElementValue(rep, 'e-data') + if self.strict_checking: + self.assertIsNotNone(edata) + if edata is not None: + rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA()) + self.assertGreater(len(rep_padata), 0) + else: + rep_padata = [] + + if self.strict_checking: + for i in range(0, len(expected_patypes)): + self.assertElementEqual(rep_padata[i], 'padata-type', expected_patypes[i]) + self.assertEqual(len(rep_padata), len(expected_patypes)) + + etype_info2 = None + etype_info = None + enc_timestamp = None + pk_as_req = None + pk_as_rep19 = None + for pa in rep_padata: + patype = self.getElementValue(pa, 'padata-type') + pavalue = self.getElementValue(pa, 'padata-value') + if patype == PADATA_ETYPE_INFO2: + self.assertIsNone(etype_info2) + etype_info2 = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO2()) + continue + if patype == PADATA_ETYPE_INFO: + self.assertIsNone(etype_info) + etype_info = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO()) + continue + if patype == PADATA_ENC_TIMESTAMP: + self.assertIsNone(enc_timestamp) + enc_timestamp = pavalue + self.assertEqual(len(enc_timestamp), 0) + continue + if patype == PADATA_PK_AS_REQ: + self.assertIsNone(pk_as_req) + pk_as_req = pavalue + self.assertEqual(len(pk_as_req), 0) + continue + if patype == PADATA_PK_AS_REP_19: + self.assertIsNone(pk_as_rep19) + pk_as_rep19 = pavalue + self.assertEqual(len(pk_as_rep19), 0) + continue + + if expected_error == KDC_ERR_ETYPE_NOSUPP: + self.assertIsNone(etype_info2) + self.assertIsNone(etype_info) + if self.strict_checking: + self.assertIsNotNone(enc_timestamp) + self.assertIsNotNone(pk_as_req) + self.assertIsNotNone(pk_as_rep19) + return + + self.assertIsNotNone(etype_info2) + if expect_etype_info: + self.assertIsNotNone(etype_info) + else: + if self.strict_checking: + self.assertIsNone(etype_info) + if unexpect_etype_info: + self.assertIsNone(etype_info) + + self.assertGreaterEqual(len(etype_info2), 1) + self.assertLessEqual(len(etype_info2), len(expect_etype_info2)) + if self.strict_checking: + self.assertEqual(len(etype_info2), len(expect_etype_info2)) + for i in range(0, len(etype_info2)): + e = self.getElementValue(etype_info2[i], 'etype') + self.assertEqual(e, expect_etype_info2[i]) + salt = self.getElementValue(etype_info2[i], 'salt') + if e == kcrypto.Enctype.RC4: + self.assertIsNone(salt) + else: + self.assertIsNotNone(salt) + if expected_salt is not None: + self.assertEqual(salt, expected_salt) + s2kparams = self.getElementValue(etype_info2[i], 's2kparams') + if self.strict_checking: + self.assertIsNone(s2kparams) + if etype_info is not None: + self.assertEqual(len(etype_info), 1) + e = self.getElementValue(etype_info[0], 'etype') + self.assertEqual(e, kcrypto.Enctype.RC4) + self.assertEqual(e, expect_etype_info2[0]) + salt = self.getElementValue(etype_info[0], 'salt') + if self.strict_checking: + self.assertIsNotNone(salt) + self.assertEqual(len(salt), 0) + + self.assertIsNotNone(enc_timestamp) + self.assertIsNotNone(pk_as_req) + self.assertIsNotNone(pk_as_rep19) + + kdc_exchange_dict['preauth_etype_info2'] = etype_info2 + return + + def generate_simple_tgs_padata(self, + kdc_exchange_dict, + callback_dict, + req_body): + 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()) + + req_body_checksum = self.Checksum_create(tgt.session_key, + KU_TGS_REQ_AUTH_CKSUM, + req_body_blob, + ctype=body_checksum_type) + + subkey_obj = None + if authenticator_subkey is not None: + subkey_obj = authenticator_subkey.export_obj() + seq_number = random.randint(0, 0xfffffffe) + (ctime, cusec) = self.get_KerberosTimeWithUsec() + authenticator_obj = self.Authenticator_create(crealm=tgt.crealm, + cname=tgt.cname, + cksum=req_body_checksum, + cusec=cusec, + ctime=ctime, + subkey=subkey_obj, + seq_number=seq_number, + authorization_data=None) + authenticator_blob = self.der_encode(authenticator_obj, asn1Spec=krb5_asn1.Authenticator()) + + authenticator = self.EncryptedData_create(tgt.session_key, + KU_TGS_REQ_AUTH, + authenticator_blob) + + ap_options = krb5_asn1.APOptions('0') + ap_req_obj = self.AP_REQ_create(ap_options=str(ap_options), + ticket=tgt.ticket, + authenticator=authenticator) + ap_req = self.der_encode(ap_req_obj, asn1Spec=krb5_asn1.AP_REQ()) + pa_tgs_req = self.PA_DATA_create(PADATA_KDC_REQ, ap_req) + padata = [pa_tgs_req] + + return padata, req_body + + def check_simple_tgs_padata(self, + kdc_exchange_dict, + callback_dict, + rep, + padata): + tgt = kdc_exchange_dict['tgt'] + authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] + if authenticator_subkey is not None: + subkey = authenticator_subkey + subkey_usage = KU_TGS_REP_ENC_PART_SUB_KEY + else: + subkey = tgt.session_key + subkey_usage = KU_TGS_REP_ENC_PART_SESSION + + return subkey, subkey_usage + + def _test_as_exchange(self, + cname, + realm, + sname, + till, + client_as_etypes, + expected_error_mode, + expected_crealm, + expected_cname, + expected_srealm, + expected_sname, + expected_salt, + etypes, + padata, + kdc_options, + preauth_key=None, + ticket_decryption_key=None): + + def _generate_padata_copy(_kdc_exchange_dict, + _callback_dict, + req_body): + return padata, req_body + + def _check_padata_preauth_key(_kdc_exchange_dict, + _callback_dict, + rep, + padata): + as_rep_usage = KU_AS_REP_ENC_PART + return preauth_key, as_rep_usage + + kdc_exchange_dict = self.as_exchange_dict( + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + ticket_decryption_key=ticket_decryption_key, + generate_padata_fn=_generate_padata_copy, + check_error_fn=self.generic_check_as_error, + check_rep_fn=self.generic_check_kdc_rep, + check_padata_fn=_check_padata_preauth_key, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error_mode, + client_as_etypes=client_as_etypes, + expected_salt=expected_salt) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + kdc_options=str(kdc_options), + cname=cname, + realm=realm, + sname=sname, + till_time=till, + etypes=etypes) + + if expected_error_mode == 0: # AS-REP + return rep + + return kdc_exchange_dict['preauth_etype_info2'] diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 702f6084217..a4c5e079b66 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -28,16 +28,27 @@ ARCFOUR_HMAC_MD5 = int( # Message types KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) 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')) # PAData types PADATA_ENC_TIMESTAMP = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ENC-TIMESTAMP')) +PADATA_ETYPE_INFO = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO')) PADATA_ETYPE_INFO2 = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) +PADATA_KDC_REQ = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-KDC-REQ')) +PADATA_PK_AS_REQ = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REQ')) +PADATA_PK_AS_REP_19 = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REP-19')) # Error codes KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 +KDC_ERR_ETYPE_NOSUPP = 14 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 KDC_ERR_BADMATCH = 36 -- 2.25.1 From 81ac9bcca2e1ddae0a18b4ac85c8777772f16faa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Apr 2020 11:07:45 +0200 Subject: [PATCH 097/645] tests/krb5/as_req_tests.py: add new tests to cover more of the AS-REQ protocol Example commands: Windows 2012R2: SERVER=172.31.9.188 STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE CLIENT_USERNAME=ldaptestuser CLIENT_PASSWORD=a1B2c3D4 CLIENT_AS_SUPPORTED_ENCTYPES=28 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests SERVER=172.31.9.188 STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests Windows 2008R2: SERVER=172.31.9.133 STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests SERVER=172.31.9.133 STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests Samba 4.14: SERVER=172.31.9.163 STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests SERVER=172.31.9.163 STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 01d86954d217e38be333aa1ce7db1d3d9059cd4c) --- python/samba/tests/krb5/as_req_tests.py | 121 ++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + 2 files changed, 122 insertions(+) create mode 100755 python/samba/tests/krb5/as_req_tests.py diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py new file mode 100755 index 00000000000..3ad37c6bdf2 --- /dev/null +++ b/python/samba/tests/krb5/as_req_tests.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests import DynamicTestCase +from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_PREAUTH_REQUIRED, + NT_PRINCIPAL, + NT_SRV_INST +) + +global_asn1_print = False +global_hexdump = False + +@DynamicTestCase +class AsReqKerberosTests(RawKerberosTest): + + @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) + return + + 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, + initial_padata=None, + initial_kdc_options=None): + client_creds = self.get_client_creds() + client_account = client_creds.get_username() + client_as_etypes = client_creds.get_as_krb5_etypes() + krbtgt_creds = self.get_krbtgt_creds() + 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_error_mode = KDC_ERR_PREAUTH_REQUIRED + expected_crealm = realm + expected_cname = cname + expected_srealm = realm + expected_sname = sname + expected_salt = client_creds.get_forced_salt() + + def _generate_padata_copy(_kdc_exchange_dict, + _callback_dict, + req_body): + return initial_padata, req_body + + 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=_generate_padata_copy, + check_error_fn=self.generic_check_as_error, + check_rep_fn=self.generic_check_kdc_rep, + expected_error_mode=expected_error_mode, + client_as_etypes=client_as_etypes, + expected_salt=expected_salt) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + kdc_options=str(initial_kdc_options), + cname=cname, + realm=realm, + sname=sname, + etypes=initial_etypes) + + return kdc_exchange_dict['preauth_etype_info2'] + + def _test_as_req_no_preauth_with_args(self, etype_idx, pac): + name, etypes = self.etype_test_permutation_by_idx(etype_idx) + if pac is None: + padata = None + else: + pa_pac = self.KERB_PA_PAC_REQUEST_create(pac) + padata = [pa_pac] + return self._test_as_req_nopreauth( + initial_padata=padata, + initial_etypes=etypes, + initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) + + +if __name__ == "__main__": + global_asn1_print = True + global_hexdump = True + import unittest + unittest.main() + diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index e8eda7d6896..11170a2d241 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -100,6 +100,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/test_rpc.py', 'python/samba/tests/krb5/test_smb.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', + 'python/samba/tests/krb5/as_req_tests.py', } EXCLUDE_HELP = { -- 2.25.1 From 2c24daaefcba0339ec569462a78361de2aef8be0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Apr 2020 11:07:45 +0200 Subject: [PATCH 098/645] selftest: run new as_req_tests against fl2008r2dc and fl2003dc There are a lot of things we should improve in our KDC in order to work like a Windows KDC. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d91665d33130aed11fa82d8d2796ab1627e04dc4) --- .../knownfail.d/samba.tests.krb5.as_req_tests | 276 +++++++++++++ selftest/knownfail_mit_kdc | 389 +++++++++++++++++- selftest/target/Samba.pm | 1 + selftest/target/Samba4.pm | 6 +- source4/selftest/tests.py | 10 + 5 files changed, 680 insertions(+), 2 deletions(-) create mode 100644 selftest/knownfail.d/samba.tests.krb5.as_req_tests diff --git a/selftest/knownfail.d/samba.tests.krb5.as_req_tests b/selftest/knownfail.d/samba.tests.krb5.as_req_tests new file mode 100644 index 00000000000..390d6cd0ab6 --- /dev/null +++ b/selftest/knownfail.d/samba.tests.krb5.as_req_tests @@ -0,0 +1,276 @@ +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2003dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 2c2a643944c..b610929a8dd 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -290,4 +290,391 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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_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_c ^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_6_c - +# +# MIT currently fails some as_req_no_preauth tests. +# +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_False.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2008r2dc diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index 9319f301327..4b4da053d83 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -714,6 +714,7 @@ my @exported_envvars = ( "DNSNAME", "REALM", "DOMSID", + "SUPPORTED_ENCTYPE_BITS", # stuff related to a trusted domain "TRUST_SERVER", diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 927638cb7c4..193b2456cb4 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -510,7 +510,10 @@ sub provision_raw_prepare($$$$$$$$$$$$) $ctx->{kdc_ipv6} = $kdc_ipv6; $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}"; if ($functional_level eq "2000") { - $ctx->{supported_enctypes} = "arcfour-hmac-md5 des-cbc-md5 des-cbc-crc" + $ctx->{supported_enctypes} = "arcfour-hmac-md5 des-cbc-md5 des-cbc-crc"; + $ctx->{supported_enctypes_bits} = "4"; + } else { + $ctx->{supported_enctypes_bits} = "28"; } # @@ -812,6 +815,7 @@ nogroup:x:65534:nobody KRB5_CONFIG => $ctx->{krb5_conf}, KRB5_CCACHE => $ctx->{krb5_ccache}, MITKDC_CONFIG => $ctx->{mitkdc_conf}, + SUPPORTED_ENCTYPE_BITS => $ctx->{supported_enctypes_bits}, PIDDIR => $ctx->{piddir}, SERVER => $ctx->{hostname}, DC_SERVER => $ctx->{hostname}, diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index f26bdc2bf6f..a3113e6b77e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1273,6 +1273,16 @@ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", ' '--option=torture:krb5-hostname=testupnspn.$DNSNAME', '--option=torture:krb5-service=http'], "samba4.krb5.kdc with account having identical UPN and SPN") +for env in ["fl2008r2dc", "fl2003dc"]: + planoldpythontestsuite(env, "samba.tests.krb5.as_req_tests", + environ={ + 'CLIENT_USERNAME': '$USERNAME', + 'CLIENT_PASSWORD': '$PASSWORD', + 'CLIENT_AS_SUPPORTED_ENCTYPES': '$SUPPORTED_ENCTYPE_BITS', + 'SERVER_USERNAME': '$SERVER', + 'SERVER_PASSWORD': 'machine$PASSWORD', + 'STRICT_CHECKING': '0', + }) for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: -- 2.25.1 From bdf3b11abb830cd9196b1db8b043599ec8cea92e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 15:38:28 +1200 Subject: [PATCH 099/645] tests/krb5/kdc_base_test.py: Defer account deletion until tearDownClass() is called This allows accounts created for permutation tests to be reused, rather than having to be recreated for every test. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 5412bffb9b4fc13023e650bbc9436a79b60b6fa2) --- python/samba/tests/krb5/kdc_base_test.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e345f739e1c..578736574ae 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -99,21 +99,27 @@ class KDCBaseTest(RawKerberosTest): base="", expression="", scope=SCOPE_BASE, attrs=["dnsHostName"]) cls.dns_host_name = str(res[0]['dnsHostName']) + # A set containing DNs of accounts created as part of testing. + cls.accounts = set() + + @classmethod + def tearDownClass(cls): + # Clean up any accounts created by create_account. This is + # done in tearDownClass() rather than tearDown(), so that + # accounts need only be created once for permutation tests. + for dn in cls.accounts: + delete_force(cls.ldb, dn) + super().tearDownClass() + def setUp(self): super().setUp() self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - self.accounts = [] - - def tearDown(self): - # Clean up any accounts created by create_account - for dn in self.accounts: - delete_force(self.ldb, dn) def create_account(self, name, machine_account=False, spn=None, upn=None): '''Create an account for testing. The dn of the created account is added to self.accounts, - which is used by tearDown to clean up the created accounts. + which is used by tearDownClass to clean up the created accounts. ''' dn = "cn=%s,%s" % (name, self.ldb.domain_dn()) @@ -153,8 +159,8 @@ class KDCBaseTest(RawKerberosTest): if machine_account: creds.set_workstation(name) # - # Save the account name so it can be deleted in the tearDown - self.accounts.append(dn) + # Save the account name so it can be deleted in tearDownClass + self.accounts.add(dn) return (creds, dn) -- 2.25.1 From de3d2e294ffdb9de934282a61c9d0685cc7c4a24 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 13:14:33 +1200 Subject: [PATCH 100/645] tests/krb5/raw_testcase.py: Add get_admin_creds() This method allows obtaining credentials that can be used for administrative tasks such as creating accounts. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 5afae39da0ab408bb36dde3a7801634bd9cc24f6) --- python/samba/tests/krb5/raw_testcase.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8c8926b0ad2..7e41245f706 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -526,6 +526,11 @@ class RawKerberosTest(TestCaseInTempDir): allow_missing_password=allow_missing_password) return c + def get_admin_creds(self, allow_missing_password=False): + c = self._get_krb5_creds(prefix='ADMIN', + allow_missing_password=allow_missing_password) + return c + def get_krbtgt_creds(self, require_strongest_key=False): c = self._get_krb5_creds(prefix='KRBTGT', default_username='krbtgt', -- 2.25.1 From af1d02ea0154e017ecaf8470cf1feb64db1ce762 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 11:04:00 +1200 Subject: [PATCH 101/645] tests/krb5/kdc_base_test.py: Create database connection only when needed Now the database connection is only created on its first use, which means database credentials are no longer required for tests that don't make use of it. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4f5566be4839838e0e3e501a030bcf6e85ff5159) --- python/samba/tests/krb5/kdc_base_test.py | 56 +++++++------ python/samba/tests/krb5/kdc_tgs_tests.py | 17 ++-- .../ms_kile_client_principal_lookup_tests.py | 84 +++++++++++-------- python/samba/tests/krb5/test_ccache.py | 15 ++-- python/samba/tests/krb5/test_ldap.py | 12 +-- python/samba/tests/krb5/test_rpc.py | 6 +- python/samba/tests/krb5/test_smb.py | 12 +-- 7 files changed, 116 insertions(+), 86 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 578736574ae..b191f905366 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -89,15 +89,7 @@ class KDCBaseTest(RawKerberosTest): cls.credentials = c - cls.session = system_session() - cls.ldb = SamDB(url="ldap://%s" % cls.host, - session_info=cls.session, - credentials=cls.credentials, - lp=cls.lp) - # fetch the dnsHostName from the RootDse - res = cls.ldb.search( - base="", expression="", scope=SCOPE_BASE, attrs=["dnsHostName"]) - cls.dns_host_name = str(res[0]['dnsHostName']) + cls._ldb = None # A set containing DNs of accounts created as part of testing. cls.accounts = set() @@ -107,8 +99,9 @@ class KDCBaseTest(RawKerberosTest): # Clean up any accounts created by create_account. This is # done in tearDownClass() rather than tearDown(), so that # accounts need only be created once for permutation tests. - for dn in cls.accounts: - delete_force(cls.ldb, dn) + if cls._ldb is not None: + for dn in cls.accounts: + delete_force(cls._ldb, dn) super().tearDownClass() def setUp(self): @@ -116,16 +109,27 @@ class KDCBaseTest(RawKerberosTest): self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - def create_account(self, name, machine_account=False, spn=None, upn=None): + def get_samdb(self): + if self._ldb is None: + session = system_session() + type(self)._ldb = SamDB(url="ldap://%s" % self.host, + session_info=session, + credentials=self.credentials, + lp=self.lp) + + return self._ldb + + def create_account(self, ldb, name, machine_account=False, + spn=None, upn=None): '''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. ''' - dn = "cn=%s,%s" % (name, self.ldb.domain_dn()) + dn = "cn=%s,%s" % (name, ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed - delete_force(self.ldb, dn) + delete_force(ldb, dn) if machine_account: object_class = "computer" account_name = "%s$" % name @@ -148,12 +152,12 @@ class KDCBaseTest(RawKerberosTest): details["servicePrincipalName"] = spn if upn is not None: details["userPrincipalName"] = upn - self.ldb.add(details) + ldb.add(details) creds = Credentials() creds.guess(self.lp) - creds.set_realm(self.ldb.domain_dns_name().upper()) - creds.set_domain(self.ldb.domain_netbios_name().upper()) + creds.set_realm(ldb.domain_dns_name().upper()) + creds.set_domain(ldb.domain_netbios_name().upper()) creds.set_password(password) creds.set_username(account_name) if machine_account: @@ -425,38 +429,38 @@ class KDCBaseTest(RawKerberosTest): enc_part, asn1Spec=krb5_asn1.EncTicketPart()) return enc_ticket_part - def get_objectSid(self, dn): + def get_objectSid(self, samdb, dn): ''' Get the objectSID for a DN Note: performs an Ldb query. ''' - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["objectSID"]) + res = samdb.search(dn, scope=SCOPE_BASE, attrs=["objectSID"]) self.assertTrue(len(res) == 1, "did not get objectSid for %s" % dn) - sid = self.ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + sid = samdb.schema_format_value("objectSID", res[0]["objectSID"][0]) return sid.decode('utf8') - def add_attribute(self, dn_str, name, value): + def add_attribute(self, samdb, dn_str, name, value): if isinstance(value, list): values = value else: values = [value] flag = ldb.FLAG_MOD_ADD - dn = ldb.Dn(self.ldb, dn_str) + dn = ldb.Dn(samdb, dn_str) msg = ldb.Message(dn) msg[name] = ldb.MessageElement(values, flag, name) - self.ldb.modify(msg) + samdb.modify(msg) - def modify_attribute(self, dn_str, name, value): + def modify_attribute(self, samdb, dn_str, name, value): if isinstance(value, list): values = value else: values = [value] flag = ldb.FLAG_MOD_REPLACE - dn = ldb.Dn(self.ldb, dn_str) + dn = ldb.Dn(samdb, dn_str) msg = ldb.Message(dn) msg[name] = ldb.MessageElement(values, flag, name) - self.ldb.modify(msg) + samdb.modify(msg) def create_ccache(self, cname, ticket, enc_part): """ Lay out a version 4 on-disk credentials cache, to be read using the diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 23a1d868a79..0c757bd5e5f 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -49,8 +49,9 @@ class KdcTgsTests(KDCBaseTest): that differs from that provided to the krbtgt ''' # Create the user account + samdb = self.get_samdb() user_name = "tsttktusr" - (uc, _) = self.create_account(user_name) + (uc, _) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required @@ -81,7 +82,7 @@ class KdcTgsTests(KDCBaseTest): names=["Administrator"]) sname = self.PrincipalName_create( name_type=NT_PRINCIPAL, - names=["host", self.dns_host_name]) + names=["host", samdb.host_dns_name()]) (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype) @@ -98,8 +99,9 @@ class KdcTgsTests(KDCBaseTest): '''Get a ticket to the ldap service ''' # Create the user account + samdb = self.get_samdb() user_name = "tsttktusr" - (uc, _) = self.create_account(user_name) + (uc, _) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required @@ -126,7 +128,7 @@ class KdcTgsTests(KDCBaseTest): # Request a ticket to the ldap service sname = self.PrincipalName_create( name_type=NT_SRV_INST, - names=["ldap", self.dns_host_name]) + names=["ldap", samdb.host_dns_name()]) (rep, _) = self.tgs_req( cname, sname, uc.get_realm(), ticket, key, etype) @@ -137,9 +139,10 @@ class KdcTgsTests(KDCBaseTest): # Create a user and machine account for the test. # + samdb = self.get_samdb() user_name = "tsttktusr" - (uc, dn) = self.create_account(user_name) - (mc, _) = self.create_account("tsttktmac", machine_account=True) + (uc, dn) = self.create_account(samdb, user_name) + (mc, _) = self.create_account(samdb, "tsttktmac", machine_account=True) realm = uc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required @@ -179,7 +182,7 @@ class KdcTgsTests(KDCBaseTest): enc_part = self.decode_service_ticket(mc, ticket) pac_data = self.get_pac_data(enc_part['authorization-data']) - sid = self.get_objectSid(dn) + sid = self.get_objectSid(samdb, dn) upn = "%s@%s" % (uc.get_username(), realm) self.assertEqual( uc.get_username(), diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 356a25f8e18..63f67b09c4c 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -49,10 +49,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - def check_pac(self, auth_data, dn, uc, name, upn=None): + def check_pac(self, samdb, auth_data, dn, uc, name, upn=None): pac_data = self.get_pac_data(auth_data) - sid = self.get_objectSid(dn) + sid = self.get_objectSid(samdb, dn) if upn is None: upn = "%s@%s" % (name, uc.get_realm().lower()) if name.endswith('$'): @@ -89,12 +89,13 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create user and machine accounts for the test. # + samdb = self.get_samdb() user_name = "mskileusr" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -131,7 +132,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Check the contents of the pac, and the ticket ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) - self.check_pac(enc_part['authorization-data'], dn, uc, user_name) + self.check_pac(samdb, enc_part['authorization-data'], dn, uc, user_name) # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_PRINCIPAL, cname['name-type']) @@ -147,12 +148,13 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create a machine account for the test. # + samdb = self.get_samdb() user_name = "mskilemac" - (mc, dn) = self.create_account(user_name, machine_account=True) + (mc, dn) = self.create_account(samdb, user_name, machine_account=True) realm = mc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -189,7 +191,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Check the contents of the pac, and the ticket ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) - self.check_pac(enc_part['authorization-data'], dn, mc, mach_name + '$') + self.check_pac(samdb, enc_part['authorization-data'], dn, mc, mach_name + '$') # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_PRINCIPAL, cname['name-type']) @@ -206,14 +208,15 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ''' # Create a user account for the test. # + samdb = self.get_samdb() user_name = "mskileusr" upn_name = "mskileupn" upn = upn_name + "@" + self.credentials.get_realm().lower() - (uc, dn) = self.create_account(user_name, upn=upn) + (uc, dn) = self.create_account(samdb, user_name, upn=upn) realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -250,7 +253,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Check the contents of the service ticket ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) - self.check_pac(enc_part['authorization-data'], dn, uc, upn_name) + self.check_pac(samdb, enc_part['authorization-data'], dn, uc, upn_name) # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_PRINCIPAL, cname['name-type']) @@ -273,19 +276,21 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # setting UF_DONT_REQUIRE_PREAUTH seems to be the only way # to trigger the no pre-auth step + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) self.modify_attribute( + samdb, dn, "userAccountControl", str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH # we should get a valid AS-RESP @@ -340,15 +345,16 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create user and machine accounts for the test. # + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -406,15 +412,16 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create user and machine accounts for the test. # + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -445,14 +452,15 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create a user account for the test. # + samdb = self.get_samdb() user_name = "mskileusr" upn_name = "mskileupn" upn = upn_name + "@" + self.credentials.get_realm().lower() - (uc, dn) = self.create_account(user_name, upn=upn) + (uc, dn) = self.create_account(samdb, user_name, upn=upn) realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -508,13 +516,14 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create a user account for the test. # + samdb = self.get_samdb() user_name = "mskileusr" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() ename = user_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -570,12 +579,13 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create a user account for the test. # + samdb = self.get_samdb() user_name = "mskileusr" - (uc, _) = self.create_account(user_name) + (uc, _) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, dn) = self.create_account(mach_name, machine_account=True) + (mc, dn) = self.create_account(samdb, mach_name, machine_account=True) ename = mach_name + "@" + realm uname = mach_name + "$@" + realm @@ -638,20 +648,22 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # setting UF_DONT_REQUIRE_PREAUTH seems to be the only way # to trigger the no pre-auth step + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) self.modify_attribute( + samdb, dn, "userAccountControl", str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) ename = alt_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH # we should get a valid AS-RESP @@ -706,17 +718,18 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create user and machine accounts for the test. # + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) ename = alt_name + "@" + realm uname = user_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -775,16 +788,17 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create user and machine accounts for the test. # + samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(user_name) + (uc, dn) = self.create_account(samdb, user_name) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) - self.add_attribute(dn, "altSecurityIdentities", alt_sec) + self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) ename = alt_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, machine_account=True) # Do the initial AS-REQ, should get a pre-authentication required # response diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index 32c9e3cce6b..c7857a6cf0e 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -49,11 +49,14 @@ class CcacheTests(KDCBaseTest): mach_name = "ccachemac" service = "host" + samdb = self.get_samdb() + # Create the user account. - (user_credentials, _) = self.create_account(user_name) + (user_credentials, _) = self.create_account(samdb, user_name) # Create the machine account. - (mach_credentials, _) = self.create_account(mach_name, + (mach_credentials, _) = self.create_account(samdb, + mach_name, machine_account=True, spn="%s/%s" % (service, mach_name)) @@ -77,7 +80,7 @@ class CcacheTests(KDCBaseTest): gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") - auth_context = AuthContext(lp_ctx=self.lp, ldb=self.ldb, methods=[]) + auth_context = AuthContext(lp_ctx=self.lp, ldb=samdb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) gensec_server.set_credentials(mach_credentials) @@ -104,9 +107,9 @@ class CcacheTests(KDCBaseTest): # token is the SID of the user we created. # Retrieve the user account's SID. - ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, - expression="(sAMAccountName=%s)" % user_name, - attrs=["objectSid"]) + ldb_res = samdb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) self.assertEqual(1, len(ldb_res)) sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 6a4bf52d77f..7e9405a8a92 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -44,12 +44,14 @@ class LdapTests(KDCBaseTest): # credentials cache file where the service ticket authenticating the # user are stored. + samdb = self.get_samdb() + user_name = "ldapusr" - mach_name = self.dns_host_name + mach_name = samdb.host_dns_name() service = "ldap" # Create the user account. - (user_credentials, _) = self.create_account(user_name) + (user_credentials, _) = self.create_account(samdb, user_name) # 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 @@ -63,9 +65,9 @@ class LdapTests(KDCBaseTest): # cached credentials. # Retrieve the user account's SID. - ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, - expression="(sAMAccountName=%s)" % user_name, - attrs=["objectSid"]) + ldb_res = samdb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) self.assertEqual(1, len(ldb_res)) sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index da1c4eb88ac..c474e479d81 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -41,12 +41,14 @@ class RpcTests(KDCBaseTest): # credentials cache file where the service ticket authenticating the # user are stored. + samdb = self.get_samdb() + user_name = "rpcusr" - mach_name = self.dns_host_name + mach_name = samdb.host_dns_name() service = "cifs" # Create the user account. - (user_credentials, _) = self.create_account(user_name) + (user_credentials, _) = self.create_account(samdb, user_name) # 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 diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 0262a37ebb5..8f76e78afe3 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -45,13 +45,15 @@ class SmbTests(KDCBaseTest): # credentials cache file where the service ticket authenticating the # user are stored. + samdb = self.get_samdb() + user_name = "smbusr" - mach_name = self.dns_host_name + mach_name = samdb.host_dns_name() service = "cifs" share = "tmp" # Create the user account. - (user_credentials, _) = self.create_account(user_name) + (user_credentials, _) = self.create_account(samdb, user_name) # 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 @@ -72,9 +74,9 @@ class SmbTests(KDCBaseTest): # cached credentials. # Retrieve the user account's SID. - ldb_res = self.ldb.search(scope=SCOPE_SUBTREE, - expression="(sAMAccountName=%s)" % user_name, - attrs=["objectSid"]) + ldb_res = samdb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) self.assertEqual(1, len(ldb_res)) sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) -- 2.25.1 From 63d604c0c50dbe98c908aa10f2389205606edc87 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 11:31:26 +1200 Subject: [PATCH 102/645] tests/krb5/kdc_base_test.py: Remove 'credentials' class attribute Credentials for tests are now obtained using the get_user_creds() method. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 364f1ce8d8221cb8926635fc864db782cee61cf9) --- python/samba/tests/krb5/kdc_base_test.py | 24 +++---------------- .../ms_kile_client_principal_lookup_tests.py | 4 ++-- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b191f905366..f3c6b37d29f 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -67,28 +67,8 @@ class KDCBaseTest(RawKerberosTest): @classmethod def setUpClass(cls): cls.lp = cls.get_loadparm(cls) - cls.username = os.environ["USERNAME"] - cls.password = os.environ["PASSWORD"] cls.host = os.environ["SERVER"] - c = Credentials() - c.set_username(cls.username) - c.set_password(cls.password) - try: - realm = os.environ["REALM"] - c.set_realm(realm) - except KeyError: - pass - try: - domain = os.environ["DOMAIN"] - c.set_domain(domain) - except KeyError: - pass - - c.guess() - - cls.credentials = c - cls._ldb = None # A set containing DNs of accounts created as part of testing. @@ -111,10 +91,12 @@ class KDCBaseTest(RawKerberosTest): def get_samdb(self): if self._ldb is None: + creds = self.get_user_creds() + session = system_session() type(self)._ldb = SamDB(url="ldap://%s" % self.host, session_info=session, - credentials=self.credentials, + credentials=creds, lp=self.lp) return self._ldb diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 63f67b09c4c..e9d251e72f6 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -211,7 +211,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): samdb = self.get_samdb() user_name = "mskileusr" upn_name = "mskileupn" - upn = upn_name + "@" + self.credentials.get_realm().lower() + upn = upn_name + "@" + self.get_user_creds().get_realm().lower() (uc, dn) = self.create_account(samdb, user_name, upn=upn) realm = uc.get_realm().lower() @@ -455,7 +455,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): samdb = self.get_samdb() user_name = "mskileusr" upn_name = "mskileupn" - upn = upn_name + "@" + self.credentials.get_realm().lower() + upn = upn_name + "@" + self.get_user_creds().get_realm().lower() (uc, dn) = self.create_account(samdb, user_name, upn=upn) realm = uc.get_realm().lower() -- 2.25.1 From a3b3fd25d1b92d9c22a94d0a017c199e9891cb23 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 11:40:41 +1200 Subject: [PATCH 103/645] tests/krb5/kdc_base_test.py: Create loadparm only when needed Now the .conf file is only loaded on its first use, which means that SMB_CONF_PATH need not be defined for tests that don't make use of it. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 210e544016a3a4de1cdb76ce28a2148811ff07eb) --- python/samba/tests/krb5/kdc_base_test.py | 15 +++++++++++---- python/samba/tests/krb5/test_ccache.py | 6 ++++-- python/samba/tests/krb5/test_ldap.py | 2 +- python/samba/tests/krb5/test_rpc.py | 2 +- python/samba/tests/krb5/test_smb.py | 2 +- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index f3c6b37d29f..59ce546a181 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -66,7 +66,7 @@ class KDCBaseTest(RawKerberosTest): @classmethod def setUpClass(cls): - cls.lp = cls.get_loadparm(cls) + cls._lp = None cls.host = os.environ["SERVER"] cls._ldb = None @@ -89,15 +89,22 @@ class KDCBaseTest(RawKerberosTest): self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump + def get_lp(self): + if self._lp is None: + type(self)._lp = self.get_loadparm() + + return self._lp + def get_samdb(self): if self._ldb is None: creds = self.get_user_creds() + lp = self.get_lp() session = system_session() type(self)._ldb = SamDB(url="ldap://%s" % self.host, session_info=session, credentials=creds, - lp=self.lp) + lp=lp) return self._ldb @@ -137,7 +144,7 @@ class KDCBaseTest(RawKerberosTest): ldb.add(details) creds = Credentials() - creds.guess(self.lp) + creds.guess(self.get_lp()) creds.set_realm(ldb.domain_dns_name().upper()) creds.set_domain(ldb.domain_netbios_name().upper()) creds.set_password(password) @@ -607,7 +614,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_kerberos_state(MUST_USE_KERBEROS) creds.set_username(user_name, SPECIFIED) creds.set_realm(realm) - creds.set_named_ccache(cachefile.name, SPECIFIED, self.lp) + creds.set_named_ccache(cachefile.name, SPECIFIED, self.get_lp()) # Return the credentials along with the cache file. return (creds, cachefile) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index c7857a6cf0e..feb7a7bd9be 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -71,8 +71,10 @@ class CcacheTests(KDCBaseTest): # Authenticate in-process to the machine account using the user's # cached credentials. + lp = self.get_lp() + settings = {} - settings["lp_ctx"] = self.lp + settings["lp_ctx"] = lp settings["target_hostname"] = mach_name gensec_client = gensec.Security.start_client(settings) @@ -80,7 +82,7 @@ class CcacheTests(KDCBaseTest): gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") - auth_context = AuthContext(lp_ctx=self.lp, ldb=samdb, methods=[]) + auth_context = AuthContext(lp_ctx=lp, ldb=samdb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) gensec_server.set_credentials(mach_credentials) diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 7e9405a8a92..d304fb9d71e 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -74,7 +74,7 @@ class LdapTests(KDCBaseTest): # Connect to the machine account and retrieve the user SID. ldb_as_user = SamDB(url="ldap://%s" % mach_name, credentials=creds, - lp=self.lp) + lp=self.get_lp()) ldb_res = ldb_as_user.search('', scope=SCOPE_BASE, attrs=["tokenGroups"]) diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index c474e479d81..324b57f2847 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -62,7 +62,7 @@ class RpcTests(KDCBaseTest): # cached credentials. binding_str = "ncacn_np:%s[\\pipe\\lsarpc]" % mach_name - conn = lsa.lsarpc(binding_str, self.lp, creds) + conn = lsa.lsarpc(binding_str, self.get_lp(), creds) (account_name, _) = conn.GetUserName(None, None, None) diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 8f76e78afe3..45d4fe5e0c1 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -82,7 +82,7 @@ class SmbTests(KDCBaseTest): # Connect to a share and retrieve the user SID. s3_lp = s3param.get_context() - s3_lp.load(self.lp.configfile) + s3_lp.load(self.get_lp().configfile) min_protocol = s3_lp.get("client min protocol") self.addCleanup(s3_lp.set, "client min protocol", min_protocol) -- 2.25.1 From 8e0f990d7bd8520a971d348d56eb473a2e15f298 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 15:12:38 +1200 Subject: [PATCH 104/645] tests/krb5/kdc_base_test.py: Add methods to determine supported encryption types This is done based on the domain functional level, which corresponds to the logic Samba uses to decide whether or not to generate a Primary:Kerberos-Newer-Keys element for the supplementalCredentials attribute. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 7d4a0ed21be49d13c2b815582f2d04f0c058bf3a) --- python/samba/tests/krb5/kdc_base_test.py | 38 ++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 59ce546a181..e1b73dd8ff7 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -29,8 +29,13 @@ from ldb import SCOPE_BASE from samba import generate_random_password from samba.auth import system_session from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS -from samba.dcerpc import krb5pac, krb5ccache -from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_NORMAL_ACCOUNT +from samba.dcerpc import krb5pac, krb5ccache, security +from samba.dsdb import ( + DS_DOMAIN_FUNCTION_2000, + DS_DOMAIN_FUNCTION_2008, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_NORMAL_ACCOUNT +) from samba.ndr import ndr_pack, ndr_unpack from samba.samdb import SamDB @@ -71,6 +76,8 @@ class KDCBaseTest(RawKerberosTest): cls._ldb = None + cls._functional_level = None + # A set containing DNs of accounts created as part of testing. cls.accounts = set() @@ -108,6 +115,33 @@ class KDCBaseTest(RawKerberosTest): return self._ldb + def get_domain_functional_level(self, ldb): + if self._functional_level is None: + res = ldb.search(base='', + scope=SCOPE_BASE, + attrs=['domainFunctionality']) + try: + functional_level = int(res[0]['domainFunctionality'][0]) + except KeyError: + functional_level = DS_DOMAIN_FUNCTION_2000 + + type(self)._functional_level = functional_level + + return self._functional_level + + def get_default_enctypes(self): + samdb = self.get_samdb() + functional_level = self.get_domain_functional_level(samdb) + + # RC4 should always be supported + default_enctypes = security.KERB_ENCTYPE_RC4_HMAC_MD5 + if functional_level >= DS_DOMAIN_FUNCTION_2008: + # AES is only supported at functional level 2008 or higher + default_enctypes |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 + default_enctypes |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + + return default_enctypes + def create_account(self, ldb, name, machine_account=False, spn=None, upn=None): '''Create an account for testing. -- 2.25.1 From 5dce9cba31253ca38a65a296789e7a9c7a52c8f3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 13:15:10 +1200 Subject: [PATCH 105/645] tests/krb5/raw_testcase.py: Add method to obtain Kerberos keys over DRS This requires admin credentials, and removes the need to pass these keys as environment variables. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1f2ddd3c97e3ff243c8bd0c17299f27b761f5e7f) --- python/samba/tests/krb5/kdc_base_test.py | 100 ++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e1b73dd8ff7..7ae22bc5929 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -20,6 +20,8 @@ import sys import os from datetime import datetime, timezone import tempfile +import binascii +import struct sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" @@ -29,7 +31,8 @@ from ldb import SCOPE_BASE from samba import generate_random_password from samba.auth import system_session from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS -from samba.dcerpc import krb5pac, krb5ccache, security +from samba.dcerpc import drsblobs, drsuapi, misc, krb5pac, krb5ccache, security +from samba.drs_utils import drsuapi_connect from samba.dsdb import ( DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, @@ -37,6 +40,7 @@ from samba.dsdb import ( UF_NORMAL_ACCOUNT ) from samba.ndr import ndr_pack, ndr_unpack +from samba import net from samba.samdb import SamDB from samba.tests import delete_force @@ -191,6 +195,100 @@ class KDCBaseTest(RawKerberosTest): return (creds, dn) + def get_keys(self, samdb, dn): + admin_creds = self.get_admin_creds() + + dns_hostname = samdb.host_dns_name() + (bind, handle, _) = drsuapi_connect(dns_hostname, + self.get_lp(), + admin_creds) + + destination_dsa_guid = misc.GUID(samdb.get_ntds_GUID()) + + req = drsuapi.DsGetNCChangesRequest8() + + req.destination_dsa_guid = destination_dsa_guid + req.source_dsa_invocation_id = misc.GUID() + + naming_context = drsuapi.DsReplicaObjectIdentifier() + naming_context.dn = str(dn) + + req.naming_context = naming_context + + hwm = drsuapi.DsReplicaHighWaterMark() + hwm.tmp_highest_usn = 0 + hwm.reserved_usn = 0 + hwm.highest_usn = 0 + + req.highwatermark = hwm + req.uptodateness_vector = None + + req.replica_flags = 0 + + req.max_object_count = 1 + req.max_ndr_size = 402116 + req.extended_op = drsuapi.DRSUAPI_EXOP_REPL_SECRET + + attids = [drsuapi.DRSUAPI_ATTID_supplementalCredentials, + drsuapi.DRSUAPI_ATTID_unicodePwd] + + partial_attribute_set = drsuapi.DsPartialAttributeSet() + partial_attribute_set.version = 1 + partial_attribute_set.attids = attids + partial_attribute_set.num_attids = len(attids) + + req.partial_attribute_set = partial_attribute_set + + req.partial_attribute_set_ex = None + req.mapping_ctr.num_mappings = 0 + req.mapping_ctr.mappings = None + + _, ctr = bind.DsGetNCChanges(handle, 8, req) + identifier = ctr.first_object.object.identifier + attributes = ctr.first_object.object.attribute_ctr.attributes + + rid = identifier.sid.split()[1] + + forced_keys = dict() + + net_ctx = net.Net(admin_creds) + + keys = {} + + for attr in attributes: + if attr.attid == drsuapi.DRSUAPI_ATTID_supplementalCredentials: + net_ctx.replicate_decrypt(bind, attr, rid) + attr_val = attr.value_ctr.values[0].blob + + spl = ndr_unpack(drsblobs.supplementalCredentialsBlob, + attr_val) + for pkg in spl.sub.packages: + if pkg.name == 'Primary:Kerberos-Newer-Keys': + krb5_new_keys_raw = binascii.a2b_hex(pkg.data) + krb5_new_keys = ndr_unpack( + drsblobs.package_PrimaryKerberosBlob, + krb5_new_keys_raw) + for key in krb5_new_keys.ctr.keys: + keytype = key.keytype + if keytype in (kcrypto.Enctype.AES256, + kcrypto.Enctype.AES128): + keys[keytype] = key.value.hex() + elif attr.attid == drsuapi.DRSUAPI_ATTID_unicodePwd: + net_ctx.replicate_decrypt(bind, attr, rid) + pwd = attr.value_ctr.values[0].blob + keys[kcrypto.Enctype.RC4] = pwd.hex() + + default_enctypes = self.get_default_enctypes() + + if default_enctypes & security.KERB_ENCTYPE_RC4_HMAC_MD5: + self.assertIn(kcrypto.Enctype.RC4, keys) + if default_enctypes & security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96: + self.assertIn(kcrypto.Enctype.AES256, keys) + if default_enctypes & security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96: + self.assertIn(kcrypto.Enctype.AES128, keys) + + return keys + def as_req(self, cname, sname, realm, etypes, padata=None): '''Send a Kerberos AS_REQ, returns the undecoded response ''' -- 2.25.1 From 3d3f6170e285fcfe8d94354958ebb2300fc34ee7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 15:59:11 +1200 Subject: [PATCH 106/645] tests/krb5/raw_testcase.py: Make env_get_var() a standalone method This allows it to be used elsewhere in the tests. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 948bbc9cecbfc1b33a338891d26a4a706864b9c6) --- python/samba/tests/krb5/raw_testcase.py | 80 +++++++++++++------------ 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 7e41245f706..7d9f0cd94f9 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -424,6 +424,23 @@ class RawKerberosTest(TestCaseInTempDir): sys.stderr.write("connected[%s]\n" % self.host) return + def env_get_var(self, varname, prefix, + fallback_default=True, + allow_missing=False): + val = None + if prefix is not None: + allow_missing_prefix = allow_missing + if fallback_default: + allow_missing_prefix = True + val = samba.tests.env_get_var_value('%s_%s' % (prefix, varname), + allow_missing=allow_missing_prefix) + else: + fallback_default = True + if val is None and fallback_default: + val = samba.tests.env_get_var_value(varname, + allow_missing=allow_missing) + return val + def _get_krb5_creds(self, prefix, default_username=None, allow_missing_password=False, @@ -431,49 +448,34 @@ class RawKerberosTest(TestCaseInTempDir): c = KerberosCredentials() c.guess() - def env_get_var(varname, prefix, fallback_default=True, allow_missing=False): - val = None - if prefix is not None: - allow_missing_prefix = allow_missing - if fallback_default: - allow_missing_prefix = True - val = samba.tests.env_get_var_value('%s_%s' % (prefix, varname), - allow_missing=allow_missing_prefix) - else: - fallback_default = True - if val is None and fallback_default: - val = samba.tests.env_get_var_value(varname, - allow_missing=allow_missing) - return val - - domain = env_get_var('DOMAIN', prefix) - realm = env_get_var('REALM', prefix) + domain = self.env_get_var('DOMAIN', prefix) + realm = self.env_get_var('REALM', prefix) allow_missing_username = False if default_username is not None: allow_missing_username = True - username = env_get_var('USERNAME', prefix, - fallback_default=False, - allow_missing=allow_missing_username) + username = self.env_get_var('USERNAME', prefix, + fallback_default=False, + allow_missing=allow_missing_username) if username is None: username = default_username - password = env_get_var('PASSWORD', prefix, - fallback_default=False, - allow_missing=allow_missing_password) + password = self.env_get_var('PASSWORD', prefix, + fallback_default=False, + allow_missing=allow_missing_password) c.set_domain(domain) c.set_realm(realm) c.set_username(username) if password is not None: c.set_password(password) - as_supported_enctypes = env_get_var('AS_SUPPORTED_ENCTYPES', - prefix, allow_missing=True) + as_supported_enctypes = self.env_get_var('AS_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) if as_supported_enctypes is not None: c.set_as_supported_enctypes(as_supported_enctypes) - tgs_supported_enctypes = env_get_var('TGS_SUPPORTED_ENCTYPES', - prefix, allow_missing=True) + tgs_supported_enctypes = self.env_get_var('TGS_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) if tgs_supported_enctypes is not None: c.set_tgs_supported_enctypes(tgs_supported_enctypes) - ap_supported_enctypes = env_get_var('AP_SUPPORTED_ENCTYPES', - prefix, allow_missing=True) + ap_supported_enctypes = self.env_get_var('AP_SUPPORTED_ENCTYPES', + prefix, allow_missing=True) if ap_supported_enctypes is not None: c.set_ap_supported_enctypes(ap_supported_enctypes) @@ -486,22 +488,22 @@ class RawKerberosTest(TestCaseInTempDir): else: kvno_allow_missing = True aes256_allow_missing = True - kvno = env_get_var('KVNO', prefix, - fallback_default=False, - allow_missing=kvno_allow_missing) + kvno = self.env_get_var('KVNO', prefix, + fallback_default=False, + allow_missing=kvno_allow_missing) if kvno is not None: c.set_kvno(kvno) - aes256_key = env_get_var('AES256_KEY_HEX', prefix, - fallback_default=False, - allow_missing=aes256_allow_missing) + aes256_key = self.env_get_var('AES256_KEY_HEX', prefix, + fallback_default=False, + allow_missing=aes256_allow_missing) if aes256_key is not None: c.set_forced_key(kcrypto.Enctype.AES256, aes256_key) - aes128_key = env_get_var('AES128_KEY_HEX', prefix, - fallback_default=False, allow_missing=True) + aes128_key = self.env_get_var('AES128_KEY_HEX', prefix, + fallback_default=False, allow_missing=True) if aes128_key is not None: c.set_forced_key(kcrypto.Enctype.AES128, aes128_key) - rc4_key = env_get_var('RC4_KEY_HEX', prefix, - fallback_default=False, allow_missing=True) + rc4_key = self.env_get_var('RC4_KEY_HEX', prefix, + fallback_default=False, allow_missing=True) if rc4_key is not None: c.set_forced_key(kcrypto.Enctype.RC4, rc4_key) return c -- 2.25.1 From d3b08e517d576397766ad41c2b67cd05bd1d8f26 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 16:55:02 +1200 Subject: [PATCH 107/645] tests/krb5/raw_testcase.py: Add allow_missing_keys parameter for getting creds This allows us to require encryption keys in the case that a password would not be required, such as for the krbtgt account. Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Joseph Sutton Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 6a77c2b93315503008627ce786388f281bd6bb87) --- python/samba/tests/krb5/as_req_tests.py | 2 +- python/samba/tests/krb5/raw_testcase.py | 53 +++++++++++++++++++------ python/samba/tests/krb5/simple_tests.py | 2 +- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 3ad37c6bdf2..3099c224c18 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -58,7 +58,7 @@ class AsReqKerberosTests(RawKerberosTest): client_creds = self.get_client_creds() client_account = client_creds.get_username() client_as_etypes = client_creds.get_as_krb5_etypes() - krbtgt_creds = self.get_krbtgt_creds() + krbtgt_creds = self.get_krbtgt_creds(require_keys=False) krbtgt_account = krbtgt_creds.get_username() realm = krbtgt_creds.get_realm() diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 7d9f0cd94f9..9c0f5800b42 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -444,6 +444,7 @@ class RawKerberosTest(TestCaseInTempDir): def _get_krb5_creds(self, prefix, default_username=None, allow_missing_password=False, + allow_missing_keys=True, require_strongest_key=False): c = KerberosCredentials() c.guess() @@ -486,8 +487,8 @@ class RawKerberosTest(TestCaseInTempDir): else: aes256_allow_missing = True else: - kvno_allow_missing = True - aes256_allow_missing = True + kvno_allow_missing = allow_missing_keys + aes256_allow_missing = allow_missing_keys kvno = self.env_get_var('KVNO', prefix, fallback_default=False, allow_missing=kvno_allow_missing) @@ -506,37 +507,63 @@ class RawKerberosTest(TestCaseInTempDir): fallback_default=False, allow_missing=True) if rc4_key is not None: c.set_forced_key(kcrypto.Enctype.RC4, rc4_key) + + if not allow_missing_keys: + self.assertTrue(c.forced_keys, + 'Please supply %s encryption keys ' + 'in environment' % prefix) + return c - def get_user_creds(self, allow_missing_password=False): + def get_user_creds(self, + allow_missing_password=False, + allow_missing_keys=True): c = self._get_krb5_creds(prefix=None, - allow_missing_password=allow_missing_password) + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) return c - def get_service_creds(self, allow_missing_password=False): + def get_service_creds(self, + allow_missing_password=False, + allow_missing_keys=True): c = self._get_krb5_creds(prefix='SERVICE', - allow_missing_password=allow_missing_password) + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) return c - def get_client_creds(self, allow_missing_password=False): + def get_client_creds(self, + allow_missing_password=False, + allow_missing_keys=True): c = self._get_krb5_creds(prefix='CLIENT', - allow_missing_password=allow_missing_password) + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) return c - def get_server_creds(self, allow_missing_password=False): + def get_server_creds(self, + allow_missing_password=False, + allow_missing_keys=True): c = self._get_krb5_creds(prefix='SERVER', - allow_missing_password=allow_missing_password) + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) return c - def get_admin_creds(self, allow_missing_password=False): + def get_admin_creds(self, + allow_missing_password=False, + allow_missing_keys=True): c = self._get_krb5_creds(prefix='ADMIN', - allow_missing_password=allow_missing_password) + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) return c - def get_krbtgt_creds(self, require_strongest_key=False): + def get_krbtgt_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) c = self._get_krb5_creds(prefix='KRBTGT', default_username='krbtgt', allow_missing_password=True, + allow_missing_keys=not require_keys, require_strongest_key=require_strongest_key) return c diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 2da76a3cf5e..9650702c6c6 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -44,7 +44,7 @@ class SimpleKerberosTests(RawKerberosTest): def test_simple(self): user_creds = self.get_user_creds() user = user_creds.get_username() - krbtgt_creds = self.get_krbtgt_creds() + krbtgt_creds = self.get_krbtgt_creds(require_keys=False) krbtgt_account = krbtgt_creds.get_username() realm = krbtgt_creds.get_realm() -- 2.25.1 From d5ab76d1488ff8b605173a6a17994b09cf895707 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 17:10:44 +1200 Subject: [PATCH 108/645] tests/krb5/raw_testcase.py: Cache obtained credentials If credentials are used more than once, we can now use the credentials that we already obtained and so avoid fetching them again. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 22a90aea82ba6ef86bde835f2369daa6e23ed2fd) --- python/samba/tests/krb5/kdc_base_test.py | 1 + python/samba/tests/krb5/raw_testcase.py | 38 ++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 7ae22bc5929..120084616e9 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -75,6 +75,7 @@ class KDCBaseTest(RawKerberosTest): @classmethod def setUpClass(cls): + super().setUpClass() cls._lp = None cls.host = os.environ["SERVER"] diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 9c0f5800b42..5b59eede806 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -371,6 +371,14 @@ class RawKerberosTest(TestCaseInTempDir): e = self.etype_test_permutations[idx] return (e['name'], e['etypes']) + @classmethod + def setUpClass(cls): + super().setUpClass() + + # A dictionary containing credentials that have already been + # obtained. + cls.creds_dict = {} + def setUp(self): super().setUp() self.do_asn1_print = False @@ -441,11 +449,11 @@ class RawKerberosTest(TestCaseInTempDir): allow_missing=allow_missing) return val - def _get_krb5_creds(self, prefix, - default_username=None, - allow_missing_password=False, - allow_missing_keys=True, - require_strongest_key=False): + def _get_krb5_creds_from_env(self, prefix, + default_username=None, + allow_missing_password=False, + allow_missing_keys=True, + require_strongest_key=False): c = KerberosCredentials() c.guess() @@ -515,6 +523,26 @@ class RawKerberosTest(TestCaseInTempDir): return c + def _get_krb5_creds(self, + prefix, + default_username=None, + allow_missing_password=False, + allow_missing_keys=True, + require_strongest_key=False): + if prefix not in self.creds_dict: + # We don't have the credentials already + creds = self._get_krb5_creds_from_env(prefix, + default_username=default_username, + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys, + require_strongest_key=require_strongest_key) + self.assertIsNotNone(creds) + + # Save the obtained credentials + self.creds_dict[prefix] = creds + + return self.creds_dict[prefix] + def get_user_creds(self, allow_missing_password=False, allow_missing_keys=True): -- 2.25.1 From 608a62715cddb0f29b024f8827b3b2360ebea6a6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 17:12:39 +1200 Subject: [PATCH 109/645] tests/krb5/raw_testcase.py: Allow specifying a fallback credentials function This allows us to use other methods of obtaining credentials if getting them from the environment fails. Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Joseph Sutton Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit e1601f2b56f09a944c5cfb119502fdcf49a03c99) --- python/samba/tests/krb5/raw_testcase.py | 39 +++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 5b59eede806..ade980cb46d 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -528,20 +528,47 @@ class RawKerberosTest(TestCaseInTempDir): default_username=None, allow_missing_password=False, allow_missing_keys=True, - require_strongest_key=False): - if prefix not in self.creds_dict: - # We don't have the credentials already + require_strongest_key=False, + fallback_creds_fn=None): + if prefix in self.creds_dict: + return self.creds_dict[prefix] + + # We don't have the credentials already + creds = None + env_err = None + try: + # Try to obtain them from the environment creds = self._get_krb5_creds_from_env(prefix, default_username=default_username, allow_missing_password=allow_missing_password, allow_missing_keys=allow_missing_keys, require_strongest_key=require_strongest_key) + except Exception as err: + # An error occurred, so save it for later + env_err = err + else: self.assertIsNotNone(creds) - # Save the obtained credentials self.creds_dict[prefix] = creds - - return self.creds_dict[prefix] + return creds + + if fallback_creds_fn is not None: + try: + # Try to use the fallback method + creds = fallback_creds_fn() + except Exception as err: + print("ERROR FROM ENV: %r" % (env_err)) + print("FALLBACK-FN: %s" % (fallback_creds_fn)) + print("FALLBACK-ERROR: %r" % (err)) + else: + self.assertIsNotNone(creds) + # Save the obtained credentials + self.creds_dict[prefix] = creds + return creds + + # Both methods failed, so raise the exception from the + # environment method + raise env_err def get_user_creds(self, allow_missing_password=False, -- 2.25.1 From 86e3641758678dc16363fd3d11117b88c6f3e651 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 15:55:17 +1200 Subject: [PATCH 110/645] tests/krb5/raw_testcase.py: Simplify conditionals Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ec5c2b040b63d06a17bcd7bd133c2d68d07df587) --- python/samba/tests/krb5/raw_testcase.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index ade980cb46d..0e08f0ef7d2 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -437,9 +437,7 @@ class RawKerberosTest(TestCaseInTempDir): allow_missing=False): val = None if prefix is not None: - allow_missing_prefix = allow_missing - if fallback_default: - allow_missing_prefix = True + allow_missing_prefix = allow_missing or fallback_default val = samba.tests.env_get_var_value('%s_%s' % (prefix, varname), allow_missing=allow_missing_prefix) else: @@ -459,9 +457,7 @@ class RawKerberosTest(TestCaseInTempDir): domain = self.env_get_var('DOMAIN', prefix) realm = self.env_get_var('REALM', prefix) - allow_missing_username = False - if default_username is not None: - allow_missing_username = True + allow_missing_username = default_username is not None username = self.env_get_var('USERNAME', prefix, fallback_default=False, allow_missing=allow_missing_username) -- 2.25.1 From 1d05a6da0d8bcdbe82f07233ab466a2b5cde8194 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 16:07:16 +1200 Subject: [PATCH 111/645] tests/krb5/kdc_base_test.py: Add fallback methods to obtain client and krbtgt credentials Now if the client credentials are not supplied in the environment, we can fall back to creating a new user account. Similarly, if the krbtgt credentials are not supplied, we can fetch the credentials of the existing krbtgt account. Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Joseph Sutton Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit fd45bea7a88837cbe4f99adf3a6b3f69ce32f34c) --- python/samba/tests/krb5/kdc_base_test.py | 86 +++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 120084616e9..1f042aa78aa 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -44,7 +44,8 @@ from samba import net from samba.samdb import SamDB from samba.tests import delete_force -from samba.tests.krb5.raw_testcase import RawKerberosTest +import samba.tests.krb5.kcrypto as kcrypto +from samba.tests.krb5.raw_testcase import KerberosCredentials, RawKerberosTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( AD_IF_RELEVANT, @@ -182,7 +183,7 @@ class KDCBaseTest(RawKerberosTest): details["userPrincipalName"] = upn ldb.add(details) - creds = Credentials() + creds = KerberosCredentials() creds.guess(self.get_lp()) creds.set_realm(ldb.domain_dns_name().upper()) creds.set_domain(ldb.domain_netbios_name().upper()) @@ -290,6 +291,87 @@ class KDCBaseTest(RawKerberosTest): return keys + def creds_set_keys(self, creds, keys): + if keys is not None: + for enctype, key in keys.items(): + creds.set_forced_key(enctype, key) + + supported_enctypes = 0 + if kcrypto.Enctype.AES256 in keys: + supported_enctypes |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 + if kcrypto.Enctype.AES128 in keys: + supported_enctypes |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + if kcrypto.Enctype.RC4 in keys: + supported_enctypes |= security.KERB_ENCTYPE_RC4_HMAC_MD5 + + creds.set_as_supported_enctypes(supported_enctypes) + creds.set_tgs_supported_enctypes(supported_enctypes) + creds.set_ap_supported_enctypes(supported_enctypes) + + def get_client_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + def create_client_account(): + samdb = self.get_samdb() + + creds, dn = self.create_account(samdb, 'kdctestclient') + + res = samdb.search(base=dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='CLIENT', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys, + fallback_creds_fn=create_client_account) + return c + + def get_krbtgt_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + def download_krbtgt_creds(): + samdb = self.get_samdb() + + krbtgt_rid = 502 + krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid) + + res = samdb.search(base='' % krbtgt_sid, + scope=ldb.SCOPE_BASE, + attrs=['sAMAccountName', + 'msDS-KeyVersionNumber']) + dn = res[0].dn + username = str(res[0]['sAMAccountName']) + + creds = KerberosCredentials() + creds.set_domain(self.env_get_var('DOMAIN', 'KRBTGT')) + creds.set_realm(self.env_get_var('REALM', 'KRBTGT')) + creds.set_username(username) + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='KRBTGT', + default_username='krbtgt', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key, + fallback_creds_fn=download_krbtgt_creds) + return c + def as_req(self, cname, sname, realm, etypes, padata=None): '''Send a Kerberos AS_REQ, returns the undecoded response ''' -- 2.25.1 From f879426d6f839d9ddede8e77718f9e5d232dc77c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 14:51:22 +1200 Subject: [PATCH 112/645] tests/krb5/as_req_tests.py: Automatically obtain credentials The credentials for the client and krbtgt accounts are now fetched automatically rather than using environment variables, and the client account is now automatically created. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 0fd71ed3c37c8cf326f9f676b7fddda3d2d24072) --- python/samba/tests/krb5/as_req_tests.py | 4 +- .../knownfail.d/samba.tests.krb5.as_req_tests | 180 ------------------ selftest/knownfail_mit_kdc | 42 ---- selftest/target/Samba.pm | 1 - selftest/target/Samba4.pm | 4 - source4/selftest/tests.py | 7 +- 6 files changed, 4 insertions(+), 234 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 3099c224c18..e8c2a29221d 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -23,7 +23,7 @@ sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests import DynamicTestCase -from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.kdc_base_test import KDCBaseTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_PREAUTH_REQUIRED, @@ -35,7 +35,7 @@ global_asn1_print = False global_hexdump = False @DynamicTestCase -class AsReqKerberosTests(RawKerberosTest): +class AsReqKerberosTests(KDCBaseTest): @classmethod def setUpDynamicTestCases(cls): diff --git a/selftest/knownfail.d/samba.tests.krb5.as_req_tests b/selftest/knownfail.d/samba.tests.krb5.as_req_tests index 390d6cd0ab6..f395bdc553b 100644 --- a/selftest/knownfail.d/samba.tests.krb5.as_req_tests +++ b/selftest/knownfail.d/samba.tests.krb5.as_req_tests @@ -94,183 +94,3 @@ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2003dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index b610929a8dd..776148314d1 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -294,11 +294,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # MIT currently fails some as_req_no_preauth tests. # ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False.fl2003dc @@ -306,11 +303,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2008r2dc @@ -324,11 +318,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2008r2dc @@ -336,11 +327,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2008r2dc @@ -354,11 +342,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2003dc @@ -391,11 +376,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2008r2dc @@ -403,11 +385,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2003dc @@ -422,11 +401,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2008r2dc @@ -434,11 +410,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2008r2dc @@ -452,11 +425,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2008r2dc @@ -488,11 +458,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2008r2dc @@ -500,11 +467,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2008r2dc @@ -518,11 +482,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2008r2dc @@ -530,11 +491,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2008r2dc diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index 4b4da053d83..9319f301327 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -714,7 +714,6 @@ my @exported_envvars = ( "DNSNAME", "REALM", "DOMSID", - "SUPPORTED_ENCTYPE_BITS", # stuff related to a trusted domain "TRUST_SERVER", diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 193b2456cb4..aaadd946e03 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -511,9 +511,6 @@ sub provision_raw_prepare($$$$$$$$$$$$) $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}"; if ($functional_level eq "2000") { $ctx->{supported_enctypes} = "arcfour-hmac-md5 des-cbc-md5 des-cbc-crc"; - $ctx->{supported_enctypes_bits} = "4"; - } else { - $ctx->{supported_enctypes_bits} = "28"; } # @@ -815,7 +812,6 @@ nogroup:x:65534:nobody KRB5_CONFIG => $ctx->{krb5_conf}, KRB5_CCACHE => $ctx->{krb5_ccache}, MITKDC_CONFIG => $ctx->{mitkdc_conf}, - SUPPORTED_ENCTYPE_BITS => $ctx->{supported_enctypes_bits}, PIDDIR => $ctx->{piddir}, SERVER => $ctx->{hostname}, DC_SERVER => $ctx->{hostname}, diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index a3113e6b77e..71e4bf73a4e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1276,11 +1276,8 @@ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", ' for env in ["fl2008r2dc", "fl2003dc"]: planoldpythontestsuite(env, "samba.tests.krb5.as_req_tests", environ={ - 'CLIENT_USERNAME': '$USERNAME', - 'CLIENT_PASSWORD': '$PASSWORD', - 'CLIENT_AS_SUPPORTED_ENCTYPES': '$SUPPORTED_ENCTYPE_BITS', - 'SERVER_USERNAME': '$SERVER', - 'SERVER_PASSWORD': 'machine$PASSWORD', + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', }) -- 2.25.1 From b2c15428165a469faf59a3c9c71627541a80da44 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Apr 2020 11:07:45 +0200 Subject: [PATCH 113/645] tests/krb5/as_req_tests.py: add simple test_as_req_enc_timestamp test Example commands: Windows 2012R2: SERVER=172.31.9.188 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE CLIENT_USERNAME=ldaptestuser CLIENT_PASSWORD=a1B2c3D4 CLIENT_AS_SUPPORTED_ENCTYPES=28 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=2eb6d146a2653d333cdbfb641a4efbc3de81af49e878e112bb4f6cbdd73fca52 KRBTGT_RC4_KEY_HEX=4e6d99c30e5fab901ea71f8894289d3b python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests SERVER=172.31.9.188 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=2eb6d146a2653d333cdbfb641a4efbc3de81af49e878e112bb4f6cbdd73fca52 KRBTGT_RC4_KEY_HEX=4e6d99c30e5fab901ea71f8894289d3b python/samba/tests/krb5/as_req_tests.py AsReqKerberosTests SERVER=172.31.9.188 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.188 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 CLIENT_KVNO=1 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.188 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W2012R2-L6 REALM=W2012R2-L6.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=ldaptestuser CLIENT_PASSWORD=a1B2c3D4 CLIENT_AS_SUPPORTED_ENCTYPES=28 CLIENT_KVNO=4 python/samba/tests/krb5/as_req_tests.py Windows 2008R2: SERVER=172.31.9.133 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 CLIENT_KVNO=17 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=550aea2ea2719cb81c87692569796d1b3a099d433a93438f53bee798cc2f83be KRBTGT_RC4_KEY_HEX=dbc0d1feaaca3d5abc6794857b7f6fe0 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.133 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 CLIENT_KVNO=1 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=550aea2ea2719cb81c87692569796d1b3a099d433a93438f53bee798cc2f83be KRBTGT_RC4_KEY_HEX=dbc0d1feaaca3d5abc6794857b7f6fe0 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.133 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 CLIENT_KVNO=1 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.133 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 CLIENT_KVNO=17 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.133 SMB_CONF_PATH=/dev/null STRICT_CHECKING=1 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 python/samba/tests/krb5/as_req_tests.py Samba: SERVER=172.31.9.163 SMB_CONF_PATH=/dev/null STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 CLIENT_KVNO=17 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=550aea2ea2719cb81c87692569796d1b3a099d433a93438f53bee798cc2f83be KRBTGT_RC4_KEY_HEX=dbc0d1feaaca3d5abc6794857b7f6fe0 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.163 SMB_CONF_PATH=/dev/null STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 CLIENT_KVNO=1 KRBTGT_KVNO=2 KRBTGT_AES256_KEY_HEX=550aea2ea2719cb81c87692569796d1b3a099d433a93438f53bee798cc2f83be KRBTGT_RC4_KEY_HEX=dbc0d1feaaca3d5abc6794857b7f6fe0 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.163 SMB_CONF_PATH=/dev/null STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=administrator CLIENT_PASSWORD=A1b2C3d4 CLIENT_AS_SUPPORTED_ENCTYPES=4 CLIENT_KVNO=1 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.163 SMB_CONF_PATH=/dev/null STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 CLIENT_USERNAME=cifsmount CLIENT_PASSWORD=A1b2C3d4-08 CLIENT_AS_SUPPORTED_ENCTYPES=28 CLIENT_KVNO=17 python/samba/tests/krb5/as_req_tests.py SERVER=172.31.9.163 SMB_CONF_PATH=/dev/null STRICT_CHECKING=0 DOMAIN=W4EDOM-L4 REALM=W4EDOM-L4.BASE ADMIN_USERNAME=administrator ADMIN_PASSWORD=A1b2C3d4 python/samba/tests/krb5/as_req_tests.py Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d5e350a4a490fecf570f1c248c9dde1466796166) --- python/samba/tests/krb5/as_req_tests.py | 85 ++++++++++++++++++++++++- selftest/knownfail_mit_kdc | 5 ++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index e8c2a29221d..be33748dfb6 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -27,8 +27,10 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_PREAUTH_REQUIRED, + KU_PA_ENC_TIMESTAMP, NT_PRINCIPAL, - NT_SRV_INST + NT_SRV_INST, + PADATA_ENC_TIMESTAMP ) global_asn1_print = False @@ -112,6 +114,87 @@ class AsReqKerberosTests(KDCBaseTest): initial_etypes=etypes, initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) + def test_as_req_enc_timestamp(self): + client_creds = self.get_client_creds() + client_account = client_creds.get_username() + client_as_etypes = client_creds.get_as_krb5_etypes() + krbtgt_creds = self.get_krbtgt_creds(require_strongest_key=True) + 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_forced_salt() + + till = self.get_KerberosTime(offset=36000) + + pa_pac = self.KERB_PA_PAC_REQUEST_create(True) + initial_padata = [pa_pac] + initial_etypes = client_as_etypes + initial_kdc_options = krb5_asn1.KDCOptions('forwardable') + initial_error_mode = KDC_ERR_PREAUTH_REQUIRED + + etype_info2 = self._test_as_exchange(cname, + realm, + sname, + till, + client_as_etypes, + initial_error_mode, + expected_crealm, + expected_cname, + expected_srealm, + expected_sname, + expected_salt, + initial_etypes, + initial_padata, + initial_kdc_options) + self.assertIsNotNone(etype_info2) + + preauth_key = self.PasswordKey_from_etype_info2(client_creds, etype_info2[0], kvno=0) + + (patime, pausec) = self.get_KerberosTimeWithUsec() + pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + enc_pa_ts_usage = KU_PA_ENC_TIMESTAMP + pa_ts = self.EncryptedData_create(preauth_key, enc_pa_ts_usage, pa_ts) + pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) + + pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) + + preauth_padata = [pa_ts, pa_pac] + preauth_etypes = client_as_etypes + preauth_kdc_options = krb5_asn1.KDCOptions('forwardable') + preauth_error_mode = 0 # AS-REP + + krbtgt_decryption_key = ( + self.TicketDecryptionKey_from_creds(krbtgt_creds)) + + as_rep = self._test_as_exchange(cname, + realm, + sname, + till, + client_as_etypes, + preauth_error_mode, + expected_crealm, + expected_cname, + expected_srealm, + expected_sname, + expected_salt, + preauth_etypes, + preauth_padata, + preauth_kdc_options, + preauth_key=preauth_key, + ticket_decryption_key=krbtgt_decryption_key) + self.assertIsNotNone(as_rep) + return if __name__ == "__main__": global_asn1_print = True diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 776148314d1..db40b0614fa 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -291,6 +291,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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_c ^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_6_c # +# MIT currently fails the test_as_req_enc_timestamp test. +# +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_enc_timestamp.fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_enc_timestamp.fl2008r2dc +# # MIT currently fails some as_req_no_preauth tests. # ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256.fl2008r2dc -- 2.25.1 From 1de246fbb5d07cf004df5c340df154d037ac5855 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 13:24:22 +1200 Subject: [PATCH 114/645] tests/krb5/as_req_tests.py: Check the client kvno Ensure we have the correct kvno for the client, rather than an 'unknown' value. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d4c38678e0cc782965edfe40a0423fafb7d5a5ff) --- python/samba/tests/krb5/as_req_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index be33748dfb6..10e7b603609 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -118,6 +118,7 @@ class AsReqKerberosTests(KDCBaseTest): client_creds = self.get_client_creds() client_account = client_creds.get_username() client_as_etypes = client_creds.get_as_krb5_etypes() + client_kvno = client_creds.get_kvno() krbtgt_creds = self.get_krbtgt_creds(require_strongest_key=True) krbtgt_account = krbtgt_creds.get_username() realm = krbtgt_creds.get_realm() @@ -157,7 +158,9 @@ class AsReqKerberosTests(KDCBaseTest): initial_kdc_options) self.assertIsNotNone(etype_info2) - preauth_key = self.PasswordKey_from_etype_info2(client_creds, etype_info2[0], kvno=0) + preauth_key = self.PasswordKey_from_etype_info2(client_creds, + etype_info2[0], + kvno=client_kvno) (patime, pausec) = self.get_KerberosTimeWithUsec() pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) -- 2.25.1 From c054c736b080464ec57f982bc39d5010d9f1c627 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 15 Jun 2021 13:25:34 +1200 Subject: [PATCH 115/645] tests/krb5/raw_testcase.py: Check for an explicit 'unspecified kvno' value This is clearer than using the constant zero, which could be mistaken for a valid kvno value. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 381223117e0bae4c348d538bffaa8227b18ef3d1) --- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0e08f0ef7d2..b7044546cbd 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -393,6 +393,8 @@ class RawKerberosTest(TestCaseInTempDir): self.s = None + self.unspecified_kvno = object() + def tearDown(self): self._disconnect("tearDown") super().tearDown() @@ -861,10 +863,11 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(v) # The value on the wire should never be 0 self.assertNotEqual(v, 0) - # value == 0 means we don't know the kvno - # but enforce at any value != 0 is present - value = int(value) - if value != 0: + # unspecified_kvno means we don't know the kvno, + # but want to enforce its presense + if value is not self.unspecified_kvno: + value = int(value) + self.assertNotEqual(value, 0) self.assertEqual(v, value) else: self.assertIsNone(v) @@ -1584,8 +1587,8 @@ class RawKerberosTest(TestCaseInTempDir): ticket_encpart = self.getElementValue(ticket, 'enc-part') if ticket_encpart is not None: # Never None, but gives indentation self.assertElementPresent(ticket_encpart, 'etype') - # 0 means present, with any value != 0 - self.assertElementKVNO(ticket_encpart, 'kvno', 0) + # 'unspecified' means present, with any value != 0 + self.assertElementKVNO(ticket_encpart, 'kvno', self.unspecified_kvno) self.assertElementPresent(ticket_encpart, 'cipher') ticket_cipher = self.getElementValue(ticket_encpart, 'cipher') self.assertElementPresent(rep, 'enc-part') -- 2.25.1 From a359a0df39f46c5f23cc81c0303b3d62576796fc Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 11:01:50 +1200 Subject: [PATCH 116/645] tests/krb5: Deduplicate 'host' attribute initialisation Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 3e621dcb6966f75034bb948a2705358d43454202) --- python/samba/tests/krb5/kdc_base_test.py | 1 - python/samba/tests/krb5/raw_testcase.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1f042aa78aa..89d374fc5cc 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -78,7 +78,6 @@ class KDCBaseTest(RawKerberosTest): def setUpClass(cls): super().setUpClass() cls._lp = None - cls.host = os.environ["SERVER"] cls._ldb = None diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b7044546cbd..b9bc08d1fa9 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -375,6 +375,8 @@ class RawKerberosTest(TestCaseInTempDir): def setUpClass(cls): super().setUpClass() + cls.host = samba.tests.env_get_var_value('SERVER') + # A dictionary containing credentials that have already been # obtained. cls.creds_dict = {} @@ -389,8 +391,6 @@ class RawKerberosTest(TestCaseInTempDir): strict_checking = '1' self.strict_checking = bool(int(strict_checking)) - self.host = samba.tests.env_get_var_value('SERVER') - self.s = None self.unspecified_kvno = object() -- 2.25.1 From ae2075ec6d2f808c9d84afffbb803921fedfa251 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 11:49:05 +1200 Subject: [PATCH 117/645] tests/krb5/as_canonicalization_tests.py: Refactor account creation Making this test a subclass of KDCBaseTest allows us to make use of its methods for obtaining credentials and creating accounts, which helps to eliminate some duplicated code. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit fc857ea60e2a66d20d4174cb121e0a6949f8a0c1) --- .../tests/krb5/as_canonicalization_tests.py | 136 ++++-------------- 1 file changed, 25 insertions(+), 111 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 43f532dc483..abb3f96a1e6 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -25,20 +25,11 @@ import pyasn1 sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" -from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.kdc_base_test import KDCBaseTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 -import samba -from samba.auth import system_session -from samba.credentials import ( - Credentials, - DONT_USE_KERBEROS) +from samba.credentials import DONT_USE_KERBEROS from samba.dcerpc.misc import SEC_CHAN_WKSTA -from samba.dsdb import ( - UF_WORKSTATION_TRUST_ACCOUNT, - UF_PASSWD_NOTREQD, - UF_NORMAL_ACCOUNT) -from samba.samdb import SamDB -from samba.tests import delete_force, DynamicTestCase +from samba.tests import DynamicTestCase from samba.tests.krb5.rfc4120_constants import ( AES256_CTS_HMAC_SHA1_96, AES128_CTS_HMAC_SHA1_96, @@ -96,12 +87,12 @@ class TestData: else: client_name_type = NT_PRINCIPAL - self.cname = RawKerberosTest.PrincipalName_create( + self.cname = KDCBaseTest.PrincipalName_create( name_type=client_name_type, names=[self.user_name]) if TestOptions.AsReqSelf.is_set(options): self.sname = self.cname else: - self.sname = RawKerberosTest.PrincipalName_create( + self.sname = KDCBaseTest.PrincipalName_create( name_type=NT_SRV_INST, names=["krbtgt", self.realm]) self.canonicalize = TestOptions.Canonicalize.is_set(options) @@ -141,7 +132,7 @@ USER_NAME = "tstkrb5cnnusr" @DynamicTestCase -class KerberosASCanonicalizationTests(RawKerberosTest): +class KerberosASCanonicalizationTests(KDCBaseTest): @classmethod def setUpDynamicTestCases(cls): @@ -170,114 +161,37 @@ class KerberosASCanonicalizationTests(RawKerberosTest): name = build_test_name(ct, x) cls.generate_dynamic_test("test", name, x, ct) - @classmethod - def setUpClass(cls): - cls.lp = cls.get_loadparm(cls) - cls.username = os.environ["USERNAME"] - cls.password = os.environ["PASSWORD"] - cls.host = os.environ["SERVER"] - - c = Credentials() - c.set_username(cls.username) - c.set_password(cls.password) - try: - realm = os.environ["REALM"] - c.set_realm(realm) - except KeyError: - pass - try: - domain = os.environ["DOMAIN"] - c.set_domain(domain) - except KeyError: - pass + def user_account_creds(self): + if self.user_creds is None: + samdb = self.get_samdb() + self.user_creds, _ = self.create_account(samdb, USER_NAME) - c.guess() + return self.user_creds - cls.credentials = c + def machine_account_creds(self): + if self.machine_creds is None: + samdb = self.get_samdb() + self.machine_creds, _ = self.create_account(samdb, + MACHINE_NAME, + machine_account=True) + self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) + self.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) - cls.session = system_session() - cls.ldb = SamDB(url="ldap://%s" % cls.host, - session_info=cls.session, - credentials=cls.credentials, - lp=cls.lp) - cls.create_machine_account() - cls.create_user_account() - - @classmethod - def tearDownClass(cls): - super(KerberosASCanonicalizationTests, cls).tearDownClass() - delete_force(cls.ldb, cls.machine_dn) - delete_force(cls.ldb, cls.user_dn) + return self.machine_creds def setUp(self): - super(KerberosASCanonicalizationTests, self).setUp() + super().setUp() self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - # - # Create a test user account - @classmethod - def create_user_account(cls): - cls.user_pass = samba.generate_random_password(32, 32) - cls.user_name = USER_NAME - cls.user_dn = "cn=%s,%s" % (cls.user_name, cls.ldb.domain_dn()) - - # remove the account if it exists, this will happen if a previous test - # run failed - delete_force(cls.ldb, cls.user_dn) - - utf16pw = ('"%s"' % cls.user_pass).encode('utf-16-le') - cls.ldb.add({ - "dn": cls.user_dn, - "objectclass": "user", - "sAMAccountName": "%s" % cls.user_name, - "userAccountControl": str(UF_NORMAL_ACCOUNT), - "unicodePwd": utf16pw}) - - cls.user_creds = Credentials() - cls.user_creds.guess(cls.lp) - cls.user_creds.set_realm(cls.ldb.domain_dns_name().upper()) - cls.user_creds.set_domain(cls.ldb.domain_netbios_name().upper()) - cls.user_creds.set_password(cls.user_pass) - cls.user_creds.set_username(cls.user_name) - cls.user_creds.set_workstation(cls.machine_name) - - # - # Create the machine account - @classmethod - def create_machine_account(cls): - cls.machine_pass = samba.generate_random_password(32, 32) - cls.machine_name = MACHINE_NAME - cls.machine_dn = "cn=%s,%s" % (cls.machine_name, cls.ldb.domain_dn()) - - # remove the account if it exists, this will happen if a previous test - # run failed - delete_force(cls.ldb, cls.machine_dn) - - utf16pw = ('"%s"' % cls.machine_pass).encode('utf-16-le') - cls.ldb.add({ - "dn": cls.machine_dn, - "objectclass": "computer", - "sAMAccountName": "%s$" % cls.machine_name, - "userAccountControl": - str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), - "unicodePwd": utf16pw}) - - cls.machine_creds = Credentials() - cls.machine_creds.guess(cls.lp) - cls.machine_creds.set_realm(cls.ldb.domain_dns_name().upper()) - cls.machine_creds.set_domain(cls.ldb.domain_netbios_name().upper()) - cls.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) - cls.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) - cls.machine_creds.set_password(cls.machine_pass) - cls.machine_creds.set_username(cls.machine_name + "$") - cls.machine_creds.set_workstation(cls.machine_name) + self.user_creds = None + self.machine_creds = None def _test_with_args(self, x, ct): if ct == CredentialsType.User: - creds = self.user_creds + creds = self.user_account_creds() elif ct == CredentialsType.Machine: - creds = self.machine_creds + creds = self.machine_account_creds() else: raise Exception("Unexpected credential type") data = TestData(x, creds) -- 2.25.1 From 6020a456a8bf86831bfb55ae82c682fee6380bf8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Jun 2021 12:52:11 +1200 Subject: [PATCH 118/645] tests/krb5: Use admin creds for SamDB rather than user creds This makes the purpose of each set of credentials more consistent, and makes some tests more convenient to run standalone as they no longer require user credentials. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ab221c1b3e24696aa0eed6aa970f310447657069) --- python/samba/tests/krb5/kdc_base_test.py | 2 +- source4/selftest/tests.py | 42 ++++++++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 89d374fc5cc..0f5238a3de9 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -109,7 +109,7 @@ class KDCBaseTest(RawKerberosTest): def get_samdb(self): if self._ldb is None: - creds = self.get_user_creds() + creds = self.get_admin_creds() lp = self.get_lp() session = system_session() diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 71e4bf73a4e..d99f08899de 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -752,10 +752,26 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") -planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache") -planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap") -planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc") -planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb") +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) +planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) @@ -1296,15 +1312,27 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: '--option=torture:expect_machine_account=true'] + extra_options, "samba4.krb5.kdc with machine account") -planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests") +planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests") planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") planpythontestsuite( "ad_dc", - "samba.tests.krb5.kdc_tgs_tests") + "samba.tests.krb5.kdc_tgs_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) planpythontestsuite( "ad_dc", - "samba.tests.krb5.ms_kile_client_principal_lookup_tests") + "samba.tests.krb5.ms_kile_client_principal_lookup_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD' + }) for env in [ 'vampire_dc', -- 2.25.1 From 28899ea7794fa1e080688f8553c9edac96ea4eb3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 21 Jun 2021 14:14:48 +1200 Subject: [PATCH 119/645] s4:torture/krb5/kdc-heimdal: Automatically determine AS-REP enctype to check against This enables us to more easily switch to a different algorithm to find the strongest key in _kdc_find_etype(). Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit bf71fa038e9b97f770e06e88226e885d67342d47) --- selftest/knownfail | 6 +- selftest/knownfail_mit_kdc | 6 ++ source4/torture/krb5/kdc-heimdal.c | 104 +++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 44ab3e59069..0d114d32f02 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -281,10 +281,6 @@ ^samba4.winbind.struct.lookup_name_sid\(ad_member:local\) ^samba4.winbind.struct.getdcname\(nt4_member:local\) # Works in other modes, just not against the classic/NT4 DC # -# Differences in our KDC compared to windows -# -^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally -# # This will fail against the classic DC, because it requires kerberos # ^samba4.winbind.pac.*\(nt4_member:local\) # No KDC on a classic DC @@ -323,7 +319,7 @@ # ^samba4.smb.signing.*disabled.*signing=off.*\(ad_dc\) # fl2000dc doesn't support AES -^samba4.krb5.kdc.*as-req-aes.*fl2000dc +^samba4.krb5.kdc.*as-req-aes.fl2000dc # nt4_member and ad_member don't support ntlmv1 (not even over SMB1) ^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.member.creds.*as.user.*_member ^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.*mNT1.member.creds.*as.user.*_member diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index db40b0614fa..fffa5c3cd7e 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -641,3 +641,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2008r2dc +# Differences in our KDC compared to windows +# +^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally +# +# fl2000dc doesn't support AES +^samba4.krb5.kdc.*as-req-aes.*fl2000dc diff --git a/source4/torture/krb5/kdc-heimdal.c b/source4/torture/krb5/kdc-heimdal.c index cc70c9eda67..ccd9919b33a 100644 --- a/source4/torture/krb5/kdc-heimdal.c +++ b/source4/torture/krb5/kdc-heimdal.c @@ -204,11 +204,12 @@ static bool torture_check_krb5_error(struct torture_krb5_context *test_context, static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context, const krb5_data *reply, - krb5_enctype expected_enctype) + const krb5_enctype* allowed_enctypes) { ENCTYPE reply_enctype = { 0 }; size_t used = 0; int rc; + int expected_enctype = ETYPE_NULL; rc = decode_AS_REP(reply->data, reply->length, @@ -230,8 +231,84 @@ static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_ test_context->as_rep.ticket.enc_part.kvno, "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); - reply_enctype = test_context->as_rep.enc_part.etype; + if (test_context->as_req.padata) { + /* + * If the AS-REQ contains a PA-ENC-TIMESTAMP, then + * that encryption type is used to determine the reply + * enctype. + */ + int i = 0; + const PA_DATA *pa = krb5_find_padata(test_context->as_req.padata->val, + test_context->as_req.padata->len, + KRB5_PADATA_ENC_TIMESTAMP, + &i); + if (pa) { + EncryptedData ed; + size_t len; + krb5_error_code ret = decode_EncryptedData(pa->padata_value.data, + pa->padata_value.length, + &ed, &len); + torture_assert_int_equal(test_context->tctx, + ret, + 0, + "decode_EncryptedData failed"); + expected_enctype = ed.etype; + free_EncryptedData(&ed); + } + } + if (expected_enctype == ETYPE_NULL) { + /* + * Otherwise, find the strongest enctype contained in + * the AS-REQ supported enctypes list. + */ + const krb5_enctype *p = NULL; + + for (p = krb5_kerberos_enctypes(NULL); *p != (krb5_enctype)ETYPE_NULL; ++p) { + int j; + + if ((*p == (krb5_enctype)ETYPE_AES256_CTS_HMAC_SHA1_96 || + *p == (krb5_enctype)ETYPE_AES128_CTS_HMAC_SHA1_96) && + !test_context->as_req.req_body.kdc_options.canonicalize) + { + /* + * AES encryption types are only used here when + * we set the canonicalize flag, as the salt + * needs to match. + */ + continue; + } + + for (j = 0; j < test_context->as_req.req_body.etype.len; ++j) { + krb5_enctype etype = test_context->as_req.req_body.etype.val[j]; + if (*p == etype) { + expected_enctype = etype; + break; + } + } + + if (expected_enctype != (krb5_enctype)ETYPE_NULL) { + break; + } + } + } + + { + /* Ensure the enctype to check against is an expected type. */ + const krb5_enctype *p = NULL; + bool found = false; + for (p = allowed_enctypes; *p != (krb5_enctype)ETYPE_NULL; ++p) { + if (*p == expected_enctype) { + found = true; + break; + } + } + torture_assert(test_context->tctx, + found, + "Calculated enctype not in allowed list"); + } + + reply_enctype = test_context->as_rep.enc_part.etype; torture_assert_int_equal(test_context->tctx, reply_enctype, expected_enctype, "Ticket encrypted with invalid algorithm"); @@ -310,7 +387,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex if (test_context->packet_count == 0) { ok = torture_check_krb5_error(test_context, recv_buf, - KRB5KRB_ERR_RESPONSE_TOO_BIG, + KRB5KDC_ERR_PREAUTH_REQUIRED, false); torture_assert(test_context->tctx, ok, @@ -318,7 +395,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex } else if (test_context->packet_count == 1) { ok = torture_check_krb5_error(test_context, recv_buf, - KRB5KDC_ERR_PREAUTH_REQUIRED, + KRB5KRB_ERR_RESPONSE_TOO_BIG, false); torture_assert(test_context->tctx, ok, @@ -411,9 +488,13 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed"); @@ -443,9 +524,13 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_ARCFOUR_HMAC_MD5); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed"); @@ -475,9 +560,14 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, + KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed"); -- 2.25.1 From 47c119c6d32194dd6f381b41fac80734bf5217ca Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Sep 2021 09:08:58 +1200 Subject: [PATCH 120/645] selftest: add space after --list in output of selftesthelpers.py Selected and backported from: commit b113a3bbcd03ab6a62883fbca85ee8749e038887 Author: Volker Lendecke Date: Mon Apr 19 16:04:00 2021 +0200 torture: Show sddl_decode() failure for "GWFX" access mask Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (This allows subsequent patches to be cherry-picked cleanly) Signed-off-by: Andrew Bartlett --- selftest/selftesthelpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 1afabf3cdca..c2a74a30614 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -109,7 +109,7 @@ def plantestsuite_loadlist(name, env, cmdline): raise AssertionError("loadlist test %s does not support not --list" % name) if "$LOADLIST" not in cmdline: raise AssertionError("loadlist test %s does not support --load-list" % name) - print(("%s | %s" % (cmdline.replace("$LOADLIST", ""), add_prefix(name, env, support_list))).replace("$LISTOPT", "--list")) + print(("%s | %s" % (cmdline.replace("$LOADLIST", ""), add_prefix(name, env, support_list))).replace("$LISTOPT", "--list ")) print(cmdline.replace("$LISTOPT", "") + " 2>&1 " + " | " + add_prefix(name, env, False)) -- 2.25.1 From 0a13806fb0041724fedfdc974365ac1d1818fc6b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 27 Jul 2021 08:50:54 +0200 Subject: [PATCH 121/645] selftest: Re-format long lines in selftesthelpers.py Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 18976a9568b23759060377d09304e9d7badb143a) --- selftest/selftesthelpers.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index c2a74a30614..3c544a0057c 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -1,4 +1,5 @@ -#!/usr/bin/python +#!/usr/bin/env python3 +# # This script generates a list of testsuites that should be run as part of # the Samba 4 test suite. @@ -25,7 +26,8 @@ import sys def srcdir(): - return os.path.normpath(os.getenv("SRCDIR", os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))) + alternate_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") + return os.path.normpath(os.getenv("SRCDIR", alternate_path)) def source4dir(): @@ -91,7 +93,8 @@ def add_prefix(prefix, env, support_list=False): listopt = "$LISTOPT " else: listopt = "" - return "%s %s/selftest/filter-subunit %s--fail-on-empty --prefix=\"%s.\" --suffix=\"(%s)\"" % (python, srcdir(), listopt, prefix, env) + return ("%s %s/selftest/filter-subunit %s--fail-on-empty --prefix=\"%s.\" --suffix=\"(%s)\"" % + (python, srcdir(), listopt, prefix, env)) def plantestsuite_loadlist(name, env, cmdline): @@ -109,7 +112,9 @@ def plantestsuite_loadlist(name, env, cmdline): raise AssertionError("loadlist test %s does not support not --list" % name) if "$LOADLIST" not in cmdline: raise AssertionError("loadlist test %s does not support --load-list" % name) - print(("%s | %s" % (cmdline.replace("$LOADLIST", ""), add_prefix(name, env, support_list))).replace("$LISTOPT", "--list ")) + print(("%s | %s" % + (cmdline.replace("$LOADLIST", ""), + add_prefix(name, env, support_list))).replace("$LISTOPT", "--list ")) print(cmdline.replace("$LISTOPT", "") + " 2>&1 " + " | " + add_prefix(name, env, False)) @@ -162,7 +167,10 @@ bbdir = os.path.join(srcdir(), "testprogs/blackbox") configuration = "--configfile=$SMB_CONF_PATH" smbtorture4 = binpath("smbtorture") -smbtorture4_testsuite_list = subprocess.Popen([smbtorture4, "--list-suites"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate("")[0].decode('utf8').splitlines() +smbtorture4_testsuite_list = subprocess.Popen( + [smbtorture4, "--list-suites"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE).communicate("")[0].decode('utf8').splitlines() smbtorture4_options = [ configuration, -- 2.25.1 From 63eaa376844fae152f923beb47c445f5e66958e9 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 27 Jul 2021 13:25:59 +0200 Subject: [PATCH 122/645] selftest: Add support for setting ENV variables in plansmbtorture4testsuite() Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 3db299e586fd9464b6e1b145f29b10c8ae325d3a) --- selftest/selftesthelpers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 3c544a0057c..697a4d08abb 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -181,13 +181,14 @@ smbtorture4_options = [ ] + get_env_torture_options() -def plansmbtorture4testsuite(name, env, options, target, modname=None): +def plansmbtorture4testsuite(name, env, options, target, environ={}, modname=None): if modname is None: modname = "samba4.%s" % name if isinstance(options, list): options = " ".join(options) options = " ".join(smbtorture4_options + ["--target=%s" % target]) + " " + options - cmdline = "%s $LISTOPT $LOADLIST %s %s" % (valgrindify(smbtorture4), options, name) + cmdline = ["%s=%s" % item for item in environ.items()] + cmdline += "%s $LISTOPT $LOADLIST %s %s" % (valgrindify(smbtorture4), options, name) plantestsuite_loadlist(modname, env, cmdline) -- 2.25.1 From 50ff113a636c9f0b15756e848ce5165cd7dc2d98 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 27 Jul 2021 13:45:03 +0200 Subject: [PATCH 123/645] selftest: Add support for setting ENV variables in plantestsuite() Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 48289b6964d28e153fec885aceca02c6a9b436ef) --- selftest/selftesthelpers.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 697a4d08abb..167777e3d47 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -67,7 +67,7 @@ def valgrindify(cmdline): return valgrind + " " + cmdline -def plantestsuite(name, env, cmdline): +def plantestsuite(name, env, cmd, environ={}): """Plan a test suite. :param name: Testsuite name @@ -81,8 +81,18 @@ def plantestsuite(name, env, cmdline): fullname = "%s(%s)" % (name, env) print(fullname) print(env) - if isinstance(cmdline, list): - cmdline = " ".join(cmdline) + + cmdline = "" + if environ: + environ = dict(environ) + cmdline_env = ["%s=%s" % item for item in environ.items()] + cmdline = " ".join(cmdline_env) + " " + + if isinstance(cmd, list): + cmdline += " ".join(cmd) + else: + cmdline += cmd + if "$LISTOPT" in cmdline: raise AssertionError("test %s supports --list, but not --load-list" % name) print(cmdline + " 2>&1 " + " | " + add_prefix(name, env)) @@ -181,14 +191,17 @@ smbtorture4_options = [ ] + get_env_torture_options() -def plansmbtorture4testsuite(name, env, options, target, environ={}, modname=None): +def plansmbtorture4testsuite(name, env, options, target, modname=None, environ={}): if modname is None: modname = "samba4.%s" % name if isinstance(options, list): options = " ".join(options) options = " ".join(smbtorture4_options + ["--target=%s" % target]) + " " + options - cmdline = ["%s=%s" % item for item in environ.items()] - cmdline += "%s $LISTOPT $LOADLIST %s %s" % (valgrindify(smbtorture4), options, name) + cmdline = "" + if environ: + environ = dict(environ) + cmdline = ["%s=%s" % item for item in environ.items()] + cmdline += " %s $LISTOPT $LOADLIST %s %s" % (valgrindify(smbtorture4), options, name) plantestsuite_loadlist(modname, env, cmdline) -- 2.25.1 From 6906a5325a156d7bca42788b9f016f440c7d1c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Baumbach?= Date: Fri, 24 Jul 2020 12:18:11 +0200 Subject: [PATCH 124/645] selftest: add option to pass args to tests to planpythontestsuite() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic is basically a copy from planoldpythontestsuite(). Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Björn Baumbach Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 3e9f0e97255de1b4235c4dca6912635386328746) --- selftest/selftesthelpers.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 167777e3d47..1dd30b01ea7 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -150,16 +150,18 @@ def planperltestsuite(name, path): skiptestsuite(name, "Test::More not available") -def planpythontestsuite(env, module, name=None, extra_path=None): +def planpythontestsuite(env, module, name=None, extra_path=[], environ={}, extra_args=[]): + environ = dict(environ) + py_path = list(extra_path) + if py_path is not None: + environ["PYTHONPATH"] = ":".join(["$PYTHONPATH"] + py_path) + args = ["%s=%s" % item for item in environ.items()] + args += [python, "-m", "samba.subunit.run", "$LISTOPT", "$LOADLIST", module] + args += extra_args if name is None: name = module - args = [python, "-m", "samba.subunit.run", "$LISTOPT", "$LOADLIST", module] - if extra_path: - pypath = ["PYTHONPATH=$PYTHONPATH:%s" % ":".join(extra_path)] - else: - pypath = [] - plantestsuite_loadlist(name, env, pypath + args) + plantestsuite_loadlist(name, env, args) def get_env_torture_options(): -- 2.25.1 From ec1aa53eeaa408e77faee8d7f10a0fddf22fed5d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 19 Jul 2021 17:29:39 +1200 Subject: [PATCH 125/645] pygensec: Fix memory leaks Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 814df05f8c10e9d82e6082d42ece1df569db4385) --- source4/auth/gensec/pygensec.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index 35095344168..cf522f76385 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -310,9 +310,13 @@ static PyObject *py_gensec_session_info(PyObject *self, return NULL; } mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } status = gensec_session_info(security, mem_ctx, &info); if (NT_STATUS_IS_ERR(status)) { + talloc_free(mem_ctx); PyErr_SetNTSTATUS(status); return NULL; } @@ -337,6 +341,9 @@ static PyObject *py_gensec_session_key(PyObject *self, return NULL; } mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } status = gensec_session_key(security, mem_ctx, &session_key); if (!NT_STATUS_IS_OK(status)) { @@ -466,7 +473,12 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args) return NULL; mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } + if (!PyBytes_Check(py_in)) { + talloc_free(mem_ctx); PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } @@ -510,8 +522,12 @@ static PyObject *py_gensec_wrap(PyObject *self, PyObject *args) return NULL; mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } if (!PyBytes_Check(py_in)) { + talloc_free(mem_ctx); PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } @@ -545,8 +561,12 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args) return NULL; mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } if (!PyBytes_Check(py_in)) { + talloc_free(mem_ctx); PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } @@ -599,6 +619,9 @@ static PyObject *py_gensec_sign_packet(PyObject *self, PyObject *args) pdu.length = pdu_length; mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + return PyErr_NoMemory(); + } status = gensec_sign_packet(security, mem_ctx, data.data, data.length, -- 2.25.1 From 3e9daaa73bbc94894d5ac4f696b04d2cfdae2e48 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 20 Jul 2021 10:48:41 +1200 Subject: [PATCH 126/645] pygensec: Don't modify Python bytes objects gensec_update() and gensec_unwrap() can both modify their input buffers (for example, during the inplace RRC operation on GSSAPI tokens). However, buffers obtained from Python bytes objects must not be modified in any way. Create a copy of the input buffer so the original isn't modified. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 6818d204897d0b7946dcfbedf79cd53fb9b3f159) --- source4/auth/gensec/gensec_gssapi.c | 4 ++++ source4/auth/gensec/pygensec.c | 36 ++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index d66abf32a7f..dbda18ede09 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1167,6 +1167,10 @@ static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, } } + /* + * FIXME: input_message_buffer is marked const, but gss_unwrap() may + * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()). + */ maj_stat = gss_unwrap(&min_stat, gensec_gssapi_state->gssapi_context, &input_token, diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index cf522f76385..1a8d7b0489f 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -468,6 +468,9 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args) PyObject *py_bytes, *result, *py_in; struct gensec_security *security = pytalloc_get_type(self, struct gensec_security); PyObject *finished_processing; + char *data = NULL; + Py_ssize_t len; + int err; if (!PyArg_ParseTuple(args, "O", &py_in)) return NULL; @@ -477,14 +480,21 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args) return PyErr_NoMemory(); } - if (!PyBytes_Check(py_in)) { + err = PyBytes_AsStringAndSize(py_in, &data, &len); + if (err) { talloc_free(mem_ctx); - PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } - in.data = (uint8_t *)PyBytes_AsString(py_in); - in.length = PyBytes_Size(py_in); + /* + * Make a copy of the input buffer, as gensec_update may modify its + * input argument. + */ + in = data_blob_talloc(mem_ctx, data, len); + if (!in.data) { + talloc_free(mem_ctx); + return PyErr_NoMemory(); + } status = gensec_update(security, mem_ctx, in, &out); @@ -556,6 +566,9 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args) DATA_BLOB in, out; PyObject *ret, *py_in; struct gensec_security *security = pytalloc_get_type(self, struct gensec_security); + char *data = NULL; + Py_ssize_t len; + int err; if (!PyArg_ParseTuple(args, "O", &py_in)) return NULL; @@ -565,14 +578,21 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args) return PyErr_NoMemory(); } - if (!PyBytes_Check(py_in)) { + err = PyBytes_AsStringAndSize(py_in, &data, &len); + if (err) { talloc_free(mem_ctx); - PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } - in.data = (uint8_t *)PyBytes_AsString(py_in); - in.length = PyBytes_Size(py_in); + /* + * Make a copy of the input buffer, as gensec_unwrap may modify its + * input argument. + */ + in = data_blob_talloc(mem_ctx, data, len); + if (!in.data) { + talloc_free(mem_ctx); + return PyErr_NoMemory(); + } status = gensec_unwrap(security, mem_ctx, &in, &out); -- 2.25.1 From 53ce6d1330b7bd479fac0ff7d6132e737f9bd414 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 26 Jul 2021 17:15:23 +1200 Subject: [PATCH 127/645] tests/krb5: Fix ms_kile_client_principal_lookup_test errors Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4797ced89095155c01e44727cf8b66ee4fb39710) --- .../krb5/ms_kile_client_principal_lookup_tests.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index e9d251e72f6..1598959a18c 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -395,7 +395,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Check the contents of the pac, and the ticket ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) - self.check_pac(enc_part['authorization-data'], dn, uc, user_name) + self.check_pac(samdb, + enc_part['authorization-data'], dn, uc, user_name) # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_PRINCIPAL, cname['name-type']) @@ -497,7 +498,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) self.check_pac( - enc_part['authorization-data'], dn, uc, upn, upn=upn) + samdb, enc_part['authorization-data'], dn, uc, upn, upn=upn) # check the crealm and cname cname = enc_part['cname'] crealm = enc_part['crealm'] @@ -560,7 +561,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) self.check_pac( - enc_part['authorization-data'], dn, uc, ename, upn=ename) + samdb, enc_part['authorization-data'], dn, uc, ename, upn=ename) # check the crealm and cname cname = enc_part['cname'] crealm = enc_part['crealm'] @@ -624,7 +625,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) self.check_pac( - enc_part['authorization-data'], dn, mc, ename, upn=uname) + samdb, enc_part['authorization-data'], dn, mc, ename, upn=uname) # check the crealm and cname cname = enc_part['cname'] crealm = enc_part['crealm'] @@ -771,7 +772,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ticket = rep['ticket'] enc_part = self.decode_service_ticket(mc, ticket) self.check_pac( - enc_part['authorization-data'], dn, uc, uname, upn=uname) + samdb, enc_part['authorization-data'], dn, uc, uname, upn=uname) # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) -- 2.25.1 From 6a0fa4f9575d61881ac6a75f4d23aac39f284da7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 22 Jul 2021 16:26:17 +1200 Subject: [PATCH 128/645] tests/krb5: Fix comment typo Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 9eb4c4b7b1c2e8d124456e6a57262dc9c02d67d4) --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b9bc08d1fa9..9c090e4d005 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -864,7 +864,7 @@ class RawKerberosTest(TestCaseInTempDir): # The value on the wire should never be 0 self.assertNotEqual(v, 0) # unspecified_kvno means we don't know the kvno, - # but want to enforce its presense + # but want to enforce its presence if value is not self.unspecified_kvno: value = int(value) self.assertNotEqual(value, 0) -- 2.25.1 From 8c1fa29e924e7bde36ee99e3686e2cdd010319c9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:17:52 +1200 Subject: [PATCH 129/645] tests/krb5: Fix method name typo Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 7013a8edd1f628b8659f0836f3b37ccf13156ae2) --- python/samba/tests/krb5/kdc_base_test.py | 4 ++-- python/samba/tests/krb5/kdc_tgs_tests.py | 6 +++--- .../ms_kile_client_principal_lookup_tests.py | 20 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 0f5238a3de9..4bd856b217e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -444,7 +444,7 @@ class KDCBaseTest(RawKerberosTest): return enc_part - def check_pre_authenication(self, rep): + def check_pre_authentication(self, rep): """ Check that the kdc response was pre-authentication required """ self.check_error_rep(rep, KDC_ERR_PREAUTH_REQUIRED) @@ -794,7 +794,7 @@ class KDCBaseTest(RawKerberosTest): names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(user_credentials, rep) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 0c757bd5e5f..25a1f5f3ed8 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -63,7 +63,7 @@ class KdcTgsTests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -113,7 +113,7 @@ class KdcTgsTests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -154,7 +154,7 @@ class KdcTgsTests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 1598959a18c..e42b643b357 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -106,7 +106,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -165,7 +165,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(mc, rep) @@ -227,7 +227,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -365,7 +365,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -433,7 +433,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -472,7 +472,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -535,7 +535,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -599,7 +599,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(mc, rep) @@ -741,7 +741,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) @@ -810,7 +810,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=["krbtgt", realm]) rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authenication(rep) + self.check_pre_authentication(rep) # Do the next AS-REQ padata = self.get_pa_data(uc, rep) -- 2.25.1 From 43ec869b1d7da701c993c98bc0a39968b2142e9e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 2 Aug 2021 17:00:09 +1200 Subject: [PATCH 130/645] tests/krb5: formatting Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit df6623363a7ec1a13af48a09e1d29fa8784e825c) --- python/samba/tests/krb5/as_req_tests.py | 20 +- python/samba/tests/krb5/kdc_base_test.py | 22 +- python/samba/tests/krb5/raw_testcase.py | 323 +++++++++++++---------- 3 files changed, 209 insertions(+), 156 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 10e7b603609..09cfc9e1fc8 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -82,16 +82,16 @@ class AsReqKerberosTests(KDCBaseTest): return initial_padata, req_body 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=_generate_padata_copy, - check_error_fn=self.generic_check_as_error, - check_rep_fn=self.generic_check_kdc_rep, - expected_error_mode=expected_error_mode, - client_as_etypes=client_as_etypes, - expected_salt=expected_salt) + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + generate_padata_fn=_generate_padata_copy, + check_error_fn=self.generic_check_as_error, + check_rep_fn=self.generic_check_kdc_rep, + expected_error_mode=expected_error_mode, + client_as_etypes=client_as_etypes, + expected_salt=expected_salt) rep = self._generic_kdc_exchange(kdc_exchange_dict, kdc_options=str(initial_kdc_options), diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 4bd856b217e..c23c71e1d74 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -21,10 +21,7 @@ import os from datetime import datetime, timezone import tempfile import binascii -import struct -sys.path.insert(0, "bin/python") -os.environ["PYTHONUNBUFFERED"] = "1" from collections import namedtuple import ldb from ldb import SCOPE_BASE @@ -66,6 +63,9 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_ETYPE_INFO2, ) +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + global_asn1_print = False global_hexdump = False @@ -114,9 +114,9 @@ class KDCBaseTest(RawKerberosTest): session = system_session() type(self)._ldb = SamDB(url="ldap://%s" % self.host, - session_info=session, - credentials=creds, - lp=lp) + session_info=session, + credentials=creds, + lp=lp) return self._ldb @@ -337,6 +337,7 @@ class KDCBaseTest(RawKerberosTest): require_strongest_key=False): if require_strongest_key: self.assertTrue(require_keys) + def download_krbtgt_creds(): samdb = self.get_samdb() @@ -742,15 +743,16 @@ class KDCBaseTest(RawKerberosTest): .replace(tzinfo=timezone.utc).timestamp()) # Account for clock skew of up to five minutes. - self.assertLess(cred.authtime - 5*60, + self.assertLess(cred.authtime - 5 * 60, datetime.now(timezone.utc).timestamp(), "Ticket not yet valid - clocks may be out of sync.") - self.assertLess(cred.starttime - 5*60, + self.assertLess(cred.starttime - 5 * 60, datetime.now(timezone.utc).timestamp(), "Ticket not yet valid - clocks may be out of sync.") - self.assertGreater(cred.endtime - 60*60, + self.assertGreater(cred.endtime - 60 * 60, datetime.now(timezone.utc).timestamp(), - "Ticket already expired/about to expire - clocks may be out of sync.") + "Ticket already expired/about to expire - " + "clocks may be out of sync.") cred.renew_till = cred.endtime cred.is_skey = 0 diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 9c090e4d005..de9c25751d2 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -24,11 +24,19 @@ import datetime import random import binascii import itertools +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 +from pyasn1.codec.native.encoder import encode as pyasn1_native_encode + +from pyasn1.codec.ber.encoder import BitStringEncoder -import samba.tests from samba.credentials import Credentials -from samba.tests import TestCaseInTempDir from samba.dcerpc import security + +import samba.tests +from samba.tests import TestCaseInTempDir + import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_ETYPE_NOSUPP, @@ -53,13 +61,6 @@ from samba.tests.krb5.rfc4120_constants import ( ) import samba.tests.krb5.kcrypto as kcrypto -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 -from pyasn1.codec.native.encoder import encode as pyasn1_native_encode - -from pyasn1.codec.ber.encoder import BitStringEncoder as BitStringEncoder - def BitStringEncoder_encodeValue32( self, value, asn1Spec, encodeFun, **options): @@ -217,6 +218,7 @@ class Krb5EncryptionKey(object): } return EncryptionKey_obj + class KerberosCredentials(Credentials): def __init__(self): super(KerberosCredentials, self).__init__() @@ -293,6 +295,7 @@ class KerberosCredentials(Credentials): def get_forced_salt(self): return self.forced_salt + class KerberosTicketCreds(object): def __init__(self, ticket, session_key, crealm=None, cname=None, @@ -311,14 +314,15 @@ class KerberosTicketCreds(object): self.encpart_private = encpart_private return + class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" etypes_to_test = ( - { "value": -1111, "name": "dummy", }, - { "value": kcrypto.Enctype.AES256, "name": "aes128", }, - { "value": kcrypto.Enctype.AES128, "name": "aes256", }, - { "value": kcrypto.Enctype.RC4, "name": "rc4", }, + {"value": -1111, "name": "dummy", }, + {"value": kcrypto.Enctype.AES256, "name": "aes128", }, + {"value": kcrypto.Enctype.AES128, "name": "aes256", }, + {"value": kcrypto.Enctype.RC4, "name": "rc4", }, ) setup_etype_test_permutations_done = False @@ -332,7 +336,7 @@ class RawKerberosTest(TestCaseInTempDir): num_idxs = len(cls.etypes_to_test) permutations = [] - for num in range(1, num_idxs+1): + for num in range(1, num_idxs + 1): chunk = list(itertools.permutations(range(num_idxs), num)) for e in chunk: el = list(e) @@ -349,7 +353,7 @@ class RawKerberosTest(TestCaseInTempDir): name += "_%s" % n etypes += (cls.etypes_to_test[idx]["value"],) - r = { "name": name, "etypes": etypes, } + r = {"name": name, "etypes": etypes, } res.append(r) cls.etype_test_permutations = res @@ -386,7 +390,8 @@ class RawKerberosTest(TestCaseInTempDir): self.do_asn1_print = False self.do_hexdump = False - strict_checking = samba.tests.env_get_var_value('STRICT_CHECKING', allow_missing=True) + strict_checking = samba.tests.env_get_var_value('STRICT_CHECKING', + allow_missing=True) if strict_checking is None: strict_checking = '1' self.strict_checking = bool(int(strict_checking)) @@ -440,8 +445,9 @@ class RawKerberosTest(TestCaseInTempDir): val = None if prefix is not None: allow_missing_prefix = allow_missing or fallback_default - val = samba.tests.env_get_var_value('%s_%s' % (prefix, varname), - allow_missing=allow_missing_prefix) + val = samba.tests.env_get_var_value( + '%s_%s' % (prefix, varname), + allow_missing=allow_missing_prefix) else: fallback_default = True if val is None and fallback_default: @@ -506,7 +512,8 @@ class RawKerberosTest(TestCaseInTempDir): if aes256_key is not None: c.set_forced_key(kcrypto.Enctype.AES256, aes256_key) aes128_key = self.env_get_var('AES128_KEY_HEX', prefix, - fallback_default=False, allow_missing=True) + fallback_default=False, + allow_missing=True) if aes128_key is not None: c.set_forced_key(kcrypto.Enctype.AES128, aes128_key) rc4_key = self.env_get_var('RC4_KEY_HEX', prefix, @@ -536,11 +543,12 @@ class RawKerberosTest(TestCaseInTempDir): env_err = None try: # Try to obtain them from the environment - creds = self._get_krb5_creds_from_env(prefix, - default_username=default_username, - allow_missing_password=allow_missing_password, - allow_missing_keys=allow_missing_keys, - require_strongest_key=require_strongest_key) + creds = self._get_krb5_creds_from_env( + prefix, + default_username=default_username, + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys, + require_strongest_key=require_strongest_key) except Exception as err: # An error occurred, so save it for later env_err = err @@ -886,8 +894,8 @@ class RawKerberosTest(TestCaseInTempDir): return s def get_Nonce(self): - nonce_min=0x7f000000 - nonce_max=0x7fffffff + nonce_min = 0x7f000000 + nonce_max = 0x7fffffff v = random.randint(nonce_min, nonce_max) return v @@ -936,15 +944,20 @@ class RawKerberosTest(TestCaseInTempDir): if etype == kcrypto.Enctype.RC4: nthash = creds.get_nt_hash() self.assertIsNotNone(nthash, msg=fail_msg) - return self.SessionKey_create(etype=etype, contents=nthash, kvno=kvno) + return self.SessionKey_create(etype=etype, + contents=nthash, + kvno=kvno) password = creds.get_password() self.assertIsNotNone(password, msg=fail_msg) salt = creds.get_forced_salt() if salt is None: salt = bytes("%s%s" % (creds.get_realm(), creds.get_username()), - encoding='utf-8') - return self.PasswordKey_create(etype=etype, pwd=password, salt=salt, kvno=kvno) + encoding='utf-8') + return self.PasswordKey_create(etype=etype, + pwd=password, + salt=salt, + kvno=kvno) def RandomKey(self, etype): e = kcrypto._get_enctype_profile(etype) @@ -1020,10 +1033,12 @@ class RawKerberosTest(TestCaseInTempDir): return PA_ENC_TS_ENC_obj def KERB_PA_PAC_REQUEST_create(self, include_pac, pa_data_create=True): - #KERB-PA-PAC-REQUEST ::= SEQUENCE { - # include-pac[0] BOOLEAN --If TRUE, and no pac present, include PAC. - # --If FALSE, and PAC present, remove PAC - #} + # KERB-PA-PAC-REQUEST ::= SEQUENCE { + # include-pac[0] BOOLEAN --If TRUE, and no pac present, + # -- include PAC. + # --If FALSE, and PAC present, + # -- remove PAC. + # } KERB_PA_PAC_REQUEST_obj = { 'include-pac': include_pac, } @@ -1031,7 +1046,7 @@ class RawKerberosTest(TestCaseInTempDir): return KERB_PA_PAC_REQUEST_obj pa_pac = self.der_encode(KERB_PA_PAC_REQUEST_obj, asn1Spec=krb5_asn1.KERB_PA_PAC_REQUEST()) - pa_data = self.PA_DATA_create(128, pa_pac) # PA-PAC-REQUEST + pa_data = self.PA_DATA_create(128, pa_pac) # PA-PAC-REQUEST return pa_data def KDC_REQ_BODY_create(self, @@ -1327,11 +1342,14 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData=EncAuthorizationData, EncAuthorizationData_key=EncAuthorizationData_key, additional_tickets=additional_tickets) - req_body_blob = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), + req_body_blob = self.der_encode(req_body, + asn1Spec=krb5_asn1.KDC_REQ_BODY(), asn1_print=asn1_print, hexdump=hexdump) - req_body_checksum = self.Checksum_create( - ticket_session_key, 6, req_body_blob, ctype=body_checksum_type) + req_body_checksum = self.Checksum_create(ticket_session_key, + 6, + req_body_blob, + ctype=body_checksum_type) subkey_obj = None if authenticator_subkey is not None: @@ -1390,7 +1408,10 @@ class RawKerberosTest(TestCaseInTempDir): cksum_data += n.encode() cksum_data += realm.encode() cksum_data += "Kerberos".encode() - cksum = self.Checksum_create(tgt_session_key, 17, cksum_data, ctype) + cksum = self.Checksum_create(tgt_session_key, + 17, + cksum_data, + ctype) PA_S4U2Self_obj = { 'name': name, @@ -1403,20 +1424,20 @@ class RawKerberosTest(TestCaseInTempDir): return self.PA_DATA_create(129, pa_s4u2self) def _generic_kdc_exchange(self, - kdc_exchange_dict, # required - kdc_options=None, # required - cname=None, # optional - realm=None, # required - sname=None, # optional - from_time=None, # optional - till_time=None, # required - renew_time=None, # optional - nonce=None, # required - etypes=None, # required - addresses=None, # optional - EncAuthorizationData=None, # optional - EncAuthorizationData_key=None, # optional - additional_tickets=None): # optional + kdc_exchange_dict, # required + kdc_options=None, # required + cname=None, # optional + realm=None, # required + sname=None, # optional + from_time=None, # optional + till_time=None, # required + renew_time=None, # optional + nonce=None, # required + etypes=None, # required + addresses=None, # optional + EncAuthorizationData=None, # optional + EncAuthorizationData_key=None, # optional + additional_tickets=None): # optional check_error_fn = kdc_exchange_dict['check_error_fn'] check_rep_fn = kdc_exchange_dict['check_rep_fn'] @@ -1431,19 +1452,20 @@ class RawKerberosTest(TestCaseInTempDir): if nonce is None: nonce = self.get_Nonce() - req_body = self.KDC_REQ_BODY_create(kdc_options=kdc_options, - cname=cname, - realm=realm, - sname=sname, - from_time=from_time, - till_time=till_time, - renew_time=renew_time, - nonce=nonce, - etypes=etypes, - addresses=addresses, - EncAuthorizationData=EncAuthorizationData, - EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets) + req_body = self.KDC_REQ_BODY_create( + kdc_options=kdc_options, + cname=cname, + realm=realm, + sname=sname, + from_time=from_time, + till_time=till_time, + renew_time=renew_time, + nonce=nonce, + etypes=etypes, + addresses=addresses, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + additional_tickets=additional_tickets) if generate_padata_fn is not None: # This can alter req_body... padata, req_body = generate_padata_fn(kdc_exchange_dict, @@ -1455,10 +1477,10 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['req_padata'] = padata kdc_exchange_dict['req_body'] = req_body - req_obj,req_decoded = self.KDC_REQ_create(msg_type=req_msg_type, - padata=padata, - req_body=req_body, - asn1Spec=req_asn1Spec()) + req_obj, req_decoded = self.KDC_REQ_create(msg_type=req_msg_type, + padata=padata, + req_body=req_body, + asn1Spec=req_asn1Spec()) rep = self.send_recv_transaction(req_decoded) self.assertIsNotNone(rep) @@ -1571,7 +1593,7 @@ class RawKerberosTest(TestCaseInTempDir): rep_encpart_asn1Spec = kdc_exchange_dict['rep_encpart_asn1Spec'] msg_type = kdc_exchange_dict['rep_msg_type'] - self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP + self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP padata = self.getElementValue(rep, 'padata') self.assertElementEqualUTF8(rep, 'crealm', expected_crealm) self.assertElementEqualPrincipal(rep, 'cname', expected_cname) @@ -1579,22 +1601,23 @@ class RawKerberosTest(TestCaseInTempDir): ticket = self.getElementValue(rep, 'ticket') ticket_encpart = None ticket_cipher = None - if ticket is not None: # Never None, but gives indentation + if ticket is not None: # Never None, but gives indentation self.assertElementPresent(ticket, 'tkt-vno') self.assertElementEqualUTF8(ticket, 'realm', expected_srealm) self.assertElementEqualPrincipal(ticket, 'sname', expected_sname) self.assertElementPresent(ticket, 'enc-part') ticket_encpart = self.getElementValue(ticket, 'enc-part') - if ticket_encpart is not None: # Never None, but gives indentation + if ticket_encpart is not None: # Never None, but gives indentation self.assertElementPresent(ticket_encpart, 'etype') # 'unspecified' means present, with any value != 0 - self.assertElementKVNO(ticket_encpart, 'kvno', self.unspecified_kvno) + self.assertElementKVNO(ticket_encpart, 'kvno', + self.unspecified_kvno) self.assertElementPresent(ticket_encpart, 'cipher') ticket_cipher = self.getElementValue(ticket_encpart, 'cipher') self.assertElementPresent(rep, 'enc-part') encpart = self.getElementValue(rep, 'enc-part') encpart_cipher = None - if encpart is not None: # Never None, but gives indentation + if encpart is not None: # Never None, but gives indentation self.assertElementPresent(encpart, 'etype') self.assertElementKVNO(ticket_encpart, 'kvno', 'autodetect') self.assertElementPresent(encpart, 'cipher') @@ -1602,24 +1625,35 @@ class RawKerberosTest(TestCaseInTempDir): encpart_decryption_key = None if check_padata_fn is not None: - # See if get the decryption key from the preauth phase - encpart_decryption_key,encpart_decryption_usage = \ - check_padata_fn(kdc_exchange_dict, callback_dict, - rep, padata) + # See if we can get the decryption key from the preauth phase + encpart_decryption_key, encpart_decryption_usage = ( + check_padata_fn(kdc_exchange_dict, callback_dict, + rep, padata)) ticket_private = None if ticket_decryption_key is not None: - self.assertElementEqual(ticket_encpart, 'etype', ticket_decryption_key.etype) - self.assertElementKVNO(ticket_encpart, 'kvno', ticket_decryption_key.kvno) - ticket_decpart = ticket_decryption_key.decrypt(KU_TICKET, ticket_cipher) - ticket_private = self.der_decode(ticket_decpart, asn1Spec=krb5_asn1.EncTicketPart()) + self.assertElementEqual(ticket_encpart, 'etype', + ticket_decryption_key.etype) + self.assertElementKVNO(ticket_encpart, 'kvno', + ticket_decryption_key.kvno) + ticket_decpart = ticket_decryption_key.decrypt(KU_TICKET, + ticket_cipher) + ticket_private = self.der_decode( + ticket_decpart, + asn1Spec=krb5_asn1.EncTicketPart()) encpart_private = None if encpart_decryption_key is not None: - self.assertElementEqual(encpart, 'etype', encpart_decryption_key.etype) - self.assertElementKVNO(encpart, 'kvno', encpart_decryption_key.kvno) - rep_decpart = encpart_decryption_key.decrypt(encpart_decryption_usage, encpart_cipher) - encpart_private = self.der_decode(rep_decpart, asn1Spec=rep_encpart_asn1Spec()) + self.assertElementEqual(encpart, 'etype', + encpart_decryption_key.etype) + self.assertElementKVNO(encpart, 'kvno', + encpart_decryption_key.kvno) + rep_decpart = encpart_decryption_key.decrypt( + encpart_decryption_usage, + encpart_cipher) + encpart_private = self.der_decode( + rep_decpart, + asn1Spec=rep_encpart_asn1Spec()) if check_kdc_private_fn is not None: check_kdc_private_fn(kdc_exchange_dict, callback_dict, @@ -1647,12 +1681,14 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(ticket_private, 'flags') self.assertElementPresent(ticket_private, 'key') ticket_key = self.getElementValue(ticket_private, 'key') - if ticket_key is not None: # Never None, but gives indentation + if ticket_key is not None: # Never None, but gives indentation self.assertElementPresent(ticket_key, 'keytype') self.assertElementPresent(ticket_key, 'keyvalue') ticket_session_key = self.EncryptionKey_import(ticket_key) - self.assertElementEqualUTF8(ticket_private, 'crealm', expected_crealm) - self.assertElementEqualPrincipal(ticket_private, 'cname', expected_cname) + self.assertElementEqualUTF8(ticket_private, 'crealm', + expected_crealm) + self.assertElementEqualPrincipal(ticket_private, 'cname', + expected_cname) self.assertElementPresent(ticket_private, 'transited') self.assertElementPresent(ticket_private, 'authtime') if self.strict_checking: @@ -1666,39 +1702,45 @@ class RawKerberosTest(TestCaseInTempDir): if encpart_private is not None: self.assertElementPresent(encpart_private, 'key') encpart_key = self.getElementValue(encpart_private, 'key') - if encpart_key is not None: # Never None, but gives indentation + if encpart_key is not None: # Never None, but gives indentation self.assertElementPresent(encpart_key, 'keytype') self.assertElementPresent(encpart_key, 'keyvalue') encpart_session_key = self.EncryptionKey_import(encpart_key) self.assertElementPresent(encpart_private, 'last-req') self.assertElementPresent(encpart_private, 'nonce') - # TODO self.assertElementPresent(encpart_private, 'key-expiration') + # TODO self.assertElementPresent(encpart_private, + # 'key-expiration') self.assertElementPresent(encpart_private, 'flags') self.assertElementPresent(encpart_private, 'authtime') if self.strict_checking: self.assertElementPresent(encpart_private, 'starttime') self.assertElementPresent(encpart_private, 'endtime') # TODO self.assertElementPresent(encpart_private, 'renew-till') - self.assertElementEqualUTF8(encpart_private, 'srealm', expected_srealm) - self.assertElementEqualPrincipal(encpart_private, 'sname', expected_sname) + self.assertElementEqualUTF8(encpart_private, 'srealm', + expected_srealm) + self.assertElementEqualPrincipal(encpart_private, 'sname', + expected_sname) # TODO self.assertElementMissing(encpart_private, 'caddr') if ticket_session_key is not None and encpart_session_key is not None: - self.assertEqual(ticket_session_key.etype, encpart_session_key.etype) - self.assertEqual(ticket_session_key.key.contents, encpart_session_key.key.contents) + self.assertEqual(ticket_session_key.etype, + encpart_session_key.etype) + self.assertEqual(ticket_session_key.key.contents, + encpart_session_key.key.contents) if encpart_session_key is not None: session_key = encpart_session_key else: session_key = ticket_session_key - ticket_creds = KerberosTicketCreds(ticket, - session_key, - crealm=expected_crealm, - cname=expected_cname, - srealm=expected_srealm, - sname=expected_sname, - decryption_key=ticket_decryption_key, - ticket_private=ticket_private, - encpart_private=encpart_private) + ticket_creds = KerberosTicketCreds( + ticket, + session_key, + crealm=expected_crealm, + cname=expected_cname, + srealm=expected_srealm, + sname=expected_sname, + decryption_key=ticket_decryption_key, + ticket_private=ticket_private, + encpart_private=encpart_private) kdc_exchange_dict['rep_ticket_creds'] = ticket_creds return @@ -1728,11 +1770,11 @@ class RawKerberosTest(TestCaseInTempDir): if kcrypto.Enctype.RC4 in proposed_etypes: expect_etype_info = True for etype in proposed_etypes: - if etype in (kcrypto.Enctype.AES256,kcrypto.Enctype.AES128): + if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): expect_etype_info = False if etype not in client_as_etypes: continue - if etype in (kcrypto.Enctype.AES256,kcrypto.Enctype.AES128): + if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): if etype > expected_aes_type: expected_aes_type = etype if etype in (kcrypto.Enctype.RC4,): @@ -1779,14 +1821,17 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertIsNotNone(edata) if edata is not None: - rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA()) + rep_padata = self.der_decode(edata, + asn1Spec=krb5_asn1.METHOD_DATA()) self.assertGreater(len(rep_padata), 0) else: rep_padata = [] if self.strict_checking: for i in range(0, len(expected_patypes)): - self.assertElementEqual(rep_padata[i], 'padata-type', expected_patypes[i]) + self.assertElementEqual(rep_padata[i], + 'padata-type', + expected_patypes[i]) self.assertEqual(len(rep_padata), len(expected_patypes)) etype_info2 = None @@ -1799,11 +1844,13 @@ class RawKerberosTest(TestCaseInTempDir): pavalue = self.getElementValue(pa, 'padata-value') if patype == PADATA_ETYPE_INFO2: self.assertIsNone(etype_info2) - etype_info2 = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO2()) + etype_info2 = self.der_decode(pavalue, + asn1Spec=krb5_asn1.ETYPE_INFO2()) continue if patype == PADATA_ETYPE_INFO: self.assertIsNone(etype_info) - etype_info = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO()) + etype_info = self.der_decode(pavalue, + asn1Spec=krb5_asn1.ETYPE_INFO()) continue if patype == PADATA_ENC_TIMESTAMP: self.assertIsNone(enc_timestamp) @@ -1881,7 +1928,8 @@ class RawKerberosTest(TestCaseInTempDir): 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()) + 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, @@ -1893,15 +1941,18 @@ class RawKerberosTest(TestCaseInTempDir): subkey_obj = authenticator_subkey.export_obj() seq_number = random.randint(0, 0xfffffffe) (ctime, cusec) = self.get_KerberosTimeWithUsec() - authenticator_obj = self.Authenticator_create(crealm=tgt.crealm, - cname=tgt.cname, - cksum=req_body_checksum, - cusec=cusec, - ctime=ctime, - subkey=subkey_obj, - seq_number=seq_number, - authorization_data=None) - authenticator_blob = self.der_encode(authenticator_obj, asn1Spec=krb5_asn1.Authenticator()) + authenticator_obj = self.Authenticator_create( + crealm=tgt.crealm, + cname=tgt.cname, + cksum=req_body_checksum, + cusec=cusec, + ctime=ctime, + subkey=subkey_obj, + seq_number=seq_number, + authorization_data=None) + authenticator_blob = self.der_encode( + authenticator_obj, + asn1Spec=krb5_asn1.Authenticator()) authenticator = self.EncryptedData_create(tgt.session_key, KU_TGS_REQ_AUTH, @@ -1909,8 +1960,8 @@ class RawKerberosTest(TestCaseInTempDir): ap_options = krb5_asn1.APOptions('0') ap_req_obj = self.AP_REQ_create(ap_options=str(ap_options), - ticket=tgt.ticket, - authenticator=authenticator) + ticket=tgt.ticket, + authenticator=authenticator) ap_req = self.der_encode(ap_req_obj, asn1Spec=krb5_asn1.AP_REQ()) pa_tgs_req = self.PA_DATA_create(PADATA_KDC_REQ, ap_req) padata = [pa_tgs_req] @@ -1964,19 +2015,19 @@ class RawKerberosTest(TestCaseInTempDir): return preauth_key, as_rep_usage kdc_exchange_dict = self.as_exchange_dict( - expected_crealm=expected_crealm, - expected_cname=expected_cname, - expected_srealm=expected_srealm, - expected_sname=expected_sname, - ticket_decryption_key=ticket_decryption_key, - generate_padata_fn=_generate_padata_copy, - check_error_fn=self.generic_check_as_error, - check_rep_fn=self.generic_check_kdc_rep, - check_padata_fn=_check_padata_preauth_key, - check_kdc_private_fn=self.generic_check_kdc_private, - expected_error_mode=expected_error_mode, - client_as_etypes=client_as_etypes, - expected_salt=expected_salt) + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + ticket_decryption_key=ticket_decryption_key, + generate_padata_fn=_generate_padata_copy, + check_error_fn=self.generic_check_as_error, + check_rep_fn=self.generic_check_kdc_rep, + check_padata_fn=_check_padata_preauth_key, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error_mode, + client_as_etypes=client_as_etypes, + expected_salt=expected_salt) rep = self._generic_kdc_exchange(kdc_exchange_dict, kdc_options=str(kdc_options), @@ -1986,7 +2037,7 @@ class RawKerberosTest(TestCaseInTempDir): till_time=till, etypes=etypes) - if expected_error_mode == 0: # AS-REP + if expected_error_mode == 0: # AS-REP return rep return kdc_exchange_dict['preauth_etype_info2'] -- 2.25.1 From cb33cb52d930054f68f23102c7236efff77ddea8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 2 Aug 2021 17:01:39 +1200 Subject: [PATCH 131/645] tests/krb5: Remove unneeded statements A return statement is redundant as the last statement in a method, as methods will otherwise return None. Also, code blocks consisting of a single 'pass' statement can be safely omitted. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1320ac0f91a9b0fc8156840ec498059ee10b5a2d) --- python/samba/tests/krb5/as_req_tests.py | 2 - python/samba/tests/krb5/raw_testcase.py | 99 +++++++++---------------- 2 files changed, 33 insertions(+), 68 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 09cfc9e1fc8..106c7489e9c 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -46,7 +46,6 @@ class AsReqKerberosTests(KDCBaseTest): tname = "%s_pac_%s" % (name, pac) targs = (idx, pac) cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs) - return def setUp(self): super(AsReqKerberosTests, self).setUp() @@ -197,7 +196,6 @@ class AsReqKerberosTests(KDCBaseTest): preauth_key=preauth_key, ticket_decryption_key=krbtgt_decryption_key) self.assertIsNotNone(as_rep) - return if __name__ == "__main__": global_asn1_print = True diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index de9c25751d2..34eae177882 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -195,7 +195,6 @@ class Krb5EncryptionKey(object): self.etype = key.enctype self.ctype = EncTypeChecksum[self.etype] self.kvno = kvno - return def encrypt(self, usage, plaintext): ciphertext = kcrypto.encrypt(self.key, usage, plaintext) @@ -235,19 +234,15 @@ class KerberosCredentials(Credentials): self.forced_keys = {} self.forced_salt = None - return def set_as_supported_enctypes(self, value): self.as_supported_enctypes = int(value) - return def set_tgs_supported_enctypes(self, value): self.tgs_supported_enctypes = int(value) - return def set_ap_supported_enctypes(self, value): self.ap_supported_enctypes = int(value) - return def _get_krb5_etypes(self, supported_enctypes): etypes = () @@ -290,7 +285,6 @@ class KerberosCredentials(Credentials): def set_forced_salt(self, salt): self.forced_salt = bytes(salt) - return def get_forced_salt(self): return self.forced_salt @@ -312,7 +306,6 @@ class KerberosTicketCreds(object): self.decryption_key = decryption_key self.ticket_private = ticket_private self.encpart_private = encpart_private - return class RawKerberosTest(TestCaseInTempDir): @@ -358,7 +351,6 @@ class RawKerberosTest(TestCaseInTempDir): cls.etype_test_permutations = res cls.setup_etype_test_permutations_done = True - return @classmethod def etype_test_permutation_name_idx(cls): @@ -427,17 +419,12 @@ class RawKerberosTest(TestCaseInTempDir): except IOError: self.s.close() raise - except Exception: - raise - finally: - pass def connect(self): self.assertNotConnected() self._connect_tcp() if self.do_hexdump: sys.stderr.write("connected[%s]\n" % self.host) - return def env_get_var(self, varname, prefix, fallback_default=True, @@ -704,8 +691,6 @@ class RawKerberosTest(TestCaseInTempDir): except IOError as e: self._disconnect("send_pdu: %s" % e) raise - finally: - pass def recv_raw(self, num_recv=0xffff, hexdump=None, timeout=None): rep_pdu = None @@ -721,57 +706,51 @@ class RawKerberosTest(TestCaseInTempDir): except socket.timeout: self.s.settimeout(10) sys.stderr.write("recv_raw: TIMEOUT\n") - pass except socket.error as e: self._disconnect("recv_raw: %s" % e) raise except IOError as e: self._disconnect("recv_raw: %s" % e) raise - finally: - pass return rep_pdu def recv_pdu_raw(self, asn1_print=None, hexdump=None, timeout=None): rep_pdu = None rep = None - try: + raw_pdu = self.recv_raw( + num_recv=4, hexdump=hexdump, timeout=timeout) + if raw_pdu is None: + return (None, None) + header = struct.unpack(">I", raw_pdu[0:4]) + k5_len = header[0] + if k5_len == 0: + return (None, "") + missing = k5_len + rep_pdu = b'' + while missing > 0: raw_pdu = self.recv_raw( - num_recv=4, hexdump=hexdump, timeout=timeout) - if raw_pdu is None: - return (None, None) - header = struct.unpack(">I", raw_pdu[0:4]) - k5_len = header[0] - if k5_len == 0: - return (None, "") - missing = k5_len - rep_pdu = b'' - while missing > 0: - raw_pdu = self.recv_raw( - num_recv=missing, hexdump=hexdump, timeout=timeout) - self.assertGreaterEqual(len(raw_pdu), 1) - rep_pdu += raw_pdu - missing = k5_len - len(rep_pdu) - k5_raw = self.der_decode( - rep_pdu, - asn1Spec=None, - native_encode=False, - asn1_print=False, - hexdump=False) - pvno = k5_raw['field-0'] - self.assertEqual(pvno, 5) - msg_type = k5_raw['field-1'] - self.assertIn(msg_type, [11, 13, 30]) - if msg_type == 11: - asn1Spec = krb5_asn1.AS_REP() - elif msg_type == 13: - asn1Spec = krb5_asn1.TGS_REP() - elif msg_type == 30: - asn1Spec = krb5_asn1.KRB_ERROR() - rep = self.der_decode(rep_pdu, asn1Spec=asn1Spec, - asn1_print=asn1_print, hexdump=False) - finally: - pass + num_recv=missing, hexdump=hexdump, timeout=timeout) + self.assertGreaterEqual(len(raw_pdu), 1) + rep_pdu += raw_pdu + missing = k5_len - len(rep_pdu) + k5_raw = self.der_decode( + rep_pdu, + asn1Spec=None, + native_encode=False, + asn1_print=False, + hexdump=False) + pvno = k5_raw['field-0'] + self.assertEqual(pvno, 5) + msg_type = k5_raw['field-1'] + self.assertIn(msg_type, [11, 13, 30]) + if msg_type == 11: + asn1Spec = krb5_asn1.AS_REP() + elif msg_type == 13: + asn1Spec = krb5_asn1.TGS_REP() + elif msg_type == 30: + asn1Spec = krb5_asn1.KRB_ERROR() + rep = self.der_decode(rep_pdu, asn1Spec=asn1Spec, + asn1_print=asn1_print, hexdump=False) return (rep, rep_pdu) def recv_pdu(self, asn1_print=None, hexdump=None, timeout=None): @@ -782,11 +761,9 @@ class RawKerberosTest(TestCaseInTempDir): def assertIsConnected(self): self.assertIsNotNone(self.s, msg="Not connected") - return def assertNotConnected(self): self.assertIsNone(self.s, msg="Is connected") - return def send_recv_transaction( self, @@ -807,11 +784,9 @@ class RawKerberosTest(TestCaseInTempDir): def assertNoValue(self, value): self.assertTrue(value.isNoValue) - return def assertHasValue(self, value): self.assertIsNotNone(value) - return def getElementValue(self, obj, elem): v = None @@ -824,24 +799,20 @@ class RawKerberosTest(TestCaseInTempDir): def assertElementMissing(self, obj, elem): v = self.getElementValue(obj, elem) self.assertIsNone(v) - return def assertElementPresent(self, obj, elem): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) - return def assertElementEqual(self, obj, elem, value): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) self.assertEqual(v, value) - return def assertElementEqualUTF8(self, obj, elem, value): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) self.assertEqual(v, bytes(value, 'utf8')) - return def assertPrincipalEqual(self, princ1, princ2): self.assertEqual(princ1['name-type'], princ2['name-type']) @@ -854,14 +825,12 @@ class RawKerberosTest(TestCaseInTempDir): princ1['name-string'][idx], princ2['name-string'][idx], msg="princ1=%s != princ2=%s" % (princ1, princ2)) - return def assertElementEqualPrincipal(self, obj, elem, value): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) v = pyasn1_native_decode(v, asn1Spec=krb5_asn1.PrincipalName()) self.assertPrincipalEqual(v, value) - return def assertElementKVNO(self, obj, elem, value): v = self.getElementValue(obj, elem) @@ -879,7 +848,6 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(v, value) else: self.assertIsNone(v) - return def get_KerberosTimeWithUsec(self, epoch=None, offset=None): if epoch is None: @@ -1743,7 +1711,6 @@ class RawKerberosTest(TestCaseInTempDir): encpart_private=encpart_private) kdc_exchange_dict['rep_ticket_creds'] = ticket_creds - return def generic_check_as_error(self, kdc_exchange_dict, -- 2.25.1 From 6df8a91d59f89d1b8dce5fca6c8d3f5fab778f93 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 2 Aug 2021 17:10:32 +1200 Subject: [PATCH 132/645] tests/krb5: Use more compact dict lookup Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 38b3a361819c716adb773fb3b4507c28d7d26c0d) --- python/samba/tests/krb5/kdc_base_test.py | 5 +---- python/samba/tests/krb5/raw_testcase.py | 18 ++++-------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index c23c71e1d74..79efc68254e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -722,10 +722,7 @@ class KDCBaseTest(RawKerberosTest): ticket_data = self.der_encode(ticket, asn1Spec=krb5_asn1.Ticket()) authtime = enc_part['authtime'] - try: - starttime = enc_part['starttime'] - except KeyError: - starttime = authtime + starttime = enc_part.get('starttime', authtime) endtime = enc_part['endtime'] cred = krb5ccache.CREDENTIAL() diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 34eae177882..15bbd9ec999 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -279,9 +279,7 @@ class KerberosCredentials(Credentials): def get_forced_key(self, etype): etype = int(etype) - if etype in self.forced_keys: - return self.forced_keys[etype] - return None + return self.forced_keys.get(etype, None) def set_forced_salt(self, salt): self.forced_salt = bytes(salt) @@ -789,12 +787,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(value) def getElementValue(self, obj, elem): - v = None - try: - v = obj[elem] - except KeyError: - pass - return v + return obj.get(elem, None) def assertElementMissing(self, obj, elem): v = self.getElementValue(obj, elem) @@ -879,11 +872,8 @@ class RawKerberosTest(TestCaseInTempDir): def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): e = etype_info2['etype'] - salt = None - try: - salt = etype_info2['salt'] - except Exception: - pass + + salt = etype_info2.get('salt', None) if e == kcrypto.Enctype.RC4: nthash = creds.get_nt_hash() -- 2.25.1 From fee1632b6ce52e62a7500af3985713e6a0b5a876 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 3 Aug 2021 15:03:00 +1200 Subject: [PATCH 133/645] tests/krb5: Simplify Python syntax Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 41c3e410344280d691e5a21fa5240ef52e71bd2d) --- python/samba/tests/krb5/raw_testcase.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 15bbd9ec999..31731a6547c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -184,7 +184,7 @@ krb5_asn1.KerbErrorDataType.prettyPrint =\ Integer_NamedValues_prettyPrint -class Krb5EncryptionKey(object): +class Krb5EncryptionKey: def __init__(self, key, kvno): EncTypeChecksum = { kcrypto.Enctype.AES256: kcrypto.Cksumtype.SHA1_AES256, @@ -288,7 +288,7 @@ class KerberosCredentials(Credentials): return self.forced_salt -class KerberosTicketCreds(object): +class KerberosTicketCreds: def __init__(self, ticket, session_key, crealm=None, cname=None, srealm=None, sname=None, @@ -956,7 +956,7 @@ class RawKerberosTest(TestCaseInTempDir): return Checksum_obj @classmethod - def PrincipalName_create(self, name_type, names): + def PrincipalName_create(cls, name_type, names): # PrincipalName ::= SEQUENCE { # name-type [0] Int32, # name-string [1] SEQUENCE OF KerberosString @@ -1785,10 +1785,8 @@ class RawKerberosTest(TestCaseInTempDir): rep_padata = [] if self.strict_checking: - for i in range(0, len(expected_patypes)): - self.assertElementEqual(rep_padata[i], - 'padata-type', - expected_patypes[i]) + for i, patype in enumerate(expected_patypes): + self.assertElementEqual(rep_padata[i], 'padata-type', patype) self.assertEqual(len(rep_padata), len(expected_patypes)) etype_info2 = None -- 2.25.1 From 7619178cc86d700ca53dab5c3355cd0dd600a5d6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 13:49:27 +1200 Subject: [PATCH 134/645] tests/krb5: Remove magic constants Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit a2b183c179e74634438c85a4b35518836ba59e47) --- python/samba/tests/krb5/raw_testcase.py | 30 +++++++++++--------- python/samba/tests/krb5/rfc4120_constants.py | 7 +++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 31731a6547c..dfa6a71467a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -41,12 +41,14 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_ETYPE_NOSUPP, KDC_ERR_PREAUTH_REQUIRED, + KRB_AP_REQ, KRB_AS_REP, KRB_AS_REQ, KRB_ERROR, KRB_TGS_REP, KRB_TGS_REQ, KU_AS_REP_ENC_PART, + KU_NON_KERB_CKSUM_SALT, KU_TGS_REP_ENC_PART_SESSION, KU_TGS_REP_ENC_PART_SUB_KEY, KU_TGS_REQ_AUTH, @@ -55,7 +57,9 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO, PADATA_ETYPE_INFO2, + PADATA_FOR_USER, PADATA_KDC_REQ, + PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, PADATA_PK_AS_REP_19 ) @@ -740,12 +744,12 @@ class RawKerberosTest(TestCaseInTempDir): pvno = k5_raw['field-0'] self.assertEqual(pvno, 5) msg_type = k5_raw['field-1'] - self.assertIn(msg_type, [11, 13, 30]) - if msg_type == 11: + self.assertIn(msg_type, [KRB_AS_REP, KRB_TGS_REP, KRB_ERROR]) + if msg_type == KRB_AS_REP: asn1Spec = krb5_asn1.AS_REP() - elif msg_type == 13: + elif msg_type == KRB_TGS_REP: asn1Spec = krb5_asn1.TGS_REP() - elif msg_type == 30: + elif msg_type == KRB_ERROR: asn1Spec = krb5_asn1.KRB_ERROR() rep = self.der_decode(rep_pdu, asn1Spec=asn1Spec, asn1_print=asn1_print, hexdump=False) @@ -1004,7 +1008,7 @@ class RawKerberosTest(TestCaseInTempDir): return KERB_PA_PAC_REQUEST_obj pa_pac = self.der_encode(KERB_PA_PAC_REQUEST_obj, asn1Spec=krb5_asn1.KERB_PA_PAC_REQUEST()) - pa_data = self.PA_DATA_create(128, pa_pac) # PA-PAC-REQUEST + pa_data = self.PA_DATA_create(PADATA_PAC_REQUEST, pa_pac) return pa_data def KDC_REQ_BODY_create(self, @@ -1172,7 +1176,7 @@ class RawKerberosTest(TestCaseInTempDir): asn1_print=asn1_print, hexdump=hexdump) obj, decoded = self.KDC_REQ_create( - msg_type=10, + msg_type=KRB_AS_REQ, padata=padata, req_body=KDC_REQ_BODY_obj, asn1Spec=krb5_asn1.AS_REQ(), @@ -1192,7 +1196,7 @@ class RawKerberosTest(TestCaseInTempDir): # } AP_REQ_obj = { 'pvno': 5, - 'msg-type': 14, + 'msg-type': KRB_AP_REQ, 'ap-options': ap_options, 'ticket': ticket, 'authenticator': authenticator, @@ -1305,7 +1309,7 @@ class RawKerberosTest(TestCaseInTempDir): asn1_print=asn1_print, hexdump=hexdump) req_body_checksum = self.Checksum_create(ticket_session_key, - 6, + KU_TGS_REQ_AUTH_CKSUM, req_body_blob, ctype=body_checksum_type) @@ -1329,7 +1333,7 @@ class RawKerberosTest(TestCaseInTempDir): hexdump=hexdump) authenticator = self.EncryptedData_create( - ticket_session_key, 7, authenticator) + ticket_session_key, KU_TGS_REQ_AUTH, authenticator) ap_options = krb5_asn1.APOptions('0') ap_req = self.AP_REQ_create(ap_options=str(ap_options), @@ -1337,14 +1341,14 @@ class RawKerberosTest(TestCaseInTempDir): authenticator=authenticator) ap_req = self.der_encode(ap_req, asn1Spec=krb5_asn1.AP_REQ(), asn1_print=asn1_print, hexdump=hexdump) - pa_tgs_req = self.PA_DATA_create(1, ap_req) + pa_tgs_req = self.PA_DATA_create(PADATA_KDC_REQ, ap_req) if padata is not None: padata.append(pa_tgs_req) else: padata = [pa_tgs_req] obj, decoded = self.KDC_REQ_create( - msg_type=12, + msg_type=KRB_TGS_REQ, padata=padata, req_body=req_body, asn1Spec=krb5_asn1.TGS_REQ(), @@ -1367,7 +1371,7 @@ class RawKerberosTest(TestCaseInTempDir): cksum_data += realm.encode() cksum_data += "Kerberos".encode() cksum = self.Checksum_create(tgt_session_key, - 17, + KU_NON_KERB_CKSUM_SALT, cksum_data, ctype) @@ -1379,7 +1383,7 @@ class RawKerberosTest(TestCaseInTempDir): } pa_s4u2self = self.der_encode( PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) - return self.PA_DATA_create(129, pa_s4u2self) + return self.PA_DATA_create(PADATA_FOR_USER, pa_s4u2self) def _generic_kdc_exchange(self, kdc_exchange_dict, # required diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index a4c5e079b66..adcc93e1d6b 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -27,6 +27,7 @@ ARCFOUR_HMAC_MD5 = int( # Message types KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) +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')) @@ -39,8 +40,12 @@ PADATA_ETYPE_INFO = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO')) PADATA_ETYPE_INFO2 = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) +PADATA_FOR_USER = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-FOR-USER')) PADATA_KDC_REQ = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-KDC-REQ')) +PADATA_PAC_REQUEST = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-PA-PAC-REQUEST')) PADATA_PK_AS_REQ = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REQ')) PADATA_PK_AS_REP_19 = int( @@ -125,3 +130,5 @@ KU_KRB_CRED = 14 KU_KRB_SAFE_CKSUM = 15 ''' KRB-SAFE cksum, keyed with a key chosen by the application (section 5.6.1) ''' +KU_NON_KERB_SALT = 16 +KU_NON_KERB_CKSUM_SALT = 17 -- 2.25.1 From 7b51e09e38dd2128e11cf654b8b5446e233d103c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 26 Jul 2021 17:14:08 +1200 Subject: [PATCH 135/645] tests/krb5: Fix including enc-authorization-data Remove the EncAuthorizationData parameters from AS_REQ_create(), since it should only be present in the TGS-REQ form. Also, fix a call to EncryptedData_create() to supply the key usage when creating enc-authorization-data. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 67ff72395cec2e5170c0ebae8db416a1f226df72) --- .../tests/krb5/as_canonicalization_tests.py | 4 --- .../samba/tests/krb5/compatability_tests.py | 4 --- python/samba/tests/krb5/kdc_base_test.py | 2 -- python/samba/tests/krb5/kdc_tests.py | 2 -- python/samba/tests/krb5/raw_testcase.py | 31 +++++++++++++------ python/samba/tests/krb5/s4u_tests.py | 4 --- python/samba/tests/krb5/simple_tests.py | 4 --- python/samba/tests/krb5/xrealm_tests.py | 4 --- 8 files changed, 21 insertions(+), 34 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index abb3f96a1e6..29d8cf418f5 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -257,8 +257,6 @@ class KerberosASCanonicalizationTests(KDCBaseTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) @@ -314,8 +312,6 @@ class KerberosASCanonicalizationTests(KDCBaseTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index 5a1ef02ef80..cd67549212a 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -147,8 +147,6 @@ class SimpleKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) @@ -209,8 +207,6 @@ class SimpleKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 79efc68254e..7874562d32d 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -390,8 +390,6 @@ class KDCBaseTest(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) return rep diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py index c7c53953a86..930edd0a63e 100755 --- a/python/samba/tests/krb5/kdc_tests.py +++ b/python/samba/tests/krb5/kdc_tests.py @@ -79,8 +79,6 @@ class KdcTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) return rep diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index dfa6a71467a..f39656d5e03 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -53,6 +53,8 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TGS_REP_ENC_PART_SUB_KEY, KU_TGS_REQ_AUTH, KU_TGS_REQ_AUTH_CKSUM, + KU_TGS_REQ_AUTH_DAT_SESSION, + KU_TGS_REQ_AUTH_DAT_SUBKEY, KU_TICKET, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO, @@ -1022,9 +1024,10 @@ class RawKerberosTest(TestCaseInTempDir): nonce, etypes, addresses, + additional_tickets, EncAuthorizationData, EncAuthorizationData_key, - additional_tickets, + EncAuthorizationData_usage, asn1_print=None, hexdump=None): # KDC-REQ-BODY ::= SEQUENCE { @@ -1054,8 +1057,9 @@ class RawKerberosTest(TestCaseInTempDir): asn1Spec=krb5_asn1.AuthorizationData(), asn1_print=asn1_print, hexdump=hexdump) - enc_ad = self.EncryptedData_create( - EncAuthorizationData_key, enc_ad_plain) + enc_ad = self.EncryptedData_create(EncAuthorizationData_key, + EncAuthorizationData_usage, + enc_ad_plain) else: enc_ad = None KDC_REQ_BODY_obj = { @@ -1123,8 +1127,6 @@ class RawKerberosTest(TestCaseInTempDir): nonce, # required etypes, # required addresses, # optional - EncAuthorizationData, - EncAuthorizationData_key, additional_tickets, native_decoded_only=True, asn1_print=None, @@ -1170,9 +1172,10 @@ class RawKerberosTest(TestCaseInTempDir): nonce, etypes, addresses, - EncAuthorizationData, - EncAuthorizationData_key, additional_tickets, + EncAuthorizationData=None, + EncAuthorizationData_key=None, + EncAuthorizationData_usage=None, asn1_print=asn1_print, hexdump=hexdump) obj, decoded = self.KDC_REQ_create( @@ -1290,6 +1293,11 @@ class RawKerberosTest(TestCaseInTempDir): # -- NOTE: not empty # } + if authenticator_subkey is not None: + EncAuthorizationData_usage = KU_TGS_REQ_AUTH_DAT_SUBKEY + else: + EncAuthorizationData_usage = KU_TGS_REQ_AUTH_DAT_SESSION + req_body = self.KDC_REQ_BODY_create( kdc_options=kdc_options, cname=None, @@ -1301,9 +1309,10 @@ class RawKerberosTest(TestCaseInTempDir): nonce=nonce, etypes=etypes, addresses=addresses, + additional_tickets=additional_tickets, EncAuthorizationData=EncAuthorizationData, EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets) + EncAuthorizationData_usage=EncAuthorizationData_usage) req_body_blob = self.der_encode(req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY(), asn1_print=asn1_print, hexdump=hexdump) @@ -1397,9 +1406,10 @@ class RawKerberosTest(TestCaseInTempDir): nonce=None, # required etypes=None, # required addresses=None, # optional + additional_tickets=None, # optional EncAuthorizationData=None, # optional EncAuthorizationData_key=None, # optional - additional_tickets=None): # optional + EncAuthorizationData_usage=None): # optional check_error_fn = kdc_exchange_dict['check_error_fn'] check_rep_fn = kdc_exchange_dict['check_rep_fn'] @@ -1425,9 +1435,10 @@ class RawKerberosTest(TestCaseInTempDir): nonce=nonce, etypes=etypes, addresses=addresses, + additional_tickets=additional_tickets, EncAuthorizationData=EncAuthorizationData, EncAuthorizationData_key=EncAuthorizationData_key, - additional_tickets=additional_tickets) + EncAuthorizationData_usage=EncAuthorizationData_usage) if generate_padata_fn is not None: # This can alter req_body... padata, req_body = generate_padata_fn(kdc_exchange_dict, diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 30a58d6345a..57575f0595d 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -69,8 +69,6 @@ class S4UKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) @@ -113,8 +111,6 @@ class S4UKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 9650702c6c6..795d753b4f7 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -69,8 +69,6 @@ class SimpleKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) @@ -113,8 +111,6 @@ class SimpleKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) diff --git a/python/samba/tests/krb5/xrealm_tests.py b/python/samba/tests/krb5/xrealm_tests.py index efb953bdf7e..073cb755b46 100755 --- a/python/samba/tests/krb5/xrealm_tests.py +++ b/python/samba/tests/krb5/xrealm_tests.py @@ -68,8 +68,6 @@ class XrealmKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) @@ -112,8 +110,6 @@ class XrealmKerberosTests(RawKerberosTest): nonce=0x7fffffff, etypes=etypes, addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, additional_tickets=None) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) -- 2.25.1 From d7d149dd8d8b3edf729b81511aab227959b4ce84 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:12:34 +1200 Subject: [PATCH 136/645] tests/krb5: Fix callback_dict parameter Items contained in a default-created callback_dict should not be carried over between unrelated calls to {as,tgs}_as_exchange_dict(). Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit bad5f4ee5fdf64ca9d775233fec24975e0b510bf) --- python/samba/tests/krb5/raw_testcase.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f39656d5e03..fc8e6990834 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1486,7 +1486,7 @@ class RawKerberosTest(TestCaseInTempDir): check_rep_fn=None, check_padata_fn=None, check_kdc_private_fn=None, - callback_dict=dict(), + callback_dict=None, expected_error_mode=None, client_as_etypes=None, expected_salt=None): @@ -1511,6 +1511,9 @@ class RawKerberosTest(TestCaseInTempDir): 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, } + if callback_dict is None: + callback_dict = {} + return kdc_exchange_dict def tgs_exchange_dict(self, @@ -1524,7 +1527,7 @@ class RawKerberosTest(TestCaseInTempDir): check_rep_fn=None, check_padata_fn=None, check_kdc_private_fn=None, - callback_dict=dict(), + callback_dict=None, tgt=None, authenticator_subkey=None, body_checksum_type=None): @@ -1549,6 +1552,9 @@ class RawKerberosTest(TestCaseInTempDir): 'body_checksum_type': body_checksum_type, 'authenticator_subkey': authenticator_subkey, } + if callback_dict is None: + callback_dict = {} + return kdc_exchange_dict def generic_check_kdc_rep(self, -- 2.25.1 From acfde071110f702a2f85d40b1373a94e2d31b0da Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:06:29 +1200 Subject: [PATCH 137/645] tests/krb5: Fix encpart_decryption_key with MIT KDC Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit a0c6538a97126671f9c7bcf3b581f3d98cbc7fd1) --- python/samba/tests/krb5/raw_testcase.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index fc8e6990834..1c08b76061f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1630,9 +1630,16 @@ class RawKerberosTest(TestCaseInTempDir): rep_decpart = encpart_decryption_key.decrypt( encpart_decryption_usage, encpart_cipher) - encpart_private = self.der_decode( - rep_decpart, - asn1Spec=rep_encpart_asn1Spec()) + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with + # application tag 26 + try: + encpart_private = self.der_decode( + rep_decpart, + asn1Spec=rep_encpart_asn1Spec()) + except Exception: + encpart_private = self.der_decode( + rep_decpart, + asn1Spec=krb5_asn1.EncTGSRepPart()) if check_kdc_private_fn is not None: check_kdc_private_fn(kdc_exchange_dict, callback_dict, -- 2.25.1 From b5ab4662b563dd380b4a05b12d4dc77410549fbe Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Jul 2021 17:00:09 +1200 Subject: [PATCH 138/645] tests/krb5: Expect e-data except when the error code is KDC_ERR_GENERIC Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 8194b2a2611c6b1db2d29ec22c70e14decd1784b) --- python/samba/tests/krb5/raw_testcase.py | 3 ++- python/samba/tests/krb5/rfc4120_constants.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 1c08b76061f..c0e997a86a1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -40,6 +40,7 @@ from samba.tests import TestCaseInTempDir import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_ETYPE_NOSUPP, + KDC_ERR_GENERIC, KDC_ERR_PREAUTH_REQUIRED, KRB_AP_REQ, KRB_AS_REP, @@ -1799,7 +1800,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqualPrincipal(rep, 'sname', expected_sname) if self.strict_checking: self.assertElementMissing(rep, 'e-text') - if expected_error_mode != KDC_ERR_PREAUTH_REQUIRED: + if expected_error_mode == KDC_ERR_GENERIC: self.assertElementMissing(rep, 'e-data') return edata = self.getElementValue(rep, 'e-data') diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index adcc93e1d6b..b00b8b48ae5 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -58,6 +58,7 @@ KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 KDC_ERR_BADMATCH = 36 KDC_ERR_SKEW = 37 +KDC_ERR_GENERIC = 60 # Name types NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) -- 2.25.1 From 9acf691827a5c488c407f31296b5a2b14605daf3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 15:07:59 +1200 Subject: [PATCH 139/645] tests/krb5: Check Kerberos protocol version number Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d6a242e20004217a0ce02dc4ef620a121e5944da) --- python/samba/tests/krb5/raw_testcase.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c0e997a86a1..693f196940c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1786,6 +1786,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_PK_AS_REQ,) expected_patypes += (PADATA_PK_AS_REP_19,) + self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) self.assertElementEqual(rep, 'error-code', expected_error) self.assertElementMissing(rep, 'ctime') -- 2.25.1 From a0ec3204d4697630b69bfc3ee0ee69de3d0c265a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 11:28:37 +1200 Subject: [PATCH 140/645] tests/krb5: Use credentials kvno when creating password key Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 17d5a267298ccd7272e86fd24c2c608511cf46b7) --- python/samba/tests/krb5/kdc_base_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 7874562d32d..aa172640399 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -409,7 +409,8 @@ class KDCBaseTest(RawKerberosTest): etype_info2 = self.der_decode( padata_value, asn1Spec=krb5_asn1.ETYPE_INFO2()) - key = self.PasswordKey_from_etype_info2(creds, etype_info2[0]) + key = self.PasswordKey_from_etype_info2(creds, etype_info2[0], + creds.get_kvno()) return key def get_pa_data(self, creds, rep, skew=0): -- 2.25.1 From 2bac1a05b33bd8630f12ae883290a846e6bfafd3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:24:52 +1200 Subject: [PATCH 141/645] tests/krb5: Allow cf2 to automatically use the enctype of the first key RFC6113 states: "Unless otherwise specified, the resulting enctype of KRB-FX-CF2 is the enctype of k1." This change means the enctype no longer has to be specified manually. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit a5e5f8fdfe8b6952592d7d682af893c79080826f) --- python/samba/tests/krb5/kcrypto.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index 23502d7bb62..c861e3cc96e 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -653,9 +653,11 @@ def prfplus(key, pepper, ln): return out[:ln] -def cf2(enctype, key1, key2, pepper1, pepper2): +def cf2(key1, key2, pepper1, pepper2, enctype=None): # Combine two keys and two pepper strings to produce a result key # of type enctype, using the RFC 6113 KRB-FX-CF2 function. + if enctype is None: + enctype = key1.enctype e = _get_enctype_profile(enctype) return e.random_to_key(_xorbytes(prfplus(key1, pepper1, e.seedsize), prfplus(key2, pepper2, e.seedsize))) @@ -748,7 +750,7 @@ class KcrytoTest(TestCase): kb = h('97DF97E4B798B29EB31ED7280287A92A') k1 = string_to_key(Enctype.AES128, b'key1', b'key1') k2 = string_to_key(Enctype.AES128, b'key2', b'key2') - k = cf2(Enctype.AES128, k1, k2, b'a', b'b') + k = cf2(k1, k2, b'a', b'b') self.assertEqual(k.contents, kb) def test_aes256_cf2(self): @@ -757,7 +759,7 @@ class KcrytoTest(TestCase): 'E72B1C7B') k1 = string_to_key(Enctype.AES256, b'key1', b'key1') k2 = string_to_key(Enctype.AES256, b'key2', b'key2') - k = cf2(Enctype.AES256, k1, k2, b'a', b'b') + k = cf2(k1, k2, b'a', b'b') self.assertEqual(k.contents, kb) def test_des3_crypt(self): @@ -794,7 +796,7 @@ class KcrytoTest(TestCase): kb = h('E58F9EB643862C13AD38E529313462A7F73E62834FE54A01') k1 = string_to_key(Enctype.DES3, b'key1', b'key1') k2 = string_to_key(Enctype.DES3, b'key2', b'key2') - k = cf2(Enctype.DES3, k1, k2, b'a', b'b') + k = cf2(k1, k2, b'a', b'b') self.assertEqual(k.contents, kb) def test_rc4_crypt(self): @@ -830,7 +832,7 @@ class KcrytoTest(TestCase): kb = h('24D7F6B6BAE4E5C00D2082C5EBAB3672') k1 = string_to_key(Enctype.RC4, b'key1', b'key1') k2 = string_to_key(Enctype.RC4, b'key2', b'key2') - k = cf2(Enctype.RC4, k1, k2, b'a', b'b') + k = cf2(k1, k2, b'a', b'b') self.assertEqual(k.contents, kb) def _test_md5_unkeyed_checksum(self, etype, usage): -- 2.25.1 From aa0e2a2424c78bd45feb92ee3dd0716c7ad7710c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:16:01 +1200 Subject: [PATCH 142/645] tests/krb5: Refactor get_pa_data() The function now returns a single padata object rather than a list, making it easier to combine multiple padata elements into a request. The new name 'get_enc_timestamp_pa_data' also makes it clearer as to what the method generates. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2c80f7f851a7a4ffbcde2c42b2c383b683b67731) --- python/samba/tests/krb5/kdc_base_test.py | 8 ++-- python/samba/tests/krb5/kdc_tests.py | 25 ++++++------ python/samba/tests/krb5/kdc_tgs_tests.py | 12 +++--- .../ms_kile_client_principal_lookup_tests.py | 40 +++++++++---------- 4 files changed, 42 insertions(+), 43 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index aa172640399..7748eae6225 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -413,7 +413,7 @@ class KDCBaseTest(RawKerberosTest): creds.get_kvno()) return key - def get_pa_data(self, creds, rep, skew=0): + def get_enc_timestamp_pa_data(self, creds, rep, skew=0): '''generate the pa_data data element for an AS-REQ ''' key = self.get_as_rep_key(creds, rep) @@ -427,7 +427,7 @@ class KDCBaseTest(RawKerberosTest): padata = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, padata) - return [padata] + return padata def get_as_rep_enc_data(self, key, rep): ''' Decrypt and Decode the encrypted data in an AS-REP @@ -795,9 +795,9 @@ class KDCBaseTest(RawKerberosTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(user_credentials, rep) + padata = self.get_enc_timestamp_pa_data(user_credentials, rep) key = self.get_as_rep_key(user_credentials, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py index 930edd0a63e..928f3c25c0f 100755 --- a/python/samba/tests/krb5/kdc_tests.py +++ b/python/samba/tests/krb5/kdc_tests.py @@ -83,7 +83,7 @@ class KdcTests(RawKerberosTest): rep = self.send_recv_transaction(req) return rep - def get_pa_data(self, creds, rep, skew=0): + def get_enc_timestamp_pa_data(self, creds, rep, skew=0): rep_padata = self.der_decode( rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) @@ -107,8 +107,7 @@ class KdcTests(RawKerberosTest): pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) - padata = [pa_ts] - return padata + return pa_ts def check_pre_authenication(self, rep): """ Check that the kdc response was pre-authentication required @@ -160,8 +159,8 @@ class KdcTests(RawKerberosTest): rep = self.as_req(creds, etype) self.check_pre_authenication(rep) - padata = self.get_pa_data(creds, rep) - rep = self.as_req(creds, etype, padata=padata) + padata = self.get_enc_timestamp_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=[padata]) self.check_as_reply(rep) etype = rep['enc-part']['etype'] @@ -174,8 +173,8 @@ class KdcTests(RawKerberosTest): rep = self.as_req(creds, etype) self.check_pre_authenication(rep) - padata = self.get_pa_data(creds, rep) - rep = self.as_req(creds, etype, padata=padata) + padata = self.get_enc_timestamp_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=[padata]) self.check_as_reply(rep) etype = rep['enc-part']['etype'] @@ -188,8 +187,8 @@ class KdcTests(RawKerberosTest): rep = self.as_req(creds, etype) self.check_pre_authenication(rep) - padata = self.get_pa_data(creds, rep) - rep = self.as_req(creds, etype, padata=padata) + padata = self.get_enc_timestamp_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=[padata]) self.check_as_reply(rep) etype = rep['enc-part']['etype'] @@ -202,8 +201,8 @@ class KdcTests(RawKerberosTest): rep = self.as_req(creds, etype) self.check_pre_authenication(rep) - padata = self.get_pa_data(creds, rep, skew=3600) - rep = self.as_req(creds, etype, padata=padata) + padata = self.get_enc_timestamp_pa_data(creds, rep, skew=3600) + rep = self.as_req(creds, etype, padata=[padata]) self.check_error_rep(rep, KDC_ERR_SKEW) @@ -216,8 +215,8 @@ class KdcTests(RawKerberosTest): rep = self.as_req(creds, etype) self.check_pre_authenication(rep) - padata = self.get_pa_data(creds, rep) - rep = self.as_req(creds, etype, padata=padata) + padata = self.get_enc_timestamp_pa_data(creds, rep) + rep = self.as_req(creds, etype, padata=[padata]) self.check_error_rep(rep, KDC_ERR_PREAUTH_FAILED) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 25a1f5f3ed8..97f9dd41339 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -66,9 +66,9 @@ class KdcTgsTests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a service ticket, but use a cname that does not match @@ -116,9 +116,9 @@ class KdcTgsTests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) enc_part2 = self.get_as_rep_enc_data(key, rep) @@ -157,9 +157,9 @@ class KdcTgsTests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index e42b643b357..99c842701ea 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -109,9 +109,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -168,9 +168,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(mc, rep) + padata = self.get_enc_timestamp_pa_data(mc, rep) key = self.get_as_rep_key(mc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -230,9 +230,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -368,13 +368,13 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) # Note: although we used the alt security id for the pre-auth # we need to use the username for the auth cname = self.PrincipalName_create( name_type=NT_PRINCIPAL, names=[user_name]) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -436,12 +436,12 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) # Use the alternate security identifier # this should fail cname = self.PrincipalName_create( name_type=NT_PRINCIPAL, names=[alt_sec]) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_error_rep(rep, KDC_ERR_C_PRINCIPAL_UNKNOWN) def test_enterprise_principal_step_1_3(self): @@ -475,9 +475,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -538,9 +538,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -602,9 +602,9 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(mc, rep) + padata = self.get_enc_timestamp_pa_data(mc, rep) key = self.get_as_rep_key(mc, rep) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -744,13 +744,13 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) key = self.get_as_rep_key(uc, rep) # Note: although we used the alt security id for the pre-auth # we need to use the username for the auth cname = self.PrincipalName_create( name_type=NT_ENTERPRISE_PRINCIPAL, names=[uname]) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_as_reply(rep) # Request a ticket to the host service on the machine account @@ -813,12 +813,12 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.check_pre_authentication(rep) # Do the next AS-REQ - padata = self.get_pa_data(uc, rep) + padata = self.get_enc_timestamp_pa_data(uc, rep) # Use the alternate security identifier # this should fail cname = self.PrincipalName_create( name_type=NT_ENTERPRISE_PRINCIPAL, names=[ename]) - rep = self.as_req(cname, sname, realm, etype, padata=padata) + rep = self.as_req(cname, sname, realm, etype, padata=[padata]) self.check_error_rep(rep, KDC_ERR_C_PRINCIPAL_UNKNOWN) -- 2.25.1 From 1f29d0e4f0d39ba23c0825bc3384b563e1029d2f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 26 Jul 2021 17:18:38 +1200 Subject: [PATCH 143/645] tests/krb5: Add get_enc_timestamp_pa_data_from_key() This makes it easier to create encrypted timestamp padata when the key has already been obtained. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit f5a906f74f9665a894db3c13722022f732180620) --- python/samba/tests/krb5/kdc_base_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 7748eae6225..64d9e627672 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -416,8 +416,12 @@ class KDCBaseTest(RawKerberosTest): def get_enc_timestamp_pa_data(self, creds, rep, skew=0): '''generate the pa_data data element for an AS-REQ ''' + key = self.get_as_rep_key(creds, rep) + return self.get_enc_timestamp_pa_data_from_key(key, skew=skew) + + def get_enc_timestamp_pa_data_from_key(self, key, skew=0): (patime, pausec) = self.get_KerberosTimeWithUsec(offset=skew) padata = self.PA_ENC_TS_ENC_create(patime, pausec) padata = self.der_encode(padata, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) -- 2.25.1 From 8d8d171d6c8f7c6d5ace696d81a59ac34172d49d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 12:51:54 +1200 Subject: [PATCH 144/645] tests/krb5: Add method to return dict containing padata elements This makes checking multiple padata elements easier. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit cb332d83008aa97a60eaca9e008054f641d514d6) --- python/samba/tests/krb5/raw_testcase.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 693f196940c..9b0b953e565 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -867,6 +867,18 @@ class RawKerberosTest(TestCaseInTempDir): v = random.randint(nonce_min, nonce_max) return v + def get_pa_dict(self, pa_data): + pa_dict = {} + + if pa_data is not None: + for pa in pa_data: + pa_type = pa['padata-type'] + if pa_type in pa_dict: + raise RuntimeError(f'Duplicate type {pa_type}') + pa_dict[pa_type] = pa['padata-value'] + + return pa_dict + def SessionKey_create(self, etype, contents, kvno=None): key = kcrypto.Key(etype, contents) return Krb5EncryptionKey(key, kvno) -- 2.25.1 From ca7e54bf1dee7fd68cf5fc1b1cae9561d7ae86de Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:27:47 +1200 Subject: [PATCH 145/645] tests/krb5: Make _test_as_exchange() return value more consistent Always return the reply and the kdc_exchange_dict so that the caller has more potentially useful information. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit fe8912e4a85c5fd614ad3079b041c0e1975958e3) --- python/samba/tests/krb5/as_req_tests.py | 62 +++++++++++++------------ python/samba/tests/krb5/raw_testcase.py | 5 +- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 106c7489e9c..3b7841243c5 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -141,20 +141,21 @@ class AsReqKerberosTests(KDCBaseTest): initial_kdc_options = krb5_asn1.KDCOptions('forwardable') initial_error_mode = KDC_ERR_PREAUTH_REQUIRED - etype_info2 = self._test_as_exchange(cname, - realm, - sname, - till, - client_as_etypes, - initial_error_mode, - expected_crealm, - expected_cname, - expected_srealm, - expected_sname, - expected_salt, - initial_etypes, - initial_padata, - initial_kdc_options) + rep, kdc_exchange_dict = self._test_as_exchange(cname, + realm, + sname, + till, + client_as_etypes, + initial_error_mode, + expected_crealm, + expected_cname, + expected_srealm, + expected_sname, + expected_salt, + initial_etypes, + initial_padata, + initial_kdc_options) + etype_info2 = kdc_exchange_dict['preauth_etype_info2'] self.assertIsNotNone(etype_info2) preauth_key = self.PasswordKey_from_etype_info2(client_creds, @@ -179,22 +180,23 @@ class AsReqKerberosTests(KDCBaseTest): krbtgt_decryption_key = ( self.TicketDecryptionKey_from_creds(krbtgt_creds)) - as_rep = self._test_as_exchange(cname, - realm, - sname, - till, - client_as_etypes, - preauth_error_mode, - expected_crealm, - expected_cname, - expected_srealm, - expected_sname, - expected_salt, - preauth_etypes, - preauth_padata, - preauth_kdc_options, - preauth_key=preauth_key, - ticket_decryption_key=krbtgt_decryption_key) + as_rep, kdc_exchange_dict = self._test_as_exchange( + cname, + realm, + sname, + till, + client_as_etypes, + preauth_error_mode, + expected_crealm, + expected_cname, + expected_srealm, + expected_sname, + expected_salt, + preauth_etypes, + preauth_padata, + preauth_kdc_options, + preauth_key=preauth_key, + ticket_decryption_key=krbtgt_decryption_key) self.assertIsNotNone(as_rep) if __name__ == "__main__": diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 9b0b953e565..e9b4c6c9efa 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2034,7 +2034,4 @@ class RawKerberosTest(TestCaseInTempDir): till_time=till, etypes=etypes) - if expected_error_mode == 0: # AS-REP - return rep - - return kdc_exchange_dict['preauth_etype_info2'] + return rep, kdc_exchange_dict -- 2.25.1 From d7891a7099ca6122deb4a6492994d72bbc4a1026 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 22 Jul 2021 16:27:17 +1200 Subject: [PATCH 146/645] tests/krb5: Add get_EpochFromKerberosTime() Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit bab7503e3043002b1422b00f40cd03a0a29538aa) --- python/samba/tests/krb5/kdc_base_test.py | 12 +++--------- python/samba/tests/krb5/raw_testcase.py | 11 +++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 64d9e627672..f0a9e7311a5 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -732,15 +732,9 @@ class KDCBaseTest(RawKerberosTest): cred.client = cprincipal cred.server = sprincipal cred.keyblock = keyblock - cred.authtime = int(datetime.strptime(authtime.decode(), - "%Y%m%d%H%M%SZ") - .replace(tzinfo=timezone.utc).timestamp()) - cred.starttime = int(datetime.strptime(starttime.decode(), - "%Y%m%d%H%M%SZ") - .replace(tzinfo=timezone.utc).timestamp()) - cred.endtime = int(datetime.strptime(endtime.decode(), - "%Y%m%d%H%M%SZ") - .replace(tzinfo=timezone.utc).timestamp()) + cred.authtime = self.get_EpochFromKerberosTime(authtime) + cred.starttime = self.get_EpochFromKerberosTime(starttime) + cred.endtime = self.get_EpochFromKerberosTime(endtime) # Account for clock skew of up to five minutes. self.assertLess(cred.authtime - 5 * 60, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e9b4c6c9efa..3ab63cd01d0 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -861,6 +861,17 @@ class RawKerberosTest(TestCaseInTempDir): (s, _) = self.get_KerberosTimeWithUsec(epoch=epoch, offset=offset) return s + def get_EpochFromKerberosTime(self, kerberos_time): + if isinstance(kerberos_time, bytes): + kerberos_time = kerberos_time.decode() + + epoch = datetime.datetime.strptime(kerberos_time, + '%Y%m%d%H%M%SZ') + epoch = epoch.replace(tzinfo=datetime.timezone.utc) + epoch = int(epoch.timestamp()) + + return epoch + def get_Nonce(self): nonce_min = 0x7f000000 nonce_max = 0x7fffffff -- 2.25.1 From f63324ec1ccc65a7fbde1ba74f038ed34a736b1b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 3 Aug 2021 15:58:19 +1200 Subject: [PATCH 147/645] tests/krb5: Use encryption with admin credentials This ensures that account creation using admin credentials succeeds. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ce379edf2e135b105b18d35e24d732389de94291) --- python/samba/tests/krb5/raw_testcase.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 3ab63cd01d0..e48d501ad19 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -33,6 +33,7 @@ from pyasn1.codec.ber.encoder import BitStringEncoder from samba.credentials import Credentials from samba.dcerpc import security +from samba.gensec import FEATURE_SEAL import samba.tests from samba.tests import TestCaseInTempDir @@ -606,6 +607,7 @@ class RawKerberosTest(TestCaseInTempDir): c = self._get_krb5_creds(prefix='ADMIN', allow_missing_password=allow_missing_password, allow_missing_keys=allow_missing_keys) + c.set_gensec_features(c.get_gensec_features() | FEATURE_SEAL) return c def get_krbtgt_creds(self, -- 2.25.1 From af394abfffb834518f03e757195f2d377e6a72c9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 11:25:55 +1200 Subject: [PATCH 148/645] tests/krb5: Allow specifying additional details when creating an account Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4790b6b04ae145a2ebb418dd734487a6ba28a30c) --- python/samba/tests/krb5/kdc_base_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index f0a9e7311a5..279e15c13ce 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -148,7 +148,7 @@ class KDCBaseTest(RawKerberosTest): return default_enctypes def create_account(self, ldb, name, machine_account=False, - spn=None, upn=None): + spn=None, upn=None, additional_details=None): '''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. @@ -180,6 +180,8 @@ class KDCBaseTest(RawKerberosTest): details["servicePrincipalName"] = spn if upn is not None: details["userPrincipalName"] = upn + if additional_details is not None: + details.update(additional_details) ldb.add(details) creds = KerberosCredentials() -- 2.25.1 From 0e8a2fa8c43bcfd61e3ae6a816e1cb05b65b645a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:19:57 +1200 Subject: [PATCH 149/645] tests/krb5: Add more methods for obtaining machine and service credentials Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 50d743bafc7aa9f7b4688bae652a501001e9fdbb) --- python/samba/tests/krb5/kdc_base_test.py | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 279e15c13ce..21e2c04cea1 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -334,6 +334,80 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=create_client_account) return c + def get_mach_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + def create_mach_account(): + samdb = self.get_samdb() + + mach_name = 'kdctestmac' + details = { + 'msDS-SupportedEncryptionTypes': str( + security.KERB_ENCTYPE_FAST_SUPPORTED | + security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | + security.KERB_ENCTYPE_CLAIMS_SUPPORTED + ) + } + + creds, dn = self.create_account(samdb, mach_name, + machine_account=True, + spn='host/' + mach_name, + additional_details=details) + + res = samdb.search(base=dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='MAC', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys, + fallback_creds_fn=create_mach_account) + return c + + def get_service_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + def create_service_account(): + samdb = self.get_samdb() + + mach_name = 'kdctestservice' + details = { + 'msDS-SupportedEncryptionTypes': str( + security.KERB_ENCTYPE_FAST_SUPPORTED | + security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | + security.KERB_ENCTYPE_CLAIMS_SUPPORTED + ) + } + + creds, dn = self.create_account(samdb, mach_name, + machine_account=True, + spn='host/' + mach_name, + additional_details=details) + + res = samdb.search(base=dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='SERVICE', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys, + fallback_creds_fn=create_service_account) + return c + def get_krbtgt_creds(self, require_keys=True, require_strongest_key=False): -- 2.25.1 From 2c4b1a172b81dd465b96bc4098bfbfcfee4cc244 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 22 Jul 2021 16:22:09 +1200 Subject: [PATCH 150/645] tests/krb5: Add method to calculate account salt Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit f5689bb8fab82d5fcbdbd3c63b86e7618834aac5) --- python/samba/tests/krb5/kdc_base_test.py | 2 ++ python/samba/tests/krb5/raw_testcase.py | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 21e2c04cea1..0dbaeab4a0e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -192,6 +192,8 @@ class KDCBaseTest(RawKerberosTest): creds.set_username(account_name) if machine_account: creds.set_workstation(name) + else: + creds.set_workstation('') # # Save the account name so it can be deleted in tearDownClass self.accounts.add(dn) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e48d501ad19..2dbcc39114a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -295,6 +295,20 @@ class KerberosCredentials(Credentials): def get_forced_salt(self): return self.forced_salt + def get_salt(self): + if self.forced_salt is not None: + return self.forced_salt + + if self.get_workstation(): + salt_string = '%shost%s.%s' % ( + self.get_realm().upper(), + self.get_username().lower().rsplit('$', 1)[0], + self.get_realm().lower()) + else: + salt_string = self.get_realm().upper() + self.get_username() + + return salt_string.encode('utf-8') + class KerberosTicketCreds: def __init__(self, ticket, session_key, @@ -940,10 +954,7 @@ class RawKerberosTest(TestCaseInTempDir): password = creds.get_password() self.assertIsNotNone(password, msg=fail_msg) - salt = creds.get_forced_salt() - if salt is None: - salt = bytes("%s%s" % (creds.get_realm(), creds.get_username()), - encoding='utf-8') + salt = creds.get_salt() return self.PasswordKey_create(etype=etype, pwd=password, salt=salt, -- 2.25.1 From af64b9158ee9a55883a3a451a50c2af2e93cac61 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 26 Jul 2021 17:19:04 +1200 Subject: [PATCH 151/645] tests/krb5: Add check_reply() method to check for AS or TGS reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 28fb50f511f3f693709aa9b41c001d6a5f9c3329) --- python/samba/tests/krb5/kdc_base_test.py | 26 +++++------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 0dbaeab4a0e..1b550179e0e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -540,26 +540,7 @@ class KDCBaseTest(RawKerberosTest): kvno match the expected values """ - - # Should have a reply, and it should an AS-REP message. - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], KRB_AS_REP, "rep = {%s}" % rep) - - # Protocol version number should be 5 - pvno = int(rep['pvno']) - self.assertEqual(5, pvno, "rep = {%s}" % rep) - - # The ticket version number should be 5 - tkt_vno = int(rep['ticket']['tkt-vno']) - self.assertEqual(5, tkt_vno, "rep = {%s}" % rep) - - # Check that the kvno is not an RODC kvno - # MIT kerberos does not provide the kvno, so we treat it as optional. - # This is tested in compatability_test.py - if 'kvno' in rep['enc-part']: - kvno = int(rep['enc-part']['kvno']) - # If the high order bits are set this is an RODC kvno. - self.assertEqual(0, kvno & 0xFFFF0000, "rep = {%s}" % rep) + self.check_reply(rep, msg_type=KRB_AS_REP) def check_tgs_reply(self, rep): """ Check that the kdc response is an TGS-REP and that the @@ -570,10 +551,13 @@ class KDCBaseTest(RawKerberosTest): kvno match the expected values """ + self.check_reply(rep, msg_type=KRB_TGS_REP) + + def check_reply(self, rep, msg_type): # Should have a reply, and it should an TGS-REP message. self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], KRB_TGS_REP, "rep = {%s}" % rep) + self.assertEqual(rep['msg-type'], msg_type, "rep = {%s}" % rep) # Protocol version number should be 5 pvno = int(rep['pvno']) -- 2.25.1 From 547e1232ab436c58c0c8bf4d984bc8941ccbb076 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 10:32:52 +1200 Subject: [PATCH 152/645] tests/krb5: Always specify expected error code Now the expected error code is always determined by the test code itself rather than by generic_check_as_error(). Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 21c64fda8f98d451e028ea483dbe351b1280390c) --- python/samba/tests/krb5/as_req_tests.py | 11 ++++++++++- python/samba/tests/krb5/raw_testcase.py | 13 ++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 3b7841243c5..861d2371b75 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -24,8 +24,10 @@ os.environ["PYTHONUNBUFFERED"] = "1" from samba.tests import DynamicTestCase 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_ETYPE_NOSUPP, KDC_ERR_PREAUTH_REQUIRED, KU_PA_ENC_TIMESTAMP, NT_PRINCIPAL, @@ -68,13 +70,20 @@ class AsReqKerberosTests(KDCBaseTest): sname = self.PrincipalName_create(name_type=NT_SRV_INST, names=[krbtgt_account, realm]) - expected_error_mode = KDC_ERR_PREAUTH_REQUIRED expected_crealm = realm expected_cname = cname expected_srealm = realm expected_sname = sname expected_salt = client_creds.get_forced_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 + def _generate_padata_copy(_kdc_exchange_dict, _callback_dict, req_body): diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 2dbcc39114a..5579e989d1c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -40,9 +40,7 @@ from samba.tests import TestCaseInTempDir import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( - KDC_ERR_ETYPE_NOSUPP, KDC_ERR_GENERIC, - KDC_ERR_PREAUTH_REQUIRED, KRB_AP_REQ, KRB_AS_REP, KRB_AS_REQ, @@ -1524,7 +1522,7 @@ class RawKerberosTest(TestCaseInTempDir): check_padata_fn=None, check_kdc_private_fn=None, callback_dict=None, - expected_error_mode=None, + expected_error_mode=0, client_as_etypes=None, expected_salt=None): kdc_exchange_dict = { @@ -1809,13 +1807,11 @@ class RawKerberosTest(TestCaseInTempDir): if expected_rc4_type != 0: expect_etype_info2 += (expected_rc4_type,) - expected_error = KDC_ERR_ETYPE_NOSUPP expected_patypes = () if expect_etype_info: self.assertGreater(len(expect_etype_info2), 0) expected_patypes += (PADATA_ETYPE_INFO,) if len(expect_etype_info2) != 0: - expected_error = KDC_ERR_PREAUTH_REQUIRED expected_patypes += (PADATA_ETYPE_INFO2,) expected_patypes += (PADATA_ENC_TIMESTAMP,) @@ -1824,7 +1820,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) - self.assertElementEqual(rep, 'error-code', expected_error) + self.assertElementEqual(rep, 'error-code', expected_error_mode) self.assertElementMissing(rep, 'ctime') self.assertElementMissing(rep, 'cusec') self.assertElementPresent(rep, 'stime') @@ -1889,7 +1885,10 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(len(pk_as_rep19), 0) continue - if expected_error == KDC_ERR_ETYPE_NOSUPP: + if all(etype not in client_as_etypes or etype not in proposed_etypes + for etype in (kcrypto.Enctype.AES256, + kcrypto.Enctype.AES128, + kcrypto.Enctype.RC4)): self.assertIsNone(etype_info2) self.assertIsNone(etype_info) if self.strict_checking: -- 2.25.1 From f228a66b3f1e5ac459c9ab3355f9015728e909b5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 10:35:40 +1200 Subject: [PATCH 153/645] tests/krb5: Include kdc_options in kdc_exchange_dict Make kdc_options an element of kdc_exchange_dict instead of a parameter to _generic_kdc_exchange(). This allows testing code to adjust the reply checking based on the options that were specified in the request. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 8fe9589da2d8fe6f5c47770c618ebabe028f6a95) --- python/samba/tests/krb5/as_req_tests.py | 4 ++-- python/samba/tests/krb5/raw_testcase.py | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 861d2371b75..ed97a10b616 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -99,10 +99,10 @@ class AsReqKerberosTests(KDCBaseTest): check_rep_fn=self.generic_check_kdc_rep, expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, - expected_salt=expected_salt) + expected_salt=expected_salt, + kdc_options=str(initial_kdc_options)) rep = self._generic_kdc_exchange(kdc_exchange_dict, - kdc_options=str(initial_kdc_options), cname=cname, realm=realm, sname=sname, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 5579e989d1c..00f90c5dea9 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1431,7 +1431,6 @@ class RawKerberosTest(TestCaseInTempDir): def _generic_kdc_exchange(self, kdc_exchange_dict, # required - kdc_options=None, # required cname=None, # optional realm=None, # required sname=None, # optional @@ -1454,6 +1453,8 @@ class RawKerberosTest(TestCaseInTempDir): req_asn1Spec = kdc_exchange_dict['req_asn1Spec'] rep_msg_type = kdc_exchange_dict['rep_msg_type'] + kdc_options = kdc_exchange_dict['kdc_options'] + if till_time is None: till_time = self.get_KerberosTime(offset=36000) if nonce is None: @@ -1524,7 +1525,8 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict=None, expected_error_mode=0, client_as_etypes=None, - expected_salt=None): + expected_salt=None, + kdc_options=''): kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, 'req_asn1Spec': krb5_asn1.AS_REQ, @@ -1545,6 +1547,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_error_mode': expected_error_mode, 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, + 'kdc_options': kdc_options, } if callback_dict is None: callback_dict = {} @@ -1565,7 +1568,8 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict=None, tgt=None, authenticator_subkey=None, - body_checksum_type=None): + body_checksum_type=None, + kdc_options=''): kdc_exchange_dict = { 'req_msg_type': KRB_TGS_REQ, 'req_asn1Spec': krb5_asn1.TGS_REQ, @@ -1586,6 +1590,7 @@ class RawKerberosTest(TestCaseInTempDir): 'tgt': tgt, 'body_checksum_type': body_checksum_type, 'authenticator_subkey': authenticator_subkey, + 'kdc_options': kdc_options } if callback_dict is None: callback_dict = {} @@ -2047,10 +2052,10 @@ class RawKerberosTest(TestCaseInTempDir): check_kdc_private_fn=self.generic_check_kdc_private, expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, - expected_salt=expected_salt) + expected_salt=expected_salt, + kdc_options=str(kdc_options)) rep = self._generic_kdc_exchange(kdc_exchange_dict, - kdc_options=str(kdc_options), cname=cname, realm=realm, sname=sname, -- 2.25.1 From da83932a3ac3ef6fcbd12f5a311cb245566a944c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:06:15 +1200 Subject: [PATCH 154/645] tests/krb5: Only allow specifying one of check_rep_fn and check_error_fn This means that there can no longer be surprises where a test receives a reply when it was expecting an error, or vice versa. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 78818655505b3183251940e86270cd40bae73206) --- python/samba/tests/krb5/as_req_tests.py | 2 +- python/samba/tests/krb5/raw_testcase.py | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index ed97a10b616..d9a66f99ecf 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -96,7 +96,7 @@ class AsReqKerberosTests(KDCBaseTest): expected_sname=expected_sname, generate_padata_fn=_generate_padata_copy, check_error_fn=self.generic_check_as_error, - check_rep_fn=self.generic_check_kdc_rep, + check_rep_fn=None, expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, expected_salt=expected_salt, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 00f90c5dea9..d7813387941 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1453,6 +1453,7 @@ class RawKerberosTest(TestCaseInTempDir): req_asn1Spec = kdc_exchange_dict['req_asn1Spec'] rep_msg_type = kdc_exchange_dict['rep_msg_type'] + expected_error_mode = kdc_exchange_dict['expected_error_mode'] kdc_options = kdc_exchange_dict['kdc_options'] if till_time is None: @@ -1497,12 +1498,17 @@ class RawKerberosTest(TestCaseInTempDir): msg_type = self.getElementValue(rep, 'msg-type') self.assertIsNotNone(msg_type) - allowed_msg_types = () + expected_msg_type = None if check_error_fn is not None: - allowed_msg_types = (KRB_ERROR,) + expected_msg_type = KRB_ERROR + self.assertIsNone(check_rep_fn) + self.assertNotEqual(0, expected_error_mode) if check_rep_fn is not None: - allowed_msg_types += (rep_msg_type,) - self.assertIn(msg_type, allowed_msg_types) + expected_msg_type = rep_msg_type + self.assertIsNone(check_error_fn) + self.assertEqual(0, expected_error_mode) + self.assertIsNotNone(expected_msg_type) + self.assertEqual(msg_type, expected_msg_type) if msg_type == KRB_ERROR: return check_error_fn(kdc_exchange_dict, @@ -2039,6 +2045,13 @@ class RawKerberosTest(TestCaseInTempDir): as_rep_usage = KU_AS_REP_ENC_PART return preauth_key, as_rep_usage + if expected_error_mode == 0: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + else: + check_error_fn = self.generic_check_as_error + check_rep_fn = None + kdc_exchange_dict = self.as_exchange_dict( expected_crealm=expected_crealm, expected_cname=expected_cname, @@ -2046,8 +2059,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_sname=expected_sname, ticket_decryption_key=ticket_decryption_key, generate_padata_fn=_generate_padata_copy, - check_error_fn=self.generic_check_as_error, - check_rep_fn=self.generic_check_kdc_rep, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, check_padata_fn=_check_padata_preauth_key, check_kdc_private_fn=self.generic_check_kdc_private, expected_error_mode=expected_error_mode, -- 2.25.1 From c476ef0a42719c7dd29223423219317e8faa4ad4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 10:37:48 +1200 Subject: [PATCH 155/645] tests/krb5: Ensure in assertElementPresent() that container elements are not empty Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ba3c92f77b20e1e0d298cd92399dc69535739c27) --- python/samba/tests/krb5/raw_testcase.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index d7813387941..e1baf0ce943 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -24,6 +24,8 @@ import datetime import random import binascii import itertools +import collections + 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 @@ -817,6 +819,9 @@ class RawKerberosTest(TestCaseInTempDir): def assertElementPresent(self, obj, elem): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) + if self.strict_checking: + if isinstance(v, collections.abc.Container): + self.assertNotEqual(0, len(v)) def assertElementEqual(self, obj, elem, value): v = self.getElementValue(obj, elem) -- 2.25.1 From 3b0c6ce42a7da754255b628fa32f3b588a6822f2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:39:42 +1200 Subject: [PATCH 156/645] tests/krb5: Assert that more variables are not None Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 3d1066e923815782036bd11524fda110a2528951) --- python/samba/tests/krb5/raw_testcase.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e1baf0ce943..3a178f4bce3 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1631,12 +1631,14 @@ class RawKerberosTest(TestCaseInTempDir): ticket = self.getElementValue(rep, 'ticket') ticket_encpart = None ticket_cipher = None + self.assertIsNotNone(ticket) if ticket is not None: # Never None, but gives indentation self.assertElementPresent(ticket, 'tkt-vno') self.assertElementEqualUTF8(ticket, 'realm', expected_srealm) self.assertElementEqualPrincipal(ticket, 'sname', expected_sname) self.assertElementPresent(ticket, 'enc-part') ticket_encpart = self.getElementValue(ticket, 'enc-part') + self.assertIsNotNone(ticket_encpart) if ticket_encpart is not None: # Never None, but gives indentation self.assertElementPresent(ticket_encpart, 'etype') # 'unspecified' means present, with any value != 0 @@ -1647,6 +1649,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(rep, 'enc-part') encpart = self.getElementValue(rep, 'enc-part') encpart_cipher = None + self.assertIsNotNone(encpart) if encpart is not None: # Never None, but gives indentation self.assertElementPresent(encpart, 'etype') self.assertElementKVNO(ticket_encpart, 'kvno', 'autodetect') @@ -1654,6 +1657,7 @@ class RawKerberosTest(TestCaseInTempDir): encpart_cipher = self.getElementValue(encpart, 'cipher') encpart_decryption_key = None + self.assertIsNotNone(check_padata_fn) if check_padata_fn is not None: # See if we can get the decryption key from the preauth phase encpart_decryption_key, encpart_decryption_usage = ( @@ -1661,6 +1665,7 @@ class RawKerberosTest(TestCaseInTempDir): rep, padata)) ticket_private = None + self.assertIsNotNone(ticket_decryption_key) if ticket_decryption_key is not None: self.assertElementEqual(ticket_encpart, 'etype', ticket_decryption_key.etype) @@ -1673,6 +1678,7 @@ class RawKerberosTest(TestCaseInTempDir): asn1Spec=krb5_asn1.EncTicketPart()) encpart_private = None + self.assertIsNotNone(encpart_decryption_key) if encpart_decryption_key is not None: self.assertElementEqual(encpart, 'etype', encpart_decryption_key.etype) @@ -1692,6 +1698,7 @@ class RawKerberosTest(TestCaseInTempDir): rep_decpart, asn1Spec=krb5_asn1.EncTGSRepPart()) + self.assertIsNotNone(check_kdc_private_fn) if check_kdc_private_fn is not None: check_kdc_private_fn(kdc_exchange_dict, callback_dict, rep, ticket_private, encpart_private) @@ -1718,6 +1725,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(ticket_private, 'flags') self.assertElementPresent(ticket_private, 'key') ticket_key = self.getElementValue(ticket_private, 'key') + self.assertIsNotNone(ticket_key) if ticket_key is not None: # Never None, but gives indentation self.assertElementPresent(ticket_key, 'keytype') self.assertElementPresent(ticket_key, 'keyvalue') @@ -1739,6 +1747,7 @@ class RawKerberosTest(TestCaseInTempDir): if encpart_private is not None: self.assertElementPresent(encpart_private, 'key') encpart_key = self.getElementValue(encpart_private, 'key') + self.assertIsNotNone(encpart_key) if encpart_key is not None: # Never None, but gives indentation self.assertElementPresent(encpart_key, 'keytype') self.assertElementPresent(encpart_key, 'keyvalue') -- 2.25.1 From c6e7e5226dec6e4559bf73014bbe51bed4538145 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:34:19 +1200 Subject: [PATCH 157/645] tests/krb5: Check version number of obtained ticket Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 98dc19e8c817fc66e253e544874a45b17b8bfa7b) --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 3a178f4bce3..70062ca338a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1633,7 +1633,7 @@ class RawKerberosTest(TestCaseInTempDir): ticket_cipher = None self.assertIsNotNone(ticket) if ticket is not None: # Never None, but gives indentation - self.assertElementPresent(ticket, 'tkt-vno') + self.assertElementEqual(ticket, 'tkt-vno', 5) self.assertElementEqualUTF8(ticket, 'realm', expected_srealm) self.assertElementEqualPrincipal(ticket, 'sname', expected_sname) self.assertElementPresent(ticket, 'enc-part') -- 2.25.1 From c58104db34b0ccfd2d300fa0650fa7d06f43ae36 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:39:37 +1200 Subject: [PATCH 158/645] tests/krb5: Make checking less strict Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 6df0e406f1f823bf4d65cd478eb6f2424b69adcc) [abartlet@samba.org Adapted to add knownfail because in this Samba 4.14 backport we do not include b3ee034b4d457607ef25a5b01da64e1eaf5906dd (s4:kdc: prefer newer enctypes for preauth responses)] --- python/samba/tests/krb5/raw_testcase.py | 52 ++++++++++--------- .../knownfail.d/samba.tests.krb5.as_req_tests | 42 --------------- 2 files changed, 27 insertions(+), 67 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 70062ca338a..69b7c7adc9b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1625,8 +1625,9 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP padata = self.getElementValue(rep, 'padata') - self.assertElementEqualUTF8(rep, 'crealm', expected_crealm) - self.assertElementEqualPrincipal(rep, 'cname', expected_cname) + if self.strict_checking: + self.assertElementEqualUTF8(rep, 'crealm', expected_crealm) + self.assertElementEqualPrincipal(rep, 'cname', expected_cname) self.assertElementPresent(rep, 'ticket') ticket = self.getElementValue(rep, 'ticket') ticket_encpart = None @@ -1682,8 +1683,9 @@ class RawKerberosTest(TestCaseInTempDir): if encpart_decryption_key is not None: self.assertElementEqual(encpart, 'etype', encpart_decryption_key.etype) - self.assertElementKVNO(encpart, 'kvno', - encpart_decryption_key.kvno) + if self.strict_checking: + self.assertElementKVNO(encpart, 'kvno', + encpart_decryption_key.kvno) rep_decpart = encpart_decryption_key.decrypt( encpart_decryption_usage, encpart_cipher) @@ -1846,17 +1848,17 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) self.assertElementEqual(rep, 'error-code', expected_error_mode) - self.assertElementMissing(rep, 'ctime') - self.assertElementMissing(rep, 'cusec') + if self.strict_checking: + self.assertElementMissing(rep, 'ctime') + self.assertElementMissing(rep, 'cusec') self.assertElementPresent(rep, 'stime') self.assertElementPresent(rep, 'susec') # error-code checked above if self.strict_checking: self.assertElementMissing(rep, 'crealm') self.assertElementMissing(rep, 'cname') - self.assertElementEqualUTF8(rep, 'realm', expected_srealm) - self.assertElementEqualPrincipal(rep, 'sname', expected_sname) - if self.strict_checking: + self.assertElementEqualUTF8(rep, 'realm', expected_srealm) + self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') if expected_error_mode == KDC_ERR_GENERIC: self.assertElementMissing(rep, 'e-data') @@ -1922,7 +1924,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(pk_as_rep19) return - self.assertIsNotNone(etype_info2) + if self.strict_checking: + self.assertIsNotNone(etype_info2) if expect_etype_info: self.assertIsNotNone(etype_info) else: @@ -1931,23 +1934,22 @@ class RawKerberosTest(TestCaseInTempDir): if unexpect_etype_info: self.assertIsNone(etype_info) - self.assertGreaterEqual(len(etype_info2), 1) - self.assertLessEqual(len(etype_info2), len(expect_etype_info2)) if self.strict_checking: + self.assertGreaterEqual(len(etype_info2), 1) self.assertEqual(len(etype_info2), len(expect_etype_info2)) - for i in range(0, len(etype_info2)): - e = self.getElementValue(etype_info2[i], 'etype') - self.assertEqual(e, expect_etype_info2[i]) - salt = self.getElementValue(etype_info2[i], 'salt') - if e == kcrypto.Enctype.RC4: - self.assertIsNone(salt) - else: - self.assertIsNotNone(salt) - if expected_salt is not None: - self.assertEqual(salt, expected_salt) - s2kparams = self.getElementValue(etype_info2[i], 's2kparams') - if self.strict_checking: - self.assertIsNone(s2kparams) + for i in range(0, len(etype_info2)): + e = self.getElementValue(etype_info2[i], 'etype') + self.assertEqual(e, expect_etype_info2[i]) + salt = self.getElementValue(etype_info2[i], 'salt') + if e == kcrypto.Enctype.RC4: + self.assertIsNone(salt) + else: + self.assertIsNotNone(salt) + if expected_salt is not None: + self.assertEqual(salt, expected_salt) + s2kparams = self.getElementValue(etype_info2[i], 's2kparams') + if self.strict_checking: + self.assertIsNone(s2kparams) if etype_info is not None: self.assertEqual(len(etype_info), 1) e = self.getElementValue(etype_info[0], 'etype') diff --git a/selftest/knownfail.d/samba.tests.krb5.as_req_tests b/selftest/knownfail.d/samba.tests.krb5.as_req_tests index f395bdc553b..35375dfcc8e 100644 --- a/selftest/knownfail.d/samba.tests.krb5.as_req_tests +++ b/selftest/knownfail.d/samba.tests.krb5.as_req_tests @@ -1,45 +1,3 @@ -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc -- 2.25.1 From 61bf6453b5d0a9971db10b5156db1aa9affc69cc Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 12:52:42 +1200 Subject: [PATCH 159/645] tests/krb5: Check nonce in EncKDCRepPart Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4951a105b0448854115a7ecc3d867be6f34b0dcf) --- python/samba/tests/krb5/raw_testcase.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 69b7c7adc9b..60e589464f3 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1442,7 +1442,6 @@ class RawKerberosTest(TestCaseInTempDir): from_time=None, # optional till_time=None, # required renew_time=None, # optional - nonce=None, # required etypes=None, # required addresses=None, # optional additional_tickets=None, # optional @@ -1463,8 +1462,12 @@ class RawKerberosTest(TestCaseInTempDir): if till_time is None: till_time = self.get_KerberosTime(offset=36000) - if nonce is None: + + if 'nonce' in kdc_exchange_dict: + nonce = kdc_exchange_dict['nonce'] + else: nonce = self.get_Nonce() + kdc_exchange_dict['nonce'] = nonce req_body = self.KDC_REQ_BODY_create( kdc_options=kdc_options, @@ -1755,7 +1758,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(encpart_key, 'keyvalue') encpart_session_key = self.EncryptionKey_import(encpart_key) self.assertElementPresent(encpart_private, 'last-req') - self.assertElementPresent(encpart_private, 'nonce') + self.assertElementEqual(encpart_private, 'nonce', + kdc_exchange_dict['nonce']) # TODO self.assertElementPresent(encpart_private, # 'key-expiration') self.assertElementPresent(encpart_private, 'flags') -- 2.25.1 From de50b98999c3d1db3acf97be545d7443163bbaeb Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Jul 2021 19:27:02 +1200 Subject: [PATCH 160/645] tests/krb5: Add generate_ap_req() method This method will be useful to generate an AP-REQ for use as FAST armor. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4824dd4e9f40abcbd4134b79e2b2b8fb960f47e7) --- python/samba/tests/krb5/raw_testcase.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 60e589464f3..67b359f07d8 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1971,10 +1971,10 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['preauth_etype_info2'] = etype_info2 return - def generate_simple_tgs_padata(self, - kdc_exchange_dict, - callback_dict, - req_body): + def generate_ap_req(self, + kdc_exchange_dict, + _callback_dict, + req_body): tgt = kdc_exchange_dict['tgt'] authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] body_checksum_type = kdc_exchange_dict['body_checksum_type'] @@ -2014,6 +2014,16 @@ class RawKerberosTest(TestCaseInTempDir): ticket=tgt.ticket, authenticator=authenticator) ap_req = self.der_encode(ap_req_obj, asn1Spec=krb5_asn1.AP_REQ()) + + return ap_req + + def generate_simple_tgs_padata(self, + kdc_exchange_dict, + callback_dict, + req_body): + ap_req = self.generate_ap_req(kdc_exchange_dict, + callback_dict, + req_body) pa_tgs_req = self.PA_DATA_create(PADATA_KDC_REQ, ap_req) padata = [pa_tgs_req] -- 2.25.1 From ab91d706e848a74e7a0652d0b3a58edd7d60f580 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:06:35 +1200 Subject: [PATCH 161/645] tests/krb5: Ensure generated padata is not None Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b6f96dd6395a30e15fa906959cbe665757aaba8d) --- python/samba/tests/krb5/as_req_tests.py | 6 +++++- python/samba/tests/krb5/raw_testcase.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index d9a66f99ecf..b5a6cfd31c7 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -89,12 +89,16 @@ class AsReqKerberosTests(KDCBaseTest): req_body): return initial_padata, req_body + generate_padata_fn = (_generate_padata_copy + if initial_padata is not None + else None) + 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=_generate_padata_copy, + generate_padata_fn=generate_padata_fn, check_error_fn=self.generic_check_as_error, check_rep_fn=None, expected_error_mode=expected_error_mode, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 67b359f07d8..e15fc44a962 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1489,6 +1489,7 @@ class RawKerberosTest(TestCaseInTempDir): padata, req_body = generate_padata_fn(kdc_exchange_dict, callback_dict, req_body) + self.assertIsNotNone(padata) else: padata = None @@ -2082,13 +2083,18 @@ class RawKerberosTest(TestCaseInTempDir): check_error_fn = self.generic_check_as_error check_rep_fn = None + if padata is not None: + generate_padata_fn = _generate_padata_copy + else: + generate_padata_fn = None + kdc_exchange_dict = self.as_exchange_dict( expected_crealm=expected_crealm, expected_cname=expected_cname, expected_srealm=expected_srealm, expected_sname=expected_sname, ticket_decryption_key=ticket_decryption_key, - generate_padata_fn=_generate_padata_copy, + generate_padata_fn=generate_padata_fn, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, check_padata_fn=_check_padata_preauth_key, -- 2.25.1 From 3e0cf5233537cfbff4818c4a810087d78fcc51f5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 13:59:36 +1200 Subject: [PATCH 162/645] tests/krb5: Generate AP-REQ for TGS request in _generic_kdc_exchange() Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 025737deb5325d25b2ae4c57583c24ae1d0eca33) --- python/samba/tests/krb5/raw_testcase.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e15fc44a962..4f399467cfe 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1484,13 +1484,34 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData=EncAuthorizationData, EncAuthorizationData_key=EncAuthorizationData_key, EncAuthorizationData_usage=EncAuthorizationData_usage) + + if req_msg_type == KRB_AS_REQ: + tgs_req = None + tgs_req_padata = None + else: + self.assertEqual(KRB_TGS_REQ, req_msg_type) + + tgs_req = self.generate_ap_req(kdc_exchange_dict, + callback_dict, + req_body) + tgs_req_padata = self.PA_DATA_create(PADATA_KDC_REQ, tgs_req) + if generate_padata_fn is not None: # This can alter req_body... padata, req_body = generate_padata_fn(kdc_exchange_dict, callback_dict, req_body) self.assertIsNotNone(padata) + self.assertNotIn(PADATA_KDC_REQ, + [pa['padata-type'] for pa in padata], + 'Don\'t create TGS-REQ manually') else: + padata = [] + + if tgs_req_padata is not None: + padata.insert(0, tgs_req_padata) + + if not padata: padata = None kdc_exchange_dict['req_padata'] = padata -- 2.25.1 From c93576b53b7f5e01b5fe794a710b4bfbf7afc65b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:21:07 +1200 Subject: [PATCH 163/645] tests/krb5: Add more ASN1 definitions for FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ec702900295100ae4e48ba57242eee6670bf30d6) --- python/samba/tests/krb5/rfc4120.asn1 | 106 ++++++++++++++++++- python/samba/tests/krb5/rfc4120_constants.py | 33 ++++++ python/samba/tests/krb5/rfc4120_pyasn1.py | 100 ++++++++++++++++- 3 files changed, 236 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index d81d06ad6f7..f47c1d00202 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -1,3 +1,43 @@ +-- Portions of these ASN.1 modules are structures are from RFC6113 +-- authored by S. Hartman (Painless Security) and L. Zhu (Microsoft) +-- +-- Copyright (c) 2011 IETF Trust and the persons identified as authors of the +-- code. All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, is permitted pursuant to, and subject to the license terms +-- contained in, the Simplified BSD License set forth in Section 4.c of the IETF +-- Trust’s Legal Provisions Relating to IETF Documents +-- (http://trustee.ietf.org/license-info). +-- +-- BSD License: +-- +-- Copyright (c) 2011 IETF Trust and the persons identified as authors of the code. All rights reserved. +-- Redistribution and use in source and binary forms, with or without modification, are permitted provided +-- that the following conditions are met: +-- • Redistributions of source code must retain the above copyright notice, this list of conditions and +-- the following disclaimer. +-- +-- • Redistributions in binary form must reproduce the above copyright notice, this list of conditions +-- and the following disclaimer in the documentation and/or other materials provided with the +-- distribution. +-- +-- • Neither the name of Internet Society, IETF or IETF Trust, nor the names of specific contributors, +-- may be used to endorse or promote products derived from this software without specific prior written +-- permission. +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- + KerberosV5Spec2 { iso(1) identified-organization(3) dod(6) internet(1) security(5) kerberosV5(2) modules(4) krb5spec2(2) @@ -464,6 +504,69 @@ PA-PAC-OPTIONS ::= SEQUENCE { KERB-KEY-LIST-REQ ::= SEQUENCE OF EncryptionType -- Int32 encryption type -- KERB-KEY-LIST-REP ::= SEQUENCE OF EncryptionKey +FastOptions ::= BIT STRING { + reserved(0), + hide-client-names(1), + kdc-follow-referrals(16) +} + +KrbFastReq ::= SEQUENCE { + fast-options [0] FastOptions, + padata [1] SEQUENCE OF PA-DATA, + req-body [2] KDC-REQ-BODY, + ... +} + +KrbFastArmor ::= SEQUENCE { + armor-type [0] Int32, + armor-value [1] OCTET STRING, + ... +} + +KrbFastArmoredReq ::= SEQUENCE { + armor [0] KrbFastArmor OPTIONAL, + req-checksum [1] Checksum, + enc-fast-req [2] EncryptedData -- KrbFastReq -- +} + +PA-FX-FAST-REQUEST ::= CHOICE { + armored-data [0] KrbFastArmoredReq, + ... +} + +KrbFastFinished ::= SEQUENCE { + timestamp [0] KerberosTime, + usec [1] Int32, + crealm [2] Realm, + cname [3] PrincipalName, + ticket-checksum [4] Checksum, + ... +} + +KrbFastResponse ::= SEQUENCE { + padata [0] SEQUENCE OF PA-DATA, + -- padata typed holes. + strengthen-key [1] EncryptionKey OPTIONAL, + -- This, if present, strengthens the reply key for AS and + -- TGS. MUST be present for TGS. + -- MUST be absent in KRB-ERROR. + finished [2] KrbFastFinished OPTIONAL, + -- Present in AS or TGS reply; absent otherwise. + nonce [3] UInt32, + -- Nonce from the client request. + ... +} + +KrbFastArmoredRep ::= SEQUENCE { + enc-fast-rep [0] EncryptedData, -- KrbFastResponse -- + ... +} + +PA-FX-FAST-REPLY ::= CHOICE { + armored-data [0] KrbFastArmoredRep, + ... +} + -- MS-KILE End -- -- @@ -631,7 +734,8 @@ PADataTypeValues ::= INTEGER { kRB5-PADATA-PKINIT-KX(147), -- krb-wg-anon kRB5-PADATA-PKU2U-NAME(148), -- zhu-pku2u kRB5-PADATA-REQ-ENC-PA-REP(149), -- - kRB5-PADATA-SUPPORTED-ETYPES(165) -- MS-KILE + kRB5-PADATA-SUPPORTED-ETYPES(165), -- MS-KILE + kRB5-PADATA-PAC-OPTIONS(167) -- MS-KILE } PADataTypeSequence ::= SEQUENCE { dummy [0] PADataTypeValues diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index b00b8b48ae5..e1a688991a7 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -36,29 +36,44 @@ KRB_TGS_REQ = int(krb5_asn1.MessageTypeValues('krb-tgs-req')) # PAData types PADATA_ENC_TIMESTAMP = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ENC-TIMESTAMP')) +PADATA_ENCRYPTED_CHALLENGE = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-ENCRYPTED-CHALLENGE')) PADATA_ETYPE_INFO = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO')) PADATA_ETYPE_INFO2 = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-ETYPE-INFO2')) PADATA_FOR_USER = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-FOR-USER')) +PADATA_FX_COOKIE = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-FX-COOKIE')) +PADATA_FX_ERROR = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-FX-ERROR')) +PADATA_FX_FAST = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-FX-FAST')) PADATA_KDC_REQ = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-KDC-REQ')) +PADATA_PAC_OPTIONS = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-PAC-OPTIONS')) PADATA_PAC_REQUEST = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PA-PAC-REQUEST')) PADATA_PK_AS_REQ = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REQ')) PADATA_PK_AS_REP_19 = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REP-19')) +PADATA_SUPPORTED_ETYPES = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-SUPPORTED-ETYPES')) # Error codes KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 +KDC_ERR_POLICY = 12 KDC_ERR_ETYPE_NOSUPP = 14 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 +KDC_ERR_NOT_US = 35 KDC_ERR_BADMATCH = 36 KDC_ERR_SKEW = 37 KDC_ERR_GENERIC = 60 +KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 # Name types NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) @@ -67,6 +82,7 @@ NT_SRV_HST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-HST')) NT_SRV_INST = int(krb5_asn1.NameTypeValues('kRB5-NT-SRV-INST')) NT_ENTERPRISE_PRINCIPAL = int(krb5_asn1.NameTypeValues( 'kRB5-NT-ENTERPRISE-PRINCIPAL')) +NT_WELLKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-WELLKNOWN')) # Authorization data ad-type values @@ -79,6 +95,8 @@ AD_MANDATORY_TICKET_EXTENSIONS = 6 AD_IN_TICKET_EXTENSIONS = 7 AD_MANDATORY_FOR_KDC = 8 AD_INITIAL_VERIFIED_CAS = 9 +AD_FX_FAST_ARMOR = 71 +AD_FX_FAST_USED = 72 AD_WIN2K_PAC = 128 AD_SIGNTICKET = 512 @@ -133,3 +151,18 @@ KU_KRB_SAFE_CKSUM = 15 (section 5.6.1) ''' KU_NON_KERB_SALT = 16 KU_NON_KERB_CKSUM_SALT = 17 + +KU_ACCEPTOR_SEAL = 22 +KU_ACCEPTOR_SIGN = 23 +KU_INITIATOR_SEAL = 24 +KU_INITIATOR_SIGN = 25 + +KU_FAST_REQ_CHKSUM = 50 +KU_FAST_ENC = 51 +KU_FAST_REP = 52 +KU_FAST_FINISHED = 53 +KU_ENC_CHALLENGE_CLIENT = 54 +KU_ENC_CHALLENGE_KDC = 55 + +# Armor types +FX_FAST_ARMOR_AP_REQUEST = 1 diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index 56fe02a68f0..39ec8ed7982 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/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-16 08:54:13.969508) +# (last modified on 2021-06-25 12:10:34.484667) # KerberosV5Spec2 from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful @@ -619,6 +619,17 @@ EncryptionTypeSequence.componentType = namedtype.NamedTypes( ) +class FastOptions(univ.BitString): + pass + + +FastOptions.namedValues = namedval.NamedValues( + ('reserved', 0), + ('hide-client-names', 1), + ('kdc-follow-referrals', 16) +) + + class KDCOptionsValues(univ.BitString): pass @@ -800,6 +811,72 @@ KerbErrorDataTypeSequence.componentType = namedtype.NamedTypes( ) +class KrbFastArmor(univ.Sequence): + pass + + +KrbFastArmor.componentType = namedtype.NamedTypes( + namedtype.NamedType('armor-type', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('armor-value', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class KrbFastArmoredRep(univ.Sequence): + pass + + +KrbFastArmoredRep.componentType = namedtype.NamedTypes( + namedtype.NamedType('enc-fast-rep', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) +) + + +class KrbFastArmoredReq(univ.Sequence): + pass + + +KrbFastArmoredReq.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('armor', KrbFastArmor().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('req-checksum', Checksum().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.NamedType('enc-fast-req', EncryptedData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + + +class KrbFastFinished(univ.Sequence): + pass + + +KrbFastFinished.componentType = namedtype.NamedTypes( + namedtype.NamedType('timestamp', KerberosTime().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('usec', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('crealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('cname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.NamedType('ticket-checksum', Checksum().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))) +) + + +class KrbFastReq(univ.Sequence): + pass + + +KrbFastReq.componentType = namedtype.NamedTypes( + namedtype.NamedType('fast-options', FastOptions().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('padata', univ.SequenceOf(componentType=PA_DATA()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('req-body', KDC_REQ_BODY().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + + +class KrbFastResponse(univ.Sequence): + pass + + +KrbFastResponse.componentType = namedtype.NamedTypes( + namedtype.NamedType('padata', univ.SequenceOf(componentType=PA_DATA()).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('strengthen-key', EncryptionKey().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('finished', KrbFastFinished().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.NamedType('nonce', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) +) + + class MessageTypeValues(univ.Integer): pass @@ -871,6 +948,24 @@ PA_ENC_TS_ENC.componentType = namedtype.NamedTypes( ) +class PA_FX_FAST_REPLY(univ.Choice): + pass + + +PA_FX_FAST_REPLY.componentType = namedtype.NamedTypes( + namedtype.NamedType('armored-data', KrbFastArmoredRep().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) +) + + +class PA_FX_FAST_REQUEST(univ.Choice): + pass + + +PA_FX_FAST_REQUEST.componentType = namedtype.NamedTypes( + namedtype.NamedType('armored-data', KrbFastArmoredReq().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))) +) + + class PACOptionFlags(KerberosFlags): pass @@ -980,7 +1075,8 @@ PADataTypeValues.namedValues = namedval.NamedValues( ('kRB5-PADATA-PKINIT-KX', 147), ('kRB5-PADATA-PKU2U-NAME', 148), ('kRB5-PADATA-REQ-ENC-PA-REP', 149), - ('kRB5-PADATA-SUPPORTED-ETYPES', 165) + ('kRB5-PADATA-SUPPORTED-ETYPES', 165), + ('kRB5-PADATA-PAC-OPTIONS', 167) ) -- 2.25.1 From 3655819f95e7075dd6a85af17f5d5105fe26731e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 10:23:26 +1200 Subject: [PATCH 164/645] tests/krb5: Add more methods to create ASN1 objects for FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 69a66c0d2a7ed415c8d8acdb8da0f2f3d1abf60d) --- python/samba/tests/krb5/raw_testcase.py | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4f399467cfe..46ce7605edf 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1013,6 +1013,17 @@ class RawKerberosTest(TestCaseInTempDir): } return PrincipalName_obj + def AuthorizationData_create(self, ad_type, ad_data): + # AuthorizationData ::= SEQUENCE { + # ad-type [0] Int32, + # ad-data [1] OCTET STRING + # } + AUTH_DATA_obj = { + 'ad-type': ad_type, + 'ad-data': ad_data + } + return AUTH_DATA_obj + def PA_DATA_create(self, padata_type, padata_value): # PA-DATA ::= SEQUENCE { # -- NOTE: first tag is [1], not [0] @@ -1036,6 +1047,65 @@ class RawKerberosTest(TestCaseInTempDir): } return PA_ENC_TS_ENC_obj + def PA_PAC_OPTIONS_create(self, options): + # PA-PAC-OPTIONS ::= SEQUENCE { + # options [0] PACOptionFlags + # } + PA_PAC_OPTIONS_obj = { + 'options': options + } + return PA_PAC_OPTIONS_obj + + def KRB_FAST_ARMOR_create(self, armor_type, armor_value): + # KrbFastArmor ::= SEQUENCE { + # armor-type [0] Int32, + # armor-value [1] OCTET STRING, + # ... + # } + KRB_FAST_ARMOR_obj = { + 'armor-type': armor_type, + 'armor-value': armor_value + } + return KRB_FAST_ARMOR_obj + + def KRB_FAST_REQ_create(self, fast_options, padata, req_body): + # KrbFastReq ::= SEQUENCE { + # fast-options [0] FastOptions, + # padata [1] SEQUENCE OF PA-DATA, + # req-body [2] KDC-REQ-BODY, + # ... + # } + KRB_FAST_REQ_obj = { + 'fast-options': fast_options, + 'padata': padata, + 'req-body': req_body + } + return KRB_FAST_REQ_obj + + def KRB_FAST_ARMORED_REQ_create(self, armor, req_checksum, enc_fast_req): + # KrbFastArmoredReq ::= SEQUENCE { + # armor [0] KrbFastArmor OPTIONAL, + # req-checksum [1] Checksum, + # enc-fast-req [2] EncryptedData -- KrbFastReq -- + # } + KRB_FAST_ARMORED_REQ_obj = { + 'req-checksum': req_checksum, + 'enc-fast-req': enc_fast_req + } + if armor is not None: + KRB_FAST_ARMORED_REQ_obj['armor'] = armor + return KRB_FAST_ARMORED_REQ_obj + + def PA_FX_FAST_REQUEST_create(self, armored_data): + # PA-FX-FAST-REQUEST ::= CHOICE { + # armored-data [0] KrbFastArmoredReq, + # ... + # } + PA_FX_FAST_REQUEST_obj = { + 'armored-data': armored_data + } + return PA_FX_FAST_REQUEST_obj + def KERB_PA_PAC_REQUEST_create(self, include_pac, pa_data_create=True): # KERB-PA-PAC-REQUEST ::= SEQUENCE { # include-pac[0] BOOLEAN --If TRUE, and no pac present, -- 2.25.1 From 9a15a294f4c5d9204d00d9bf67ebe5ba85099856 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 12:47:18 +1200 Subject: [PATCH 165/645] tests/krb5: Add method to generate FAST encrypted challenge padata Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit aafc86896969d02ff1daecdf2668bfa642860082) --- python/samba/tests/krb5/kdc_base_test.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1b550179e0e..24a1e7cfbc8 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -54,11 +54,13 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REP, KRB_ERROR, KU_AS_REP_ENC_PART, + KU_ENC_CHALLENGE_CLIENT, KU_PA_ENC_TIMESTAMP, KU_TGS_REP_ENC_PART_SUB_KEY, KU_TICKET, NT_PRINCIPAL, NT_SRV_HST, + PADATA_ENCRYPTED_CHALLENGE, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO2, ) @@ -511,6 +513,23 @@ class KDCBaseTest(RawKerberosTest): return padata + def get_challenge_pa_data(self, client_challenge_key, skew=0): + patime, pausec = self.get_KerberosTimeWithUsec(offset=skew) + padata = self.PA_ENC_TS_ENC_create(patime, pausec) + padata = self.der_encode(padata, + asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + padata = self.EncryptedData_create(client_challenge_key, + KU_ENC_CHALLENGE_CLIENT, + padata) + padata = self.der_encode(padata, + asn1Spec=krb5_asn1.EncryptedData()) + + padata = self.PA_DATA_create(PADATA_ENCRYPTED_CHALLENGE, + padata) + + return padata + def get_as_rep_enc_data(self, key, rep): ''' Decrypt and Decode the encrypted data in an AS-REP ''' -- 2.25.1 From 6d273dc87ed6ccf3e95ac5418aeb9831e6608ec5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 6 Jul 2021 12:49:05 +1200 Subject: [PATCH 166/645] tests/krb5: Add methods to calculate keys for FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 080894067469d60e2c71961c2d1c1990ba15b917) --- python/samba/tests/krb5/raw_testcase.py | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 46ce7605edf..113f08628b6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2137,6 +2137,43 @@ class RawKerberosTest(TestCaseInTempDir): return subkey, subkey_usage + def generate_armor_key(self, subkey, session_key): + armor_key = kcrypto.cf2(subkey.key, + session_key.key, + b'subkeyarmor', + b'ticketarmor') + armor_key = Krb5EncryptionKey(armor_key, None) + + return armor_key + + def generate_strengthen_reply_key(self, strengthen_key, reply_key): + strengthen_reply_key = kcrypto.cf2(strengthen_key.key, + reply_key.key, + b'strengthenkey', + b'replykey') + strengthen_reply_key = Krb5EncryptionKey(strengthen_reply_key, + reply_key.kvno) + + return strengthen_reply_key + + def generate_client_challenge_key(self, armor_key, longterm_key): + client_challenge_key = kcrypto.cf2(armor_key.key, + longterm_key.key, + b'clientchallengearmor', + b'challengelongterm') + client_challenge_key = Krb5EncryptionKey(client_challenge_key, None) + + return client_challenge_key + + def generate_kdc_challenge_key(self, armor_key, longterm_key): + kdc_challenge_key = kcrypto.cf2(armor_key.key, + longterm_key.key, + b'kdcchallengearmor', + b'challengelongterm') + kdc_challenge_key = Krb5EncryptionKey(kdc_challenge_key, None) + + return kdc_challenge_key + def _test_as_exchange(self, cname, realm, -- 2.25.1 From 7b5450a30e03fed96c45572ecdc98e3696e7b698 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Jul 2021 20:49:12 +1200 Subject: [PATCH 167/645] tests/krb5: Rename generic_check_as_error() to generic_check_kdc_error() This method will also be useful in checking TGS-REP error replies. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 74f332c6f9e31b933837cefee69b219054970713) --- python/samba/tests/krb5/as_req_tests.py | 2 +- python/samba/tests/krb5/raw_testcase.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index b5a6cfd31c7..fd258e8164a 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -99,7 +99,7 @@ class AsReqKerberosTests(KDCBaseTest): expected_srealm=expected_srealm, expected_sname=expected_sname, generate_padata_fn=generate_padata_fn, - check_error_fn=self.generic_check_as_error, + check_error_fn=self.generic_check_kdc_error, check_rep_fn=None, expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 113f08628b6..047bf413b34 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1888,10 +1888,10 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['rep_ticket_creds'] = ticket_creds - def generic_check_as_error(self, - kdc_exchange_dict, - callback_dict, - rep): + def generic_check_kdc_error(self, + kdc_exchange_dict, + callback_dict, + rep): expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] @@ -2208,7 +2208,7 @@ class RawKerberosTest(TestCaseInTempDir): check_error_fn = None check_rep_fn = self.generic_check_kdc_rep else: - check_error_fn = self.generic_check_as_error + check_error_fn = self.generic_check_kdc_error check_rep_fn = None if padata is not None: -- 2.25.1 From 2e4cb2a76a88b2cc9260147d5e81cd451d935fac Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 10:19:46 +1200 Subject: [PATCH 168/645] tests/krb5: Include authenticator_subkey in AS-REQ exchange dict This is needed for FAST. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d554b6dc0f4e14d154e487dc2a842321aa746155) --- python/samba/tests/krb5/raw_testcase.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 047bf413b34..9375f39937e 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1632,6 +1632,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode=0, client_as_etypes=None, expected_salt=None, + authenticator_subkey=None, kdc_options=''): kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, @@ -1653,6 +1654,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_error_mode': expected_error_mode, 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, + 'authenticator_subkey': authenticator_subkey, 'kdc_options': kdc_options, } if callback_dict is None: -- 2.25.1 From 3104ed28289999f88bf3c6f7d1b6c8ed23758a98 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 10:33:10 +1200 Subject: [PATCH 169/645] tests/krb5: Modify generate_ap_req() to also generate FAST armor AP-REQ Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 5c2cd71ae704b853a886c8af5e3cf50b53af7f9e) --- python/samba/tests/krb5/raw_testcase.py | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 9375f39937e..29ea41ec92b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -49,6 +49,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_ERROR, KRB_TGS_REP, KRB_TGS_REQ, + KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, KU_NON_KERB_CKSUM_SALT, KU_TGS_REP_ENC_PART_SESSION, @@ -1563,7 +1564,8 @@ class RawKerberosTest(TestCaseInTempDir): tgs_req = self.generate_ap_req(kdc_exchange_dict, callback_dict, - req_body) + req_body, + armor=False) tgs_req_padata = self.PA_DATA_create(PADATA_KDC_REQ, tgs_req) if generate_padata_fn is not None: @@ -1633,6 +1635,8 @@ class RawKerberosTest(TestCaseInTempDir): client_as_etypes=None, expected_salt=None, authenticator_subkey=None, + armor_tgt=None, + armor_subkey=None, kdc_options=''): kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, @@ -1655,6 +1659,8 @@ class RawKerberosTest(TestCaseInTempDir): 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, 'authenticator_subkey': authenticator_subkey, + 'armor_tgt': armor_tgt, + 'armor_subkey': armor_subkey, 'kdc_options': kdc_options, } if callback_dict is None: @@ -1675,6 +1681,8 @@ class RawKerberosTest(TestCaseInTempDir): check_kdc_private_fn=None, callback_dict=None, tgt=None, + armor_tgt=None, + armor_subkey=None, authenticator_subkey=None, body_checksum_type=None, kdc_options=''): @@ -1697,6 +1705,8 @@ class RawKerberosTest(TestCaseInTempDir): 'callback_dict': callback_dict, 'tgt': tgt, 'body_checksum_type': body_checksum_type, + 'armor_tgt': armor_tgt, + 'armor_subkey': armor_subkey, 'authenticator_subkey': authenticator_subkey, 'kdc_options': kdc_options } @@ -2068,18 +2078,25 @@ class RawKerberosTest(TestCaseInTempDir): def generate_ap_req(self, kdc_exchange_dict, _callback_dict, - req_body): - tgt = kdc_exchange_dict['tgt'] - authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] - body_checksum_type = kdc_exchange_dict['body_checksum_type'] + req_body, + armor): + if armor: + tgt = kdc_exchange_dict['armor_tgt'] + authenticator_subkey = kdc_exchange_dict['armor_subkey'] - req_body_blob = self.der_encode(req_body, - asn1Spec=krb5_asn1.KDC_REQ_BODY()) + 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_checksum = self.Checksum_create(tgt.session_key, - KU_TGS_REQ_AUTH_CKSUM, - req_body_blob, - ctype=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) subkey_obj = None if authenticator_subkey is not None: @@ -2099,8 +2116,9 @@ class RawKerberosTest(TestCaseInTempDir): authenticator_obj, asn1Spec=krb5_asn1.Authenticator()) + usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH authenticator = self.EncryptedData_create(tgt.session_key, - KU_TGS_REQ_AUTH, + usage, authenticator_blob) ap_options = krb5_asn1.APOptions('0') @@ -2117,7 +2135,8 @@ class RawKerberosTest(TestCaseInTempDir): req_body): ap_req = self.generate_ap_req(kdc_exchange_dict, callback_dict, - req_body) + req_body, + armor=False) pa_tgs_req = self.PA_DATA_create(PADATA_KDC_REQ, ap_req) padata = [pa_tgs_req] -- 2.25.1 From 87e2203840aa4e78af2f07fddf1345ce402af74d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 10:33:24 +1200 Subject: [PATCH 170/645] tests/krb5: Add FAST armor generation to _generic_kdc_exchange() Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 0df385fc49cc2693c195209936a29e31216df16d) --- python/samba/tests/krb5/raw_testcase.py | 95 +++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 29ea41ec92b..151dc0355a3 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -42,6 +42,7 @@ from samba.tests import TestCaseInTempDir import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( + FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_GENERIC, KRB_AP_REQ, KRB_AS_REP, @@ -51,6 +52,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REQ, KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, + KU_FAST_REQ_CHKSUM, KU_NON_KERB_CKSUM_SALT, KU_TGS_REP_ENC_PART_SESSION, KU_TGS_REP_ENC_PART_SUB_KEY, @@ -1522,6 +1524,9 @@ class RawKerberosTest(TestCaseInTempDir): check_error_fn = kdc_exchange_dict['check_error_fn'] check_rep_fn = kdc_exchange_dict['check_rep_fn'] + generate_fast_fn = kdc_exchange_dict['generate_fast_fn'] + generate_fast_armor_fn = kdc_exchange_dict['generate_fast_armor_fn'] + generate_fast_padata_fn = kdc_exchange_dict['generate_fast_padata_fn'] generate_padata_fn = kdc_exchange_dict['generate_padata_fn'] callback_dict = kdc_exchange_dict['callback_dict'] req_msg_type = kdc_exchange_dict['req_msg_type'] @@ -1568,25 +1573,81 @@ class RawKerberosTest(TestCaseInTempDir): armor=False) tgs_req_padata = self.PA_DATA_create(PADATA_KDC_REQ, tgs_req) + if generate_fast_padata_fn is not None: + self.assertIsNotNone(generate_fast_fn) + # This can alter req_body... + fast_padata, req_body = generate_fast_padata_fn(kdc_exchange_dict, + callback_dict, + req_body) + else: + fast_padata = [] + + if generate_fast_armor_fn is not None: + self.assertIsNotNone(generate_fast_fn) + fast_ap_req = generate_fast_armor_fn(kdc_exchange_dict, + callback_dict, + req_body, + armor=True) + + fast_armor_type = kdc_exchange_dict['fast_armor_type'] + fast_armor = self.KRB_FAST_ARMOR_create(fast_armor_type, + fast_ap_req) + else: + fast_armor = None + if generate_padata_fn is not None: # This can alter req_body... - padata, req_body = generate_padata_fn(kdc_exchange_dict, - callback_dict, - req_body) - self.assertIsNotNone(padata) + outer_padata, req_body = generate_padata_fn(kdc_exchange_dict, + callback_dict, + req_body) + self.assertIsNotNone(outer_padata) self.assertNotIn(PADATA_KDC_REQ, - [pa['padata-type'] for pa in padata], + [pa['padata-type'] for pa in outer_padata], 'Don\'t create TGS-REQ manually') else: - padata = [] + outer_padata = None + + if generate_fast_fn is not None: + armor_key = kdc_exchange_dict['armor_key'] + self.assertIsNotNone(armor_key) + + if req_msg_type == KRB_AS_REQ: + checksum_blob = self.der_encode( + req_body, + asn1Spec=krb5_asn1.KDC_REQ_BODY()) + else: + self.assertEqual(KRB_TGS_REQ, req_msg_type) + checksum_blob = tgs_req + + checksum = self.Checksum_create(armor_key, + KU_FAST_REQ_CHKSUM, + checksum_blob) + + fast = generate_fast_fn(kdc_exchange_dict, + callback_dict, + req_body, + fast_padata, + fast_armor, + checksum) + else: + fast = None + + padata = [] if tgs_req_padata is not None: - padata.insert(0, tgs_req_padata) + padata.append(tgs_req_padata) + + if fast is not None: + padata.append(fast) + + if outer_padata is not None: + padata += outer_padata if not padata: padata = None kdc_exchange_dict['req_padata'] = padata + kdc_exchange_dict['fast_padata'] = fast_padata kdc_exchange_dict['req_body'] = req_body req_obj, req_decoded = self.KDC_REQ_create(msg_type=req_msg_type, @@ -1625,6 +1686,10 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, ticket_decryption_key=None, + generate_fast_fn=None, + generate_fast_armor_fn=None, + generate_fast_padata_fn=None, + fast_armor_type=FX_FAST_ARMOR_AP_REQUEST, generate_padata_fn=None, check_error_fn=None, check_rep_fn=None, @@ -1635,6 +1700,7 @@ class RawKerberosTest(TestCaseInTempDir): client_as_etypes=None, expected_salt=None, authenticator_subkey=None, + armor_key=None, armor_tgt=None, armor_subkey=None, kdc_options=''): @@ -1649,6 +1715,10 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'ticket_decryption_key': ticket_decryption_key, + 'generate_fast_fn': generate_fast_fn, + 'generate_fast_armor_fn': generate_fast_armor_fn, + 'generate_fast_padata_fn': generate_fast_padata_fn, + 'fast_armor_type': fast_armor_type, 'generate_padata_fn': generate_padata_fn, 'check_error_fn': check_error_fn, 'check_rep_fn': check_rep_fn, @@ -1659,6 +1729,7 @@ class RawKerberosTest(TestCaseInTempDir): 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, 'authenticator_subkey': authenticator_subkey, + 'armor_key': armor_key, 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, 'kdc_options': kdc_options, @@ -1674,6 +1745,10 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, ticket_decryption_key=None, + generate_fast_fn=None, + generate_fast_armor_fn=None, + generate_fast_padata_fn=None, + fast_armor_type=FX_FAST_ARMOR_AP_REQUEST, generate_padata_fn=None, check_error_fn=None, check_rep_fn=None, @@ -1681,6 +1756,7 @@ class RawKerberosTest(TestCaseInTempDir): check_kdc_private_fn=None, callback_dict=None, tgt=None, + armor_key=None, armor_tgt=None, armor_subkey=None, authenticator_subkey=None, @@ -1697,6 +1773,10 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'ticket_decryption_key': ticket_decryption_key, + 'generate_fast_fn': generate_fast_fn, + 'generate_fast_armor_fn': generate_fast_armor_fn, + 'generate_fast_padata_fn': generate_fast_padata_fn, + 'fast_armor_type': fast_armor_type, 'generate_padata_fn': generate_padata_fn, 'check_error_fn': check_error_fn, 'check_rep_fn': check_rep_fn, @@ -1705,6 +1785,7 @@ class RawKerberosTest(TestCaseInTempDir): 'callback_dict': callback_dict, 'tgt': tgt, 'body_checksum_type': body_checksum_type, + 'armor_key': armor_key, 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, 'authenticator_subkey': authenticator_subkey, -- 2.25.1 From 5638b13a769711e412f180afb291c56fc2356e8c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:01:36 +1200 Subject: [PATCH 171/645] tests/krb5: Allow specifying parameters specific to the outer request body This is useful for testing FAST. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 16ce1a1d304b87ed5b390fb87a4542c7c9a484fb) --- python/samba/tests/krb5/raw_testcase.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 151dc0355a3..a173caf98d1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1536,6 +1536,9 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode = kdc_exchange_dict['expected_error_mode'] kdc_options = kdc_exchange_dict['kdc_options'] + # Parameters specific to the outer request body + outer_req = kdc_exchange_dict['outer_req'] + if till_time is None: till_time = self.get_KerberosTime(offset=36000) @@ -1561,6 +1564,14 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData_key=EncAuthorizationData_key, EncAuthorizationData_usage=EncAuthorizationData_usage) + inner_req_body = dict(req_body) + if outer_req is not None: + for key, value in outer_req.items(): + if value is not None: + req_body[key] = value + else: + del req_body[key] + if req_msg_type == KRB_AS_REQ: tgs_req = None tgs_req_padata = None @@ -1625,7 +1636,7 @@ class RawKerberosTest(TestCaseInTempDir): fast = generate_fast_fn(kdc_exchange_dict, callback_dict, - req_body, + inner_req_body, fast_padata, fast_armor, checksum) @@ -1648,7 +1659,7 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['req_padata'] = padata kdc_exchange_dict['fast_padata'] = fast_padata - kdc_exchange_dict['req_body'] = req_body + kdc_exchange_dict['req_body'] = inner_req_body req_obj, req_decoded = self.KDC_REQ_create(msg_type=req_msg_type, padata=padata, @@ -1703,7 +1714,8 @@ class RawKerberosTest(TestCaseInTempDir): armor_key=None, armor_tgt=None, armor_subkey=None, - kdc_options=''): + kdc_options='', + outer_req=None): kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, 'req_asn1Spec': krb5_asn1.AS_REQ, @@ -1733,6 +1745,7 @@ class RawKerberosTest(TestCaseInTempDir): 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, 'kdc_options': kdc_options, + 'outer_req': outer_req } if callback_dict is None: callback_dict = {} @@ -1761,7 +1774,8 @@ class RawKerberosTest(TestCaseInTempDir): armor_subkey=None, authenticator_subkey=None, body_checksum_type=None, - kdc_options=''): + kdc_options='', + outer_req=None): kdc_exchange_dict = { 'req_msg_type': KRB_TGS_REQ, 'req_asn1Spec': krb5_asn1.TGS_REQ, @@ -1789,7 +1803,8 @@ class RawKerberosTest(TestCaseInTempDir): 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, 'authenticator_subkey': authenticator_subkey, - 'kdc_options': kdc_options + 'kdc_options': kdc_options, + 'outer_req': outer_req } if callback_dict is None: callback_dict = {} -- 2.25.1 From a9aaae2bee2403eea8acebaf45d2cca251dd73de Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:04:37 +1200 Subject: [PATCH 172/645] tests/krb5: Add method to check PA-FX-FAST-REPLY Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b62488113f6053755f9be9faa9b757e7193074fa) --- python/samba/tests/krb5/raw_testcase.py | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a173caf98d1..dd733aea09b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -52,6 +52,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REQ, KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, + KU_FAST_REP, KU_FAST_REQ_CHKSUM, KU_NON_KERB_CKSUM_SALT, KU_TGS_REP_ENC_PART_SESSION, @@ -1910,6 +1911,36 @@ class RawKerberosTest(TestCaseInTempDir): return rep + def check_fx_fast_data(self, + kdc_exchange_dict, + fx_fast_data, + armor_key, + finished=False, + expect_strengthen_key=True): + fx_fast_data = self.der_decode(fx_fast_data, + asn1Spec=krb5_asn1.PA_FX_FAST_REPLY()) + + enc_fast_rep = fx_fast_data['armored-data']['enc-fast-rep'] + self.assertEqual(enc_fast_rep['etype'], armor_key.etype) + + fast_rep = armor_key.decrypt(KU_FAST_REP, enc_fast_rep['cipher']) + + fast_response = self.der_decode(fast_rep, + asn1Spec=krb5_asn1.KrbFastResponse()) + + if expect_strengthen_key and self.strict_checking: + self.assertIn('strengthen-key', fast_response) + + if finished: + self.assertIn('finished', fast_response) + + # Ensure that the nonce matches the nonce in the body of the request + # (RFC6113 5.4.3). + nonce = kdc_exchange_dict['nonce'] + self.assertEqual(nonce, fast_response['nonce']) + + return fast_response + def generic_check_kdc_private(self, kdc_exchange_dict, callback_dict, -- 2.25.1 From 7a0aed4f3a4caa553e1edf2e9bd0f0febf8fc21c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:10:13 +1200 Subject: [PATCH 173/645] tests/krb5: Add method to verify ticket checksum for FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 4ca05402b36ba13a987b07b2402906764d3cd49b) --- python/samba/tests/krb5/raw_testcase.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index dd733aea09b..da38a9dfa62 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -52,6 +52,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REQ, KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, + KU_FAST_FINISHED, KU_FAST_REP, KU_FAST_REQ_CHKSUM, KU_NON_KERB_CKSUM_SALT, @@ -2322,6 +2323,17 @@ class RawKerberosTest(TestCaseInTempDir): return kdc_challenge_key + def verify_ticket_checksum(self, ticket, expected_checksum, armor_key): + expected_type = expected_checksum['cksumtype'] + self.assertEqual(armor_key.ctype, expected_type) + + ticket_blob = self.der_encode(ticket, + asn1Spec=krb5_asn1.Ticket()) + checksum = self.Checksum_create(armor_key, + KU_FAST_FINISHED, + ticket_blob) + self.assertEqual(expected_checksum, checksum) + def _test_as_exchange(self, cname, realm, -- 2.25.1 From c57537fade29c4d67cddc953c3a8f4902599e173 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:42:57 +1200 Subject: [PATCH 174/645] tests/krb5: Check FAST response Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit d878bd6404d26c8be45bb2016ec206ed79d4ef6e) --- python/samba/tests/krb5/raw_testcase.py | 41 +++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index da38a9dfa62..ab1f711cde1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -67,6 +67,7 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_ETYPE_INFO, PADATA_ETYPE_INFO2, PADATA_FOR_USER, + PADATA_FX_FAST, PADATA_KDC_REQ, PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, @@ -1827,6 +1828,7 @@ class RawKerberosTest(TestCaseInTempDir): check_kdc_private_fn = kdc_exchange_dict['check_kdc_private_fn'] rep_encpart_asn1Spec = kdc_exchange_dict['rep_encpart_asn1Spec'] msg_type = kdc_exchange_dict['rep_msg_type'] + armor_key = kdc_exchange_dict['armor_key'] self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP padata = self.getElementValue(rep, 'padata') @@ -1862,6 +1864,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(encpart, 'cipher') encpart_cipher = self.getElementValue(encpart, 'cipher') + ticket_checksum = None + encpart_decryption_key = None self.assertIsNotNone(check_padata_fn) if check_padata_fn is not None: @@ -1870,6 +1874,33 @@ class RawKerberosTest(TestCaseInTempDir): check_padata_fn(kdc_exchange_dict, callback_dict, rep, padata)) + if armor_key is not None: + pa_dict = self.get_pa_dict(padata) + + if PADATA_FX_FAST in pa_dict: + fx_fast_data = pa_dict[PADATA_FX_FAST] + fast_response = self.check_fx_fast_data(kdc_exchange_dict, + fx_fast_data, + armor_key, + finished=True) + + if 'strengthen-key' in fast_response: + strengthen_key = self.EncryptionKey_import( + fast_response['strengthen-key']) + encpart_decryption_key = ( + self.generate_strengthen_reply_key( + strengthen_key, + encpart_decryption_key)) + + fast_finished = fast_response.get('finished', None) + if fast_finished is not None: + ticket_checksum = fast_finished['ticket-checksum'] + + self.check_rep_padata(kdc_exchange_dict, + callback_dict, + rep, + fast_response['padata']) + ticket_private = None self.assertIsNotNone(ticket_decryption_key) if ticket_decryption_key is not None: @@ -1908,7 +1939,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(check_kdc_private_fn) if check_kdc_private_fn is not None: check_kdc_private_fn(kdc_exchange_dict, callback_dict, - rep, ticket_private, encpart_private) + rep, ticket_private, encpart_private, + ticket_checksum) return rep @@ -1947,7 +1979,8 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict, rep, ticket_private, - encpart_private): + encpart_private, + ticket_checksum): expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] @@ -1957,6 +1990,10 @@ class RawKerberosTest(TestCaseInTempDir): ticket = self.getElementValue(rep, 'ticket') + if ticket_checksum is not None: + armor_key = kdc_exchange_dict['armor_key'] + self.verify_ticket_checksum(ticket, ticket_checksum, armor_key) + ticket_session_key = None if ticket_private is not None: self.assertElementPresent(ticket_private, 'flags') -- 2.25.1 From b23f606205d922a11def96f2c5fdae1b3c4eab27 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 15:20:44 +1200 Subject: [PATCH 175/645] tests/krb5: Add functions to get dicts of request padata Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit dc7dac95ec509d90d8372005cd7b13fabd8e64c6) --- python/samba/tests/krb5/raw_testcase.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index ab1f711cde1..2963df70003 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2371,6 +2371,17 @@ class RawKerberosTest(TestCaseInTempDir): ticket_blob) self.assertEqual(expected_checksum, checksum) + def get_outer_pa_dict(self, kdc_exchange_dict): + return self.get_pa_dict(kdc_exchange_dict['req_padata']) + + def get_fast_pa_dict(self, kdc_exchange_dict): + req_pa_dict = self.get_pa_dict(kdc_exchange_dict['fast_padata']) + + if req_pa_dict: + return req_pa_dict + + return self.get_outer_pa_dict(kdc_exchange_dict) + def _test_as_exchange(self, cname, realm, -- 2.25.1 From 693845aa93a3025eb18013b05a96f1bde5005a55 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 15:21:01 +1200 Subject: [PATCH 176/645] tests/krb5: Add methods to determine whether elements were included in the request Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 99e3b909edf27c751b959a3d0b672ddd2b7140e2) --- python/samba/tests/krb5/raw_testcase.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 2963df70003..d96cd1cfc15 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -69,6 +69,7 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_FOR_USER, PADATA_FX_FAST, PADATA_KDC_REQ, + PADATA_PAC_OPTIONS, PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, PADATA_PK_AS_REP_19 @@ -2382,6 +2383,30 @@ class RawKerberosTest(TestCaseInTempDir): return self.get_outer_pa_dict(kdc_exchange_dict) + def sent_fast(self, kdc_exchange_dict): + outer_pa_dict = self.get_outer_pa_dict(kdc_exchange_dict) + + return PADATA_FX_FAST in outer_pa_dict + + def sent_enc_challenge(self, kdc_exchange_dict): + fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict) + + return PADATA_ENCRYPTED_CHALLENGE in fast_pa_dict + + def sent_claims(self, kdc_exchange_dict): + fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict) + + if PADATA_PAC_OPTIONS not in fast_pa_dict: + return False + + pac_options = self.der_decode(fast_pa_dict[PADATA_PAC_OPTIONS], + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) + pac_options = pac_options['options'] + claims_pos = len(tuple(krb5_asn1.PACOptionFlags('claims'))) - 1 + + return (claims_pos < len(pac_options) + and pac_options[claims_pos] == '1') + def _test_as_exchange(self, cname, realm, -- 2.25.1 From 22a7433fb60132a707d6e3ff52ff233c7897e42e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:34:49 +1200 Subject: [PATCH 177/645] tests/krb5: Check encrypted-pa-data Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 0c029e780cf16a49c674593e8329eaf3b87aec69) --- python/samba/tests/krb5/raw_testcase.py | 52 ++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index d96cd1cfc15..2512ee1b99f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -72,7 +72,8 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_PAC_OPTIONS, PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, - PADATA_PK_AS_REP_19 + PADATA_PK_AS_REP_19, + PADATA_SUPPORTED_ETYPES ) import samba.tests.krb5.kcrypto as kcrypto @@ -1982,6 +1983,10 @@ class RawKerberosTest(TestCaseInTempDir): ticket_private, encpart_private, ticket_checksum): + kdc_options = kdc_exchange_dict['kdc_options'] + canon_pos = len(tuple(krb5_asn1.KDCOptions('canonicalize'))) - 1 + canonicalize = (canon_pos < len(kdc_options) + and kdc_options[canon_pos] == '1') expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] @@ -2044,6 +2049,46 @@ class RawKerberosTest(TestCaseInTempDir): expected_sname) # TODO self.assertElementMissing(encpart_private, 'caddr') + sent_claims = self.sent_claims(kdc_exchange_dict) + + if self.strict_checking: + if sent_claims or canonicalize: + self.assertElementPresent(encpart_private, + 'encrypted-pa-data') + enc_pa_dict = self.get_pa_dict( + encpart_private['encrypted-pa-data']) + if canonicalize: + self.assertIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) + + (supported_etypes,) = struct.unpack( + ' Date: Tue, 27 Jul 2021 14:05:59 +1200 Subject: [PATCH 178/645] tests/krb5: Add expected_cname_private parameter to kdc_exchange_dict This is useful for testing the 'hide client names' FAST option. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2ee87dbf08e66e1dc812430026bfe214f9f5503d) --- python/samba/tests/krb5/raw_testcase.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 2512ee1b99f..b79b84686a6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1699,6 +1699,7 @@ class RawKerberosTest(TestCaseInTempDir): def as_exchange_dict(self, expected_crealm=None, expected_cname=None, + expected_cname_private=None, expected_srealm=None, expected_sname=None, ticket_decryption_key=None, @@ -1752,6 +1753,10 @@ class RawKerberosTest(TestCaseInTempDir): 'kdc_options': kdc_options, 'outer_req': outer_req } + if expected_cname_private is not None: + kdc_exchange_dict['expected_cname_private'] = ( + expected_cname_private) + if callback_dict is None: callback_dict = {} @@ -1760,6 +1765,7 @@ class RawKerberosTest(TestCaseInTempDir): def tgs_exchange_dict(self, expected_crealm=None, expected_cname=None, + expected_cname_private=None, expected_srealm=None, expected_sname=None, ticket_decryption_key=None, @@ -1811,6 +1817,10 @@ class RawKerberosTest(TestCaseInTempDir): 'kdc_options': kdc_options, 'outer_req': outer_req } + if expected_cname_private is not None: + kdc_exchange_dict['expected_cname_private'] = ( + expected_cname_private) + if callback_dict is None: callback_dict = {} @@ -1989,11 +1999,15 @@ class RawKerberosTest(TestCaseInTempDir): and kdc_options[canon_pos] == '1') expected_crealm = kdc_exchange_dict['expected_crealm'] - expected_cname = kdc_exchange_dict['expected_cname'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] + try: + expected_cname = kdc_exchange_dict['expected_cname_private'] + except KeyError: + expected_cname = kdc_exchange_dict['expected_cname'] + ticket = self.getElementValue(rep, 'ticket') if ticket_checksum is not None: -- 2.25.1 From 95041ddc48a3acce492f7f166d9fd95eb2be776d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:18:29 +1200 Subject: [PATCH 179/645] tests/krb5: Include authdata in kdc_exchange_dict Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ea1ed63e8819926db1cf15974009601c7d37e944) --- python/samba/tests/krb5/raw_testcase.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b79b84686a6..c1dfe44dfd1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1720,6 +1720,7 @@ class RawKerberosTest(TestCaseInTempDir): armor_key=None, armor_tgt=None, armor_subkey=None, + auth_data=None, kdc_options='', outer_req=None): kdc_exchange_dict = { @@ -1750,6 +1751,7 @@ class RawKerberosTest(TestCaseInTempDir): 'armor_key': armor_key, 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, + 'auth_data': auth_data, 'kdc_options': kdc_options, 'outer_req': outer_req } @@ -1784,6 +1786,7 @@ class RawKerberosTest(TestCaseInTempDir): armor_tgt=None, armor_subkey=None, authenticator_subkey=None, + auth_data=None, body_checksum_type=None, kdc_options='', outer_req=None): @@ -1813,6 +1816,7 @@ class RawKerberosTest(TestCaseInTempDir): 'armor_key': armor_key, 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, + 'auth_data': auth_data, 'authenticator_subkey': authenticator_subkey, 'kdc_options': kdc_options, 'outer_req': outer_req @@ -2328,6 +2332,8 @@ class RawKerberosTest(TestCaseInTempDir): 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() @@ -2341,7 +2347,7 @@ class RawKerberosTest(TestCaseInTempDir): ctime=ctime, subkey=subkey_obj, seq_number=seq_number, - authorization_data=None) + authorization_data=auth_data) authenticator_blob = self.der_encode( authenticator_obj, asn1Spec=krb5_asn1.Authenticator()) -- 2.25.1 From 4aab7ff97e3684a574a40400491db0ef5ca35ada Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 15:20:09 +1200 Subject: [PATCH 180/645] tests/krb5: Add generate_simple_fast() method to generate FX-FAST padata Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 1389ba346df81c9ea1e1143c4e819212939f6aeb) --- python/samba/tests/krb5/raw_testcase.py | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c1dfe44dfd1..a557c424527 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -52,6 +52,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REQ, KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, + KU_FAST_ENC, KU_FAST_FINISHED, KU_FAST_REP, KU_FAST_REQ_CHKSUM, @@ -2309,6 +2310,39 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['preauth_etype_info2'] = etype_info2 return + def generate_simple_fast(self, + kdc_exchange_dict, + _callback_dict, + req_body, + fast_padata, + fast_armor, + checksum, + fast_options=''): + armor_key = kdc_exchange_dict['armor_key'] + + fast_req = self.KRB_FAST_REQ_create(fast_options, + fast_padata, + req_body) + fast_req = self.der_encode(fast_req, + asn1Spec=krb5_asn1.KrbFastReq()) + fast_req = self.EncryptedData_create(armor_key, + KU_FAST_ENC, + fast_req) + + fast_armored_req = self.KRB_FAST_ARMORED_REQ_create(fast_armor, + checksum, + fast_req) + + fx_fast_request = self.PA_FX_FAST_REQUEST_create(fast_armored_req) + fx_fast_request = self.der_encode( + fx_fast_request, + asn1Spec=krb5_asn1.PA_FX_FAST_REQUEST()) + + fast_padata = self.PA_DATA_create(PADATA_FX_FAST, + fx_fast_request) + + return fast_padata + def generate_ap_req(self, kdc_exchange_dict, _callback_dict, -- 2.25.1 From a22927095101015a6d6e219b641d61bde2d547ba Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:21:14 +1200 Subject: [PATCH 181/645] tests/krb5: Add check_rep_padata() method to check padata in reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 79b9aac65b7dbdc58275368eae9feb7d87bf6dab) --- python/samba/tests/krb5/raw_testcase.py | 83 ++++++++++++++----------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a557c424527..80c60682bd1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2144,13 +2144,54 @@ class RawKerberosTest(TestCaseInTempDir): expected_cname = kdc_exchange_dict['expected_cname'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] - expected_salt = kdc_exchange_dict['expected_salt'] - client_as_etypes = kdc_exchange_dict['client_as_etypes'] + expected_error_mode = kdc_exchange_dict['expected_error_mode'] + + self.assertElementEqual(rep, 'pvno', 5) + self.assertElementEqual(rep, 'msg-type', KRB_ERROR) + self.assertElementEqual(rep, 'error-code', expected_error_mode) + if self.strict_checking: + self.assertElementMissing(rep, 'ctime') + self.assertElementMissing(rep, 'cusec') + self.assertElementPresent(rep, 'stime') + self.assertElementPresent(rep, 'susec') + # error-code checked above + if self.strict_checking: + self.assertElementMissing(rep, 'crealm') + self.assertElementMissing(rep, 'cname') + self.assertElementEqualUTF8(rep, 'realm', expected_srealm) + self.assertElementEqualPrincipal(rep, 'sname', expected_sname) + self.assertElementMissing(rep, 'e-text') + if expected_error_mode == KDC_ERR_GENERIC: + self.assertElementMissing(rep, 'e-data') + return rep + edata = self.getElementValue(rep, 'e-data') + if self.strict_checking: + self.assertIsNotNone(edata) + if edata is not None: + rep_padata = self.der_decode(edata, + asn1Spec=krb5_asn1.METHOD_DATA()) + self.assertGreater(len(rep_padata), 0) + else: + rep_padata = [] + + etype_info2 = self.check_rep_padata(kdc_exchange_dict, + callback_dict, + rep, + rep_padata) + + kdc_exchange_dict['preauth_etype_info2'] = etype_info2 + + return rep + + def check_rep_padata(self, + kdc_exchange_dict, + callback_dict, + rep, + rep_padata): expected_error_mode = kdc_exchange_dict['expected_error_mode'] req_body = kdc_exchange_dict['req_body'] proposed_etypes = req_body['etype'] - - kdc_exchange_dict['preauth_etype_info2'] = None + client_as_etypes = kdc_exchange_dict.get('client_as_etypes', []) expect_etype_info2 = () expect_etype_info = False @@ -2188,34 +2229,6 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_PK_AS_REQ,) expected_patypes += (PADATA_PK_AS_REP_19,) - self.assertElementEqual(rep, 'pvno', 5) - self.assertElementEqual(rep, 'msg-type', KRB_ERROR) - self.assertElementEqual(rep, 'error-code', expected_error_mode) - if self.strict_checking: - self.assertElementMissing(rep, 'ctime') - self.assertElementMissing(rep, 'cusec') - self.assertElementPresent(rep, 'stime') - self.assertElementPresent(rep, 'susec') - # error-code checked above - if self.strict_checking: - self.assertElementMissing(rep, 'crealm') - self.assertElementMissing(rep, 'cname') - self.assertElementEqualUTF8(rep, 'realm', expected_srealm) - self.assertElementEqualPrincipal(rep, 'sname', expected_sname) - self.assertElementMissing(rep, 'e-text') - if expected_error_mode == KDC_ERR_GENERIC: - self.assertElementMissing(rep, 'e-data') - return - edata = self.getElementValue(rep, 'e-data') - if self.strict_checking: - self.assertIsNotNone(edata) - if edata is not None: - rep_padata = self.der_decode(edata, - asn1Spec=krb5_asn1.METHOD_DATA()) - self.assertGreater(len(rep_padata), 0) - else: - rep_padata = [] - if self.strict_checking: for i, patype in enumerate(expected_patypes): self.assertElementEqual(rep_padata[i], 'padata-type', patype) @@ -2265,7 +2278,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(enc_timestamp) self.assertIsNotNone(pk_as_req) self.assertIsNotNone(pk_as_rep19) - return + return None if self.strict_checking: self.assertIsNotNone(etype_info2) @@ -2288,6 +2301,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNone(salt) else: self.assertIsNotNone(salt) + expected_salt = kdc_exchange_dict['expected_salt'] if expected_salt is not None: self.assertEqual(salt, expected_salt) s2kparams = self.getElementValue(etype_info2[i], 's2kparams') @@ -2307,8 +2321,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(pk_as_req) self.assertIsNotNone(pk_as_rep19) - kdc_exchange_dict['preauth_etype_info2'] = etype_info2 - return + return etype_info2 def generate_simple_fast(self, kdc_exchange_dict, -- 2.25.1 From 0544feced6a78a4afb2636e9412b5ecae3eef604 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:35:32 +1200 Subject: [PATCH 182/645] tests/krb5: Don't expect RC4 in ETYPE-INFO2 for a non-error reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 705e45e37f4752e283a80626be10c38b29232359) --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 80c60682bd1..7a66b74adfe 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2208,7 +2208,7 @@ class RawKerberosTest(TestCaseInTempDir): if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): if etype > expected_aes_type: expected_aes_type = etype - if etype in (kcrypto.Enctype.RC4,): + if etype in (kcrypto.Enctype.RC4,) and expected_error_mode != 0: unexpect_etype_info = False if etype > expected_rc4_type: expected_rc4_type = etype -- 2.25.1 From 243487a1a78545167eebe3665d1ba1542927a6bc Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:26:06 +1200 Subject: [PATCH 183/645] tests/krb5: Remove unused variables Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 5edbabeb26e110648d4588c90843e4715ec1ac5c) --- python/samba/tests/krb5/kdc_base_test.py | 2 -- python/samba/tests/krb5/raw_testcase.py | 1 - 2 files changed, 3 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 24a1e7cfbc8..b148fa01f65 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -256,8 +256,6 @@ class KDCBaseTest(RawKerberosTest): rid = identifier.sid.split()[1] - forced_keys = dict() - net_ctx = net.Net(admin_creds) keys = {} diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 7a66b74adfe..60d35923b35 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2140,7 +2140,6 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict, rep): - expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] -- 2.25.1 From c88307575b020ba947f9cea7108c5cafa526c6b6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 11:15:00 +1200 Subject: [PATCH 184/645] tests/krb5: Add get_krbtgt_sname() method Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit dbe98005d5873440063b91e56679937149535be7) --- python/samba/tests/krb5/raw_testcase.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 60d35923b35..8351de1e6e3 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -64,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TGS_REQ_AUTH_DAT_SESSION, KU_TGS_REQ_AUTH_DAT_SUBKEY, KU_TICKET, + NT_SRV_INST, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO, PADATA_ETYPE_INFO2, @@ -2523,6 +2524,15 @@ class RawKerberosTest(TestCaseInTempDir): return (claims_pos < len(pac_options) and pac_options[claims_pos] == '1') + def get_krbtgt_sname(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + krbtgt_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + + return krbtgt_sname + def _test_as_exchange(self, cname, realm, -- 2.25.1 From 5f1b9ef294b169d6db98cb5c0ac3bd012d0f8246 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:25:39 +1200 Subject: [PATCH 185/645] tests/krb5: Check sname is krbtgt for FAST generic error Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 7a27b75621908a4a6449efaecb54eb20fa45aca0) --- python/samba/tests/krb5/raw_testcase.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8351de1e6e3..77b682e57ea 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2146,6 +2146,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_sname = kdc_exchange_dict['expected_sname'] expected_error_mode = kdc_exchange_dict['expected_error_mode'] + sent_fast = self.sent_fast(kdc_exchange_dict) + self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) self.assertElementEqual(rep, 'error-code', expected_error_mode) @@ -2159,7 +2161,11 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementMissing(rep, 'crealm') self.assertElementMissing(rep, 'cname') self.assertElementEqualUTF8(rep, 'realm', expected_srealm) - self.assertElementEqualPrincipal(rep, 'sname', expected_sname) + if sent_fast and expected_error_mode == KDC_ERR_GENERIC: + self.assertElementEqualPrincipal(rep, 'sname', + self.get_krbtgt_sname()) + else: + self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') if expected_error_mode == KDC_ERR_GENERIC: self.assertElementMissing(rep, 'e-data') -- 2.25.1 From 0997e700b78f2fcfd64efbcb07521e82d23dd4ed Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:31:39 +1200 Subject: [PATCH 186/645] tests/krb5: Check reply FAST padata if request included FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 056fb71832e7aa16132c58ff393ab8b752ef6a93) --- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 77b682e57ea..965a8f9fb00 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2177,6 +2177,21 @@ class RawKerberosTest(TestCaseInTempDir): rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA()) self.assertGreater(len(rep_padata), 0) + + if sent_fast: + self.assertEqual(1, len(rep_padata)) + rep_pa_dict = self.get_pa_dict(rep_padata) + self.assertIn(PADATA_FX_FAST, rep_pa_dict) + + armor_key = kdc_exchange_dict['armor_key'] + self.assertIsNotNone(armor_key) + fast_response = self.check_fx_fast_data( + kdc_exchange_dict, + rep_pa_dict[PADATA_FX_FAST], + armor_key, + expect_strengthen_key=False) + + rep_padata = fast_response['padata'] else: rep_padata = [] -- 2.25.1 From 24cf1667a4ae3180b402d5f7496f2674dc0cbaee Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:42:26 +1200 Subject: [PATCH 187/645] tests/krb5: Adjust reply padata checking depending on whether FAST was sent Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 44a44109db96eab08a3da3683c34446bc13b295b) --- python/samba/tests/krb5/raw_testcase.py | 62 ++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 965a8f9fb00..529d4d925e6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -44,6 +44,7 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_GENERIC, + KDC_ERR_PREAUTH_FAILED, KRB_AP_REQ, KRB_AS_REP, KRB_AS_REQ, @@ -65,10 +66,13 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TGS_REQ_AUTH_DAT_SUBKEY, KU_TICKET, NT_SRV_INST, + PADATA_ENCRYPTED_CHALLENGE, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO, PADATA_ETYPE_INFO2, PADATA_FOR_USER, + PADATA_FX_COOKIE, + PADATA_FX_ERROR, PADATA_FX_FAST, PADATA_KDC_REQ, PADATA_PAC_OPTIONS, @@ -407,6 +411,8 @@ class RawKerberosTest(TestCaseInTempDir): # obtained. cls.creds_dict = {} + cls.kdc_fast_support = False + def setUp(self): super().setUp() self.do_asn1_print = False @@ -2214,6 +2220,9 @@ class RawKerberosTest(TestCaseInTempDir): proposed_etypes = req_body['etype'] client_as_etypes = kdc_exchange_dict.get('client_as_etypes', []) + sent_fast = self.sent_fast(kdc_exchange_dict) + sent_enc_challenge = self.sent_enc_challenge(kdc_exchange_dict) + expect_etype_info2 = () expect_etype_info = False unexpect_etype_info = True @@ -2240,15 +2249,31 @@ class RawKerberosTest(TestCaseInTempDir): expect_etype_info2 += (expected_rc4_type,) expected_patypes = () + if sent_fast and expected_error_mode != 0: + expected_patypes += (PADATA_FX_ERROR,) + expected_patypes += (PADATA_FX_COOKIE,) + if expect_etype_info: self.assertGreater(len(expect_etype_info2), 0) expected_patypes += (PADATA_ETYPE_INFO,) if len(expect_etype_info2) != 0: expected_patypes += (PADATA_ETYPE_INFO2,) - expected_patypes += (PADATA_ENC_TIMESTAMP,) - expected_patypes += (PADATA_PK_AS_REQ,) - expected_patypes += (PADATA_PK_AS_REP_19,) + if expected_error_mode != KDC_ERR_PREAUTH_FAILED: + if sent_fast: + expected_patypes += (PADATA_ENCRYPTED_CHALLENGE,) + else: + expected_patypes += (PADATA_ENC_TIMESTAMP,) + + if not sent_enc_challenge: + expected_patypes += (PADATA_PK_AS_REQ,) + expected_patypes += (PADATA_PK_AS_REP_19,) + + if (self.kdc_fast_support + and not sent_fast + and not sent_enc_challenge): + expected_patypes += (PADATA_FX_FAST,) + expected_patypes += (PADATA_FX_COOKIE,) if self.strict_checking: for i, patype in enumerate(expected_patypes): @@ -2296,7 +2321,12 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNone(etype_info2) self.assertIsNone(etype_info) if self.strict_checking: - self.assertIsNotNone(enc_timestamp) + if sent_fast: + self.assertIsNotNone(enc_challenge) + self.assertIsNone(enc_timestamp) + else: + self.assertIsNotNone(enc_timestamp) + self.assertIsNone(enc_challenge) self.assertIsNotNone(pk_as_req) self.assertIsNotNone(pk_as_rep19) return None @@ -2338,9 +2368,27 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(salt) self.assertEqual(len(salt), 0) - self.assertIsNotNone(enc_timestamp) - self.assertIsNotNone(pk_as_req) - self.assertIsNotNone(pk_as_rep19) + if expected_error_mode != KDC_ERR_PREAUTH_FAILED: + if sent_fast: + self.assertIsNotNone(enc_challenge) + if self.strict_checking: + self.assertIsNone(enc_timestamp) + else: + self.assertIsNotNone(enc_timestamp) + if self.strict_checking: + self.assertIsNone(enc_challenge) + if not sent_enc_challenge: + self.assertIsNotNone(pk_as_req) + self.assertIsNotNone(pk_as_rep19) + else: + self.assertIsNone(pk_as_req) + self.assertIsNone(pk_as_rep19) + else: + if self.strict_checking: + self.assertIsNone(enc_timestamp) + self.assertIsNone(enc_challenge) + self.assertIsNone(pk_as_req) + self.assertIsNone(pk_as_rep19) return etype_info2 -- 2.25.1 From de8dd266fa5ccc230ae3a51d133dd05d4a7be0a3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:36:56 +1200 Subject: [PATCH 188/645] tests/krb5: Check PADATA-ENCRYPTED-CHALLENGE in reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 2f7919db395c24f6890ffe4ee46a5e34df95fccd) --- python/samba/tests/krb5/raw_testcase.py | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 529d4d925e6..ca967c1ac13 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -53,6 +53,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REQ, KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, + KU_ENC_CHALLENGE_KDC, KU_FAST_ENC, KU_FAST_FINISHED, KU_FAST_REP, @@ -2283,6 +2284,7 @@ class RawKerberosTest(TestCaseInTempDir): etype_info2 = None etype_info = None enc_timestamp = None + enc_challenge = None pk_as_req = None pk_as_rep19 = None for pa in rep_padata: @@ -2303,6 +2305,10 @@ class RawKerberosTest(TestCaseInTempDir): enc_timestamp = pavalue self.assertEqual(len(enc_timestamp), 0) continue + if patype == PADATA_ENCRYPTED_CHALLENGE: + self.assertIsNone(enc_challenge) + enc_challenge = pavalue + continue if patype == PADATA_PK_AS_REQ: self.assertIsNone(pk_as_req) pk_as_req = pavalue @@ -2314,6 +2320,54 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(len(pk_as_rep19), 0) continue + if enc_challenge is not None: + if not sent_enc_challenge: + self.assertEqual(len(enc_challenge), 0) + else: + armor_key = kdc_exchange_dict['armor_key'] + self.assertIsNotNone(armor_key) + + check_padata_fn = kdc_exchange_dict['check_padata_fn'] + padata = self.getElementValue(rep, 'padata') + self.assertIsNotNone(check_padata_fn) + preauth_key, _ = check_padata_fn(kdc_exchange_dict, + callback_dict, + rep, + padata) + + kdc_challenge_key = self.generate_kdc_challenge_key( + armor_key, preauth_key) + + # Ensure that the encrypted challenge FAST factor is supported + # (RFC6113 5.4.6). + if self.strict_checking: + self.assertNotEqual(len(enc_challenge), 0) + if len(enc_challenge) != 0: + encrypted_challenge = self.der_decode( + enc_challenge, + asn1Spec=krb5_asn1.EncryptedData()) + self.assertEqual(encrypted_challenge['etype'], + kdc_challenge_key.etype) + + challenge = kdc_challenge_key.decrypt( + KU_ENC_CHALLENGE_KDC, + encrypted_challenge['cipher']) + challenge = self.der_decode( + challenge, + asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) + + # Retrieve the returned timestamp. + rep_patime = challenge['patimestamp'] + self.assertIn('pausec', challenge) + + # Ensure the returned time is within five minutes of the + # current time. + rep_time = self.get_EpochFromKerberosTime(rep_patime) + current_time = time.time() + + self.assertLess(current_time - 300, rep_time) + self.assertLess(rep_time, current_time) + if all(etype not in client_as_etypes or etype not in proposed_etypes for etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128, -- 2.25.1 From d4213b15830c17aad188e7cdc66a97440a666a48 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:49:12 +1200 Subject: [PATCH 189/645] tests/krb5: Check PADATA-FX-COOKIE in reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 95b54078c2f82179283dfc397c4ec1f36d5edfe7) --- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index ca967c1ac13..23a4e70c22f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2287,6 +2287,8 @@ class RawKerberosTest(TestCaseInTempDir): enc_challenge = None pk_as_req = None pk_as_rep19 = None + fast_cookie = None + fx_fast = None for pa in rep_padata: patype = self.getElementValue(pa, 'padata-type') pavalue = self.getElementValue(pa, 'padata-value') @@ -2319,6 +2321,19 @@ class RawKerberosTest(TestCaseInTempDir): pk_as_rep19 = pavalue self.assertEqual(len(pk_as_rep19), 0) continue + if patype == PADATA_FX_COOKIE: + self.assertIsNone(fast_cookie) + fast_cookie = pavalue + self.assertIsNotNone(fast_cookie) + continue + if patype == PADATA_FX_FAST: + self.assertIsNone(fx_fast) + fx_fast = pavalue + self.assertEqual(len(fx_fast), 0) + continue + + if fast_cookie is not None: + kdc_exchange_dict['fast_cookie'] = fast_cookie if enc_challenge is not None: if not sent_enc_challenge: -- 2.25.1 From f439bff779890ac0e08c40c9222c9a343f90c083 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Jul 2021 20:49:25 +1200 Subject: [PATCH 190/645] tests/krb5: Make check_rep_padata() also work for checking TGS replies Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit ab4e7028a6ac01eab9531c8a26507a912df54278) --- python/samba/tests/krb5/raw_testcase.py | 72 +++++++++++++++---------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 23a4e70c22f..14f86fb87a8 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1789,6 +1789,7 @@ class RawKerberosTest(TestCaseInTempDir): check_rep_fn=None, check_padata_fn=None, check_kdc_private_fn=None, + expected_error_mode=0, callback_dict=None, tgt=None, armor_key=None, @@ -1820,6 +1821,7 @@ class RawKerberosTest(TestCaseInTempDir): 'check_padata_fn': check_padata_fn, 'check_kdc_private_fn': check_kdc_private_fn, 'callback_dict': callback_dict, + 'expected_error_mode': expected_error_mode, 'tgt': tgt, 'body_checksum_type': body_checksum_type, 'armor_key': armor_key, @@ -2216,6 +2218,8 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict, rep, rep_padata): + rep_msg_type = kdc_exchange_dict['rep_msg_type'] + expected_error_mode = kdc_exchange_dict['expected_error_mode'] req_body = kdc_exchange_dict['req_body'] proposed_etypes = req_body['etype'] @@ -2224,6 +2228,9 @@ class RawKerberosTest(TestCaseInTempDir): sent_fast = self.sent_fast(kdc_exchange_dict) sent_enc_challenge = self.sent_enc_challenge(kdc_exchange_dict) + if rep_msg_type == KRB_TGS_REP: + self.assertTrue(sent_fast) + expect_etype_info2 = () expect_etype_info = False unexpect_etype_info = True @@ -2254,27 +2261,32 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_FX_ERROR,) expected_patypes += (PADATA_FX_COOKIE,) - if expect_etype_info: - self.assertGreater(len(expect_etype_info2), 0) - expected_patypes += (PADATA_ETYPE_INFO,) - if len(expect_etype_info2) != 0: - expected_patypes += (PADATA_ETYPE_INFO2,) + if rep_msg_type == KRB_TGS_REP: + sent_claims = self.sent_claims(kdc_exchange_dict) + if sent_claims and expected_error_mode != 0: + expected_patypes += (PADATA_PAC_OPTIONS,) + else: + if expect_etype_info: + self.assertGreater(len(expect_etype_info2), 0) + expected_patypes += (PADATA_ETYPE_INFO,) + if len(expect_etype_info2) != 0: + expected_patypes += (PADATA_ETYPE_INFO2,) - if expected_error_mode != KDC_ERR_PREAUTH_FAILED: - if sent_fast: - expected_patypes += (PADATA_ENCRYPTED_CHALLENGE,) - else: - expected_patypes += (PADATA_ENC_TIMESTAMP,) + if expected_error_mode != KDC_ERR_PREAUTH_FAILED: + if sent_fast: + expected_patypes += (PADATA_ENCRYPTED_CHALLENGE,) + else: + expected_patypes += (PADATA_ENC_TIMESTAMP,) - if not sent_enc_challenge: - expected_patypes += (PADATA_PK_AS_REQ,) - expected_patypes += (PADATA_PK_AS_REP_19,) + if not sent_enc_challenge: + expected_patypes += (PADATA_PK_AS_REQ,) + expected_patypes += (PADATA_PK_AS_REP_19,) - if (self.kdc_fast_support - and not sent_fast - and not sent_enc_challenge): - expected_patypes += (PADATA_FX_FAST,) - expected_patypes += (PADATA_FX_COOKIE,) + if (self.kdc_fast_support + and not sent_fast + and not sent_enc_challenge): + expected_patypes += (PADATA_FX_FAST,) + expected_patypes += (PADATA_FX_COOKIE,) if self.strict_checking: for i, patype in enumerate(expected_patypes): @@ -2389,15 +2401,21 @@ class RawKerberosTest(TestCaseInTempDir): kcrypto.Enctype.RC4)): self.assertIsNone(etype_info2) self.assertIsNone(etype_info) - if self.strict_checking: - if sent_fast: - self.assertIsNotNone(enc_challenge) - self.assertIsNone(enc_timestamp) - else: - self.assertIsNotNone(enc_timestamp) - self.assertIsNone(enc_challenge) - self.assertIsNotNone(pk_as_req) - self.assertIsNotNone(pk_as_rep19) + if rep_msg_type == KRB_AS_REP: + if self.strict_checking: + if sent_fast: + self.assertIsNotNone(enc_challenge) + self.assertIsNone(enc_timestamp) + else: + self.assertIsNotNone(enc_timestamp) + self.assertIsNone(enc_challenge) + self.assertIsNotNone(pk_as_req) + self.assertIsNotNone(pk_as_rep19) + else: + self.assertIsNone(enc_timestamp) + self.assertIsNone(enc_challenge) + self.assertIsNone(pk_as_req) + self.assertIsNone(pk_as_rep19) return None if self.strict_checking: -- 2.25.1 From 61ded35b866f59acf8371fa1700d6527cd75e492 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 16:29:39 +1200 Subject: [PATCH 191/645] tests/krb5: Make generic_check_kdc_error() also work for checking TGS replies Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 29070e74baa18d94642efcd36930b9bab216e10c) --- python/samba/tests/krb5/raw_testcase.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 14f86fb87a8..8cbf3edbbab 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -45,6 +45,7 @@ from samba.tests.krb5.rfc4120_constants import ( FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_GENERIC, KDC_ERR_PREAUTH_FAILED, + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, KRB_AP_REQ, KRB_AS_REP, KRB_AS_REQ, @@ -2150,6 +2151,8 @@ class RawKerberosTest(TestCaseInTempDir): callback_dict, rep): + rep_msg_type = kdc_exchange_dict['rep_msg_type'] + expected_cname = kdc_exchange_dict['expected_cname'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] @@ -2157,6 +2160,8 @@ class RawKerberosTest(TestCaseInTempDir): sent_fast = self.sent_fast(kdc_exchange_dict) + fast_armor_type = kdc_exchange_dict['fast_armor_type'] + self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) self.assertElementEqual(rep, 'error-code', expected_error_mode) @@ -2176,7 +2181,12 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') - if expected_error_mode == KDC_ERR_GENERIC: + if (expected_error_mode in (KDC_ERR_GENERIC, + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS) + or (rep_msg_type == KRB_TGS_REP + and not sent_fast) + or (sent_fast and fast_armor_type is not None + and fast_armor_type != FX_FAST_ARMOR_AP_REQUEST)): self.assertElementMissing(rep, 'e-data') return rep edata = self.getElementValue(rep, 'e-data') -- 2.25.1 From d2c16d365deb3b8872ec8c26f0c5ffdbf19bb464 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:50:20 +1200 Subject: [PATCH 192/645] tests/krb5: Check PADATA-PAC-OPTIONS in reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 0c857f67a3a4a27aa4b799c9a61a1a1b59932c07) --- python/samba/tests/krb5/raw_testcase.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8cbf3edbbab..5016e14783c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2311,6 +2311,7 @@ class RawKerberosTest(TestCaseInTempDir): pk_as_rep19 = None fast_cookie = None fx_fast = None + pac_options = None for pa in rep_padata: patype = self.getElementValue(pa, 'padata-type') pavalue = self.getElementValue(pa, 'padata-value') @@ -2353,10 +2354,18 @@ class RawKerberosTest(TestCaseInTempDir): fx_fast = pavalue self.assertEqual(len(fx_fast), 0) continue + if patype == PADATA_PAC_OPTIONS: + self.assertIsNone(pac_options) + pac_options = pavalue + self.assertIsNotNone(pac_options) + continue if fast_cookie is not None: kdc_exchange_dict['fast_cookie'] = fast_cookie + if pac_options is not None: + self.check_pac_options_claims_support(pac_options) + if enc_challenge is not None: if not sent_enc_challenge: self.assertEqual(len(enc_challenge), 0) -- 2.25.1 From a26cd82ca76fa02614e96e9262387123b8bce1ea Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 11:50:16 +1200 Subject: [PATCH 193/645] tests/krb5: Allow generic_check_kdc_error() to check inner FAST errors Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit 66e1eb58bedf036ad25a868993d44480c4e0e055) --- python/samba/tests/krb5/raw_testcase.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 5016e14783c..4ebab367141 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -68,6 +68,7 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TGS_REQ_AUTH_DAT_SUBKEY, KU_TICKET, NT_SRV_INST, + NT_WELLKNOWN, PADATA_ENCRYPTED_CHALLENGE, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO, @@ -2149,7 +2150,8 @@ class RawKerberosTest(TestCaseInTempDir): def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, - rep): + rep, + inner=False): rep_msg_type = kdc_exchange_dict['rep_msg_type'] @@ -2173,7 +2175,10 @@ class RawKerberosTest(TestCaseInTempDir): # error-code checked above if self.strict_checking: self.assertElementMissing(rep, 'crealm') - self.assertElementMissing(rep, 'cname') + if expected_cname['name-type'] == NT_WELLKNOWN and not inner: + self.assertElementEqualPrincipal(rep, 'cname', expected_cname) + else: + self.assertElementMissing(rep, 'cname') self.assertElementEqualUTF8(rep, 'realm', expected_srealm) if sent_fast and expected_error_mode == KDC_ERR_GENERIC: self.assertElementEqualPrincipal(rep, 'sname', @@ -2186,7 +2191,8 @@ class RawKerberosTest(TestCaseInTempDir): or (rep_msg_type == KRB_TGS_REP and not sent_fast) or (sent_fast and fast_armor_type is not None - and fast_armor_type != FX_FAST_ARMOR_AP_REQUEST)): + and fast_armor_type != FX_FAST_ARMOR_AP_REQUEST) + or inner): self.assertElementMissing(rep, 'e-data') return rep edata = self.getElementValue(rep, 'e-data') -- 2.25.1 From 097a5bfb74780a39e5853026e54cf5d3b70d15ac Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 27 Jul 2021 14:49:58 +1200 Subject: [PATCH 194/645] tests/krb5: Check PADATA-FX-ERROR in reply Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit aa2c221f4e1bfc3403de857e62eaeaee1577560c) --- python/samba/tests/krb5/raw_testcase.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4ebab367141..17ef8df5daa 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2316,6 +2316,7 @@ class RawKerberosTest(TestCaseInTempDir): pk_as_req = None pk_as_rep19 = None fast_cookie = None + fast_error = None fx_fast = None pac_options = None for pa in rep_padata: @@ -2355,6 +2356,11 @@ class RawKerberosTest(TestCaseInTempDir): fast_cookie = pavalue self.assertIsNotNone(fast_cookie) continue + if patype == PADATA_FX_ERROR: + self.assertIsNone(fast_error) + fast_error = pavalue + self.assertIsNotNone(fast_error) + continue if patype == PADATA_FX_FAST: self.assertIsNone(fx_fast) fx_fast = pavalue @@ -2369,6 +2375,14 @@ class RawKerberosTest(TestCaseInTempDir): if fast_cookie is not None: kdc_exchange_dict['fast_cookie'] = fast_cookie + if fast_error is not None: + fast_error = self.der_decode(fast_error, + asn1Spec=krb5_asn1.KRB_ERROR()) + self.generic_check_kdc_error(kdc_exchange_dict, + callback_dict, + fast_error, + inner=True) + if pac_options is not None: self.check_pac_options_claims_support(pac_options) -- 2.25.1 From 75ce25df5464d53e81e15e83b9e5910a8c4d97c3 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 10 Jun 2021 09:56:58 +1200 Subject: [PATCH 195/645] initial FAST tests Currently incomplete, and tested only against MIT Kerberos. [abartlet@samba.org Originally "WIP inital FAST tests" Samba's general policy that we don't push WIP patches, we polish into a 'perfect' patch stream. However, I think there are good reasons to keep this patch distinct in this particular case. Gary is being modest in titling this WIP (now removed from the title to avoid confusion). They are not WIP in the normal sense of partially or untested code or random unfinished thoughts. The primary issue is that at that point where Gary had to finish up he had trouble getting FAST support enabled on Windows, so couldn't test against our standard reference. They are instead good, working initial tests written against the RFC and tested against Samba's AD DC in the mode backed by MIT Kerberos. This preserves clear authorship for the two distinct bodies of work, as in the next patch Joseph was able to extend and improve the tests significantly. ] Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 (cherry picked from commit b7b62957bdce9929fabd3812b9378bdbd6c12966) --- python/samba/tests/krb5/fast_tests.py | 245 ++++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 8 + source4/selftest/tests.py | 8 + 4 files changed, 262 insertions(+) create mode 100755 python/samba/tests/krb5/fast_tests.py diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py new file mode 100755 index 00000000000..c4d1c2c5d82 --- /dev/null +++ b/python/samba/tests/krb5/fast_tests.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + NT_PRINCIPAL, + NT_SRV_INST, + PADATA_FX_COOKIE, + PADATA_FX_FAST, +) +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + +global_asn1_print = False +global_hexdump = False + + +class FAST_Tests(KDCBaseTest): + ''' + ''' + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def get_padata_element(self, rep, padata_type): + rep_padata = self.der_decode( + rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) + for pa in rep_padata: + if pa['padata-type'] == padata_type: + return pa['padata-value'] + return None + + def test_fast_supported(self): + '''Confirm that the kdc supports FAST + The KDC SHOULD return an empty PA-FX-FAST in a + PREAUTH_REQUIRED error if FAST is supported + + + ''' + + # Create a user account for the test. + # + samdb = self.get_samdb() + user_name = "krb5fastusr" + (uc, dn) = self.create_account(samdb, user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + + fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) + self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + + def test_explicit_PA_FX_FAST_in_as_req(self): + ''' + Add an empty PA-FX-FAST in the initial AS-REQ + This should get rejected with a Generic error. + + ''' + + # Create a user account for the test. + # + samdb = self.get_samdb() + user_name = "krb5fastusr" + (uc, dn) = self.create_account(samdb, user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a generic error response + # response + 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]) + + x = self.PA_DATA_create(PADATA_FX_FAST, b'') + padata = [x] + rep = self.as_req(cname, sname, realm, etype, padata) + + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 60) + + def test_fast_cookie_retured_in_pre_auth(self): + '''Confirm that the kdc returns PA-FX-COOKIE + ''' + + # Create a user account for the test. + # + samdb = self.get_samdb() + user_name = "krb5fastusr" + (uc, dn) = self.create_account(samdb, user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + + fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) + self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + + fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) + self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") + + def test_ignore_fast(self): + ''' + TODO reword this + Attempt to authenticate with out FAST, i.e. ignoring the + FAST advertised in the pre-auth + ''' + + # Create a user account for the test. + # + samdb = self.get_samdb() + user_name = "krb5fastusr" + (uc, dn) = self.create_account(samdb, user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + + fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) + self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + + fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) + self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") + + # Do the next AS-REQ + padata = [self.get_enc_timestamp_pa_data(uc, rep)] + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + def test_fast(self): + ''' + Attempt to authenticate with + ''' + + # Create a user account for the test. + # + samdb = self.get_samdb() + user_name = "krb5fastusr" + (uc, dn) = self.create_account(samdb, user_name) + realm = uc.get_realm().lower() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + 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]) + + rep = self.as_req(cname, sname, realm, etype) + self.assertIsNotNone(rep) + self.assertEqual(rep['msg-type'], 30) + self.assertEqual(rep['error-code'], 25) + + fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) + self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + + fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) + self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") + + cookie = self.PA_DATA_create(PADATA_FX_COOKIE, fx_cookie) + + # Do the next AS-REQ + padata = [self.get_enc_timestamp_pa_data(uc, rep)] + padata.append(cookie) + # req = self.AS_REQ_create(padata=padata, + # kdc_options=str(kdc_options), + # cname=cname, + # realm=realm, + # sname=sname, + # from_time=None, + # till_time=till, + # renew_time=None, + # nonce=0x7fffffff, + # etypes=etypes, + # addresses=None, + # EncAuthorizationData=None, + # EncAuthorizationData_key=None, + # additional_tickets=None) + # rep = self.as_req(cname, sname, realm, etype, padata=padata) + # self.check_as_reply(rep) + + +if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 11170a2d241..29990ec9511 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -101,6 +101,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/test_smb.py', 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', 'python/samba/tests/krb5/as_req_tests.py', + 'python/samba/tests/krb5/fast_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 4e6ee93ce96..66f07cebc14 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -14,3 +14,11 @@ ^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_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_c ^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_6_c +# +# MIT specific FAST tests, +# +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_explicit_PA_FX_FAST_in_as_req\(ad_dc\) +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast\(ad_dc\) +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_cookie_retured_in_pre_auth\(ad_dc\) +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_supported\(ad_dc\) +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_ignore_fast\(ad_dc\) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index d99f08899de..d091eaaecf9 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1326,6 +1326,14 @@ planpythontestsuite( 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD' }) +planpythontestsuite( + "ad_dc", + "samba.tests.krb5.fast_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', + 'SERVICE_USERNAME': '$SERVER' + }) planpythontestsuite( "ad_dc", "samba.tests.krb5.ms_kile_client_principal_lookup_tests", -- 2.25.1 From b4e55395d96d6fded9099f5a18c9f56b6c8b24cd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 10:58:44 +1200 Subject: [PATCH 196/645] tests/krb5: Add FAST tests Example command: SERVER=addc STRICT_CHECKING=0 SMB_CONF_PATH=/dev/null \ KRB5_CONFIG=krb5.conf DOMAIN=ADDOMAIN REALM=ADDOM.SAMBA.EXAMPLE.COM \ ADMIN_USERNAME=Administrator ADMIN_PASSWORD=locDCpass1 \ PYTHONPATH=bin/python python/samba/tests/krb5/fast_tests.py Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Aug 18 23:20:14 UTC 2021 on sn-devel-184 (cherry picked from commit 984a0db00c3f2e38b568a75eb1944f4d7bb7f854) --- python/samba/tests/krb5/fast_tests.py | 1649 ++++++++++++++++++++++--- selftest/knownfail_heimdal_kdc | 54 +- selftest/knownfail_mit_kdc | 53 + source4/selftest/tests.py | 2 +- 4 files changed, 1585 insertions(+), 173 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index c4d1c2c5d82..e38b2e0a6e1 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -17,225 +17,1542 @@ # along with this program. If not, see . # -import sys +import functools import os +import sys -sys.path.insert(0, "bin/python") -os.environ["PYTHONUNBUFFERED"] = "1" +import ldb +from samba.dcerpc import security +from samba.tests.krb5.raw_testcase import ( + KerberosTicketCreds, + Krb5EncryptionKey +) from samba.tests.krb5.kdc_base_test import KDCBaseTest from samba.tests.krb5.rfc4120_constants import ( + AD_FX_FAST_ARMOR, + AD_FX_FAST_USED, AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5, + FX_FAST_ARMOR_AP_REQUEST, + KDC_ERR_ETYPE_NOSUPP, + KDC_ERR_GENERIC, + KDC_ERR_NOT_US, + KDC_ERR_PREAUTH_FAILED, + KDC_ERR_PREAUTH_REQUIRED, + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, + KRB_AS_REP, + KRB_TGS_REP, + KU_AS_REP_ENC_PART, + KU_TICKET, NT_PRINCIPAL, NT_SRV_INST, + NT_WELLKNOWN, PADATA_FX_COOKIE, PADATA_FX_FAST, + PADATA_PAC_OPTIONS ) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 +import samba.tests.krb5.kcrypto as kcrypto + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" global_asn1_print = False global_hexdump = False class FAST_Tests(KDCBaseTest): - ''' - ''' + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.user_tgt = None + cls.user_enc_part = None + cls.user_service_ticket = None + + cls.mach_tgt = None + cls.mach_enc_part = None + cls.mach_service_ticket = None def setUp(self): super().setUp() self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - def get_padata_element(self, rep, padata_type): - rep_padata = self.der_decode( - rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) - for pa in rep_padata: - if pa['padata-type'] == padata_type: - return pa['padata-value'] - return None + def test_simple(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': False + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': False, + 'gen_padata_fn': self.generate_enc_timestamp_padata + } + ]) - def test_fast_supported(self): - '''Confirm that the kdc supports FAST - The KDC SHOULD return an empty PA-FX-FAST in a - PREAUTH_REQUIRED error if FAST is supported + def test_simple_tgs(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': False, + 'gen_tgt_fn': self.get_user_tgt + } + ]) + def test_simple_tgs_wrong_principal(self): + mach_creds = self.get_mach_creds() + mach_name = mach_creds.get_username() + expected_cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[mach_name]) - ''' + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': False, + 'gen_tgt_fn': self.get_mach_tgt, + 'expected_cname': expected_cname + } + ]) - # Create a user account for the test. - # - samdb = self.get_samdb() - user_name = "krb5fastusr" - (uc, dn) = self.create_account(samdb, user_name) - realm = uc.get_realm().lower() + def test_simple_tgs_service_ticket(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_NOT_US, + 'use_fast': False, + 'gen_tgt_fn': self.get_user_service_ticket, + } + ]) - # Do the initial AS-REQ, should get a pre-authentication required - # response - 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]) + def test_simple_tgs_service_ticket_mach(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_NOT_US, + 'use_fast': False, + 'gen_tgt_fn': self.get_mach_service_ticket, + } + ]) - rep = self.as_req(cname, sname, realm, etype) - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 25) + def test_fast_no_claims(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'pac_options': '0' + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'pac_options': '0' + } + ]) - fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) - self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + def test_fast_tgs_no_claims(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'pac_options': '0' + } + ]) - def test_explicit_PA_FX_FAST_in_as_req(self): - ''' - Add an empty PA-FX-FAST in the initial AS-REQ - This should get rejected with a Generic error. + def test_fast_no_claims_or_canon(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'pac_options': '0', + 'kdc_options': '0' + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'pac_options': '0', + 'kdc_options': '0' + } + ]) - ''' + def test_fast_tgs_no_claims_or_canon(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'pac_options': '0', + 'kdc_options': '0' + } + ]) - # Create a user account for the test. - # - samdb = self.get_samdb() - user_name = "krb5fastusr" - (uc, dn) = self.create_account(samdb, user_name) - realm = uc.get_realm().lower() + def test_fast_no_canon(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'kdc_options': '0' + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'kdc_options': '0' + } + ]) - # Do the initial AS-REQ, should get a generic error response - # response - 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]) + def test_fast_tgs_no_canon(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'kdc_options': '0' + } + ]) + + def test_simple_tgs_no_etypes(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP, + 'use_fast': False, + 'gen_tgt_fn': self.get_mach_tgt, + 'etypes': () + } + ]) + + def test_fast_tgs_no_etypes(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP, + 'use_fast': True, + 'gen_tgt_fn': self.get_mach_tgt, + 'fast_armor': None, + 'etypes': () + } + ]) + + def test_simple_no_etypes(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP, + 'use_fast': False, + 'etypes': () + } + ]) + + def test_simple_fast_no_etypes(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'etypes': () + } + ]) + + def test_empty_fast(self): + # Add an empty PA-FX-FAST in the initial AS-REQ. This should get + # rejected with a Generic error. + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'gen_fast_fn': self.generate_empty_fast, + 'fast_armor': None, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_unknown_critical_option(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, + 'use_fast': True, + 'fast_options': '001', # unsupported critical option + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_unarmored_as_req(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'fast_armor': None, # no armor, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_invalid_armor_type(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_FAILED, + 'use_fast': True, + 'fast_armor': 0, # invalid armor type + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_invalid_armor_type2(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_FAILED, + 'use_fast': True, + 'fast_armor': 2, # invalid armor type + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_encrypted_challenge(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_encrypted_challenge_wrong_key(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_FAILED, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata_wrong_key, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_encrypted_challenge_wrong_key_kdc(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_FAILED, + 'use_fast': True, + 'gen_padata_fn': + self.generate_enc_challenge_padata_wrong_key_kdc, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_encrypted_challenge_clock_skew(self): + # The KDC is supposed to confirm that the timestamp is within its + # current clock skew, and return KRB_APP_ERR_SKEW if it is not (RFC6113 + # 5.4.6). However, Windows accepts a skewed timestamp in the encrypted + # challenge. + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': functools.partial( + self.generate_enc_challenge_padata, + skew=10000), + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_invalid_tgt(self): + # The armor ticket 'sname' field is required to identify the target + # realm TGS (RFC6113 5.4.1.1). However, Windows will still accept a + # service ticket identifying a different server principal. + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_user_service_ticket + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_user_service_ticket + # ticket not identifying TGS of current + # realm + } + ]) + + def test_fast_invalid_tgt_mach(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_service_ticket + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_service_ticket + # ticket not identifying TGS of current + # realm + } + ]) + + def test_fast_enc_timestamp(self): + # Provide ENC-TIMESTAMP as FAST padata when we should be providing + # ENCRYPTED-CHALLENGE - ensure that we get PREAUTH_REQUIRED. + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_timestamp_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_tgs(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None + } + ]) + + def test_fast_tgs_armor(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST + } + ]) + + def test_fast_outer_wrong_realm(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'realm': 'TEST' # should be ignored + } + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'realm': 'TEST' # should be ignored + } + } + ]) + + def test_fast_tgs_outer_wrong_realm(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'outer_req': { + 'realm': 'TEST' # should be ignored + } + } + ]) + + def test_fast_outer_wrong_nonce(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'nonce': '123' # should be ignored + } + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'nonce': '123' # should be ignored + } + } + ]) + + def test_fast_tgs_outer_wrong_nonce(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'outer_req': { + 'nonce': '123' # should be ignored + } + } + ]) + + def test_fast_outer_wrong_flags(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'kdc-options': '11111111111111111' # should be ignored + } + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'kdc-options': '11111111111111111' # should be ignored + } + } + ]) + + def test_fast_tgs_outer_wrong_flags(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'outer_req': { + 'kdc-options': '11111111111111111' # should be ignored + } + } + ]) + + def test_fast_outer_wrong_till(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'till': '15000101000000Z' # should be ignored + } + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'till': '15000101000000Z' # should be ignored + } + } + ]) + + def test_fast_tgs_outer_wrong_till(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'outer_req': { + 'till': '15000101000000Z' # should be ignored + } + } + ]) + + def test_fast_authdata_fast_used(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_authdata_fn': self.generate_fast_used_auth_data, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None + } + ]) + + def test_fast_authdata_fast_not_used(self): + # The AD-fx-fast-used authdata type can be included in the + # authenticator or the TGT authentication data to indicate that FAST + # must be used. The KDC must return KRB_APP_ERR_MODIFIED if it receives + # this authdata type in a request not using FAST (RFC6113 5.4.2). + self._run_test_sequence([ + # This request works without FAST. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': False, + 'gen_tgt_fn': self.get_user_tgt + }, + # Add the 'FAST used' auth data and it now fails. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + # should be KRB_APP_ERR_MODIFIED + 'use_fast': False, + 'gen_authdata_fn': self.generate_fast_used_auth_data, + 'gen_tgt_fn': self.get_user_tgt + } + ]) + + def test_fast_ad_fx_fast_armor(self): + # If the authenticator or TGT authentication data contains the + # AD-fx-fast-armor authdata type, the KDC must reject the request + # (RFC6113 5.4.1.1). + self._run_test_sequence([ + # This request works. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None + }, + # Add the 'FAST armor' auth data and it now fails. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'gen_authdata_fn': self.generate_fast_armor_auth_data, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None + } + ]) + + def test_fast_ad_fx_fast_armor2(self): + # Show that we can still use the AD-fx-fast-armor authorization data in + # FAST armor tickets. + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'gen_authdata_fn': self.generate_fast_armor_auth_data, + # include the auth data in the FAST armor. + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + } + ]) + + def test_fast_ad_fx_fast_armor_ticket(self): + # If the authenticator or TGT authentication data contains the + # AD-fx-fast-armor authdata type, the KDC must reject the request + # (RFC6113 5.4.2). + self._run_test_sequence([ + # This request works. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None + }, + # Add AD-fx-fast-armor authdata element to user TGT. This request + # fails. + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'gen_tgt_fn': self.gen_tgt_fast_armor_auth_data, + 'fast_armor': None + } + ]) + + def test_fast_ad_fx_fast_armor_ticket2(self): + self._run_test_sequence([ + # Show that we can still use the modified ticket as armor. + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.gen_tgt_fast_armor_auth_data + } + ]) + + def test_fast_tgs_service_ticket(self): + # Try to use a non-TGT ticket to establish an armor key, which fails + # (RFC6113 5.4.2). + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_NOT_US, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_service_ticket, # fails + 'fast_armor': None + } + ]) + + def test_fast_tgs_service_ticket_mach(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_NOT_US, # fails + 'use_fast': True, + 'gen_tgt_fn': self.get_mach_service_ticket, + 'fast_armor': None + } + ]) + + def test_simple_tgs_no_subkey(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': False, + 'gen_tgt_fn': self.get_user_tgt, + 'include_subkey': False + } + ]) + + def test_fast_tgs_no_subkey(self): + # Show that omitting the subkey in the TGS-REQ authenticator fails + # (RFC6113 5.4.2). + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'include_subkey': False + } + ]) + + def test_fast_hide_client_names(self): + user_creds = self.get_client_creds() + user_name = user_creds.get_username() + user_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + + expected_cname = self.PrincipalName_create( + name_type=NT_WELLKNOWN, names=['WELLKNOWN', 'ANONYMOUS']) + + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'fast_options': '01', # hide client names + 'expected_cname': expected_cname + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'fast_options': '01', # hide client names + 'expected_cname': expected_cname, + 'expected_cname_private': user_cname + } + ]) + + def test_fast_tgs_hide_client_names(self): + user_creds = self.get_client_creds() + user_name = user_creds.get_username() + user_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + + expected_cname = self.PrincipalName_create( + name_type=NT_WELLKNOWN, names=['WELLKNOWN', 'ANONYMOUS']) + + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'fast_options': '01', # hide client names + 'expected_cname': expected_cname, + 'expected_cname_private': user_cname + } + ]) + + def test_fast_encrypted_challenge_replay(self): + # The KDC is supposed to check that encrypted challenges are not + # replays (RFC6113 5.4.6), but timestamps may be reused; an encrypted + # challenge is only considered a replay if the ciphertext is identical + # to a previous challenge. Windows does not perform this check. + + class GenerateEncChallengePadataReplay: + def __init__(replay): + replay._padata = None + + def __call__(replay, key, armor_key): + if replay._padata is None: + client_challenge_key = ( + self.generate_client_challenge_key(armor_key, key)) + replay._padata = self.get_challenge_pa_data( + client_challenge_key) + + return replay._padata + + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': GenerateEncChallengePadataReplay(), + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'repeat': 2 + } + ]) + + def generate_enc_timestamp_padata(self, key, _armor_key): + return self.get_enc_timestamp_pa_data_from_key(key) + + def generate_enc_challenge_padata(self, key, armor_key, skew=0): + client_challenge_key = ( + self.generate_client_challenge_key(armor_key, key)) + return self.get_challenge_pa_data(client_challenge_key, skew=skew) + + def generate_enc_challenge_padata_wrong_key_kdc(self, key, armor_key): + kdc_challenge_key = ( + self.generate_kdc_challenge_key(armor_key, key)) + return self.get_challenge_pa_data(kdc_challenge_key) + + def generate_enc_challenge_padata_wrong_key(self, key, _armor_key): + return self.get_challenge_pa_data(key) + + def generate_empty_fast(self, + _kdc_exchange_dict, + _callback_dict, + _req_body, + _fast_padata, + _fast_armor, + _checksum, + _fast_options=''): + fast_padata = self.PA_DATA_create(PADATA_FX_FAST, b'') + + return fast_padata + + def _run_test_sequence(self, test_sequence): + if self.strict_checking: + self.check_kdc_fast_support() + + kdc_options_default = str(krb5_asn1.KDCOptions('forwardable,' + 'renewable,' + 'canonicalize,' + 'renewable-ok')) + + pac_request = self.get_pa_pac_request() + + client_creds = self.get_client_creds() + target_creds = self.get_service_creds() + krbtgt_creds = self.get_krbtgt_creds() + + client_username = client_creds.get_username() + client_realm = client_creds.get_realm() + client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_username]) + + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + krbtgt_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + krbtgt_decryption_key = self.TicketDecryptionKey_from_creds( + krbtgt_creds) + + target_username = target_creds.get_username()[:-1] + target_realm = target_creds.get_realm() + target_service = 'host' + target_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[target_service, target_username]) + target_decryption_key = self.TicketDecryptionKey_from_creds( + target_creds, etype=kcrypto.Enctype.RC4) + + fast_cookie = None + preauth_etype_info2 = None + + preauth_key = None + + for kdc_dict in test_sequence: + rep_type = kdc_dict.pop('rep_type') + self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP)) + + expected_error_mode = kdc_dict.pop('expected_error_mode') + self.assertIn(expected_error_mode, range(240)) + + use_fast = kdc_dict.pop('use_fast') + self.assertIs(type(use_fast), bool) + + if use_fast: + self.assertIn('fast_armor', kdc_dict) + fast_armor_type = kdc_dict.pop('fast_armor') + + if fast_armor_type is not None: + self.assertIn('gen_armor_tgt_fn', kdc_dict) + elif expected_error_mode != KDC_ERR_GENERIC: + self.assertNotIn('gen_armor_tgt_fn', kdc_dict) + + gen_armor_tgt_fn = kdc_dict.pop('gen_armor_tgt_fn', None) + if gen_armor_tgt_fn is not None: + armor_tgt = gen_armor_tgt_fn() + else: + armor_tgt = None - x = self.PA_DATA_create(PADATA_FX_FAST, b'') - padata = [x] - rep = self.as_req(cname, sname, realm, etype, padata) + fast_options = kdc_dict.pop('fast_options', '') + else: + fast_armor_type = None + armor_tgt = None - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 60) + self.assertNotIn('fast_options', kdc_dict) + fast_options = None - def test_fast_cookie_retured_in_pre_auth(self): - '''Confirm that the kdc returns PA-FX-COOKIE - ''' + if rep_type == KRB_TGS_REP: + gen_tgt_fn = kdc_dict.pop('gen_tgt_fn') + tgt = gen_tgt_fn() + else: + self.assertNotIn('gen_tgt_fn', kdc_dict) + tgt = None + + if expected_error_mode != 0: + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) + + cname = client_cname if rep_type == KRB_AS_REP else None + crealm = client_realm + + if rep_type == KRB_AS_REP: + sname = krbtgt_sname + srealm = krbtgt_realm + else: # KRB_TGS_REP + sname = target_sname + srealm = target_realm + + expected_cname = kdc_dict.pop('expected_cname', client_cname) + expected_cname_private = kdc_dict.pop('expected_cname_private', + None) + expected_crealm = kdc_dict.pop('expected_crealm', client_realm) + expected_sname = kdc_dict.pop('expected_sname', sname) + expected_srealm = kdc_dict.pop('expected_srealm', srealm) + + expected_salt = client_creds.get_salt() + + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + if rep_type == KRB_AS_REP: + if use_fast: + armor_key = self.generate_armor_key(authenticator_subkey, + armor_tgt.session_key) + armor_subkey = authenticator_subkey + else: + armor_key = None + armor_subkey = authenticator_subkey + else: # KRB_TGS_REP + if fast_armor_type is not None: + armor_subkey = self.RandomKey(kcrypto.Enctype.AES256) + explicit_armor_key = self.generate_armor_key( + armor_subkey, + armor_tgt.session_key) + armor_key = kcrypto.cf2(explicit_armor_key.key, + authenticator_subkey.key, + b'explicitarmor', + b'tgsarmor') + armor_key = Krb5EncryptionKey(armor_key, None) + else: + armor_key = self.generate_armor_key(authenticator_subkey, + tgt.session_key) + armor_subkey = authenticator_subkey + + if not kdc_dict.pop('include_subkey', True): + authenticator_subkey = None + + if use_fast: + generate_fast_fn = kdc_dict.pop('gen_fast_fn', None) + if generate_fast_fn is None: + generate_fast_fn = functools.partial( + self.generate_simple_fast, + fast_options=fast_options) + else: + generate_fast_fn = None + + generate_fast_armor_fn = ( + self.generate_ap_req + if fast_armor_type is not None + else None) + + def _generate_padata_copy(_kdc_exchange_dict, + _callback_dict, + req_body, + padata): + return padata, req_body + + def _check_padata_preauth_key(_kdc_exchange_dict, + _callback_dict, + _rep, + _padata): + as_rep_usage = KU_AS_REP_ENC_PART + return preauth_key, as_rep_usage + + pac_options = kdc_dict.pop('pac_options', '1') # claims support + pac_options = self.get_pa_pac_options(pac_options) + + kdc_options = kdc_dict.pop('kdc_options', kdc_options_default) + + if rep_type == KRB_AS_REP: + padata = [pac_request, pac_options] + else: + padata = [pac_options] + + gen_padata_fn = kdc_dict.pop('gen_padata_fn', None) + if gen_padata_fn is not None: + self.assertEqual(KRB_AS_REP, rep_type) + self.assertIsNotNone(preauth_etype_info2) + + preauth_key = self.PasswordKey_from_etype_info2( + client_creds, + preauth_etype_info2[0], + client_creds.get_kvno()) + gen_padata = gen_padata_fn(preauth_key, armor_key) + padata.insert(0, gen_padata) + else: + preauth_key = None + + if rep_type == KRB_AS_REP: + check_padata_fn = _check_padata_preauth_key + else: + check_padata_fn = self.check_simple_tgs_padata + + if use_fast: + inner_padata = padata + outer_padata = [] + else: + inner_padata = [] + outer_padata = padata + + if use_fast and fast_cookie is not None: + outer_padata.append(fast_cookie) + + generate_fast_padata_fn = (functools.partial(_generate_padata_copy, + padata=inner_padata) + if inner_padata else None) + generate_padata_fn = (functools.partial(_generate_padata_copy, + padata=outer_padata) + if outer_padata else None) + + gen_authdata_fn = kdc_dict.pop('gen_authdata_fn', None) + if gen_authdata_fn is not None: + auth_data = [gen_authdata_fn()] + else: + auth_data = None + + if not use_fast: + self.assertNotIn('outer_req', kdc_dict) + outer_req = kdc_dict.pop('outer_req', None) + + if rep_type == KRB_AS_REP: + kdc_exchange_dict = self.as_exchange_dict( + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_cname_private=expected_cname_private, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + ticket_decryption_key=krbtgt_decryption_key, + generate_fast_fn=generate_fast_fn, + generate_fast_armor_fn=generate_fast_armor_fn, + generate_fast_padata_fn=generate_fast_padata_fn, + fast_armor_type=fast_armor_type, + generate_padata_fn=generate_padata_fn, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, + check_padata_fn=check_padata_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + callback_dict={}, + expected_error_mode=expected_error_mode, + client_as_etypes=etypes, + expected_salt=expected_salt, + authenticator_subkey=authenticator_subkey, + auth_data=auth_data, + armor_key=armor_key, + armor_tgt=armor_tgt, + armor_subkey=armor_subkey, + kdc_options=kdc_options, + outer_req=outer_req) + else: # KRB_TGS_REP + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_cname_private=expected_cname_private, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + ticket_decryption_key=target_decryption_key, + generate_fast_fn=generate_fast_fn, + generate_fast_armor_fn=generate_fast_armor_fn, + generate_fast_padata_fn=generate_fast_padata_fn, + fast_armor_type=fast_armor_type, + generate_padata_fn=generate_padata_fn, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, + check_padata_fn=check_padata_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error_mode, + callback_dict={}, + tgt=tgt, + armor_key=armor_key, + armor_tgt=armor_tgt, + armor_subkey=armor_subkey, + authenticator_subkey=authenticator_subkey, + auth_data=auth_data, + body_checksum_type=None, + kdc_options=kdc_options, + outer_req=outer_req) + + repeat = kdc_dict.pop('repeat', 1) + for _ in range(repeat): + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=cname, + realm=crealm, + sname=sname, + etypes=etypes) + if expected_error_mode == 0: + self.check_reply(rep, rep_type) + + fast_cookie = None + preauth_etype_info2 = None + else: + self.check_error_rep(rep, expected_error_mode) + + if 'fast_cookie' in kdc_exchange_dict: + fast_cookie = self.create_fast_cookie( + kdc_exchange_dict['fast_cookie']) + else: + fast_cookie = None + + if expected_error_mode == KDC_ERR_PREAUTH_REQUIRED: + preauth_etype_info2 = ( + kdc_exchange_dict['preauth_etype_info2']) + else: + preauth_etype_info2 = None + + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + + def generate_fast_armor_auth_data(self): + auth_data = self.AuthorizationData_create(AD_FX_FAST_ARMOR, b'') + + return auth_data + + def generate_fast_used_auth_data(self): + auth_data = self.AuthorizationData_create(AD_FX_FAST_USED, b'') + + return auth_data + + def gen_tgt_fast_armor_auth_data(self): + user_tgt = self.get_user_tgt() + + ticket_decryption_key = user_tgt.decryption_key + + tgt_encpart = self.getElementValue(user_tgt.ticket, 'enc-part') + self.assertElementEqual(tgt_encpart, 'etype', + ticket_decryption_key.etype) + self.assertElementKVNO(tgt_encpart, 'kvno', + ticket_decryption_key.kvno) + tgt_cipher = self.getElementValue(tgt_encpart, 'cipher') + tgt_decpart = ticket_decryption_key.decrypt(KU_TICKET, tgt_cipher) + tgt_private = self.der_decode(tgt_decpart, + asn1Spec=krb5_asn1.EncTicketPart()) + + auth_data = self.generate_fast_armor_auth_data() + tgt_private['authorization-data'].append(auth_data) + + # Re-encrypt the user TGT. + tgt_private_new = self.der_encode( + tgt_private, + asn1Spec=krb5_asn1.EncTicketPart()) + tgt_encpart = self.EncryptedData_create(ticket_decryption_key, + KU_TICKET, + tgt_private_new) + user_ticket = user_tgt.ticket.copy() + user_ticket['enc-part'] = tgt_encpart + + user_tgt = KerberosTicketCreds( + user_ticket, + session_key=user_tgt.session_key, + crealm=user_tgt.crealm, + cname=user_tgt.cname, + srealm=user_tgt.srealm, + sname=user_tgt.sname, + decryption_key=user_tgt.decryption_key, + ticket_private=tgt_private, + encpart_private=user_tgt.encpart_private) + + # Use our modifed TGT to replace the one in the request. + return user_tgt + + def create_fast_cookie(self, cookie): + self.assertIsNotNone(cookie) + if self.strict_checking: + self.assertNotEqual(0, len(cookie)) + + return self.PA_DATA_create(PADATA_FX_COOKIE, cookie) + + def get_pa_pac_request(self, request_pac=True): + pac_request = self.KERB_PA_PAC_REQUEST_create(request_pac) + + return pac_request + + def get_pa_pac_options(self, options): + pac_options = self.PA_PAC_OPTIONS_create(options) + pac_options = self.der_encode(pac_options, + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) + pac_options = self.PA_DATA_create(PADATA_PAC_OPTIONS, pac_options) + + return pac_options + + def check_kdc_fast_support(self): + # Check that the KDC supports FAST - # Create a user account for the test. - # samdb = self.get_samdb() - user_name = "krb5fastusr" - (uc, dn) = self.create_account(samdb, user_name) - realm = uc.get_realm().lower() - # Do the initial AS-REQ, should get a pre-authentication required - # response + krbtgt_rid = 502 + krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid) + + res = samdb.search(base='' % krbtgt_sid, + scope=ldb.SCOPE_BASE, + attrs=['msDS-SupportedEncryptionTypes']) + + krbtgt_etypes = int(res[0]['msDS-SupportedEncryptionTypes'][0]) + + self.assertTrue( + security.KERB_ENCTYPE_FAST_SUPPORTED & krbtgt_etypes) + self.assertTrue( + security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED & krbtgt_etypes) + self.assertTrue( + security.KERB_ENCTYPE_CLAIMS_SUPPORTED & krbtgt_etypes) + + def get_service_ticket(self, tgt, target_creds, service='host'): 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]) - - rep = self.as_req(cname, sname, realm, etype) - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 25) - - fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) - self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") - - fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) - self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") - - def test_ignore_fast(self): - ''' - TODO reword this - Attempt to authenticate with out FAST, i.e. ignoring the - FAST advertised in the pre-auth - ''' - - # Create a user account for the test. - # - samdb = self.get_samdb() - user_name = "krb5fastusr" - (uc, dn) = self.create_account(samdb, user_name) - realm = uc.get_realm().lower() - # Do the initial AS-REQ, should get a pre-authentication required - # response + key = tgt.session_key + ticket = tgt.ticket + + cname = tgt.cname + realm = tgt.crealm + + target_name = target_creds.get_username()[:-1] + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[service, target_name]) + + rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype) + + service_ticket = rep['ticket'] + + ticket_etype = service_ticket['enc-part']['etype'] + target_key = self.TicketDecryptionKey_from_creds(target_creds, + etype=ticket_etype) + + session_key = self.EncryptionKey_import(enc_part['key']) + + service_ticket_creds = KerberosTicketCreds(service_ticket, + session_key, + crealm=realm, + cname=cname, + srealm=realm, + sname=sname, + decryption_key=target_key) + + return service_ticket_creds + + def get_tgt(self, creds): + user_name = creds.get_username() + 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]) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create(name_type=NT_SRV_INST, + names=['krbtgt', realm]) - rep = self.as_req(cname, sname, realm, etype) - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 25) + till = self.get_KerberosTime(offset=36000) - fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) - self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") + krbtgt_creds = self.get_krbtgt_creds() + ticket_decryption_key = ( + self.TicketDecryptionKey_from_creds(krbtgt_creds)) - fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) - self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") + kdc_options = str(krb5_asn1.KDCOptions('forwardable,' + 'renewable,' + 'canonicalize,' + 'renewable-ok')) - # Do the next AS-REQ - padata = [self.get_enc_timestamp_pa_data(uc, rep)] - rep = self.as_req(cname, sname, realm, etype, padata=padata) + pac_request = self.get_pa_pac_request() + pac_options = self.get_pa_pac_options('1') # supports claims + + padata = [pac_request, pac_options] + + rep, kdc_exchange_dict = self._test_as_exchange( + cname=cname, + realm=realm, + sname=sname, + till=till, + client_as_etypes=etype, + expected_error_mode=KDC_ERR_PREAUTH_REQUIRED, + expected_crealm=realm, + expected_cname=cname, + expected_srealm=realm, + expected_sname=sname, + expected_salt=salt, + etypes=etype, + padata=padata, + kdc_options=kdc_options, + preauth_key=None, + ticket_decryption_key=ticket_decryption_key) + self.check_pre_authentication(rep) + + etype_info2 = kdc_exchange_dict['preauth_etype_info2'] + + preauth_key = self.PasswordKey_from_etype_info2(creds, + etype_info2[0], + creds.get_kvno()) + + ts_enc_padata = self.get_enc_timestamp_pa_data(creds, rep) + + padata = [ts_enc_padata, pac_request, pac_options] + + 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, + sname=sname, + till=till, + client_as_etypes=etype, + expected_error_mode=0, + expected_crealm=expected_realm, + expected_cname=cname, + expected_srealm=expected_realm, + expected_sname=expected_sname, + expected_salt=salt, + etypes=etype, + padata=padata, + kdc_options=kdc_options, + preauth_key=preauth_key, + ticket_decryption_key=ticket_decryption_key) self.check_as_reply(rep) - def test_fast(self): - ''' - Attempt to authenticate with - ''' + tgt = rep['ticket'] - # Create a user account for the test. - # - samdb = self.get_samdb() - user_name = "krb5fastusr" - (uc, dn) = self.create_account(samdb, user_name) - realm = uc.get_realm().lower() + enc_part = self.get_as_rep_enc_data(preauth_key, rep) + session_key = self.EncryptionKey_import(enc_part['key']) - # Do the initial AS-REQ, should get a pre-authentication required - # response - 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]) - - rep = self.as_req(cname, sname, realm, etype) - self.assertIsNotNone(rep) - self.assertEqual(rep['msg-type'], 30) - self.assertEqual(rep['error-code'], 25) - - fx_fast = self.get_padata_element(rep, PADATA_FX_FAST) - self.assertIsNotNone(fx_fast, "No PADATA_FX_FAST element") - - fx_cookie = self.get_padata_element(rep, PADATA_FX_COOKIE) - self.assertIsNotNone(fx_cookie, "No PADATA_FX_COOKIE element") - - cookie = self.PA_DATA_create(PADATA_FX_COOKIE, fx_cookie) - - # Do the next AS-REQ - padata = [self.get_enc_timestamp_pa_data(uc, rep)] - padata.append(cookie) - # req = self.AS_REQ_create(padata=padata, - # kdc_options=str(kdc_options), - # cname=cname, - # realm=realm, - # sname=sname, - # from_time=None, - # till_time=till, - # renew_time=None, - # nonce=0x7fffffff, - # etypes=etypes, - # addresses=None, - # EncAuthorizationData=None, - # EncAuthorizationData_key=None, - # additional_tickets=None) - # rep = self.as_req(cname, sname, realm, etype, padata=padata) - # self.check_as_reply(rep) + ticket_creds = KerberosTicketCreds( + tgt, + session_key, + crealm=realm, + cname=cname, + srealm=realm, + sname=sname, + decryption_key=ticket_decryption_key) + + return ticket_creds, enc_part + + def get_mach_tgt(self): + if self.mach_tgt is None: + mach_creds = self.get_mach_creds() + type(self).mach_tgt, type(self).mach_enc_part = ( + self.get_tgt(mach_creds)) + + return self.mach_tgt + + def get_user_tgt(self): + if self.user_tgt is None: + user_creds = self.get_client_creds() + type(self).user_tgt, type(self).user_enc_part = ( + self.get_tgt(user_creds)) + + return self.user_tgt + + def get_user_service_ticket(self): + if self.user_service_ticket is None: + user_tgt = self.get_user_tgt() + service_creds = self.get_service_creds() + type(self).user_service_ticket = ( + self.get_service_ticket(user_tgt, service_creds)) + + return self.user_service_ticket + + def get_mach_service_ticket(self): + if self.mach_service_ticket is None: + mach_tgt = self.get_mach_tgt() + service_creds = self.get_service_creds() + type(self).mach_service_ticket = ( + self.get_service_ticket(mach_tgt, service_creds)) + + return self.mach_service_ticket if __name__ == "__main__": diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 66f07cebc14..02a3db1a3cd 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -15,10 +15,52 @@ ^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_c ^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_6_c # -# MIT specific FAST tests, +# FAST tests # -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_explicit_PA_FX_FAST_in_as_req\(ad_dc\) -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast\(ad_dc\) -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_cookie_retured_in_pre_auth\(ad_dc\) -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_supported\(ad_dc\) -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_ignore_fast\(ad_dc\) +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_empty_fast.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_not_used.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_used.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_enc_timestamp.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_clock_skew.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_replay.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key_kdc.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_hide_client_names.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims_or_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_flags.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_nonce.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_realm.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_till.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_armor.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_hide_client_names.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_subkey.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_flags.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_nonce.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_realm.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_till.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_unknown_critical_option.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_subkey.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_wrong_principal.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index fffa5c3cd7e..0e302343111 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -647,3 +647,56 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # # fl2000dc doesn't support AES ^samba4.krb5.kdc.*as-req-aes.*fl2000dc +# +# FAST tests +# +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_empty_fast.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_not_used.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_used.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_enc_timestamp.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_clock_skew.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_replay.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key_kdc.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_hide_client_names.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type2.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims_or_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_flags.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_nonce.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_realm.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_till.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_armor.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_hide_client_names.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims_or_canon.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_subkey.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_flags.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_nonce.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_realm.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_till.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_unknown_critical_option.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_etypes.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_subkey.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_wrong_principal.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index d091eaaecf9..4de8f84f72e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1332,7 +1332,7 @@ planpythontestsuite( environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'SERVICE_USERNAME': '$SERVER' + 'STRICT_CHECKING': '0', }) planpythontestsuite( "ad_dc", -- 2.25.1 From bd129ab664d4d68d6e1e67fa96a1620ff3a49a49 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Sep 2021 17:23:32 +1200 Subject: [PATCH 197/645] selftest: Remove knownfail for no_etypes FAST tests These test pass because b3ee034b4d457607ef25a5b01da64e1eaf5906dd (s4:kdc: prefer newer enctypes for preauth responses) is not included in the 4.13 backport. Signed-off-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 --- selftest/knownfail_heimdal_kdc | 3 --- 1 file changed, 3 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 02a3db1a3cd..9a61f476469 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -47,7 +47,6 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_armor.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_hide_client_names.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_subkey.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_flags.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_nonce.ad_dc @@ -56,9 +55,7 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket_mach.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_unknown_critical_option.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_subkey.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc -- 2.25.1 From c1389f0e25daf838331fcc19e1f8dd0e02933a64 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 27 Aug 2021 13:35:59 +1200 Subject: [PATCH 198/645] tests/krb5: Make e-data checking less strict Without this additional 'self.strict_checking' check, the tests in the following patches do not get far enough to trigger a crash with the MIT KDC, instead failing when obtaining a TGT for the user or machine. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider [abartlet@samba.org Backported from commit 79dda329f2a8382f1e46b50f4b9692e78d687826 as knownfail needed splitting into only failing in the Heimdal case due likely because b3ee034b4d457607ef25a5b01da64e1eaf5906dd (s4:kdc: prefer newer enctypes for preauth responses) is not included in the 4.14 backport. ] --- python/samba/tests/krb5/raw_testcase.py | 5 +- .../knownfail.d/samba.tests.krb5.as_req_tests | 54 --- selftest/knownfail_heimdal_kdc | 57 +++ selftest/knownfail_mit_kdc | 341 ------------------ 4 files changed, 60 insertions(+), 397 deletions(-) delete mode 100644 selftest/knownfail.d/samba.tests.krb5.as_req_tests diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 17ef8df5daa..22f64f25f14 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2504,8 +2504,9 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertIsNone(enc_challenge) if not sent_enc_challenge: - self.assertIsNotNone(pk_as_req) - self.assertIsNotNone(pk_as_rep19) + if self.strict_checking: + self.assertIsNotNone(pk_as_req) + self.assertIsNotNone(pk_as_rep19) else: self.assertIsNone(pk_as_req) self.assertIsNone(pk_as_rep19) diff --git a/selftest/knownfail.d/samba.tests.krb5.as_req_tests b/selftest/knownfail.d/samba.tests.krb5.as_req_tests deleted file mode 100644 index 35375dfcc8e..00000000000 --- a/selftest/knownfail.d/samba.tests.krb5.as_req_tests +++ /dev/null @@ -1,54 +0,0 @@ -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 9a61f476469..6a36640233e 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -15,6 +15,63 @@ ^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_c ^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_6_c # +# Heimdal (not MIT) still fails these after 'Make e-data checking less strict' +# +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc +# # FAST tests # ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_empty_fast.ad_dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 0e302343111..025504c1268 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -291,356 +291,15 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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_c ^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_6_c # -# MIT currently fails the test_as_req_enc_timestamp test. -# -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_enc_timestamp.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_enc_timestamp.fl2008r2dc -# # MIT currently fails some as_req_no_preauth tests. # ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_dummy_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_aes128_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_aes256_rc4_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_pac_True.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_pac_True.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_False.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_False.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2008r2dc # Differences in our KDC compared to windows # ^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally -- 2.25.1 From 61576e53a9439704f77efdbf155adfb670cd9e3f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 14:43:53 +1200 Subject: [PATCH 199/645] tests/krb5: Make cname checking less strict Without this additional 'self.strict_checking' check, the tests in the following patches do not get far enough to trigger a crash with the MIT KDC. Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 [abartlet@samba.org backported from commit 36798f5b651a02b74b6844c024101f7a026f1f68 as Samba 4.14 is tested on MIT 1.16 and so the knownfails need to match this version] --- python/samba/tests/krb5/raw_testcase.py | 5 ++-- selftest/knownfail_mit_kdc | 35 ------------------------- 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 22f64f25f14..32de51c2da4 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2043,8 +2043,9 @@ class RawKerberosTest(TestCaseInTempDir): ticket_session_key = self.EncryptionKey_import(ticket_key) self.assertElementEqualUTF8(ticket_private, 'crealm', expected_crealm) - self.assertElementEqualPrincipal(ticket_private, 'cname', - expected_cname) + if self.strict_checking: + self.assertElementEqualPrincipal(ticket_private, 'cname', + expected_cname) self.assertElementPresent(ticket_private, 'transited') self.assertElementPresent(ticket_private, 'authtime') if self.strict_checking: diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 025504c1268..d2114136ddb 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -309,53 +309,18 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # # FAST tests # -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_empty_fast.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor2.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_ad_fx_fast_armor_ticket2.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_not_used.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_used.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_enc_timestamp.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_clock_skew.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_replay.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key_kdc.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_hide_client_names.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_armor_type2.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt_mach.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_canon.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_claims_or_canon.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_flags.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_nonce.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_realm.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_wrong_till.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_armor.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_hide_client_names.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_canon.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_claims_or_canon.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_subkey.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_flags.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_nonce.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_realm.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_wrong_till.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_service_ticket_mach.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_unknown_critical_option.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_etypes.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_subkey.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_wrong_principal.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc -- 2.25.1 From c7bedb6cee3e4bed206877b910ed30f9048948c2 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 27 Aug 2021 11:42:48 +1000 Subject: [PATCH 200/645] CVE-2021-3671 HEIMDAL kdc: validate sname in TGS-REQ In tgs_build_reply(), validate the server name in the TGS-REQ is present before dereferencing. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 [abartlet@samba.org backported from from Heimdal commit 04171147948d0a3636bc6374181926f0fb2ec83a via reference to an earlier patch by Joseph Sutton] RN: An unuthenticated user can crash the AD DC KDC by omitting the server name in a TGS-REQ Reviewed-by: Andreas Schneider (cherry picked from commit 0cb4b939f192376bf5e33637863a91a20f74c5a5) --- source4/heimdal/kdc/krb5tgs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index efbdd6ed77f..ef337ea4faf 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1603,6 +1603,10 @@ tgs_build_reply(krb5_context context, s = &adtkt.cname; r = adtkt.crealm; + } else if (s == NULL) { + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + krb5_set_error_message(context, ret, "No server in request"); + goto out; } _krb5_principalname2krb5_principal(context, &sp, *s, r); -- 2.25.1 From 4179ff720f9d9a0c3ea66d3f1f3eda7d6ad76ff5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 29 Jul 2021 12:25:06 +1200 Subject: [PATCH 201/645] CVE-2021-3671 tests/krb5: Add tests for omitting sname in outer request Note: Without the previous patch, 'test_fast_tgs_outer_no_sname' would crash the Heimdal KDC. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit b8e2515552ffa158fab1e86a39004de4cc419da5) --- python/samba/tests/krb5/fast_tests.py | 39 +++++++++++++++++++++++++++ selftest/knownfail_heimdal_kdc | 2 ++ selftest/knownfail_mit_kdc | 2 ++ 3 files changed, 43 insertions(+) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index e38b2e0a6e1..5189411e94f 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -655,6 +655,45 @@ class FAST_Tests(KDCBaseTest): } ]) + def test_fast_outer_no_sname(self): + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'sname': None # should be ignored + } + }, + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_padata_fn': self.generate_enc_challenge_padata, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'outer_req': { + 'sname': None # should be ignored + } + } + ]) + + def test_fast_tgs_outer_no_sname(self): + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': 0, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'outer_req': { + 'sname': None # should be ignored + } + } + ]) + def test_fast_outer_wrong_till(self): self._run_test_sequence([ { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 6a36640233e..4a4e98f6727 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -118,3 +118,5 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_wrong_principal.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index d2114136ddb..41142defe6c 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -324,3 +324,5 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_service_ticket_mach.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc -- 2.25.1 From 24c87d4e30019828bffd92fe978b4c2ad123512a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Sep 2021 10:43:06 +1200 Subject: [PATCH 202/645] tests/krb5: Remove harmful and a-typical return in as_req testcase A test in a TestCase class should not return a value, the test is determined by the assertions raised. Other changes will shortly cause kdc_exchange_dict[preauth_etype_info2] to not always be filled, so we need to remove this rudundent code. This also fixes a *lot* of tests against the MIT KDC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider (cherry picked from commit 3330eaf39c6174f2d90fe4d8e016efb97005d1e5) --- python/samba/tests/krb5/as_req_tests.py | 14 ++++++-------- selftest/knownfail_mit_kdc | 10 ---------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index fd258e8164a..82ff3f4845c 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -106,13 +106,11 @@ class AsReqKerberosTests(KDCBaseTest): expected_salt=expected_salt, kdc_options=str(initial_kdc_options)) - rep = self._generic_kdc_exchange(kdc_exchange_dict, - cname=cname, - realm=realm, - sname=sname, - etypes=initial_etypes) - - return kdc_exchange_dict['preauth_etype_info2'] + 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) @@ -121,7 +119,7 @@ class AsReqKerberosTests(KDCBaseTest): else: pa_pac = self.KERB_PA_PAC_REQUEST_create(pac) padata = [pa_pac] - return self._test_as_req_nopreauth( + self._test_as_req_nopreauth( initial_padata=padata, initial_etypes=etypes, initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 41142defe6c..59db6e80c09 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -290,16 +290,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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_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_c ^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_6_c -# -# MIT currently fails some as_req_no_preauth tests. -# -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_aes256.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes128_rc4.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_aes256_aes128_rc4.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4.fl2008r2dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128.fl2008r2dc # Differences in our KDC compared to windows # ^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally -- 2.25.1 From 20a4545df62df7439aa6864cf45641172a638cad Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 27 Aug 2021 13:00:21 +1200 Subject: [PATCH 203/645] tests/krb5: Check e-data element for TGS-REP errors without FAST BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit e373c6461a88c44303ea8cdbebc2d78dd15dec4a) --- python/samba/tests/krb5/raw_testcase.py | 52 ++++++++++++-------- python/samba/tests/krb5/rfc4120_constants.py | 2 + 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 32de51c2da4..ba6d07ce465 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -82,6 +82,7 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, PADATA_PK_AS_REP_19, + PADATA_PW_SALT, PADATA_SUPPORTED_ETYPES ) import samba.tests.krb5.kcrypto as kcrypto @@ -2187,8 +2188,7 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') - if (expected_error_mode in (KDC_ERR_GENERIC, - KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS) + if (expected_error_mode == KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS or (rep_msg_type == KRB_TGS_REP and not sent_fast) or (sent_fast and fast_armor_type is not None @@ -2198,10 +2198,17 @@ class RawKerberosTest(TestCaseInTempDir): return rep edata = self.getElementValue(rep, 'e-data') if self.strict_checking: - self.assertIsNotNone(edata) + if expected_error_mode != KDC_ERR_GENERIC: + # Predicting whether an ERR_GENERIC error contains e-data is + # more complicated. + self.assertIsNotNone(edata) if edata is not None: - rep_padata = self.der_decode(edata, - asn1Spec=krb5_asn1.METHOD_DATA()) + if rep_msg_type == KRB_TGS_REP and not sent_fast: + rep_padata = [self.der_decode(edata, + asn1Spec=krb5_asn1.PA_DATA())] + else: + rep_padata = self.der_decode(edata, + asn1Spec=krb5_asn1.METHOD_DATA()) self.assertGreater(len(rep_padata), 0) if sent_fast: @@ -2218,15 +2225,13 @@ class RawKerberosTest(TestCaseInTempDir): expect_strengthen_key=False) rep_padata = fast_response['padata'] - else: - rep_padata = [] - etype_info2 = self.check_rep_padata(kdc_exchange_dict, - callback_dict, - rep, - rep_padata) + etype_info2 = self.check_rep_padata(kdc_exchange_dict, + callback_dict, + rep, + rep_padata) - kdc_exchange_dict['preauth_etype_info2'] = etype_info2 + kdc_exchange_dict['preauth_etype_info2'] = etype_info2 return rep @@ -2279,10 +2284,13 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_FX_COOKIE,) if rep_msg_type == KRB_TGS_REP: - sent_claims = self.sent_claims(kdc_exchange_dict) - if sent_claims and expected_error_mode != 0: - expected_patypes += (PADATA_PAC_OPTIONS,) - else: + if not sent_fast and expected_error_mode != 0: + expected_patypes += (PADATA_PW_SALT,) + else: + sent_claims = self.sent_claims(kdc_exchange_dict) + if sent_claims and expected_error_mode not in (0, KDC_ERR_GENERIC): + expected_patypes += (PADATA_PAC_OPTIONS,) + elif expected_error_mode != KDC_ERR_GENERIC: if expect_etype_info: self.assertGreater(len(expect_etype_info2), 0) expected_patypes += (PADATA_ETYPE_INFO,) @@ -2458,8 +2466,11 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNone(pk_as_rep19) return None - if self.strict_checking: - self.assertIsNotNone(etype_info2) + if expected_error_mode != KDC_ERR_GENERIC: + if self.strict_checking: + self.assertIsNotNone(etype_info2) + else: + self.assertIsNone(etype_info2) if expect_etype_info: self.assertIsNotNone(etype_info) else: @@ -2468,7 +2479,7 @@ class RawKerberosTest(TestCaseInTempDir): if unexpect_etype_info: self.assertIsNone(etype_info) - if self.strict_checking: + if expected_error_mode != KDC_ERR_GENERIC and self.strict_checking: self.assertGreaterEqual(len(etype_info2), 1) self.assertEqual(len(etype_info2), len(expect_etype_info2)) for i in range(0, len(etype_info2)): @@ -2495,7 +2506,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(salt) self.assertEqual(len(salt), 0) - if expected_error_mode != KDC_ERR_PREAUTH_FAILED: + if expected_error_mode not in (KDC_ERR_PREAUTH_FAILED, + KDC_ERR_GENERIC): if sent_fast: self.assertIsNotNone(enc_challenge) if self.strict_checking: diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index e1a688991a7..c70ce309b95 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -60,6 +60,8 @@ PADATA_PK_AS_REQ = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REQ')) PADATA_PK_AS_REP_19 = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PK-AS-REP-19')) +PADATA_PW_SALT = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-PW-SALT')) PADATA_SUPPORTED_ETYPES = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-SUPPORTED-ETYPES')) -- 2.25.1 From 21f1a7c40181daa7cfa9fdbe815ed62d4fb8d101 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 27 Aug 2021 13:00:37 +1200 Subject: [PATCH 204/645] tests/krb5: Check PADATA-PW-SALT element in e-data BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit 1e4d757394a0bbda587d5ff91801f88539b712b1) --- python/samba/tests/krb5/raw_testcase.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index ba6d07ce465..4e7891ae89a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2328,6 +2328,7 @@ class RawKerberosTest(TestCaseInTempDir): fast_error = None fx_fast = None pac_options = None + pw_salt = None for pa in rep_padata: patype = self.getElementValue(pa, 'padata-type') pavalue = self.getElementValue(pa, 'padata-value') @@ -2380,6 +2381,11 @@ class RawKerberosTest(TestCaseInTempDir): pac_options = pavalue self.assertIsNotNone(pac_options) continue + if patype == PADATA_PW_SALT: + self.assertIsNone(pw_salt) + pw_salt = pavalue + self.assertIsNotNone(pw_salt) + continue if fast_cookie is not None: kdc_exchange_dict['fast_cookie'] = fast_cookie @@ -2395,6 +2401,14 @@ class RawKerberosTest(TestCaseInTempDir): if pac_options is not None: self.check_pac_options_claims_support(pac_options) + if pw_salt is not None: + self.assertEqual(12, len(pw_salt)) + + status = int.from_bytes(pw_salt[:4], 'little') + flags = int.from_bytes(pw_salt[8:], 'little') + + self.assertEqual(3, flags) + if enc_challenge is not None: if not sent_enc_challenge: self.assertEqual(len(enc_challenge), 0) -- 2.25.1 From 5d235a3ed53892eedf413e105d93d7474416a968 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 27 Aug 2021 13:02:04 +1200 Subject: [PATCH 205/645] tests/krb5: Add tests for omitting sname in request BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit bbbb13caf7bd2440c80f4f4775725b7863d16a5b) --- python/samba/tests/krb5/fast_tests.py | 83 ++++++++++++++++++++++++++- selftest/knownfail_heimdal_kdc | 3 + selftest/knownfail_mit_kdc | 4 ++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 5189411e94f..e0fd3cc4d5e 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -105,6 +105,79 @@ class FAST_Tests(KDCBaseTest): } ]) + def test_simple_no_sname(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + expected_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': False, + 'sname': None, + 'expected_sname': expected_sname + } + ]) + + def test_simple_tgs_no_sname(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + expected_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': False, + 'gen_tgt_fn': self.get_user_tgt, + 'sname': None, + 'expected_sname': expected_sname + } + ]) + + def test_fast_no_sname(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + expected_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + + self._run_test_sequence([ + { + 'rep_type': KRB_AS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'sname': None, + 'expected_sname': expected_sname + } + ]) + + def test_fast_tgs_no_sname(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_username = krbtgt_creds.get_username() + krbtgt_realm = krbtgt_creds.get_realm() + expected_sname = self.PrincipalName_create( + name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + + self._run_test_sequence([ + { + 'rep_type': KRB_TGS_REP, + 'expected_error_mode': KDC_ERR_GENERIC, + 'use_fast': True, + 'gen_tgt_fn': self.get_user_tgt, + 'fast_armor': None, + 'sname': None, + 'expected_sname': expected_sname + } + ]) + def test_simple_tgs_wrong_principal(self): mach_creds = self.get_mach_creds() mach_name = mach_creds.get_username() @@ -1122,11 +1195,17 @@ class FAST_Tests(KDCBaseTest): cname = client_cname if rep_type == KRB_AS_REP else None crealm = client_realm + if 'sname' in kdc_dict: + sname = kdc_dict.pop('sname') + else: + if rep_type == KRB_AS_REP: + sname = krbtgt_sname + else: # KRB_TGS_REP + sname = target_sname + if rep_type == KRB_AS_REP: - sname = krbtgt_sname srealm = krbtgt_realm else: # KRB_TGS_REP - sname = target_sname srealm = target_realm expected_cname = kdc_dict.pop('expected_cname', client_cname) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 4a4e98f6727..b0981a06002 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -120,3 +120,6 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 59db6e80c09..f167c2bf856 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -316,3 +316,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_unarmored_as_req.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc -- 2.25.1 From 1f7316f1286b21571ad98f16f7af8c5550d9d5f4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 27 Aug 2021 13:26:45 +1200 Subject: [PATCH 206/645] tests/krb5: Allow specifying parameters specific to the inner FAST request body BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit c6d7e19ecfb264c6f79df5a20e830e4ea6fdb340) --- python/samba/tests/krb5/fast_tests.py | 4 ++++ python/samba/tests/krb5/raw_testcase.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index e0fd3cc4d5e..551790a3e42 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1325,7 +1325,9 @@ class FAST_Tests(KDCBaseTest): auth_data = None if not use_fast: + self.assertNotIn('inner_req', kdc_dict) self.assertNotIn('outer_req', kdc_dict) + inner_req = kdc_dict.pop('inner_req', None) outer_req = kdc_dict.pop('outer_req', None) if rep_type == KRB_AS_REP: @@ -1355,6 +1357,7 @@ class FAST_Tests(KDCBaseTest): armor_tgt=armor_tgt, armor_subkey=armor_subkey, kdc_options=kdc_options, + inner_req=inner_req, outer_req=outer_req) else: # KRB_TGS_REP kdc_exchange_dict = self.tgs_exchange_dict( @@ -1383,6 +1386,7 @@ class FAST_Tests(KDCBaseTest): auth_data=auth_data, body_checksum_type=None, kdc_options=kdc_options, + inner_req=inner_req, outer_req=outer_req) repeat = kdc_dict.pop('repeat', 1) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4e7891ae89a..15873d69fa6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1553,6 +1553,9 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode = kdc_exchange_dict['expected_error_mode'] kdc_options = kdc_exchange_dict['kdc_options'] + # Parameters specific to the inner request body + inner_req = kdc_exchange_dict['inner_req'] + # Parameters specific to the outer request body outer_req = kdc_exchange_dict['outer_req'] @@ -1582,6 +1585,12 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData_usage=EncAuthorizationData_usage) inner_req_body = dict(req_body) + if inner_req is not None: + for key, value in inner_req.items(): + if value is not None: + inner_req_body[key] = value + else: + del inner_req_body[key] if outer_req is not None: for key, value in outer_req.items(): if value is not None: @@ -1734,6 +1743,7 @@ class RawKerberosTest(TestCaseInTempDir): armor_subkey=None, auth_data=None, kdc_options='', + inner_req=None, outer_req=None): kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, @@ -1765,6 +1775,7 @@ class RawKerberosTest(TestCaseInTempDir): 'armor_subkey': armor_subkey, 'auth_data': auth_data, 'kdc_options': kdc_options, + 'inner_req': inner_req, 'outer_req': outer_req } if expected_cname_private is not None: @@ -1802,6 +1813,7 @@ class RawKerberosTest(TestCaseInTempDir): auth_data=None, body_checksum_type=None, kdc_options='', + inner_req=None, outer_req=None): kdc_exchange_dict = { 'req_msg_type': KRB_TGS_REQ, @@ -1833,6 +1845,7 @@ class RawKerberosTest(TestCaseInTempDir): 'auth_data': auth_data, 'authenticator_subkey': authenticator_subkey, 'kdc_options': kdc_options, + 'inner_req': inner_req, 'outer_req': outer_req } if expected_cname_private is not None: -- 2.25.1 From cef685068460d2b8d6cef42bcab8692c28d86ac6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 31 Aug 2021 19:42:33 +1200 Subject: [PATCH 207/645] tests/krb5: Allow expected_error_mode to be a container type This allows a range of possible error codes to be checked against, for cases when the particular error code returned is not so important. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider (cherry picked from commit ebd673e976aea5dd481a75f180fd526995c4fda0) --- python/samba/tests/krb5/raw_testcase.py | 56 +++++++++++++++---------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 15873d69fa6..6db17f2a118 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1702,11 +1702,12 @@ class RawKerberosTest(TestCaseInTempDir): if check_error_fn is not None: expected_msg_type = KRB_ERROR self.assertIsNone(check_rep_fn) - self.assertNotEqual(0, expected_error_mode) + self.assertNotEqual(0, len(expected_error_mode)) + self.assertNotIn(0, expected_error_mode) if check_rep_fn is not None: expected_msg_type = rep_msg_type self.assertIsNone(check_error_fn) - self.assertEqual(0, expected_error_mode) + self.assertEqual(0, len(expected_error_mode)) self.assertIsNotNone(expected_msg_type) self.assertEqual(msg_type, expected_msg_type) @@ -1745,6 +1746,11 @@ class RawKerberosTest(TestCaseInTempDir): kdc_options='', inner_req=None, outer_req=None): + if expected_error_mode == 0: + expected_error_mode = () + elif not isinstance(expected_error_mode, collections.abc.Container): + expected_error_mode = (expected_error_mode,) + kdc_exchange_dict = { 'req_msg_type': KRB_AS_REQ, 'req_asn1Spec': krb5_asn1.AS_REQ, @@ -1815,6 +1821,11 @@ class RawKerberosTest(TestCaseInTempDir): kdc_options='', inner_req=None, outer_req=None): + if expected_error_mode == 0: + expected_error_mode = () + elif not isinstance(expected_error_mode, collections.abc.Container): + expected_error_mode = (expected_error_mode,) + kdc_exchange_dict = { 'req_msg_type': KRB_TGS_REQ, 'req_asn1Spec': krb5_asn1.TGS_REQ, @@ -1942,7 +1953,8 @@ class RawKerberosTest(TestCaseInTempDir): self.check_rep_padata(kdc_exchange_dict, callback_dict, rep, - fast_response['padata']) + fast_response['padata'], + error_code=0) ticket_private = None self.assertIsNotNone(ticket_decryption_key) @@ -2181,7 +2193,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqual(rep, 'pvno', 5) self.assertElementEqual(rep, 'msg-type', KRB_ERROR) - self.assertElementEqual(rep, 'error-code', expected_error_mode) + error_code = self.getElementValue(rep, 'error-code') + self.assertIn(error_code, expected_error_mode) if self.strict_checking: self.assertElementMissing(rep, 'ctime') self.assertElementMissing(rep, 'cusec') @@ -2195,13 +2208,13 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertElementMissing(rep, 'cname') self.assertElementEqualUTF8(rep, 'realm', expected_srealm) - if sent_fast and expected_error_mode == KDC_ERR_GENERIC: + if sent_fast and error_code == KDC_ERR_GENERIC: self.assertElementEqualPrincipal(rep, 'sname', self.get_krbtgt_sname()) else: self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') - if (expected_error_mode == KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS + if (error_code == KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS or (rep_msg_type == KRB_TGS_REP and not sent_fast) or (sent_fast and fast_armor_type is not None @@ -2211,7 +2224,7 @@ class RawKerberosTest(TestCaseInTempDir): return rep edata = self.getElementValue(rep, 'e-data') if self.strict_checking: - if expected_error_mode != KDC_ERR_GENERIC: + if error_code != KDC_ERR_GENERIC: # Predicting whether an ERR_GENERIC error contains e-data is # more complicated. self.assertIsNotNone(edata) @@ -2242,7 +2255,8 @@ class RawKerberosTest(TestCaseInTempDir): etype_info2 = self.check_rep_padata(kdc_exchange_dict, callback_dict, rep, - rep_padata) + rep_padata, + error_code) kdc_exchange_dict['preauth_etype_info2'] = etype_info2 @@ -2252,10 +2266,10 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict, callback_dict, rep, - rep_padata): + rep_padata, + error_code): rep_msg_type = kdc_exchange_dict['rep_msg_type'] - expected_error_mode = kdc_exchange_dict['expected_error_mode'] req_body = kdc_exchange_dict['req_body'] proposed_etypes = req_body['etype'] client_as_etypes = kdc_exchange_dict.get('client_as_etypes', []) @@ -2281,7 +2295,7 @@ class RawKerberosTest(TestCaseInTempDir): if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): if etype > expected_aes_type: expected_aes_type = etype - if etype in (kcrypto.Enctype.RC4,) and expected_error_mode != 0: + if etype in (kcrypto.Enctype.RC4,) and error_code != 0: unexpect_etype_info = False if etype > expected_rc4_type: expected_rc4_type = etype @@ -2292,25 +2306,25 @@ class RawKerberosTest(TestCaseInTempDir): expect_etype_info2 += (expected_rc4_type,) expected_patypes = () - if sent_fast and expected_error_mode != 0: + if sent_fast and error_code != 0: expected_patypes += (PADATA_FX_ERROR,) expected_patypes += (PADATA_FX_COOKIE,) if rep_msg_type == KRB_TGS_REP: - if not sent_fast and expected_error_mode != 0: + if not sent_fast and error_code != 0: expected_patypes += (PADATA_PW_SALT,) else: sent_claims = self.sent_claims(kdc_exchange_dict) - if sent_claims and expected_error_mode not in (0, KDC_ERR_GENERIC): + if sent_claims and error_code not in (0, KDC_ERR_GENERIC): expected_patypes += (PADATA_PAC_OPTIONS,) - elif expected_error_mode != KDC_ERR_GENERIC: + elif error_code != KDC_ERR_GENERIC: if expect_etype_info: self.assertGreater(len(expect_etype_info2), 0) expected_patypes += (PADATA_ETYPE_INFO,) if len(expect_etype_info2) != 0: expected_patypes += (PADATA_ETYPE_INFO2,) - if expected_error_mode != KDC_ERR_PREAUTH_FAILED: + if error_code != KDC_ERR_PREAUTH_FAILED: if sent_fast: expected_patypes += (PADATA_ENCRYPTED_CHALLENGE,) else: @@ -2493,7 +2507,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNone(pk_as_rep19) return None - if expected_error_mode != KDC_ERR_GENERIC: + if error_code != KDC_ERR_GENERIC: if self.strict_checking: self.assertIsNotNone(etype_info2) else: @@ -2506,7 +2520,7 @@ class RawKerberosTest(TestCaseInTempDir): if unexpect_etype_info: self.assertIsNone(etype_info) - if expected_error_mode != KDC_ERR_GENERIC and self.strict_checking: + if error_code != KDC_ERR_GENERIC and self.strict_checking: self.assertGreaterEqual(len(etype_info2), 1) self.assertEqual(len(etype_info2), len(expect_etype_info2)) for i in range(0, len(etype_info2)): @@ -2533,8 +2547,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(salt) self.assertEqual(len(salt), 0) - if expected_error_mode not in (KDC_ERR_PREAUTH_FAILED, - KDC_ERR_GENERIC): + if error_code not in (KDC_ERR_PREAUTH_FAILED, + KDC_ERR_GENERIC): if sent_fast: self.assertIsNotNone(enc_challenge) if self.strict_checking: @@ -2799,7 +2813,7 @@ class RawKerberosTest(TestCaseInTempDir): as_rep_usage = KU_AS_REP_ENC_PART return preauth_key, as_rep_usage - if expected_error_mode == 0: + if not expected_error_mode: check_error_fn = None check_rep_fn = self.generic_check_kdc_rep else: -- 2.25.1 From f9a9114656f9a444252ade792af4912346d4924f Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 31 Aug 2021 17:38:16 +1200 Subject: [PATCH 208/645] kdc: KRB5KDC_ERR_{C,S}_PRINCIPAL_UNKNOWN if missing field If missing cname or sname in AS-REQ, return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN and KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN. This matches MIT behaviour. [abartlet@samba.org Backported from Heimdal commit 892a1ffcaad98157e945c540b81f65edb14d29bd and knownfail added. Further adapted knownfail for 4.14 due to conflicts as the patch that adds a test which crashes old MIT versions is omitted] BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider --- selftest/knownfail_heimdal_kdc | 1 + source4/heimdal/kdc/kerberos5.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index b0981a06002..f5ac4fa2e2b 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -123,3 +123,4 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 27d38ad84b7..0fa336e871c 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -996,7 +996,7 @@ _kdc_as_rep(krb5_context context, flags |= HDB_F_CANON; if(b->sname == NULL){ - ret = KRB5KRB_ERR_GENERIC; + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; e_text = "No server in request"; } else{ ret = _krb5_principalname2krb5_principal (context, @@ -1012,7 +1012,7 @@ _kdc_as_rep(krb5_context context, goto out; } if(b->cname == NULL){ - ret = KRB5KRB_ERR_GENERIC; + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; e_text = "No client in request"; } else { ret = _krb5_principalname2krb5_principal (context, -- 2.25.1 From 6131fbe28b0fb4d878776726af04b1841a34425a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 31 Aug 2021 22:38:01 +1200 Subject: [PATCH 209/645] tests/krb5: Allow KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN for a missing sname This allows our code to still pass with the error code that MIT and Heimdal have chosen BUG: https://bugzilla.samba.org/show_bug.cgi?id=14770 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14817 Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Thu Sep 2 14:28:31 UTC 2021 on sn-devel-184 [abartlet@samba.org: Backported from 10baaf08523200e47451aa1862430977b0365b59 to Samba 4.14 due to conflicts in knownfail as the test which crashes older MIT KDC versions is omitted] Autobuild-User(v4-13-test): Jule Anger Autobuild-Date(v4-13-test): Thu Sep 16 08:54:13 UTC 2021 on sn-devel-184 --- python/samba/tests/krb5/fast_tests.py | 23 +++++++++++++------- python/samba/tests/krb5/kdc_base_test.py | 6 ++++- python/samba/tests/krb5/rfc4120_constants.py | 1 + selftest/knownfail_heimdal_kdc | 3 --- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 551790a3e42..2d4b69f8590 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -20,6 +20,7 @@ import functools import os import sys +import collections import ldb @@ -37,6 +38,7 @@ from samba.tests.krb5.rfc4120_constants import ( FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_ETYPE_NOSUPP, KDC_ERR_GENERIC, + KDC_ERR_S_PRINCIPAL_UNKNOWN, KDC_ERR_NOT_US, KDC_ERR_PREAUTH_FAILED, KDC_ERR_PREAUTH_REQUIRED, @@ -115,7 +117,7 @@ class FAST_Tests(KDCBaseTest): self._run_test_sequence([ { 'rep_type': KRB_AS_REP, - 'expected_error_mode': KDC_ERR_GENERIC, + 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN), 'use_fast': False, 'sname': None, 'expected_sname': expected_sname @@ -132,7 +134,7 @@ class FAST_Tests(KDCBaseTest): self._run_test_sequence([ { 'rep_type': KRB_TGS_REP, - 'expected_error_mode': KDC_ERR_GENERIC, + 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN), 'use_fast': False, 'gen_tgt_fn': self.get_user_tgt, 'sname': None, @@ -169,7 +171,7 @@ class FAST_Tests(KDCBaseTest): self._run_test_sequence([ { 'rep_type': KRB_TGS_REP, - 'expected_error_mode': KDC_ERR_GENERIC, + 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN), 'use_fast': True, 'gen_tgt_fn': self.get_user_tgt, 'fast_armor': None, @@ -1147,7 +1149,12 @@ class FAST_Tests(KDCBaseTest): self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP)) expected_error_mode = kdc_dict.pop('expected_error_mode') - self.assertIn(expected_error_mode, range(240)) + if expected_error_mode == 0: + expected_error_mode = () + elif not isinstance(expected_error_mode, collections.abc.Container): + expected_error_mode = (expected_error_mode,) + for error in expected_error_mode: + self.assertIn(error, range(240)) use_fast = kdc_dict.pop('use_fast') self.assertIs(type(use_fast), bool) @@ -1158,7 +1165,7 @@ class FAST_Tests(KDCBaseTest): if fast_armor_type is not None: self.assertIn('gen_armor_tgt_fn', kdc_dict) - elif expected_error_mode != KDC_ERR_GENERIC: + elif KDC_ERR_GENERIC not in expected_error_mode: self.assertNotIn('gen_armor_tgt_fn', kdc_dict) gen_armor_tgt_fn = kdc_dict.pop('gen_armor_tgt_fn', None) @@ -1182,7 +1189,7 @@ class FAST_Tests(KDCBaseTest): self.assertNotIn('gen_tgt_fn', kdc_dict) tgt = None - if expected_error_mode != 0: + if len(expected_error_mode) != 0: check_error_fn = self.generic_check_kdc_error check_rep_fn = None else: @@ -1396,7 +1403,7 @@ class FAST_Tests(KDCBaseTest): realm=crealm, sname=sname, etypes=etypes) - if expected_error_mode == 0: + if len(expected_error_mode) == 0: self.check_reply(rep, rep_type) fast_cookie = None @@ -1410,7 +1417,7 @@ class FAST_Tests(KDCBaseTest): else: fast_cookie = None - if expected_error_mode == KDC_ERR_PREAUTH_REQUIRED: + if KDC_ERR_PREAUTH_REQUIRED in expected_error_mode: preauth_etype_info2 = ( kdc_exchange_dict['preauth_etype_info2']) else: diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b148fa01f65..f5c1eba9151 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -21,6 +21,7 @@ import os from datetime import datetime, timezone import tempfile import binascii +import collections from collections import namedtuple import ldb @@ -598,7 +599,10 @@ class KDCBaseTest(RawKerberosTest): """ self.assertIsNotNone(rep) self.assertEqual(rep['msg-type'], KRB_ERROR, "rep = {%s}" % rep) - self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) + if isinstance(expected, collections.abc.Container): + self.assertIn(rep['error-code'], expected, "rep = {%s}" % rep) + else: + self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) def tgs_req(self, cname, sname, realm, ticket, key, etypes): '''Send a TGS-REQ, returns the response and the decrypted and diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index c70ce309b95..ac2bac4d91e 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -67,6 +67,7 @@ PADATA_SUPPORTED_ETYPES = int( # Error codes KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 +KDC_ERR_S_PRINCIPAL_UNKNOWN = 7 KDC_ERR_POLICY = 12 KDC_ERR_ETYPE_NOSUPP = 14 KDC_ERR_PREAUTH_FAILED = 24 diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index f5ac4fa2e2b..80b8224f015 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -121,6 +121,3 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc -^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc -- 2.25.1 From 2fc27940fb9db01f61867f664955e55e44669518 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 11:34:56 +1200 Subject: [PATCH 210/645] pytest:segfault: Add test for ldb.msg_diff() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14645 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall [abartlet@samba.org backported form from commit a99a76722d6046a5d63032e3d2bb3f791da948a6 due to conflicts with other new segfault tests] --- python/samba/tests/segfault.py | 11 +++++++++++ selftest/knownfail.d/python-segfaults | 1 + 2 files changed, 12 insertions(+) diff --git a/python/samba/tests/segfault.py b/python/samba/tests/segfault.py index 07e2d46d56a..eac314982a8 100644 --- a/python/samba/tests/segfault.py +++ b/python/samba/tests/segfault.py @@ -174,3 +174,14 @@ class SegfaultTests(samba.tests.TestCase): def test_dcerpc_idl_inline_arrays(self): """Inline arrays were incorrectly handled.""" dnsserver.DNS_RPC_SERVER_INFO_DOTNET().pExtensions + + @segfault_detector + def test_ldb_msg_diff(self): + samdb = self.get_samdb() + + msg = ldb.Message() + msg.dn = ldb.Dn(samdb, '') + diff = samdb.msg_diff(msg, msg) + + del msg + diff.dn diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index 1be0566dcb1..b7229fc7229 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1 +1,2 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 +samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_msg_diff -- 2.25.1 From f4777b9045a7e864a0fa037f0781db5960141b67 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 14 Sep 2021 11:08:41 +1200 Subject: [PATCH 211/645] ldb_msg: Don't fail in ldb_msg_copy() if source DN is NULL BUG: https://bugzilla.samba.org/show_bug.cgi?id=14645 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit c2bbe774ce03661666a1f48922a9ab681ef4f64b) --- lib/ldb/common/ldb_msg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 2346e66ec39..7131f013f71 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -876,8 +876,10 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, msg2 = ldb_msg_copy_shallow(mem_ctx, msg); if (msg2 == NULL) return NULL; - msg2->dn = ldb_dn_copy(msg2, msg2->dn); - if (msg2->dn == NULL) goto failed; + if (msg2->dn != NULL) { + msg2->dn = ldb_dn_copy(msg2, msg2->dn); + if (msg2->dn == NULL) goto failed; + } for (i=0;inum_elements;i++) { struct ldb_message_element *el = &msg2->elements[i]; -- 2.25.1 From 845baab629064bf34bd0fa773419319d10b4b676 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 11:15:17 +1200 Subject: [PATCH 212/645] pyldb: Avoid use-after-free in msg_diff() Make a deep copy of the message elements in msg_diff() so that if either of the input messages are deallocated early, the result does not refer to non-existing elements. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14645 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall [abartlet@samba.org backported from commit 19a2af02f57d99db8ed3c6b028c3abdf4b553700 due to conflicts in the knownfail.d/python-segfaults file] Autobuild-User(v4-14-test): Jule Anger Autobuild-Date(v4-14-test): Wed Sep 29 13:14:22 UTC 2021 on sn-devel-184 --- lib/ldb/pyldb.c | 18 ++++++++++++++++-- selftest/knownfail.d/python-segfaults | 1 - 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index a6069be46a9..59a5d89dd9d 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -1805,6 +1805,7 @@ static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) struct ldb_message *diff; struct ldb_context *ldb; PyObject *py_ret; + TALLOC_CTX *mem_ctx = NULL; if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new)) return NULL; @@ -1819,19 +1820,32 @@ static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) return NULL; } + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + ldb = pyldb_Ldb_AS_LDBCONTEXT(self); - ldb_ret = ldb_msg_difference(ldb, ldb, + ldb_ret = ldb_msg_difference(ldb, mem_ctx, pyldb_Message_AsMessage(py_msg_old), pyldb_Message_AsMessage(py_msg_new), &diff); if (ldb_ret != LDB_SUCCESS) { + talloc_free(mem_ctx); PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff"); return NULL; } + diff = ldb_msg_copy(mem_ctx, diff); + if (diff == NULL) { + PyErr_NoMemory(); + return NULL; + } + py_ret = PyLdbMessage_FromMessage(diff); - talloc_unlink(ldb, diff); + talloc_free(mem_ctx); return py_ret; } diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index b7229fc7229..1be0566dcb1 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1,2 +1 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 -samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_msg_diff -- 2.25.1 From d6aa44dbf5af04f0a255dc38aa695b270d3ac62e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 28 Apr 2021 16:48:55 +1200 Subject: [PATCH 213/645] Fix Python docstrings Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sat Sep 4 00:55:32 UTC 2021 on sn-devel-184 (cherry picked from commit 02b187303369d3ce0c19dfb72ffa78f86a3911f0) --- lib/ldb/pyldb.c | 2 +- lib/tdb/pytdb.c | 2 +- lib/tevent/pytevent.c | 2 +- source4/librpc/ndr/py_security.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 59a5d89dd9d..2eda1c77a3d 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -840,7 +840,7 @@ static PyMethodDef py_ldb_dn_methods[] = { "S.get_component_value(num) -> string\n" "get the attribute value of the specified component as a binary string" }, { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS, - "S.get_component_value(num, name, value) -> None\n" + "S.set_component(num, name, value) -> None\n" "set the attribute name and value of the specified component" }, { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS, "S.get_rdn_name() -> string\n" diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c index 74e80f95ec5..9fb1d84c0d8 100644 --- a/lib/tdb/pytdb.c +++ b/lib/tdb/pytdb.c @@ -531,7 +531,7 @@ static PyMethodDef tdb_object_methods[] = { { "add_flags", (PyCFunction)obj_add_flags, METH_VARARGS, "S.add_flags(flags) -> None" }, { "remove_flags", (PyCFunction)obj_remove_flags, METH_VARARGS, "S.remove_flags(flags) -> None" }, #if PY_MAJOR_VERSION >= 3 - { "keys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, + { "keys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.keys() -> iterator" }, #else { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" }, #endif diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 73a9bd736e7..33a8c3bd64a 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -573,7 +573,7 @@ static PyMethodDef py_tevent_context_methods[] = { { "add_timer", (PyCFunction)py_tevent_context_add_timer, METH_VARARGS, "S.add_timer(next_event, handler) -> timer" }, { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset, - METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, + METH_VARARGS, "S.add_timer_offset(offset_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, { NULL }, diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index fc0aea99c3b..d957aa613b6 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -447,7 +447,7 @@ static PyMethodDef py_token_extra_methods[] = { { "has_sid", (PyCFunction)py_token_has_sid, METH_VARARGS, NULL }, { "is_anonymous", (PyCFunction)py_token_is_anonymous, METH_NOARGS, - "S.is_anonymus() -> bool\n" + "S.is_anonymous() -> bool\n" "Check whether this is an anonymous token." }, { "is_system", (PyCFunction)py_token_is_system, METH_NOARGS, NULL }, -- 2.25.1 From e3796d6fcdff7c737b432d66a901d5d95a54e860 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 10:56:25 +1200 Subject: [PATCH 214/645] pytest:segfault: Add test for deleting an ldb.Message dn BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit 6a041f6a99c39632d5c32e9d53b06719c20bef2c as other segfaulting tests are listed in knownfail.d/python-segfaults and @no_gdb_backtrace is not in 4.14] --- python/samba/tests/segfault.py | 5 +++++ selftest/knownfail.d/python-segfaults | 1 + 2 files changed, 6 insertions(+) diff --git a/python/samba/tests/segfault.py b/python/samba/tests/segfault.py index eac314982a8..24add6f3b6e 100644 --- a/python/samba/tests/segfault.py +++ b/python/samba/tests/segfault.py @@ -185,3 +185,8 @@ class SegfaultTests(samba.tests.TestCase): del msg diff.dn + + @segfault_detector + def test_ldb_msg_del_dn(self): + msg = ldb.Message() + del msg.dn diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index 1be0566dcb1..c0bd391714b 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1 +1,2 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 +samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_msg_del_dn -- 2.25.1 From 98125d68fcc266f8271df3c15216f32dfb23476a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 11:12:16 +1200 Subject: [PATCH 215/645] pyldb: Fix deleting an ldb.Message dn BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit d7af772de88885f46708329ff7bb5798da91d2c7 due to conflicts in knownfail.d/python-segfaults] --- lib/ldb/pyldb.c | 4 ++++ selftest/knownfail.d/python-segfaults | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 2eda1c77a3d..7e858a32a44 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -3742,6 +3742,10 @@ static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure) static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure) { struct ldb_message *msg = pyldb_Message_AsMessage(self); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete dn"); + return -1; + } if (!pyldb_Dn_Check(value)) { PyErr_SetString(PyExc_TypeError, "expected dn"); return -1; diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index c0bd391714b..d129dab7d47 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1,2 +1,3 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 -samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_msg_del_dn +samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dnsp_string_list +samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dns_record -- 2.25.1 From ed1429f40526048115ce147fd3d3531dba0d2adc Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 11:13:02 +1200 Subject: [PATCH 216/645] pytest:segfault: Add test for deleting an ldb.Control critical flag BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit b1adaa517c1237a473bdcf818523f5107df3d6b0 as @no_gdb_backtrace is not in Samba 4.14] --- python/samba/tests/segfault.py | 7 +++++++ selftest/knownfail.d/python-segfaults | 1 + 2 files changed, 8 insertions(+) diff --git a/python/samba/tests/segfault.py b/python/samba/tests/segfault.py index 24add6f3b6e..62b51e71794 100644 --- a/python/samba/tests/segfault.py +++ b/python/samba/tests/segfault.py @@ -190,3 +190,10 @@ class SegfaultTests(samba.tests.TestCase): def test_ldb_msg_del_dn(self): msg = ldb.Message() del msg.dn + + @segfault_detector + def test_ldb_control_del_critical(self): + samdb = self.get_samdb() + + c = ldb.Control(samdb, 'relax:1') + del c.critical diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index d129dab7d47..0c6e52d63d4 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1,3 +1,4 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dnsp_string_list samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dns_record +samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_control_del_critical -- 2.25.1 From d59e89418f924412a02ed337bb30e211e19b8835 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 11:16:09 +1200 Subject: [PATCH 217/645] pyldb: Fix deleting an ldb.Control critical flag BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 9d25a21d6024c6c2f8e4634f45e3944d8acbf8b8) --- lib/ldb/pyldb.c | 4 ++++ selftest/knownfail.d/python-segfaults | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 7e858a32a44..5934b1ad142 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -183,6 +183,10 @@ static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self, static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure) { + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete critical flag"); + return -1; + } if (PyObject_IsTrue(value)) { self->data->critical = true; } else { diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index 0c6e52d63d4..d129dab7d47 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1,4 +1,3 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dnsp_string_list samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dns_record -samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_ldb_control_del_critical -- 2.25.1 From 9873932520a10a9be0d5c5ac10a630051ed62d40 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 19:18:39 +1200 Subject: [PATCH 218/645] s4/torture/drs/python: Fix attribute existence check BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit fb758c32e7633178f42dc2c031667b10c2ca6e90 due to assertEquals vs assertEqual on the previous line] --- source4/torture/drs/python/replica_sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/torture/drs/python/replica_sync.py b/source4/torture/drs/python/replica_sync.py index 03292b57805..f787c8f0f11 100644 --- a/source4/torture/drs/python/replica_sync.py +++ b/source4/torture/drs/python/replica_sync.py @@ -140,7 +140,7 @@ objectClass: organizationalUnit # now check properties of the user name_cur = ou_cur["ou"][0] self.assertEquals(ou_cur["isDeleted"][0], b"TRUE") - self.assertTrue(not(b"objectCategory" in ou_cur)) + self.assertTrue(not("objectCategory" in ou_cur)) self.assertTrue(dodn in str(ou_cur["dn"]), "OU %s is deleted but it is not located under %s!" % (name_cur, dodn)) -- 2.25.1 From 3b3b0b7d4f0524d3f536b869c746a301e290b8ba Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 13:22:05 +1200 Subject: [PATCH 219/645] pyldb: Add test for an invalid ldb.Message index type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit b018e51d2725a23b2fedd3058644b8021f6a6a06) --- lib/ldb/tests/python/api.py | 6 ++++++ selftest/knownfail.d/pyldb | 1 + 2 files changed, 7 insertions(+) create mode 100644 selftest/knownfail.d/pyldb diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 1d3d765e607..bcb01e15f56 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -3056,6 +3056,12 @@ class LdbMsgTests(TestCase): def test_notpresent(self): self.assertRaises(KeyError, lambda: self.msg["foo"]) + def test_invalid(self): + try: + self.assertRaises(TypeError, lambda: self.msg[42]) + except KeyError: + self.fail() + def test_del(self): del self.msg["foo"] diff --git a/selftest/knownfail.d/pyldb b/selftest/knownfail.d/pyldb new file mode 100644 index 00000000000..8d24c4515d3 --- /dev/null +++ b/selftest/knownfail.d/pyldb @@ -0,0 +1 @@ +^ldb.python.api.LdbMsgTests.test_invalid -- 2.25.1 From f1cc78cc3aafdcd7697083fb8a0ec148fd0d1b1a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 13:39:56 +1200 Subject: [PATCH 220/645] pyldb: Raise TypeError for an invalid ldb.Message index Previously, a TypeError was raised and subsequently overridden by a KeyError. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 22353767ca75af9d9e8fa1e7da372dcb5eddfcb7) --- lib/ldb/pyldb.c | 22 +++++++--------------- selftest/knownfail.d/pyldb | 1 - 2 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 selftest/knownfail.d/pyldb diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 5934b1ad142..187e3b63448 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -3434,33 +3434,25 @@ static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self, return obj; } -static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name) +static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name) { - struct ldb_message_element *el; - const char *name; + struct ldb_message_element *el = NULL; + const char *name = NULL; struct ldb_message *msg = pyldb_Message_AsMessage(self); name = PyUnicode_AsUTF8(py_name); if (name == NULL) { - PyErr_SetNone(PyExc_TypeError); return NULL; } - if (!ldb_attr_cmp(name, "dn")) + if (!ldb_attr_cmp(name, "dn")) { return pyldb_Dn_FromDn(msg->dn); + } el = ldb_msg_find_element(msg, name); if (el == NULL) { - return NULL; - } - return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); -} - -static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name) -{ - PyObject *ret = py_ldb_msg_getitem_helper(self, py_name); - if (ret == NULL) { PyErr_SetString(PyExc_KeyError, "No such element"); return NULL; } - return ret; + + return PyLdbMessageElement_FromMessageElement(el, msg->elements); } static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs) diff --git a/selftest/knownfail.d/pyldb b/selftest/knownfail.d/pyldb deleted file mode 100644 index 8d24c4515d3..00000000000 --- a/selftest/knownfail.d/pyldb +++ /dev/null @@ -1 +0,0 @@ -^ldb.python.api.LdbMsgTests.test_invalid -- 2.25.1 From 654b480510d877bb5f75687960e5137db9b7a556 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 13:48:57 +1200 Subject: [PATCH 221/645] pyldb: Add tests for ldb.Message containment testing These tests verify that the 'in' operator on ldb.Message is consistent with indexing and the get() method. This means that the 'dn' element should always be present, lookups should be case-insensitive, and use of an invalid type should result in a TypeError. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 865fe238599a732360b77e06e592cb85d459acf8) --- lib/ldb/tests/python/api.py | 23 +++++++++++++++++++++++ selftest/knownfail.d/pyldb | 4 ++++ 2 files changed, 27 insertions(+) create mode 100644 selftest/knownfail.d/pyldb diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index bcb01e15f56..675b5859af8 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -3177,6 +3177,29 @@ class LdbMsgTests(TestCase): def test_get_unknown_text(self): self.assertEqual(None, self.msg.text.get("lalalala")) + def test_contains(self): + self.msg['foo'] = ['bar'] + self.assertIn('foo', self.msg) + + self.msg['Foo'] = ['bar'] + self.assertIn('Foo', self.msg) + + def test_contains_case(self): + self.msg['foo'] = ['bar'] + self.assertIn('Foo', self.msg) + + self.msg['Foo'] = ['bar'] + self.assertIn('foo', self.msg) + + def test_contains_dn(self): + self.assertIn('dn', self.msg) + + def test_contains_dn_case(self): + self.assertIn('DN', self.msg) + + def test_contains_invalid(self): + self.assertRaises(TypeError, lambda: None in self.msg) + def test_msg_diff(self): l = ldb.Ldb() msgs = l.parse_ldif("dn: foo=bar\nfoo: bar\nbaz: do\n\ndn: foo=bar\nfoo: bar\nbaz: dont\n") diff --git a/selftest/knownfail.d/pyldb b/selftest/knownfail.d/pyldb new file mode 100644 index 00000000000..34bdac4f682 --- /dev/null +++ b/selftest/knownfail.d/pyldb @@ -0,0 +1,4 @@ +^ldb.python.api.LdbMsgTests.test_contains_case +^ldb.python.api.LdbMsgTests.test_contains_dn +^ldb.python.api.LdbMsgTests.test_contains_dn_case +^ldb.python.api.LdbMsgTests.test_contains_invalid -- 2.25.1 From 89e5384d17b6db0751d259366de5aa4d9edffd4a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Sat, 25 Sep 2021 14:39:59 +1200 Subject: [PATCH 222/645] pyldb: Make ldb.Message containment testing consistent with indexing Previously, containment testing using the 'in' operator was handled by performing an equality comparison between the chosen object and each of the message's keys in turn. This behaviour was prone to errors due to not considering differences in case between otherwise equal elements, as the indexing operations do. Containment testing should now be more consistent with the indexing operations and with the get() method of ldb.Message. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14848 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 860d8902a9c502d4be83396598cf4a53c80fea69) --- lib/ldb/pyldb.c | 21 +++++++++++++++++++++ selftest/knownfail.d/pyldb | 4 ---- 2 files changed, 21 insertions(+), 4 deletions(-) delete mode 100644 selftest/knownfail.d/pyldb diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 187e3b63448..0fa444cf985 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -3434,6 +3434,22 @@ static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self, return obj; } +static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name) +{ + struct ldb_message_element *el = NULL; + const char *name = NULL; + struct ldb_message *msg = pyldb_Message_AsMessage(self); + name = PyUnicode_AsUTF8(py_name); + if (name == NULL) { + return -1; + } + if (!ldb_attr_cmp(name, "dn")) { + return 1; + } + el = ldb_msg_find_element(msg, name); + return el != NULL ? 1 : 0; +} + static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name) { struct ldb_message_element *el = NULL; @@ -3662,6 +3678,10 @@ static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self) return pyldb_Message_AsMessage(self)->num_elements; } +static PySequenceMethods py_ldb_msg_sequence = { + .sq_contains = (objobjproc)py_ldb_msg_contains, +}; + static PyMappingMethods py_ldb_msg_mapping = { .mp_length = (lenfunc)py_ldb_msg_length, .mp_subscript = (binaryfunc)py_ldb_msg_getitem, @@ -3839,6 +3859,7 @@ static PyTypeObject PyLdbMessage = { .tp_name = "ldb.Message", .tp_methods = py_ldb_msg_methods, .tp_getset = py_ldb_msg_getset, + .tp_as_sequence = &py_ldb_msg_sequence, .tp_as_mapping = &py_ldb_msg_mapping, .tp_basicsize = sizeof(PyLdbMessageObject), .tp_dealloc = (destructor)py_ldb_msg_dealloc, diff --git a/selftest/knownfail.d/pyldb b/selftest/knownfail.d/pyldb deleted file mode 100644 index 34bdac4f682..00000000000 --- a/selftest/knownfail.d/pyldb +++ /dev/null @@ -1,4 +0,0 @@ -^ldb.python.api.LdbMsgTests.test_contains_case -^ldb.python.api.LdbMsgTests.test_contains_dn -^ldb.python.api.LdbMsgTests.test_contains_dn_case -^ldb.python.api.LdbMsgTests.test_contains_invalid -- 2.25.1 From d112e6da9fbf95de69dccc8ca8c7b8b3bb208873 Mon Sep 17 00:00:00 2001 From: David Mulder Date: Mon, 14 Sep 2020 11:12:37 -0600 Subject: [PATCH 223/645] python: Move dsdb_Dn to samdb The import dsdb needed for dsdb_Dn causes import errors when trying to import get_bytes/get_string in some places. Signed-off-by: David Mulder Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [abartlet@samba.org backported from commit 85d2ff2f0003b106ca84866b7e7893723f1dd93c as the PY2 compat code is still in place in Samba 4.13] --- python/samba/common.py | 79 ------------------------- python/samba/dbchecker.py | 2 +- python/samba/kcc/kcc_utils.py | 2 +- python/samba/kcc/ldif_import_export.py | 3 +- python/samba/samdb.py | 75 +++++++++++++++++++++++ python/samba/tests/common.py | 4 +- source4/torture/drs/python/repl_rodc.py | 2 +- 7 files changed, 81 insertions(+), 86 deletions(-) diff --git a/python/samba/common.py b/python/samba/common.py index 8876e4f4faa..a8faa90065d 100644 --- a/python/samba/common.py +++ b/python/samba/common.py @@ -16,13 +16,6 @@ # along with this program. If not, see . # - -import ldb -from samba import dsdb -from samba.ndr import ndr_pack -from samba.dcerpc import misc -import binascii - from samba.compat import PY3 @@ -74,75 +67,3 @@ def normalise_int32(ivalue): return str(ivalue) -class dsdb_Dn(object): - '''a class for binary DN''' - - def __init__(self, samdb, dnstring, syntax_oid=None): - '''create a dsdb_Dn''' - if syntax_oid is None: - # auto-detect based on string - if dnstring.startswith("B:"): - syntax_oid = dsdb.DSDB_SYNTAX_BINARY_DN - elif dnstring.startswith("S:"): - syntax_oid = dsdb.DSDB_SYNTAX_STRING_DN - else: - syntax_oid = dsdb.DSDB_SYNTAX_OR_NAME - if syntax_oid in [dsdb.DSDB_SYNTAX_BINARY_DN, dsdb.DSDB_SYNTAX_STRING_DN]: - # it is a binary DN - colons = dnstring.split(':') - if len(colons) < 4: - raise RuntimeError("Invalid DN %s" % dnstring) - prefix_len = 4 + len(colons[1]) + int(colons[1]) - self.prefix = dnstring[0:prefix_len] - self.binary = self.prefix[3 + len(colons[1]):-1] - self.dnstring = dnstring[prefix_len:] - else: - self.dnstring = dnstring - self.prefix = '' - self.binary = '' - self.dn = ldb.Dn(samdb, self.dnstring) - - def __str__(self): - return self.prefix + str(self.dn.extended_str(mode=1)) - - def __cmp__(self, other): - ''' compare dsdb_Dn values similar to parsed_dn_compare()''' - dn1 = self - dn2 = other - guid1 = dn1.dn.get_extended_component("GUID") - guid2 = dn2.dn.get_extended_component("GUID") - - v = cmp(guid1, guid2) - if v != 0: - return v - v = cmp(dn1.binary, dn2.binary) - return v - - # In Python3, __cmp__ is replaced by these 6 methods - def __eq__(self, other): - return self.__cmp__(other) == 0 - - def __ne__(self, other): - return self.__cmp__(other) != 0 - - def __lt__(self, other): - return self.__cmp__(other) < 0 - - def __le__(self, other): - return self.__cmp__(other) <= 0 - - def __gt__(self, other): - return self.__cmp__(other) > 0 - - def __ge__(self, other): - return self.__cmp__(other) >= 0 - - def get_binary_integer(self): - '''return binary part of a dsdb_Dn as an integer, or None''' - if self.prefix == '': - return None - return int(self.binary, 16) - - def get_bytes(self): - '''return binary as a byte string''' - return binascii.unhexlify(self.binary) diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index 593aa8cf6d2..a50880da497 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -28,7 +28,7 @@ from samba.dcerpc import misc from samba.dcerpc import drsuapi from samba.ndr import ndr_unpack, ndr_pack from samba.dcerpc import drsblobs -from samba.common import dsdb_Dn +from samba.samdb import dsdb_Dn from samba.dcerpc import security from samba.descriptor import get_wellknown_sds, get_diff_sds from samba.auth import system_session, admin_session diff --git a/python/samba/kcc/kcc_utils.py b/python/samba/kcc/kcc_utils.py index e0712e49c82..9b4a894b743 100644 --- a/python/samba/kcc/kcc_utils.py +++ b/python/samba/kcc/kcc_utils.py @@ -30,7 +30,7 @@ from samba.dcerpc import ( drsuapi, misc, ) -from samba.common import dsdb_Dn +from samba.samdb import dsdb_Dn from samba.ndr import ndr_unpack, ndr_pack from collections import Counter diff --git a/python/samba/kcc/ldif_import_export.py b/python/samba/kcc/ldif_import_export.py index 86453f1e5c9..7ec553edcb9 100644 --- a/python/samba/kcc/ldif_import_export.py +++ b/python/samba/kcc/ldif_import_export.py @@ -23,8 +23,7 @@ import os from samba import Ldb, ldb, read_and_sub_file from samba.auth import system_session -from samba.samdb import SamDB -from samba.common import dsdb_Dn +from samba.samdb import SamDB, dsdb_Dn class LdifError(Exception): diff --git a/python/samba/samdb.py b/python/samba/samdb.py index e4030099b5c..47310f716f6 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -35,7 +35,9 @@ from samba.common import normalise_int32 from samba.compat import text_type from samba.compat import binary_type from samba.compat import get_bytes +from samba.common import cmp from samba.dcerpc import security +import binascii __docformat__ = "restructuredText" @@ -1317,3 +1319,76 @@ schemaUpdateNow: 1 if not full_dn.is_child_of(domain_dn): full_dn.add_base(domain_dn) return full_dn + +class dsdb_Dn(object): + '''a class for binary DN''' + + def __init__(self, samdb, dnstring, syntax_oid=None): + '''create a dsdb_Dn''' + if syntax_oid is None: + # auto-detect based on string + if dnstring.startswith("B:"): + syntax_oid = dsdb.DSDB_SYNTAX_BINARY_DN + elif dnstring.startswith("S:"): + syntax_oid = dsdb.DSDB_SYNTAX_STRING_DN + else: + syntax_oid = dsdb.DSDB_SYNTAX_OR_NAME + if syntax_oid in [dsdb.DSDB_SYNTAX_BINARY_DN, dsdb.DSDB_SYNTAX_STRING_DN]: + # it is a binary DN + colons = dnstring.split(':') + if len(colons) < 4: + raise RuntimeError("Invalid DN %s" % dnstring) + prefix_len = 4 + len(colons[1]) + int(colons[1]) + self.prefix = dnstring[0:prefix_len] + self.binary = self.prefix[3 + len(colons[1]):-1] + self.dnstring = dnstring[prefix_len:] + else: + self.dnstring = dnstring + self.prefix = '' + self.binary = '' + self.dn = ldb.Dn(samdb, self.dnstring) + + def __str__(self): + return self.prefix + str(self.dn.extended_str(mode=1)) + + def __cmp__(self, other): + ''' compare dsdb_Dn values similar to parsed_dn_compare()''' + dn1 = self + dn2 = other + guid1 = dn1.dn.get_extended_component("GUID") + guid2 = dn2.dn.get_extended_component("GUID") + + v = cmp(guid1, guid2) + if v != 0: + return v + v = cmp(dn1.binary, dn2.binary) + return v + + # In Python3, __cmp__ is replaced by these 6 methods + def __eq__(self, other): + return self.__cmp__(other) == 0 + + def __ne__(self, other): + return self.__cmp__(other) != 0 + + def __lt__(self, other): + return self.__cmp__(other) < 0 + + def __le__(self, other): + return self.__cmp__(other) <= 0 + + def __gt__(self, other): + return self.__cmp__(other) > 0 + + def __ge__(self, other): + return self.__cmp__(other) >= 0 + + def get_binary_integer(self): + '''return binary part of a dsdb_Dn as an integer, or None''' + if self.prefix == '': + return None + return int(self.binary, 16) + + def get_bytes(self): + '''return binary as a byte string''' + return binascii.unhexlify(self.binary) diff --git a/python/samba/tests/common.py b/python/samba/tests/common.py index 13f3ba2bc7a..2b7d22fd629 100644 --- a/python/samba/tests/common.py +++ b/python/samba/tests/common.py @@ -20,8 +20,8 @@ import samba import os import samba.tests -from samba.common import normalise_int32, dsdb_Dn -from samba.samdb import SamDB +from samba.common import normalise_int32 +from samba.samdb import SamDB, dsdb_Dn class CommonTests(samba.tests.TestCaseInTempDir): diff --git a/source4/torture/drs/python/repl_rodc.py b/source4/torture/drs/python/repl_rodc.py index 8e2b2ef51cf..f27f02814af 100644 --- a/source4/torture/drs/python/repl_rodc.py +++ b/source4/torture/drs/python/repl_rodc.py @@ -37,7 +37,7 @@ from samba.join import DCJoinContext from samba.dcerpc import drsuapi, misc, drsblobs, security from samba.drs_utils import drs_DsBind, drs_Replicate from samba.ndr import ndr_unpack, ndr_pack -from samba.common import dsdb_Dn +from samba.samdb import dsdb_Dn from samba.credentials import Credentials import random -- 2.25.1 From cdc2eb51822982dcb4512cb30e8e33637841d818 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 11 Oct 2018 13:08:38 +1300 Subject: [PATCH 224/645] python/join: use the provided krbtgt link in cleanup_old_accounts Before we were putting it in an otherwise unused variable, and deleting the previous krbtgt_dn, if any. Signed-off-by: Douglas Bagnall Reviewed-by: Andreas Schneider Reviewed-by: David Mulder BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 98f6ece5ad03a822180796873197383c17c3c6d9) --- python/samba/join.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/join.py b/python/samba/join.py index 40920f4f8e5..0cffa3055df 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -259,7 +259,7 @@ class DCJoinContext(object): ctx.del_noerror(res[0].dn, recursive=True) if "msDS-Krbtgtlink" in res[0]: - new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0] + ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0] ctx.del_noerror(ctx.new_krbtgt_dn) res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(), -- 2.25.1 From 796b4bf650a60f4b449f02653d6d3f498079ab9f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Sep 2021 16:43:00 +1200 Subject: [PATCH 225/645] autobuild: allow AUTOBUILD_FAIL_IMMEDIATELY=0 (say from a gitlab variable) This allows making a push to do a full test ignoring errors without needing "HACK!!!" commits on top. Use like this: git push -o ci.variable='AUTOBUILD_FAIL_IMMEDIATELY=0' RN: Samba CI runs can now continue past the first error if AUTOBUILD_FAIL_IMMEDIATELY=0 is set BUG: https://bugzilla.samba.org/show_bug.cgi?id=14841 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Michael Adam [abartlet@samba.org backported from commit b81f6f3d71487085bb355392ce7f8eff2db5bb4d due to changes in 4.15 and later for the autobuild dependent jobs work that avoids rebuilding Samba in each task] Autobuild-User(v4-14-test): Jule Anger Autobuild-Date(v4-14-test): Thu Sep 23 08:54:03 UTC 2021 on sn-devel-184 (cherry picked from commit f53c532c2292d07ab3374920bd83c1266663038e) --- script/autobuild.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/script/autobuild.py b/script/autobuild.py index b1a1b4800d1..cc34a5e2cc0 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -153,7 +153,6 @@ def format_option(name, value=None): def make_test( cmd='make test', - FAIL_IMMEDIATELY=1, TESTS='', include_envs=None, exclude_envs=None): @@ -168,7 +167,13 @@ def make_test( TESTS = (TESTS + ' ' + ' '.join(test_options)).strip() _options = [] - if FAIL_IMMEDIATELY: + + # Allow getting a full CI with + # git push -o ci.variable='AUTOBUILD_FAIL_IMMEDIATELY=0' + + FAIL_IMMEDIATELY = os.getenv("AUTOBUILD_FAIL_IMMEDIATELY", "1") + + if int(FAIL_IMMEDIATELY): _options.append('FAIL_IMMEDIATELY=1') if TESTS: _options.append("TESTS='{}'".format(TESTS)) -- 2.25.1 From 4d44d32ba98fbefc2611f4c124c72cd5c0ae0181 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 15:39:19 +1200 Subject: [PATCH 226/645] krb5pac.idl: Add ticket checksum PAC buffer type Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit ff2f38fae79220e16765e17671972f9a55eb7cce) --- librpc/idl/krb5pac.idl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index fb360c1257f..3239d7656b6 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -112,7 +112,8 @@ interface krb5pac PAC_TYPE_KDC_CHECKSUM = 7, PAC_TYPE_LOGON_NAME = 10, PAC_TYPE_CONSTRAINED_DELEGATION = 11, - PAC_TYPE_UPN_DNS_INFO = 12 + PAC_TYPE_UPN_DNS_INFO = 12, + PAC_TYPE_TICKET_CHECKSUM = 16 } PAC_TYPE; typedef struct { @@ -128,6 +129,7 @@ interface krb5pac [case(PAC_TYPE_CONSTRAINED_DELEGATION)][subcontext(0xFFFFFC01)] PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation; [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; + [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; /* when new PAC info types are added they are supposed to be done in such a way that they are backwards compatible with existing servers. This makes it safe to just use a [default] for -- 2.25.1 From 7867458342b7a1b709ff9f110ad5ae7fa89b106e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 15:40:59 +1200 Subject: [PATCH 227/645] security.idl: Add well-known SIDs for FAST Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 0092b4a3ed58b2c256d4dd9117cce927a3edde12) --- librpc/idl/security.idl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index a92e8f1518e..9845becd826 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -292,6 +292,9 @@ interface security const string SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = "S-1-18-1"; const string SID_SERVICE_ASSERTED_IDENTITY = "S-1-18-2"; + const string SID_COMPOUNDED_AUTHENTICATION = "S-1-5-21-0-0-0-496"; + const string SID_CLAIMS_VALID = "S-1-5-21-0-0-0-497"; + /* * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ -- 2.25.1 From ffac26e5a5c86f532569b362fbfa3794371411da Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 15:46:42 +1200 Subject: [PATCH 228/645] tests/krb5: Calculate expected salt if not given explicitly Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit c6badf818e9db44461979a931c74fc5ab6e80132) --- python/samba/tests/krb5/as_req_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 82ff3f4845c..09160bf6814 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -74,7 +74,7 @@ class AsReqKerberosTests(KDCBaseTest): expected_cname = cname expected_srealm = realm expected_sname = sname - expected_salt = client_creds.get_forced_salt() + expected_salt = client_creds.get_salt() if any(etype in client_as_etypes and etype in initial_etypes for etype in (kcrypto.Enctype.AES256, @@ -142,7 +142,7 @@ class AsReqKerberosTests(KDCBaseTest): expected_cname = cname expected_srealm = realm expected_sname = sname - expected_salt = client_creds.get_forced_salt() + expected_salt = client_creds.get_salt() till = self.get_KerberosTime(offset=36000) -- 2.25.1 From af349a0774ab4693ba8b760f1fae9db8901676b8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 15:50:26 +1200 Subject: [PATCH 229/645] tests/krb5: Add methods to obtain the length of checksum types Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 9924dd976183ea62b08f116f8b8bacc698bb9b95) --- python/samba/tests/krb5/kcrypto.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index c861e3cc96e..2a72969de00 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -478,6 +478,7 @@ class _ChecksumProfile(object): # define: # * checksum # * verify (if verification is not just checksum-and-compare) + # * checksum_len @classmethod def verify(cls, key, keyusage, text, cksum): expected = cls.checksum(key, keyusage, text) @@ -504,6 +505,10 @@ class _SimplifiedChecksum(_ChecksumProfile): raise ValueError('Wrong key type for checksum') super(_SimplifiedChecksum, cls).verify(key, keyusage, text, cksum) + @classmethod + def checksum_len(cls): + return cls.macsize + class _SHA1AES128(_SimplifiedChecksum): macsize = 12 @@ -533,6 +538,10 @@ class _HMACMD5(_ChecksumProfile): raise ValueError('Wrong key type for checksum') super(_HMACMD5, cls).verify(key, keyusage, text, cksum) + @classmethod + def checksum_len(cls): + return hashes.MD5.digest_size + class _MD5(_ChecksumProfile): @classmethod @@ -540,6 +549,10 @@ class _MD5(_ChecksumProfile): # This is unkeyed! return SIMPLE_HASH(text, hashes.MD5) + @classmethod + def checksum_len(cls): + return hashes.MD5.digest_size + class _SHA1(_ChecksumProfile): @classmethod @@ -547,6 +560,10 @@ class _SHA1(_ChecksumProfile): # This is unkeyed! return SIMPLE_HASH(text, hashes.SHA1) + @classmethod + def checksum_len(cls): + return hashes.SHA1.digest_size + class _CRC32(_ChecksumProfile): @classmethod @@ -555,6 +572,10 @@ class _CRC32(_ChecksumProfile): cksum = (~crc32(text, 0xffffffff)) & 0xffffffff return pack(' Date: Wed, 1 Sep 2021 15:57:26 +1200 Subject: [PATCH 230/645] tests/krb5: Use signed integers to represent key version numbers in ASN.1 As specified in 'MS-KILE 3.1.5.8: Key Version Numbers', Windows uses signed 32-bit integers to represent key version numbers. This makes a difference for an RODC with a msDS-SecondaryKrbTgtNumber greater than 32767, where the kvno should be encoded in four bytes rather than five. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 448b661bf8815a05f534926d8ee8d6f57d123c2c) --- python/samba/tests/krb5/raw_testcase.py | 2 +- python/samba/tests/krb5/rfc4120.asn1 | 2 +- python/samba/tests/krb5/rfc4120_pyasn1.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 6db17f2a118..c5ee5eb6083 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -995,7 +995,7 @@ class RawKerberosTest(TestCaseInTempDir): def EncryptedData_create(self, key, usage, plaintext): # EncryptedData ::= SEQUENCE { # etype [0] Int32 -- EncryptionType --, - # kvno [1] UInt32 OPTIONAL, + # kvno [1] Int32 OPTIONAL, # cipher [2] OCTET STRING -- ciphertext # } ciphertext = key.encrypt(usage, plaintext) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index f47c1d00202..a37011ae932 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -124,7 +124,7 @@ KerberosFlags ::= BIT STRING (SIZE (1..32)) EncryptedData ::= SEQUENCE { etype [0] EncryptionType, --Int32 EncryptionType -- - kvno [1] UInt32 OPTIONAL, + kvno [1] Int32 OPTIONAL, cipher [2] OCTET STRING -- ciphertext } diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index 39ec8ed7982..a9e4bcbb18f 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/python/samba/tests/krb5/rfc4120_pyasn1.py @@ -120,7 +120,7 @@ class EncryptedData(univ.Sequence): EncryptedData.componentType = namedtype.NamedTypes( namedtype.NamedType('etype', EncryptionType().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), - namedtype.OptionalNamedType('kvno', UInt32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('kvno', Int32().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), namedtype.NamedType('cipher', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) ) -- 2.25.1 From b1f8df20f1e45385e87e747474b1c632b9b18fd9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:05:39 +1200 Subject: [PATCH 231/645] tests/krb5: Add KDCOptions flag for constrained delegation Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 08086c43987abecc588ebd32ec846ff7e27a83b6) --- python/samba/tests/krb5/rfc4120.asn1 | 1 + python/samba/tests/krb5/rfc4120_pyasn1.py | 1 + 2 files changed, 2 insertions(+) diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 index a37011ae932..e0831e1f86f 100644 --- a/python/samba/tests/krb5/rfc4120.asn1 +++ b/python/samba/tests/krb5/rfc4120.asn1 @@ -632,6 +632,7 @@ KDCOptionsValues ::= BIT STRING { -- KerberosFlags opt-hardware-auth(11), unused12(12), unused13(13), + cname-in-addl-tkt(14), -- Canonicalize is used by RFC 6806 canonicalize(15), -- 26 was unused in 1510 diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py index a9e4bcbb18f..348dd8c63fb 100644 --- a/python/samba/tests/krb5/rfc4120_pyasn1.py +++ b/python/samba/tests/krb5/rfc4120_pyasn1.py @@ -649,6 +649,7 @@ KDCOptionsValues.namedValues = namedval.NamedValues( ('opt-hardware-auth', 11), ('unused12', 12), ('unused13', 13), + ('cname-in-addl-tkt', 14), ('canonicalize', 15), ('disable-transited-check', 26), ('renewable-ok', 27), -- 2.25.1 From 6d468dde7c5c5f068bd0cf1e220097601985acc0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:21:55 +1200 Subject: [PATCH 232/645] tests/krb5: Use more compact dict lookup Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 3fd73b65a3db405db5a0a82cca6c808763d4f437) --- python/samba/tests/krb5/raw_testcase.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c5ee5eb6083..0ec0f65c6d6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -305,7 +305,7 @@ class KerberosCredentials(Credentials): def get_forced_key(self, etype): etype = int(etype) - return self.forced_keys.get(etype, None) + return self.forced_keys.get(etype) def set_forced_salt(self, salt): self.forced_salt = bytes(salt) @@ -830,7 +830,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(value) def getElementValue(self, obj, elem): - return obj.get(elem, None) + return obj.get(elem) def assertElementMissing(self, obj, elem): v = self.getElementValue(obj, elem) @@ -942,7 +942,7 @@ class RawKerberosTest(TestCaseInTempDir): def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): e = etype_info2['etype'] - salt = etype_info2.get('salt', None) + salt = etype_info2.get('salt') if e == kcrypto.Enctype.RC4: nthash = creds.get_nt_hash() -- 2.25.1 From f15147b267ee8e39a5d58378a31efc7c15218f5b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:31:56 +1200 Subject: [PATCH 233/645] tests/krb5: Replace expected_cname_private with expected_anon parameter This is used in the case where the KDC returns 'WELLKNOWN/ANONYMOUS' as the cname, and makes the reply checking logic easier to follow. This also removes the need to fetch the client credentials in the test methods. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit bf55786fcd9a96daa9002661d6f5d9b3502ed8a7) --- python/samba/tests/krb5/fast_tests.py | 33 +++++------------------- python/samba/tests/krb5/raw_testcase.py | 34 ++++++++++++------------- 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 2d4b69f8590..b371ab617aa 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -49,7 +49,6 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TICKET, NT_PRINCIPAL, NT_SRV_INST, - NT_WELLKNOWN, PADATA_FX_COOKIE, PADATA_FX_FAST, PADATA_PAC_OPTIONS @@ -985,14 +984,6 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_hide_client_names(self): - user_creds = self.get_client_creds() - user_name = user_creds.get_username() - user_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=[user_name]) - - expected_cname = self.PrincipalName_create( - name_type=NT_WELLKNOWN, names=['WELLKNOWN', 'ANONYMOUS']) - self._run_test_sequence([ { 'rep_type': KRB_AS_REP, @@ -1001,7 +992,7 @@ class FAST_Tests(KDCBaseTest): 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, 'gen_armor_tgt_fn': self.get_mach_tgt, 'fast_options': '01', # hide client names - 'expected_cname': expected_cname + 'expected_anon': True }, { 'rep_type': KRB_AS_REP, @@ -1011,20 +1002,11 @@ class FAST_Tests(KDCBaseTest): 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, 'gen_armor_tgt_fn': self.get_mach_tgt, 'fast_options': '01', # hide client names - 'expected_cname': expected_cname, - 'expected_cname_private': user_cname + 'expected_anon': True } ]) def test_fast_tgs_hide_client_names(self): - user_creds = self.get_client_creds() - user_name = user_creds.get_username() - user_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=[user_name]) - - expected_cname = self.PrincipalName_create( - name_type=NT_WELLKNOWN, names=['WELLKNOWN', 'ANONYMOUS']) - self._run_test_sequence([ { 'rep_type': KRB_TGS_REP, @@ -1033,8 +1015,7 @@ class FAST_Tests(KDCBaseTest): 'gen_tgt_fn': self.get_user_tgt, 'fast_armor': None, 'fast_options': '01', # hide client names - 'expected_cname': expected_cname, - 'expected_cname_private': user_cname + 'expected_anon': True } ]) @@ -1216,8 +1197,8 @@ class FAST_Tests(KDCBaseTest): srealm = target_realm expected_cname = kdc_dict.pop('expected_cname', client_cname) - expected_cname_private = kdc_dict.pop('expected_cname_private', - None) + expected_anon = kdc_dict.pop('expected_anon', + False) expected_crealm = kdc_dict.pop('expected_crealm', client_realm) expected_sname = kdc_dict.pop('expected_sname', sname) expected_srealm = kdc_dict.pop('expected_srealm', srealm) @@ -1341,7 +1322,7 @@ class FAST_Tests(KDCBaseTest): kdc_exchange_dict = self.as_exchange_dict( expected_crealm=expected_crealm, expected_cname=expected_cname, - expected_cname_private=expected_cname_private, + expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, ticket_decryption_key=krbtgt_decryption_key, @@ -1370,7 +1351,7 @@ class FAST_Tests(KDCBaseTest): kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=expected_crealm, expected_cname=expected_cname, - expected_cname_private=expected_cname_private, + expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, ticket_decryption_key=target_decryption_key, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0ec0f65c6d6..e4dbb10d135 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1721,7 +1721,7 @@ class RawKerberosTest(TestCaseInTempDir): def as_exchange_dict(self, expected_crealm=None, expected_cname=None, - expected_cname_private=None, + expected_anon=False, expected_srealm=None, expected_sname=None, ticket_decryption_key=None, @@ -1759,6 +1759,7 @@ class RawKerberosTest(TestCaseInTempDir): 'rep_encpart_asn1Spec': krb5_asn1.EncASRepPart, 'expected_crealm': expected_crealm, 'expected_cname': expected_cname, + 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'ticket_decryption_key': ticket_decryption_key, @@ -1784,10 +1785,6 @@ class RawKerberosTest(TestCaseInTempDir): 'inner_req': inner_req, 'outer_req': outer_req } - if expected_cname_private is not None: - kdc_exchange_dict['expected_cname_private'] = ( - expected_cname_private) - if callback_dict is None: callback_dict = {} @@ -1796,7 +1793,7 @@ class RawKerberosTest(TestCaseInTempDir): def tgs_exchange_dict(self, expected_crealm=None, expected_cname=None, - expected_cname_private=None, + expected_anon=False, expected_srealm=None, expected_sname=None, ticket_decryption_key=None, @@ -1834,6 +1831,7 @@ class RawKerberosTest(TestCaseInTempDir): 'rep_encpart_asn1Spec': krb5_asn1.EncTGSRepPart, 'expected_crealm': expected_crealm, 'expected_cname': expected_cname, + 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'ticket_decryption_key': ticket_decryption_key, @@ -1859,10 +1857,6 @@ class RawKerberosTest(TestCaseInTempDir): 'inner_req': inner_req, 'outer_req': outer_req } - if expected_cname_private is not None: - kdc_exchange_dict['expected_cname_private'] = ( - expected_cname_private) - if callback_dict is None: callback_dict = {} @@ -1874,7 +1868,7 @@ class RawKerberosTest(TestCaseInTempDir): rep): expected_crealm = kdc_exchange_dict['expected_crealm'] - expected_cname = kdc_exchange_dict['expected_cname'] + expected_anon = kdc_exchange_dict['expected_anon'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] @@ -1888,6 +1882,12 @@ class RawKerberosTest(TestCaseInTempDir): padata = self.getElementValue(rep, 'padata') if self.strict_checking: self.assertElementEqualUTF8(rep, 'crealm', expected_crealm) + if expected_anon: + expected_cname = self.PrincipalName_create( + name_type=NT_WELLKNOWN, + names=['WELLKNOWN', 'ANONYMOUS']) + else: + expected_cname = kdc_exchange_dict['expected_cname'] self.assertElementEqualPrincipal(rep, 'cname', expected_cname) self.assertElementPresent(rep, 'ticket') ticket = self.getElementValue(rep, 'ticket') @@ -2042,14 +2042,11 @@ class RawKerberosTest(TestCaseInTempDir): and kdc_options[canon_pos] == '1') expected_crealm = kdc_exchange_dict['expected_crealm'] + expected_cname = kdc_exchange_dict['expected_cname'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] - try: - expected_cname = kdc_exchange_dict['expected_cname_private'] - except KeyError: - expected_cname = kdc_exchange_dict['expected_cname'] ticket = self.getElementValue(rep, 'ticket') @@ -2182,7 +2179,7 @@ class RawKerberosTest(TestCaseInTempDir): rep_msg_type = kdc_exchange_dict['rep_msg_type'] - expected_cname = kdc_exchange_dict['expected_cname'] + expected_anon = kdc_exchange_dict['expected_anon'] expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] expected_error_mode = kdc_exchange_dict['expected_error_mode'] @@ -2203,7 +2200,10 @@ class RawKerberosTest(TestCaseInTempDir): # error-code checked above if self.strict_checking: self.assertElementMissing(rep, 'crealm') - if expected_cname['name-type'] == NT_WELLKNOWN and not inner: + if expected_anon and not inner: + expected_cname = self.PrincipalName_create( + name_type=NT_WELLKNOWN, + names=['WELLKNOWN', 'ANONYMOUS']) self.assertElementEqualPrincipal(rep, 'cname', expected_cname) else: self.assertElementMissing(rep, 'cname') -- 2.25.1 From e6cb12aaca2fe9fa6fc5feca728733f52fb3e0aa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:34:02 +1200 Subject: [PATCH 234/645] tests/krb5: Allow specifying an OU to create accounts in Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 7aae0e9b100b8cb7d1da78b8cb9a4a5c20acffbd) --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index f5c1eba9151..efe11da8468 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -151,12 +151,16 @@ class KDCBaseTest(RawKerberosTest): return default_enctypes def create_account(self, ldb, name, machine_account=False, - spn=None, upn=None, additional_details=None): + spn=None, upn=None, additional_details=None, + ou=None): '''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. ''' - dn = "cn=%s,%s" % (name, ldb.domain_dn()) + if ou is None: + ou = ldb.domain_dn() + + dn = "CN=%s,%s" % (name, ou) # remove the account if it exists, this will happen if a previous test # run failed -- 2.25.1 From 3729e1a3de69541f21f6b5d83285cb0b00b5f2e9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:34:46 +1200 Subject: [PATCH 235/645] tests/krb5: Allow specifying additional User Account Control flags for account Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 9aa900857441ea7e1c2d6c60bfa1ddeb142bf3e3) --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index efe11da8468..bd5bacfaca1 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -152,7 +152,7 @@ class KDCBaseTest(RawKerberosTest): def create_account(self, ldb, name, machine_account=False, spn=None, upn=None, additional_details=None, - ou=None): + ou=None, account_control=0): '''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. @@ -168,11 +168,11 @@ class KDCBaseTest(RawKerberosTest): if machine_account: object_class = "computer" account_name = "%s$" % name - account_control = str(UF_WORKSTATION_TRUST_ACCOUNT) + account_control |= UF_WORKSTATION_TRUST_ACCOUNT else: object_class = "user" account_name = name - account_control = str(UF_NORMAL_ACCOUNT) + account_control |= UF_NORMAL_ACCOUNT password = generate_random_password(32, 32) utf16pw = ('"%s"' % password).encode('utf-16-le') @@ -181,7 +181,7 @@ class KDCBaseTest(RawKerberosTest): "dn": dn, "objectclass": object_class, "sAMAccountName": account_name, - "userAccountControl": account_control, + "userAccountControl": str(account_control), "unicodePwd": utf16pw} if spn is not None: details["servicePrincipalName"] = spn -- 2.25.1 From e8967708191a9ffe624dc555e4d7d962417b1af5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 16:35:58 +1200 Subject: [PATCH 236/645] tests/krb5: Keep track of account DN in credentials object Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 9973b51e48a5d5f3e33c6e0da46e6231a42bd77a) --- python/samba/tests/krb5/kdc_base_test.py | 2 ++ python/samba/tests/krb5/raw_testcase.py | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index bd5bacfaca1..b52452358cc 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -201,6 +201,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_workstation(name) else: creds.set_workstation('') + creds.set_dn(dn) # # Save the account name so it can be deleted in tearDownClass self.accounts.add(dn) @@ -441,6 +442,7 @@ class KDCBaseTest(RawKerberosTest): kvno = int(res[0]['msDS-KeyVersionNumber'][0]) creds.set_kvno(kvno) + creds.set_dn(dn) keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e4dbb10d135..e62fad3d187 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -261,6 +261,8 @@ class KerberosCredentials(Credentials): self.forced_salt = None + self.dn = None + def set_as_supported_enctypes(self, value): self.as_supported_enctypes = int(value) @@ -327,6 +329,12 @@ class KerberosCredentials(Credentials): return salt_string.encode('utf-8') + def set_dn(self, dn): + self.dn = dn + + def get_dn(self): + return self.dn + class KerberosTicketCreds: def __init__(self, ticket, session_key, -- 2.25.1 From d9d6a08c86a2a4bca90938e7cae07ba8a7b876de Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 2 Sep 2021 14:27:00 +1200 Subject: [PATCH 237/645] tests/krb5: Move padata generation methods to base class This allows them to be used directly from RawKerberosTest. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 1f23b16ef3a900a1bda01bf2a5a3a3847e2e79d1) --- python/samba/tests/krb5/fast_tests.py | 14 -------------- python/samba/tests/krb5/raw_testcase.py | 13 +++++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index b371ab617aa..4fc297c1e34 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -51,7 +51,6 @@ from samba.tests.krb5.rfc4120_constants import ( NT_SRV_INST, PADATA_FX_COOKIE, PADATA_FX_FAST, - PADATA_PAC_OPTIONS ) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 import samba.tests.krb5.kcrypto as kcrypto @@ -1466,19 +1465,6 @@ class FAST_Tests(KDCBaseTest): return self.PA_DATA_create(PADATA_FX_COOKIE, cookie) - def get_pa_pac_request(self, request_pac=True): - pac_request = self.KERB_PA_PAC_REQUEST_create(request_pac) - - return pac_request - - def get_pa_pac_options(self, options): - pac_options = self.PA_PAC_OPTIONS_create(options) - pac_options = self.der_encode(pac_options, - asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) - pac_options = self.PA_DATA_create(PADATA_PAC_OPTIONS, pac_options) - - return pac_options - def check_kdc_fast_support(self): # Check that the KDC supports FAST diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e62fad3d187..b724baf5cf8 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1151,6 +1151,19 @@ class RawKerberosTest(TestCaseInTempDir): pa_data = self.PA_DATA_create(PADATA_PAC_REQUEST, pa_pac) return pa_data + def get_pa_pac_request(self, request_pac=True): + pac_request = self.KERB_PA_PAC_REQUEST_create(request_pac) + + return pac_request + + def get_pa_pac_options(self, options): + pac_options = self.PA_PAC_OPTIONS_create(options) + pac_options = self.der_encode(pac_options, + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) + pac_options = self.PA_DATA_create(PADATA_PAC_OPTIONS, pac_options) + + return pac_options + def KDC_REQ_BODY_create(self, kdc_options, cname, -- 2.25.1 From b6b7a3171612def1ed628d6be6faba9aacdacabe Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 2 Sep 2021 14:36:42 +1200 Subject: [PATCH 238/645] tests/krb5: add options to kdc_exchange_dict to specify including PAC-REQUEST or PAC-OPTIONS Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit c0db1ba54d238d4b2da8895215d8314b068ce09c) --- python/samba/tests/krb5/raw_testcase.py | 40 +++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b724baf5cf8..58f246606d7 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1574,6 +1574,9 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode = kdc_exchange_dict['expected_error_mode'] kdc_options = kdc_exchange_dict['kdc_options'] + pac_request = kdc_exchange_dict['pac_request'] + pac_options = kdc_exchange_dict['pac_options'] + # Parameters specific to the inner request body inner_req = kdc_exchange_dict['inner_req'] @@ -1619,6 +1622,14 @@ class RawKerberosTest(TestCaseInTempDir): else: del req_body[key] + additional_padata = [] + if pac_request is not None: + pa_pac_request = self.KERB_PA_PAC_REQUEST_create(pac_request) + additional_padata.append(pa_pac_request) + if pac_options is not None: + pa_pac_options = self.get_pa_pac_options(pac_options) + additional_padata.append(pa_pac_options) + if req_msg_type == KRB_AS_REQ: tgs_req = None tgs_req_padata = None @@ -1637,6 +1648,8 @@ class RawKerberosTest(TestCaseInTempDir): fast_padata, req_body = generate_fast_padata_fn(kdc_exchange_dict, callback_dict, req_body) + + fast_padata += additional_padata else: fast_padata = [] @@ -1701,6 +1714,9 @@ class RawKerberosTest(TestCaseInTempDir): if outer_padata is not None: padata += outer_padata + if fast is None: + padata += additional_padata + if not padata: padata = None @@ -1766,7 +1782,9 @@ class RawKerberosTest(TestCaseInTempDir): auth_data=None, kdc_options='', inner_req=None, - outer_req=None): + outer_req=None, + pac_request=None, + pac_options=None): if expected_error_mode == 0: expected_error_mode = () elif not isinstance(expected_error_mode, collections.abc.Container): @@ -1804,7 +1822,9 @@ class RawKerberosTest(TestCaseInTempDir): 'auth_data': auth_data, 'kdc_options': kdc_options, 'inner_req': inner_req, - 'outer_req': outer_req + 'outer_req': outer_req, + 'pac_request': pac_request, + 'pac_options': pac_options } if callback_dict is None: callback_dict = {} @@ -1838,7 +1858,9 @@ class RawKerberosTest(TestCaseInTempDir): body_checksum_type=None, kdc_options='', inner_req=None, - outer_req=None): + outer_req=None, + pac_request=None, + pac_options=None): if expected_error_mode == 0: expected_error_mode = () elif not isinstance(expected_error_mode, collections.abc.Container): @@ -1876,7 +1898,9 @@ class RawKerberosTest(TestCaseInTempDir): 'authenticator_subkey': authenticator_subkey, 'kdc_options': kdc_options, 'inner_req': inner_req, - 'outer_req': outer_req + 'outer_req': outer_req, + 'pac_request': pac_request, + 'pac_options': pac_options } if callback_dict is None: callback_dict = {} @@ -2820,7 +2844,9 @@ class RawKerberosTest(TestCaseInTempDir): padata, kdc_options, preauth_key=None, - ticket_decryption_key=None): + ticket_decryption_key=None, + pac_request=None, + pac_options=None): def _generate_padata_copy(_kdc_exchange_dict, _callback_dict, @@ -2860,7 +2886,9 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, expected_salt=expected_salt, - kdc_options=str(kdc_options)) + kdc_options=str(kdc_options), + pac_request=pac_request, + pac_options=pac_options) rep = self._generic_kdc_exchange(kdc_exchange_dict, cname=cname, -- 2.25.1 From 34076ef5a68ae003c8a2eda1a5ec59f97779f517 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 2 Sep 2021 14:37:27 +1200 Subject: [PATCH 239/645] tests/krb5: Don't create PAC request manually in as_req_tests Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit bc21ba2592093c765751ed3e8083dcd3512997f8) --- python/samba/tests/krb5/as_req_tests.py | 35 ++++++++----------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 09160bf6814..35f88a0c920 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -56,7 +56,7 @@ class AsReqKerberosTests(KDCBaseTest): def _test_as_req_nopreauth(self, initial_etypes, - initial_padata=None, + pac=None, initial_kdc_options=None): client_creds = self.get_client_creds() client_account = client_creds.get_username() @@ -84,27 +84,19 @@ class AsReqKerberosTests(KDCBaseTest): else: expected_error_mode = KDC_ERR_ETYPE_NOSUPP - def _generate_padata_copy(_kdc_exchange_dict, - _callback_dict, - req_body): - return initial_padata, req_body - - generate_padata_fn = (_generate_padata_copy - if initial_padata is not None - else None) - 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=generate_padata_fn, + 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)) + kdc_options=str(initial_kdc_options), + pac_request=pac) self._generic_kdc_exchange(kdc_exchange_dict, cname=cname, @@ -114,13 +106,8 @@ class AsReqKerberosTests(KDCBaseTest): def _test_as_req_no_preauth_with_args(self, etype_idx, pac): name, etypes = self.etype_test_permutation_by_idx(etype_idx) - if pac is None: - padata = None - else: - pa_pac = self.KERB_PA_PAC_REQUEST_create(pac) - padata = [pa_pac] self._test_as_req_nopreauth( - initial_padata=padata, + pac=pac, initial_etypes=etypes, initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) @@ -146,8 +133,6 @@ class AsReqKerberosTests(KDCBaseTest): till = self.get_KerberosTime(offset=36000) - pa_pac = self.KERB_PA_PAC_REQUEST_create(True) - initial_padata = [pa_pac] initial_etypes = client_as_etypes initial_kdc_options = krb5_asn1.KDCOptions('forwardable') initial_error_mode = KDC_ERR_PREAUTH_REQUIRED @@ -164,8 +149,9 @@ class AsReqKerberosTests(KDCBaseTest): expected_sname, expected_salt, initial_etypes, - initial_padata, - initial_kdc_options) + None, + initial_kdc_options, + pac_request=True) etype_info2 = kdc_exchange_dict['preauth_etype_info2'] self.assertIsNotNone(etype_info2) @@ -183,7 +169,7 @@ class AsReqKerberosTests(KDCBaseTest): pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) - preauth_padata = [pa_ts, pa_pac] + preauth_padata = [pa_ts] preauth_etypes = client_as_etypes preauth_kdc_options = krb5_asn1.KDCOptions('forwardable') preauth_error_mode = 0 # AS-REP @@ -207,7 +193,8 @@ class AsReqKerberosTests(KDCBaseTest): preauth_padata, preauth_kdc_options, preauth_key=preauth_key, - ticket_decryption_key=krbtgt_decryption_key) + ticket_decryption_key=krbtgt_decryption_key, + pac_request=True) self.assertIsNotNone(as_rep) if __name__ == "__main__": -- 2.25.1 From 196f05ec5ba359ee1e593acf0acf152fc80a6d49 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 2 Sep 2021 14:38:33 +1200 Subject: [PATCH 240/645] tests/krb5: Don't create PAC request or options manually in fast_tests Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 7556a4dfa64650939aef14a2fc4d10b9ed3d29f7) --- python/samba/tests/krb5/fast_tests.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 4fc297c1e34..e10db90a57e 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1093,8 +1093,6 @@ class FAST_Tests(KDCBaseTest): 'canonicalize,' 'renewable-ok')) - pac_request = self.get_pa_pac_request() - client_creds = self.get_client_creds() target_creds = self.get_service_creds() krbtgt_creds = self.get_krbtgt_creds() @@ -1250,7 +1248,7 @@ class FAST_Tests(KDCBaseTest): _callback_dict, req_body, padata): - return padata, req_body + return list(padata), req_body def _check_padata_preauth_key(_kdc_exchange_dict, _callback_dict, @@ -1260,15 +1258,9 @@ class FAST_Tests(KDCBaseTest): return preauth_key, as_rep_usage pac_options = kdc_dict.pop('pac_options', '1') # claims support - pac_options = self.get_pa_pac_options(pac_options) kdc_options = kdc_dict.pop('kdc_options', kdc_options_default) - if rep_type == KRB_AS_REP: - padata = [pac_request, pac_options] - else: - padata = [pac_options] - gen_padata_fn = kdc_dict.pop('gen_padata_fn', None) if gen_padata_fn is not None: self.assertEqual(KRB_AS_REP, rep_type) @@ -1278,10 +1270,10 @@ class FAST_Tests(KDCBaseTest): client_creds, preauth_etype_info2[0], client_creds.get_kvno()) - gen_padata = gen_padata_fn(preauth_key, armor_key) - padata.insert(0, gen_padata) + padata = [gen_padata_fn(preauth_key, armor_key)] else: preauth_key = None + padata = [] if rep_type == KRB_AS_REP: check_padata_fn = _check_padata_preauth_key @@ -1345,7 +1337,9 @@ class FAST_Tests(KDCBaseTest): armor_subkey=armor_subkey, kdc_options=kdc_options, inner_req=inner_req, - outer_req=outer_req) + outer_req=outer_req, + pac_request=True, + pac_options=pac_options) else: # KRB_TGS_REP kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=expected_crealm, @@ -1374,7 +1368,9 @@ class FAST_Tests(KDCBaseTest): body_checksum_type=None, kdc_options=kdc_options, inner_req=inner_req, - outer_req=outer_req) + outer_req=outer_req, + pac_request=None, + pac_options=pac_options) repeat = kdc_dict.pop('repeat', 1) for _ in range(repeat): -- 2.25.1 From 52daf20612c87e64ddb6d32384dcc6340567738d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 17:46:02 +1200 Subject: [PATCH 241/645] tests/krb5: Remove magic constants Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 571265257f335ba7f6f1b46daa0d657b8a8dff2b) --- python/samba/tests/krb5/fast_tests.py | 2 +- python/samba/tests/krb5/kdc_base_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index e10db90a57e..29a666aad5e 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1466,7 +1466,7 @@ class FAST_Tests(KDCBaseTest): samdb = self.get_samdb() - krbtgt_rid = 502 + krbtgt_rid = security.DOMAIN_RID_KRBTGT krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid) res = samdb.search(base='' % krbtgt_sid, diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b52452358cc..ac43b2eae1a 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -425,7 +425,7 @@ class KDCBaseTest(RawKerberosTest): def download_krbtgt_creds(): samdb = self.get_samdb() - krbtgt_rid = 502 + krbtgt_rid = security.DOMAIN_RID_KRBTGT krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid) res = samdb.search(base='' % krbtgt_sid, -- 2.25.1 From e2e7d479cc563ff17d610ce91e7ac2a32845596e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:13:11 +1200 Subject: [PATCH 242/645] tests/krb5: Allow specifying ticket flags expected to be set or reset Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 85ddfc1afcf21797dab15431a5f375444c4d316e) --- python/samba/tests/krb5/fast_tests.py | 11 +++++++ python/samba/tests/krb5/raw_testcase.py | 40 +++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 29a666aad5e..687f7532a64 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1309,6 +1309,13 @@ class FAST_Tests(KDCBaseTest): inner_req = kdc_dict.pop('inner_req', None) outer_req = kdc_dict.pop('outer_req', None) + expected_flags = kdc_dict.pop('expected_flags', None) + if expected_flags is not None: + expected_flags = krb5_asn1.KDCOptions(expected_flags) + unexpected_flags = kdc_dict.pop('unexpected_flags', None) + if unexpected_flags is not None: + unexpected_flags = krb5_asn1.KDCOptions(unexpected_flags) + if rep_type == KRB_AS_REP: kdc_exchange_dict = self.as_exchange_dict( expected_crealm=expected_crealm, @@ -1316,6 +1323,8 @@ class FAST_Tests(KDCBaseTest): expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, ticket_decryption_key=krbtgt_decryption_key, generate_fast_fn=generate_fast_fn, generate_fast_armor_fn=generate_fast_armor_fn, @@ -1347,6 +1356,8 @@ class FAST_Tests(KDCBaseTest): expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, ticket_decryption_key=target_decryption_key, generate_fast_fn=generate_fast_fn, generate_fast_armor_fn=generate_fast_armor_fn, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 58f246606d7..268f6ccc6bb 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -896,6 +896,24 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertIsNone(v) + def assertElementFlags(self, obj, elem, expected, unexpected): + v = self.getElementValue(obj, elem) + self.assertIsNotNone(v) + if expected is not None: + self.assertIsInstance(expected, krb5_asn1.KDCOptions) + for i, flag in enumerate(expected): + if flag == 1: + self.assertEqual('1', v[i], + f"'{expected.namedValues[i]}' " + f"expected in {v}") + if unexpected is not None: + self.assertIsInstance(unexpected, krb5_asn1.KDCOptions) + for i, flag in enumerate(unexpected): + if flag == 1: + self.assertEqual('0', v[i], + f"'{unexpected.namedValues[i]}' " + f"unexpected in {v}") + def get_KerberosTimeWithUsec(self, epoch=None, offset=None): if epoch is None: epoch = time.time() @@ -1761,6 +1779,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_flags=None, + unexpected_flags=None, ticket_decryption_key=None, generate_fast_fn=None, generate_fast_armor_fn=None, @@ -1801,6 +1821,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_flags': expected_flags, + 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, 'generate_fast_fn': generate_fast_fn, 'generate_fast_armor_fn': generate_fast_armor_fn, @@ -1837,6 +1859,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_flags=None, + unexpected_flags=None, ticket_decryption_key=None, generate_fast_fn=None, generate_fast_armor_fn=None, @@ -1877,6 +1901,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_flags': expected_flags, + 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, 'generate_fast_fn': generate_fast_fn, 'generate_fast_armor_fn': generate_fast_armor_fn, @@ -2092,6 +2118,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] + expected_flags = kdc_exchange_dict.get('expected_flags') + unexpected_flags = kdc_exchange_dict.get('unexpected_flags') ticket = self.getElementValue(rep, 'ticket') @@ -2101,7 +2129,9 @@ class RawKerberosTest(TestCaseInTempDir): ticket_session_key = None if ticket_private is not None: - self.assertElementPresent(ticket_private, 'flags') + self.assertElementFlags(ticket_private, 'flags', + expected_flags, + unexpected_flags) self.assertElementPresent(ticket_private, 'key') ticket_key = self.getElementValue(ticket_private, 'key') self.assertIsNotNone(ticket_key) @@ -2137,7 +2167,9 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['nonce']) # TODO self.assertElementPresent(encpart_private, # 'key-expiration') - self.assertElementPresent(encpart_private, 'flags') + self.assertElementFlags(ticket_private, 'flags', + expected_flags, + unexpected_flags) self.assertElementPresent(encpart_private, 'authtime') if self.strict_checking: self.assertElementPresent(encpart_private, 'starttime') @@ -2843,6 +2875,8 @@ class RawKerberosTest(TestCaseInTempDir): etypes, padata, kdc_options, + expected_flags=None, + unexpected_flags=None, preauth_key=None, ticket_decryption_key=None, pac_request=None, @@ -2886,6 +2920,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, expected_salt=expected_salt, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, kdc_options=str(kdc_options), pac_request=pac_request, pac_options=pac_options) -- 2.25.1 From 6b629107f6223f73d5d3ee4c347f9d5c1c299689 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:15:17 +1200 Subject: [PATCH 243/645] tests/krb5: Make time assertion less strict This assertion could fail if there was a time difference between the KDC and the client. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 1974b872fb5a7da052305d01e2f1efc8d0637078) --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 268f6ccc6bb..5ae8fe4ba41 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2559,7 +2559,7 @@ class RawKerberosTest(TestCaseInTempDir): current_time = time.time() self.assertLess(current_time - 300, rep_time) - self.assertLess(rep_time, current_time) + self.assertLess(rep_time, current_time + 300) if all(etype not in client_as_etypes or etype not in proposed_etypes for etype in (kcrypto.Enctype.AES256, -- 2.25.1 From 043894e69fb56f1c1f89e193ee02299c273fb016 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:34:20 +1200 Subject: [PATCH 244/645] tests/krb5: Allow Kerberos requests to be sent to DC or RODC If run inside the 'rodc' testing environment, 'DC_SERVER' and 'SERVER' refer to the hostnames of the DC and RODC respectively, and this commit allows either one of them to be used as the KDC for Kerberos exchanges. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 0afb548a0a3221730c4a81d51bc31e99ec90e334) --- python/samba/tests/krb5/kdc_base_test.py | 2 +- python/samba/tests/krb5/raw_testcase.py | 39 +++++++++++++++--------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index ac43b2eae1a..0755040a87a 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -116,7 +116,7 @@ class KDCBaseTest(RawKerberosTest): lp = self.get_lp() session = system_session() - type(self)._ldb = SamDB(url="ldap://%s" % self.host, + type(self)._ldb = SamDB(url="ldap://%s" % self.dc_host, session_info=session, credentials=creds, lp=lp) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 5ae8fe4ba41..c03600f765b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -418,6 +418,7 @@ class RawKerberosTest(TestCaseInTempDir): super().setUpClass() cls.host = samba.tests.env_get_var_value('SERVER') + cls.dc_host = samba.tests.env_get_var_value('DC_SERVER') # A dictionary containing credentials that have already been # obtained. @@ -452,10 +453,10 @@ class RawKerberosTest(TestCaseInTempDir): if self.do_hexdump: sys.stderr.write("disconnect[%s]\n" % reason) - def _connect_tcp(self): + def _connect_tcp(self, host): tcp_port = 88 try: - self.a = socket.getaddrinfo(self.host, tcp_port, socket.AF_UNSPEC, + self.a = socket.getaddrinfo(host, tcp_port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.SOL_TCP, 0) self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2]) @@ -468,11 +469,11 @@ class RawKerberosTest(TestCaseInTempDir): self.s.close() raise - def connect(self): + def connect(self, host): self.assertNotConnected() - self._connect_tcp() + self._connect_tcp(host) if self.do_hexdump: - sys.stderr.write("connected[%s]\n" % self.host) + sys.stderr.write("connected[%s]\n" % host) def env_get_var(self, varname, prefix, fallback_default=True, @@ -819,8 +820,10 @@ class RawKerberosTest(TestCaseInTempDir): req, asn1_print=None, hexdump=None, - timeout=None): - self.connect() + timeout=None, + to_rodc=False): + host = self.host if to_rodc else self.dc_host + self.connect(host) try: self.send_pdu(req, asn1_print=asn1_print, hexdump=hexdump) rep = self.recv_pdu( @@ -1747,7 +1750,9 @@ class RawKerberosTest(TestCaseInTempDir): req_body=req_body, asn1Spec=req_asn1Spec()) - rep = self.send_recv_transaction(req_decoded) + to_rodc = kdc_exchange_dict['to_rodc'] + + rep = self.send_recv_transaction(req_decoded, to_rodc=to_rodc) self.assertIsNotNone(rep) msg_type = self.getElementValue(rep, 'msg-type') @@ -1804,7 +1809,8 @@ class RawKerberosTest(TestCaseInTempDir): inner_req=None, outer_req=None, pac_request=None, - pac_options=None): + pac_options=None, + to_rodc=False): if expected_error_mode == 0: expected_error_mode = () elif not isinstance(expected_error_mode, collections.abc.Container): @@ -1846,7 +1852,8 @@ class RawKerberosTest(TestCaseInTempDir): 'inner_req': inner_req, 'outer_req': outer_req, 'pac_request': pac_request, - 'pac_options': pac_options + 'pac_options': pac_options, + 'to_rodc': to_rodc } if callback_dict is None: callback_dict = {} @@ -1884,7 +1891,8 @@ class RawKerberosTest(TestCaseInTempDir): inner_req=None, outer_req=None, pac_request=None, - pac_options=None): + pac_options=None, + to_rodc=False): if expected_error_mode == 0: expected_error_mode = () elif not isinstance(expected_error_mode, collections.abc.Container): @@ -1926,7 +1934,8 @@ class RawKerberosTest(TestCaseInTempDir): 'inner_req': inner_req, 'outer_req': outer_req, 'pac_request': pac_request, - 'pac_options': pac_options + 'pac_options': pac_options, + 'to_rodc': to_rodc } if callback_dict is None: callback_dict = {} @@ -2880,7 +2889,8 @@ class RawKerberosTest(TestCaseInTempDir): preauth_key=None, ticket_decryption_key=None, pac_request=None, - pac_options=None): + pac_options=None, + to_rodc=False): def _generate_padata_copy(_kdc_exchange_dict, _callback_dict, @@ -2924,7 +2934,8 @@ class RawKerberosTest(TestCaseInTempDir): unexpected_flags=unexpected_flags, kdc_options=str(kdc_options), pac_request=pac_request, - pac_options=pac_options) + pac_options=pac_options, + to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, cname=cname, -- 2.25.1 From 0c51c8cb0a8fc343b2590afe2fd0e1808049f8d4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:43:41 +1200 Subject: [PATCH 245/645] tests/krb5: Check for presence of 'renew-till' element Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 9cba5f9a1b098e49315e2e3d4c0b626884c04a64) --- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c03600f765b..45ce3c092ad 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2120,6 +2120,9 @@ class RawKerberosTest(TestCaseInTempDir): canon_pos = len(tuple(krb5_asn1.KDCOptions('canonicalize'))) - 1 canonicalize = (canon_pos < len(kdc_options) and kdc_options[canon_pos] == '1') + renewable_pos = len(tuple(krb5_asn1.KDCOptions('renewable'))) - 1 + renewable = (renewable_pos < len(kdc_options) + and kdc_options[renewable_pos] == '1') expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] @@ -2158,7 +2161,11 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertElementPresent(ticket_private, 'starttime') self.assertElementPresent(ticket_private, 'endtime') - # TODO self.assertElementPresent(ticket_private, 'renew-till') + if renewable: + if self.strict_checking: + self.assertElementPresent(ticket_private, 'renew-till') + else: + self.assertElementMissing(ticket_private, 'renew-till') # TODO self.assertElementMissing(ticket_private, 'caddr') self.assertElementPresent(ticket_private, 'authorization-data') @@ -2183,7 +2190,11 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertElementPresent(encpart_private, 'starttime') self.assertElementPresent(encpart_private, 'endtime') - # TODO self.assertElementPresent(encpart_private, 'renew-till') + if renewable: + if self.strict_checking: + self.assertElementPresent(encpart_private, 'renew-till') + else: + self.assertElementMissing(encpart_private, 'renew-till') self.assertElementEqualUTF8(encpart_private, 'srealm', expected_srealm) self.assertElementEqualPrincipal(encpart_private, 'sname', -- 2.25.1 From e9e30d176707c73a773a4f49b278073580cb6edd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:45:57 +1200 Subject: [PATCH 246/645] tests/krb5: Check 'caddr' element Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit d3106a8d35225e826d548d3bea0d42edc3998c38) --- python/samba/tests/krb5/raw_testcase.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 45ce3c092ad..9e47897dd76 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2166,7 +2166,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(ticket_private, 'renew-till') else: self.assertElementMissing(ticket_private, 'renew-till') - # TODO self.assertElementMissing(ticket_private, 'caddr') + if self.strict_checking: + self.assertElementEqual(ticket_private, 'caddr', []) self.assertElementPresent(ticket_private, 'authorization-data') encpart_session_key = None @@ -2199,7 +2200,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm) self.assertElementEqualPrincipal(encpart_private, 'sname', expected_sname) - # TODO self.assertElementMissing(encpart_private, 'caddr') + if self.strict_checking: + self.assertElementEqual(encpart_private, 'caddr', []) sent_claims = self.sent_claims(kdc_exchange_dict) -- 2.25.1 From 3a2b88e649399e9c1355a11d59515f29228aef7e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:47:27 +1200 Subject: [PATCH 247/645] tests/krb5: Check for presence of 'key-expiration' element Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit c3b746290278f7b5c1dea676e3fa28b9f15bcf94) --- python/samba/tests/krb5/raw_testcase.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 9e47897dd76..e754794e48b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2130,6 +2130,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] + rep_msg_type = kdc_exchange_dict['rep_msg_type'] + expected_flags = kdc_exchange_dict.get('expected_flags') unexpected_flags = kdc_exchange_dict.get('unexpected_flags') @@ -2182,8 +2184,13 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(encpart_private, 'last-req') self.assertElementEqual(encpart_private, 'nonce', kdc_exchange_dict['nonce']) - # TODO self.assertElementPresent(encpart_private, - # 'key-expiration') + if rep_msg_type == KRB_AS_REP: + if self.strict_checking: + self.assertElementPresent(encpart_private, + 'key-expiration') + else: + self.assertElementMissing(encpart_private, + 'key-expiration') self.assertElementFlags(ticket_private, 'flags', expected_flags, unexpected_flags) -- 2.25.1 From c3e4114f686633178a14234a134c9dfc1b1ee3f8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Sep 2021 09:18:32 +1200 Subject: [PATCH 248/645] tests/krb5: Create testing accounts in appropriate containers Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Isaac Boukris BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Tue Sep 14 00:01:44 UTC 2021 on sn-devel-184 (cherry picked from commit 01378a52a1cf0b6855492673455013d5719be45b) --- python/samba/tests/krb5/kdc_base_test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 0755040a87a..49a3227c26e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -34,6 +34,8 @@ from samba.drs_utils import drsuapi_connect from samba.dsdb import ( DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, + DS_GUID_COMPUTERS_CONTAINER, + DS_GUID_USERS_CONTAINER, UF_WORKSTATION_TRUST_ACCOUNT, UF_NORMAL_ACCOUNT ) @@ -158,7 +160,10 @@ class KDCBaseTest(RawKerberosTest): which is used by tearDownClass to clean up the created accounts. ''' if ou is None: - ou = ldb.domain_dn() + guid = (DS_GUID_COMPUTERS_CONTAINER if machine_account + else DS_GUID_USERS_CONTAINER) + + ou = ldb.get_wellknown_dn(ldb.get_default_basedn(), guid) dn = "CN=%s,%s" % (name, ou) -- 2.25.1 From b2e7dd97a4c61bb88b17703aff6d5a4201e83202 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 19:26:43 +1200 Subject: [PATCH 249/645] tests/krb5: Allow specifying status code to be checked This allows us to check the status code that may be sent in an error reply to a TGS-REQ message. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 4ba5e82ae53410ec9a0bc7d47b181a88c15d9387) --- python/samba/tests/krb5/raw_testcase.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e754794e48b..f65811243ba 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1798,6 +1798,7 @@ class RawKerberosTest(TestCaseInTempDir): check_kdc_private_fn=None, callback_dict=None, expected_error_mode=0, + expected_status=None, client_as_etypes=None, expected_salt=None, authenticator_subkey=None, @@ -1841,6 +1842,7 @@ class RawKerberosTest(TestCaseInTempDir): 'check_kdc_private_fn': check_kdc_private_fn, 'callback_dict': callback_dict, 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, 'authenticator_subkey': authenticator_subkey, @@ -1879,6 +1881,7 @@ class RawKerberosTest(TestCaseInTempDir): check_padata_fn=None, check_kdc_private_fn=None, expected_error_mode=0, + expected_status=None, callback_dict=None, tgt=None, armor_key=None, @@ -1923,6 +1926,7 @@ class RawKerberosTest(TestCaseInTempDir): 'check_kdc_private_fn': check_kdc_private_fn, 'callback_dict': callback_dict, 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, 'tgt': tgt, 'body_checksum_type': body_checksum_type, 'armor_key': armor_key, @@ -2540,7 +2544,12 @@ class RawKerberosTest(TestCaseInTempDir): status = int.from_bytes(pw_salt[:4], 'little') flags = int.from_bytes(pw_salt[8:], 'little') + expected_status = kdc_exchange_dict['expected_status'] + self.assertEqual(expected_status, status) + self.assertEqual(3, flags) + else: + self.assertIsNone(kdc_exchange_dict.get('expected_status')) if enc_challenge is not None: if not sent_enc_challenge: -- 2.25.1 From f9787bb9393108ddab4d2204f61be2b36a8bfea1 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Sep 2021 09:40:02 +1200 Subject: [PATCH 250/645] tests/krb5: Get expected cname from TGT for TGS-REQ messages BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit a5186f92803009c81eca2957e1bf2eb0ff7b6dff) --- python/samba/tests/krb5/fast_tests.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 687f7532a64..e1ba4628994 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -179,18 +179,12 @@ class FAST_Tests(KDCBaseTest): ]) def test_simple_tgs_wrong_principal(self): - mach_creds = self.get_mach_creds() - mach_name = mach_creds.get_username() - expected_cname = self.PrincipalName_create( - name_type=NT_PRINCIPAL, names=[mach_name]) - self._run_test_sequence([ { 'rep_type': KRB_TGS_REP, 'expected_error_mode': 0, 'use_fast': False, - 'gen_tgt_fn': self.get_mach_tgt, - 'expected_cname': expected_cname + 'gen_tgt_fn': self.get_mach_tgt } ]) @@ -1193,7 +1187,12 @@ class FAST_Tests(KDCBaseTest): else: # KRB_TGS_REP srealm = target_realm - expected_cname = kdc_dict.pop('expected_cname', client_cname) + if rep_type == KRB_TGS_REP: + tgt_cname = tgt.cname + else: + tgt_cname = client_cname + + expected_cname = kdc_dict.pop('expected_cname', tgt_cname) expected_anon = kdc_dict.pop('expected_anon', False) expected_crealm = kdc_dict.pop('expected_crealm', client_realm) -- 2.25.1 From ebc0308ca68849c99b96db7a9cf3fa9e495a83af Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Sep 2021 09:55:10 +1200 Subject: [PATCH 251/645] tests/krb5: Get encpart decryption key from kdc_exchange_dict Instead of using check_padata_fn to get the encpart decryption key, we can get the key from the AS-REQ preauth phase or from the TGT, depending on whether the message is an AS-REQ or a TGS-REQ. This allows removal of check_padata_fn and some duplicated code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 0e99382d73f44eed7e19e83e430938d587e762d0) --- python/samba/tests/krb5/fast_tests.py | 18 +--- python/samba/tests/krb5/raw_testcase.py | 122 ++++++++++-------------- 2 files changed, 54 insertions(+), 86 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index e1ba4628994..12235cd439e 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -45,7 +45,6 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, KRB_AS_REP, KRB_TGS_REP, - KU_AS_REP_ENC_PART, KU_TICKET, NT_PRINCIPAL, NT_SRV_INST, @@ -1114,8 +1113,6 @@ class FAST_Tests(KDCBaseTest): fast_cookie = None preauth_etype_info2 = None - preauth_key = None - for kdc_dict in test_sequence: rep_type = kdc_dict.pop('rep_type') self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP)) @@ -1249,13 +1246,6 @@ class FAST_Tests(KDCBaseTest): padata): return list(padata), req_body - def _check_padata_preauth_key(_kdc_exchange_dict, - _callback_dict, - _rep, - _padata): - as_rep_usage = KU_AS_REP_ENC_PART - return preauth_key, as_rep_usage - pac_options = kdc_dict.pop('pac_options', '1') # claims support kdc_options = kdc_dict.pop('kdc_options', kdc_options_default) @@ -1274,11 +1264,6 @@ class FAST_Tests(KDCBaseTest): preauth_key = None padata = [] - if rep_type == KRB_AS_REP: - check_padata_fn = _check_padata_preauth_key - else: - check_padata_fn = self.check_simple_tgs_padata - if use_fast: inner_padata = padata outer_padata = [] @@ -1332,13 +1317,13 @@ class FAST_Tests(KDCBaseTest): generate_padata_fn=generate_padata_fn, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, - check_padata_fn=check_padata_fn, check_kdc_private_fn=self.generic_check_kdc_private, callback_dict={}, expected_error_mode=expected_error_mode, client_as_etypes=etypes, expected_salt=expected_salt, authenticator_subkey=authenticator_subkey, + preauth_key=preauth_key, auth_data=auth_data, armor_key=armor_key, armor_tgt=armor_tgt, @@ -1365,7 +1350,6 @@ class FAST_Tests(KDCBaseTest): generate_padata_fn=generate_padata_fn, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, - check_padata_fn=check_padata_fn, check_kdc_private_fn=self.generic_check_kdc_private, expected_error_mode=expected_error_mode, callback_dict={}, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f65811243ba..164d06b9788 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1794,7 +1794,6 @@ class RawKerberosTest(TestCaseInTempDir): generate_padata_fn=None, check_error_fn=None, check_rep_fn=None, - check_padata_fn=None, check_kdc_private_fn=None, callback_dict=None, expected_error_mode=0, @@ -1802,6 +1801,7 @@ class RawKerberosTest(TestCaseInTempDir): client_as_etypes=None, expected_salt=None, authenticator_subkey=None, + preauth_key=None, armor_key=None, armor_tgt=None, armor_subkey=None, @@ -1838,7 +1838,6 @@ class RawKerberosTest(TestCaseInTempDir): 'generate_padata_fn': generate_padata_fn, 'check_error_fn': check_error_fn, 'check_rep_fn': check_rep_fn, - 'check_padata_fn': check_padata_fn, 'check_kdc_private_fn': check_kdc_private_fn, 'callback_dict': callback_dict, 'expected_error_mode': expected_error_mode, @@ -1846,6 +1845,7 @@ class RawKerberosTest(TestCaseInTempDir): 'client_as_etypes': client_as_etypes, 'expected_salt': expected_salt, 'authenticator_subkey': authenticator_subkey, + 'preauth_key': preauth_key, 'armor_key': armor_key, 'armor_tgt': armor_tgt, 'armor_subkey': armor_subkey, @@ -1878,7 +1878,6 @@ class RawKerberosTest(TestCaseInTempDir): generate_padata_fn=None, check_error_fn=None, check_rep_fn=None, - check_padata_fn=None, check_kdc_private_fn=None, expected_error_mode=0, expected_status=None, @@ -1922,7 +1921,6 @@ class RawKerberosTest(TestCaseInTempDir): 'generate_padata_fn': generate_padata_fn, 'check_error_fn': check_error_fn, 'check_rep_fn': check_rep_fn, - 'check_padata_fn': check_padata_fn, 'check_kdc_private_fn': check_kdc_private_fn, 'callback_dict': callback_dict, 'expected_error_mode': expected_error_mode, @@ -1956,7 +1954,6 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm = kdc_exchange_dict['expected_srealm'] expected_sname = kdc_exchange_dict['expected_sname'] ticket_decryption_key = kdc_exchange_dict['ticket_decryption_key'] - check_padata_fn = kdc_exchange_dict['check_padata_fn'] check_kdc_private_fn = kdc_exchange_dict['check_kdc_private_fn'] rep_encpart_asn1Spec = kdc_exchange_dict['rep_encpart_asn1Spec'] msg_type = kdc_exchange_dict['rep_msg_type'] @@ -2004,41 +2001,37 @@ class RawKerberosTest(TestCaseInTempDir): ticket_checksum = None - encpart_decryption_key = None - self.assertIsNotNone(check_padata_fn) - if check_padata_fn is not None: - # See if we can get the decryption key from the preauth phase - encpart_decryption_key, encpart_decryption_usage = ( - check_padata_fn(kdc_exchange_dict, callback_dict, - rep, padata)) - - if armor_key is not None: - pa_dict = self.get_pa_dict(padata) - - if PADATA_FX_FAST in pa_dict: - fx_fast_data = pa_dict[PADATA_FX_FAST] - fast_response = self.check_fx_fast_data(kdc_exchange_dict, - fx_fast_data, - armor_key, - finished=True) - - if 'strengthen-key' in fast_response: - strengthen_key = self.EncryptionKey_import( - fast_response['strengthen-key']) - encpart_decryption_key = ( - self.generate_strengthen_reply_key( - strengthen_key, - encpart_decryption_key)) - - fast_finished = fast_response.get('finished', None) - if fast_finished is not None: - ticket_checksum = fast_finished['ticket-checksum'] - - self.check_rep_padata(kdc_exchange_dict, - callback_dict, - rep, - fast_response['padata'], - error_code=0) + # Get the decryption key for the encrypted part + encpart_decryption_key, encpart_decryption_usage = ( + self.get_preauth_key(kdc_exchange_dict)) + + if armor_key is not None: + pa_dict = self.get_pa_dict(padata) + + if PADATA_FX_FAST in pa_dict: + fx_fast_data = pa_dict[PADATA_FX_FAST] + fast_response = self.check_fx_fast_data(kdc_exchange_dict, + fx_fast_data, + armor_key, + finished=True) + + if 'strengthen-key' in fast_response: + strengthen_key = self.EncryptionKey_import( + fast_response['strengthen-key']) + encpart_decryption_key = ( + self.generate_strengthen_reply_key( + strengthen_key, + encpart_decryption_key)) + + fast_finished = fast_response.get('finished') + if fast_finished is not None: + ticket_checksum = fast_finished['ticket-checksum'] + + self.check_rep_padata(kdc_exchange_dict, + callback_dict, + rep, + fast_response['padata'], + error_code=0) ticket_private = None self.assertIsNotNone(ticket_decryption_key) @@ -2558,13 +2551,7 @@ class RawKerberosTest(TestCaseInTempDir): armor_key = kdc_exchange_dict['armor_key'] self.assertIsNotNone(armor_key) - check_padata_fn = kdc_exchange_dict['check_padata_fn'] - padata = self.getElementValue(rep, 'padata') - self.assertIsNotNone(check_padata_fn) - preauth_key, _ = check_padata_fn(kdc_exchange_dict, - callback_dict, - rep, - padata) + preauth_key, _ = self.get_preauth_key(kdc_exchange_dict) kdc_challenge_key = self.generate_kdc_challenge_key( armor_key, preauth_key) @@ -2790,21 +2777,25 @@ class RawKerberosTest(TestCaseInTempDir): return padata, req_body - def check_simple_tgs_padata(self, - kdc_exchange_dict, - callback_dict, - rep, - padata): - tgt = kdc_exchange_dict['tgt'] - authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] - if authenticator_subkey is not None: - subkey = authenticator_subkey - subkey_usage = KU_TGS_REP_ENC_PART_SUB_KEY - else: - subkey = tgt.session_key - subkey_usage = KU_TGS_REP_ENC_PART_SESSION + def get_preauth_key(self, kdc_exchange_dict): + msg_type = kdc_exchange_dict['rep_msg_type'] + + if msg_type == KRB_AS_REP: + key = kdc_exchange_dict['preauth_key'] + usage = KU_AS_REP_ENC_PART + else: # KRB_TGS_REP + authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] + if authenticator_subkey is not None: + key = authenticator_subkey + usage = KU_TGS_REP_ENC_PART_SUB_KEY + else: + tgt = kdc_exchange_dict['tgt'] + key = tgt.session_key + usage = KU_TGS_REP_ENC_PART_SESSION + + self.assertIsNotNone(key) - return subkey, subkey_usage + return key, usage def generate_armor_key(self, subkey, session_key): armor_key = kcrypto.cf2(subkey.key, @@ -2926,13 +2917,6 @@ class RawKerberosTest(TestCaseInTempDir): req_body): return padata, req_body - def _check_padata_preauth_key(_kdc_exchange_dict, - _callback_dict, - rep, - padata): - as_rep_usage = KU_AS_REP_ENC_PART - return preauth_key, as_rep_usage - if not expected_error_mode: check_error_fn = None check_rep_fn = self.generic_check_kdc_rep @@ -2954,13 +2938,13 @@ class RawKerberosTest(TestCaseInTempDir): generate_padata_fn=generate_padata_fn, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, - check_padata_fn=_check_padata_preauth_key, check_kdc_private_fn=self.generic_check_kdc_private, expected_error_mode=expected_error_mode, client_as_etypes=client_as_etypes, expected_salt=expected_salt, expected_flags=expected_flags, unexpected_flags=unexpected_flags, + preauth_key=preauth_key, kdc_options=str(kdc_options), pac_request=pac_request, pac_options=pac_options, -- 2.25.1 From 3d0b84917acf9c14f98a27702e26ce9d5bc4ef3d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Sep 2021 15:36:24 +1200 Subject: [PATCH 252/645] tests/krb5: Add get_cached_creds() method to create persistent accounts for testing BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit c9fd8ffd8927ef42fd555e690f966f65aa01332e) --- python/samba/tests/krb5/fast_tests.py | 2 +- python/samba/tests/krb5/kdc_base_test.py | 191 +++++++++++++++-------- 2 files changed, 125 insertions(+), 68 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 12235cd439e..106b9b1fb78 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1108,7 +1108,7 @@ class FAST_Tests(KDCBaseTest): target_sname = self.PrincipalName_create( name_type=NT_SRV_INST, names=[target_service, target_username]) target_decryption_key = self.TicketDecryptionKey_from_creds( - target_creds, etype=kcrypto.Enctype.RC4) + target_creds) fast_cookie = None preauth_etype_info2 = None diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 49a3227c26e..b2b9d87c3af 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -22,6 +22,7 @@ from datetime import datetime, timezone import tempfile import binascii import collections +import secrets from collections import namedtuple import ldb @@ -37,7 +38,10 @@ from samba.dsdb import ( DS_GUID_COMPUTERS_CONTAINER, DS_GUID_USERS_CONTAINER, UF_WORKSTATION_TRUST_ACCOUNT, - UF_NORMAL_ACCOUNT + UF_NO_AUTH_DATA_REQUIRED, + UF_NORMAL_ACCOUNT, + UF_NOT_DELEGATED, + UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION ) from samba.ndr import ndr_pack, ndr_unpack from samba import net @@ -88,9 +92,17 @@ class KDCBaseTest(RawKerberosTest): cls._functional_level = None + # An identifier to ensure created accounts have unique names. Windows + # caches accounts based on usernames, so account names being different + # across test runs avoids previous test runs affecting the results. + cls.account_base = f'krb5_{secrets.token_hex(5)}_' + cls.account_id = 0 + # A set containing DNs of accounts created as part of testing. cls.accounts = set() + cls.account_cache = {} + @classmethod def tearDownClass(cls): # Clean up any accounts created by create_account. This is @@ -322,24 +334,113 @@ class KDCBaseTest(RawKerberosTest): creds.set_tgs_supported_enctypes(supported_enctypes) creds.set_ap_supported_enctypes(supported_enctypes) - def get_client_creds(self, - allow_missing_password=False, - allow_missing_keys=True): - def create_client_account(): - samdb = self.get_samdb() + def get_cached_creds(self, *, + machine_account, + opts=None): + if opts is None: + opts = {} + + opts_default = { + 'no_auth_data_required': False, + 'supported_enctypes': None, + 'not_delegated': False, + 'allowed_to_delegate_to': None, + 'trusted_to_auth_for_delegation': False, + 'fast_support': False + } + + account_opts = { + 'machine_account': machine_account, + **opts_default, + **opts + } + + cache_key = tuple(sorted(account_opts.items())) + + creds = self.account_cache.get(cache_key) + if creds is None: + creds = self.create_account_opts(**account_opts) + self.account_cache[cache_key] = creds + + return creds + + def create_account_opts(self, *, + machine_account, + no_auth_data_required, + supported_enctypes, + not_delegated, + allowed_to_delegate_to, + trusted_to_auth_for_delegation, + fast_support): + if machine_account: + self.assertFalse(not_delegated) + else: + self.assertIsNone(allowed_to_delegate_to) + self.assertFalse(trusted_to_auth_for_delegation) - creds, dn = self.create_account(samdb, 'kdctestclient') + samdb = self.get_samdb() - res = samdb.search(base=dn, - scope=ldb.SCOPE_BASE, - attrs=['msDS-KeyVersionNumber']) - kvno = int(res[0]['msDS-KeyVersionNumber'][0]) - creds.set_kvno(kvno) + user_name = self.account_base + str(self.account_id) + type(self).account_id += 1 - keys = self.get_keys(samdb, dn) - self.creds_set_keys(creds, keys) + user_account_control = 0 + if trusted_to_auth_for_delegation: + user_account_control |= UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION + if not_delegated: + user_account_control |= UF_NOT_DELEGATED + if no_auth_data_required: + user_account_control |= UF_NO_AUTH_DATA_REQUIRED - return creds + details = {} + + enctypes = supported_enctypes + if fast_support: + fast_bits = (security.KERB_ENCTYPE_FAST_SUPPORTED | + security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | + security.KERB_ENCTYPE_CLAIMS_SUPPORTED) + enctypes = (enctypes or 0) | fast_bits + + if enctypes is not None: + details['msDS-SupportedEncryptionTypes'] = str(enctypes) + + if allowed_to_delegate_to: + details['msDS-AllowedToDelegateTo'] = allowed_to_delegate_to + + if machine_account: + spn = 'host/' + user_name + else: + spn = None + + creds, dn = self.create_account(samdb, user_name, + machine_account=machine_account, + spn=spn, + additional_details=details, + account_control=user_account_control) + + res = samdb.search(base=dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + if machine_account: + if supported_enctypes is not None: + tgs_enctypes = supported_enctypes + else: + tgs_enctypes = security.KERB_ENCTYPE_RC4_HMAC_MD5 + + creds.set_tgs_supported_enctypes(tgs_enctypes) + + return creds + + def get_client_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + def create_client_account(): + return self.get_cached_creds(machine_account=False) c = self._get_krb5_creds(prefix='CLIENT', allow_missing_password=allow_missing_password, @@ -351,32 +452,8 @@ class KDCBaseTest(RawKerberosTest): allow_missing_password=False, allow_missing_keys=True): def create_mach_account(): - samdb = self.get_samdb() - - mach_name = 'kdctestmac' - details = { - 'msDS-SupportedEncryptionTypes': str( - security.KERB_ENCTYPE_FAST_SUPPORTED | - security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | - security.KERB_ENCTYPE_CLAIMS_SUPPORTED - ) - } - - creds, dn = self.create_account(samdb, mach_name, - machine_account=True, - spn='host/' + mach_name, - additional_details=details) - - res = samdb.search(base=dn, - scope=ldb.SCOPE_BASE, - attrs=['msDS-KeyVersionNumber']) - kvno = int(res[0]['msDS-KeyVersionNumber'][0]) - creds.set_kvno(kvno) - - keys = self.get_keys(samdb, dn) - self.creds_set_keys(creds, keys) - - return creds + return self.get_cached_creds(machine_account=True, + opts={'fast_support': True}) c = self._get_krb5_creds(prefix='MAC', allow_missing_password=allow_missing_password, @@ -388,32 +465,12 @@ class KDCBaseTest(RawKerberosTest): allow_missing_password=False, allow_missing_keys=True): def create_service_account(): - samdb = self.get_samdb() - - mach_name = 'kdctestservice' - details = { - 'msDS-SupportedEncryptionTypes': str( - security.KERB_ENCTYPE_FAST_SUPPORTED | - security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | - security.KERB_ENCTYPE_CLAIMS_SUPPORTED - ) - } - - creds, dn = self.create_account(samdb, mach_name, - machine_account=True, - spn='host/' + mach_name, - additional_details=details) - - res = samdb.search(base=dn, - scope=ldb.SCOPE_BASE, - attrs=['msDS-KeyVersionNumber']) - kvno = int(res[0]['msDS-KeyVersionNumber'][0]) - creds.set_kvno(kvno) - - keys = self.get_keys(samdb, dn) - self.creds_set_keys(creds, keys) - - return creds + return self.get_cached_creds( + machine_account=True, + opts={ + 'trusted_to_auth_for_delegation': True, + 'fast_support': True + }) c = self._get_krb5_creds(prefix='SERVICE', allow_missing_password=allow_missing_password, -- 2.25.1 From 7b6e0349d11fcc2dad8a0b8b428163d9bc5b27d4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 8 Sep 2021 11:28:52 +1200 Subject: [PATCH 253/645] tests/krb5: Generate padata for FAST tests This gives us access to parameters of kdc_exchange_dict and enables us to simplify the logic. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 943079fd94fec66cdc2ba4ea1b2beb2971473004) --- python/samba/tests/krb5/fast_tests.py | 101 ++++++++++++++++---------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 106b9b1fb78..8024b92f445 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1017,19 +1017,6 @@ class FAST_Tests(KDCBaseTest): # challenge is only considered a replay if the ciphertext is identical # to a previous challenge. Windows does not perform this check. - class GenerateEncChallengePadataReplay: - def __init__(replay): - replay._padata = None - - def __call__(replay, key, armor_key): - if replay._padata is None: - client_challenge_key = ( - self.generate_client_challenge_key(armor_key, key)) - replay._padata = self.get_challenge_pa_data( - client_challenge_key) - - return replay._padata - self._run_test_sequence([ { 'rep_type': KRB_AS_REP, @@ -1042,28 +1029,72 @@ class FAST_Tests(KDCBaseTest): 'rep_type': KRB_AS_REP, 'expected_error_mode': 0, 'use_fast': True, - 'gen_padata_fn': GenerateEncChallengePadataReplay(), + 'gen_padata_fn': self.generate_enc_challenge_padata_replay, 'fast_armor': FX_FAST_ARMOR_AP_REQUEST, 'gen_armor_tgt_fn': self.get_mach_tgt, 'repeat': 2 } ]) - def generate_enc_timestamp_padata(self, key, _armor_key): - return self.get_enc_timestamp_pa_data_from_key(key) + def generate_enc_timestamp_padata(self, + kdc_exchange_dict, + callback_dict, + req_body): + key = kdc_exchange_dict['preauth_key'] + + padata = self.get_enc_timestamp_pa_data_from_key(key) + return [padata], req_body + + def generate_enc_challenge_padata(self, + kdc_exchange_dict, + callback_dict, + req_body, + skew=0): + armor_key = kdc_exchange_dict['armor_key'] + key = kdc_exchange_dict['preauth_key'] - def generate_enc_challenge_padata(self, key, armor_key, skew=0): client_challenge_key = ( self.generate_client_challenge_key(armor_key, key)) - return self.get_challenge_pa_data(client_challenge_key, skew=skew) + padata = self.get_challenge_pa_data(client_challenge_key, skew=skew) + return [padata], req_body + + def generate_enc_challenge_padata_wrong_key_kdc(self, + kdc_exchange_dict, + callback_dict, + req_body): + armor_key = kdc_exchange_dict['armor_key'] + key = kdc_exchange_dict['preauth_key'] - def generate_enc_challenge_padata_wrong_key_kdc(self, key, armor_key): kdc_challenge_key = ( self.generate_kdc_challenge_key(armor_key, key)) - return self.get_challenge_pa_data(kdc_challenge_key) + padata = self.get_challenge_pa_data(kdc_challenge_key) + return [padata], req_body - def generate_enc_challenge_padata_wrong_key(self, key, _armor_key): - return self.get_challenge_pa_data(key) + def generate_enc_challenge_padata_wrong_key(self, + kdc_exchange_dict, + callback_dict, + req_body): + key = kdc_exchange_dict['preauth_key'] + + padata = self.get_challenge_pa_data(key) + return [padata], req_body + + def generate_enc_challenge_padata_replay(self, + kdc_exchange_dict, + callback_dict, + req_body): + padata = callback_dict.get('replay_padata') + + if padata is None: + armor_key = kdc_exchange_dict['armor_key'] + key = kdc_exchange_dict['preauth_key'] + + client_challenge_key = ( + self.generate_client_challenge_key(armor_key, key)) + padata = self.get_challenge_pa_data(client_challenge_key) + callback_dict['replay_padata'] = padata + + return [padata], req_body def generate_empty_fast(self, _kdc_exchange_dict, @@ -1251,35 +1282,25 @@ class FAST_Tests(KDCBaseTest): kdc_options = kdc_dict.pop('kdc_options', kdc_options_default) gen_padata_fn = kdc_dict.pop('gen_padata_fn', None) - if gen_padata_fn is not None: - self.assertEqual(KRB_AS_REP, rep_type) + + if rep_type == KRB_AS_REP and gen_padata_fn is not None: self.assertIsNotNone(preauth_etype_info2) preauth_key = self.PasswordKey_from_etype_info2( client_creds, preauth_etype_info2[0], client_creds.get_kvno()) - padata = [gen_padata_fn(preauth_key, armor_key)] else: preauth_key = None - padata = [] if use_fast: - inner_padata = padata - outer_padata = [] + generate_fast_padata_fn = gen_padata_fn + generate_padata_fn = (functools.partial(_generate_padata_copy, + padata=[fast_cookie]) + if fast_cookie is not None else None) else: - inner_padata = [] - outer_padata = padata - - if use_fast and fast_cookie is not None: - outer_padata.append(fast_cookie) - - generate_fast_padata_fn = (functools.partial(_generate_padata_copy, - padata=inner_padata) - if inner_padata else None) - generate_padata_fn = (functools.partial(_generate_padata_copy, - padata=outer_padata) - if outer_padata else None) + generate_fast_padata_fn = None + generate_padata_fn = gen_padata_fn gen_authdata_fn = kdc_dict.pop('gen_authdata_fn', None) if gen_authdata_fn is not None: -- 2.25.1 From 4a4209ecca49c6aa76e5c2ab5af203349fb50527 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 21:14:18 +1200 Subject: [PATCH 254/645] tests/krb5: Sign-extend kvno from 32-bit integer This helps to avoid problems with RODC kvnos that have the high bit set. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 7bc52cecb442c4bcbd39372a8b98bb033e4d1540) --- python/samba/tests/krb5/raw_testcase.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 164d06b9788..cca38fb9480 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -294,6 +294,9 @@ class KerberosCredentials(Credentials): return self._get_krb5_etypes(self.ap_supported_enctypes) def set_kvno(self, kvno): + # Sign-extend from 32 bits. + if kvno & 1 << 31: + kvno |= -1 << 31 self.kvno = kvno def get_kvno(self): -- 2.25.1 From 2980d94cbd1d38aee0dc11b036f3718bc3abc1fd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 20:20:23 +1200 Subject: [PATCH 255/645] tests/krb5: Add method to get RODC krbtgt credentials BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit a5bf7aad54b7053417a24ae0918ee42ceed7bf21) --- python/samba/tests/krb5/kdc_base_test.py | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b2b9d87c3af..fd2e4d08cd3 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -89,6 +89,7 @@ class KDCBaseTest(RawKerberosTest): cls._lp = None cls._ldb = None + cls._rodc_ldb = None cls._functional_level = None @@ -137,6 +138,30 @@ class KDCBaseTest(RawKerberosTest): return self._ldb + def get_rodc_samdb(self): + if self._rodc_ldb is None: + creds = self.get_admin_creds() + lp = self.get_lp() + + session = system_session() + type(self)._rodc_ldb = SamDB(url="ldap://%s" % self.host, + session_info=session, + credentials=creds, + lp=lp, + am_rodc=True) + + return self._rodc_ldb + + def get_server_dn(self, samdb): + server = samdb.get_serverName() + + res = samdb.search(base=server, + scope=ldb.SCOPE_BASE, + attrs=['serverReference']) + dn = ldb.Dn(samdb, res[0]['serverReference'][0].decode('utf8')) + + return dn + def get_domain_functional_level(self, ldb): if self._functional_level is None: res = ldb.search(base='', @@ -478,6 +503,55 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=create_service_account) return c + def get_rodc_krbtgt_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + + def download_rodc_krbtgt_creds(): + samdb = self.get_samdb() + rodc_samdb = self.get_rodc_samdb() + + rodc_dn = self.get_server_dn(rodc_samdb) + + res = samdb.search(rodc_dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KrbTgtLink']) + krbtgt_dn = res[0]['msDS-KrbTgtLink'][0] + + res = samdb.search(krbtgt_dn, + scope=ldb.SCOPE_BASE, + attrs=['sAMAccountName', + 'msDS-KeyVersionNumber', + 'msDS-SecondaryKrbTgtNumber']) + krbtgt_dn = res[0].dn + username = str(res[0]['sAMAccountName']) + + creds = KerberosCredentials() + creds.set_domain(self.env_get_var('DOMAIN', 'RODC_KRBTGT')) + creds.set_realm(self.env_get_var('REALM', 'RODC_KRBTGT')) + creds.set_username(username) + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + krbtgt_number = int(res[0]['msDS-SecondaryKrbTgtNumber'][0]) + + rodc_kvno = krbtgt_number << 16 | kvno + creds.set_kvno(rodc_kvno) + creds.set_dn(krbtgt_dn) + + keys = self.get_keys(samdb, krbtgt_dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='RODC_KRBTGT', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key, + fallback_creds_fn=download_rodc_krbtgt_creds) + return c + def get_krbtgt_creds(self, require_keys=True, require_strongest_key=False): -- 2.25.1 From 27f04e44bfb946db200ab1bd59d35ebb6ea8e23e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 20:58:01 +1200 Subject: [PATCH 256/645] tests/krb5: Add get_secrets() method to get the secret attributes of a DN BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit af633992e31e839cdd7f77740c1f25d129be2f79) --- python/samba/tests/krb5/kdc_base_test.py | 26 +++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index fd2e4d08cd3..3681d26bb83 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -250,7 +250,9 @@ class KDCBaseTest(RawKerberosTest): return (creds, dn) - def get_keys(self, samdb, dn): + def get_secrets(self, samdb, dn, + destination_dsa_guid, + source_dsa_invocation_id): admin_creds = self.get_admin_creds() dns_hostname = samdb.host_dns_name() @@ -258,15 +260,13 @@ class KDCBaseTest(RawKerberosTest): self.get_lp(), admin_creds) - destination_dsa_guid = misc.GUID(samdb.get_ntds_GUID()) - req = drsuapi.DsGetNCChangesRequest8() req.destination_dsa_guid = destination_dsa_guid - req.source_dsa_invocation_id = misc.GUID() + req.source_dsa_invocation_id = source_dsa_invocation_id naming_context = drsuapi.DsReplicaObjectIdentifier() - naming_context.dn = str(dn) + naming_context.dn = dn req.naming_context = naming_context @@ -299,9 +299,25 @@ class KDCBaseTest(RawKerberosTest): req.mapping_ctr.mappings = None _, ctr = bind.DsGetNCChanges(handle, 8, req) + + self.assertEqual(1, ctr.object_count) + identifier = ctr.first_object.object.identifier attributes = ctr.first_object.object.attribute_ctr.attributes + self.assertEqual(dn, identifier.dn) + + return bind, identifier, attributes + + def get_keys(self, samdb, dn): + admin_creds = self.get_admin_creds() + + bind, identifier, attributes = self.get_secrets( + samdb, + str(dn), + destination_dsa_guid=misc.GUID(samdb.get_ntds_GUID()), + source_dsa_invocation_id=misc.GUID()) + rid = identifier.sid.split()[1] net_ctx = net.Net(admin_creds) -- 2.25.1 From d08a8c744ff49340c90e2627bfb2658a43967ab3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 22:13:24 +1200 Subject: [PATCH 257/645] tests/krb5: Allow replicating accounts to the RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 3cc9e77f38f6698aa01abca4285a520c7c0cd2ac) --- python/samba/tests/krb5/kdc_base_test.py | 141 ++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 3681d26bb83..56102cfc4ea 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -31,8 +31,9 @@ from samba import generate_random_password from samba.auth import system_session from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS from samba.dcerpc import drsblobs, drsuapi, misc, krb5pac, krb5ccache, security -from samba.drs_utils import drsuapi_connect +from samba.drs_utils import drs_Replicate, drsuapi_connect from samba.dsdb import ( + DSDB_SYNTAX_BINARY_DN, DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, DS_GUID_COMPUTERS_CONTAINER, @@ -45,7 +46,7 @@ from samba.dsdb import ( ) from samba.ndr import ndr_pack, ndr_unpack from samba import net -from samba.samdb import SamDB +from samba.samdb import SamDB, dsdb_Dn from samba.tests import delete_force import samba.tests.krb5.kcrypto as kcrypto @@ -104,12 +105,20 @@ class KDCBaseTest(RawKerberosTest): cls.account_cache = {} + cls.ldb_cleanups = [] + @classmethod def tearDownClass(cls): # Clean up any accounts created by create_account. This is # done in tearDownClass() rather than tearDown(), so that # accounts need only be created once for permutation tests. if cls._ldb is not None: + for cleanup in reversed(cls.ldb_cleanups): + try: + cls._ldb.modify(cleanup) + except ldb.LdbError: + pass + for dn in cls.accounts: delete_force(cls._ldb, dn) super().tearDownClass() @@ -250,6 +259,76 @@ class KDCBaseTest(RawKerberosTest): return (creds, dn) + def replicate_account_to_rodc(self, dn): + samdb = self.get_samdb() + rodc_samdb = self.get_rodc_samdb() + + repl_val = f'{samdb.get_dsServiceName()}:{dn}:SECRETS_ONLY' + + msg = ldb.Message() + msg.dn = ldb.Dn(rodc_samdb, '') + msg['replicateSingleObject'] = ldb.MessageElement( + repl_val, + ldb.FLAG_MOD_REPLACE, + 'replicateSingleObject') + + try: + # Try replication using the replicateSingleObject rootDSE + # operation. + rodc_samdb.modify(msg) + except ldb.LdbError as err: + enum, estr = err.args + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + self.assertIn('rootdse_modify: unknown attribute to change!', + estr) + + # If that method wasn't supported, we may be in the rodc:local test + # environment, where we can try replicating to the local database. + + lp = self.get_lp() + + rodc_creds = Credentials() + rodc_creds.guess(lp) + rodc_creds.set_machine_account(lp) + + local_samdb = SamDB(url=None, session_info=system_session(), + credentials=rodc_creds, lp=lp) + + destination_dsa_guid = misc.GUID(local_samdb.get_ntds_GUID()) + + repl = drs_Replicate(f'ncacn_ip_tcp:{self.dc_host}[seal]', + lp, rodc_creds, + local_samdb, destination_dsa_guid) + + source_dsa_invocation_id = misc.GUID(samdb.invocation_id) + + repl.replicate(dn, + source_dsa_invocation_id, + destination_dsa_guid, + exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, + rodc=True) + + def check_revealed(self, dn, rodc_dn, revealed=True): + samdb = self.get_samdb() + + res = samdb.search(base=rodc_dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-RevealedUsers']) + + revealed_users = res[0].get('msDS-RevealedUsers') + if revealed_users is None: + self.assertFalse(revealed) + return + + revealed_dns = set(str(dsdb_Dn(samdb, str(user), + syntax_oid=DSDB_SYNTAX_BINARY_DN).dn) + for user in revealed_users) + + if revealed: + self.assertIn(str(dn), revealed_dns) + else: + self.assertNotIn(str(dn), revealed_dns) + def get_secrets(self, samdb, dn, destination_dsa_guid, source_dsa_invocation_id): @@ -375,6 +454,29 @@ class KDCBaseTest(RawKerberosTest): creds.set_tgs_supported_enctypes(supported_enctypes) creds.set_ap_supported_enctypes(supported_enctypes) + def add_to_group(self, account_dn, group_dn, group_attr): + samdb = self.get_samdb() + + res = samdb.search(base=group_dn, + scope=ldb.SCOPE_BASE, + attrs=[group_attr]) + orig_msg = res[0] + + members = list(orig_msg[group_attr]) + members.append(account_dn) + + msg = ldb.Message() + msg.dn = group_dn + msg[group_attr] = ldb.MessageElement(members, + ldb.FLAG_MOD_REPLACE, + group_attr) + + cleanup = samdb.msg_diff(msg, orig_msg) + self.ldb_cleanups.append(cleanup) + samdb.modify(msg) + + return cleanup + def get_cached_creds(self, *, machine_account, opts=None): @@ -382,6 +484,9 @@ class KDCBaseTest(RawKerberosTest): opts = {} opts_default = { + 'allowed_replication': False, + 'denied_replication': False, + 'revealed_to_rodc': False, 'no_auth_data_required': False, 'supported_enctypes': None, 'not_delegated': False, @@ -407,6 +512,9 @@ class KDCBaseTest(RawKerberosTest): def create_account_opts(self, *, machine_account, + allowed_replication, + denied_replication, + revealed_to_rodc, no_auth_data_required, supported_enctypes, not_delegated, @@ -420,6 +528,9 @@ class KDCBaseTest(RawKerberosTest): self.assertFalse(trusted_to_auth_for_delegation) samdb = self.get_samdb() + rodc_samdb = self.get_rodc_samdb() + + rodc_dn = self.get_server_dn(rodc_samdb) user_name = self.account_base + str(self.account_id) type(self).account_id += 1 @@ -475,6 +586,32 @@ class KDCBaseTest(RawKerberosTest): creds.set_tgs_supported_enctypes(tgs_enctypes) + # Handle secret replication to the RODC. + + if allowed_replication or revealed_to_rodc: + # Allow replicating this account's secrets if requested, or allow + # it only temporarily if we're about to replicate them. + allowed_cleanup = self.add_to_group( + dn, rodc_dn, + 'msDS-RevealOnDemandGroup') + + if revealed_to_rodc: + # Replicate this account's secrets to the RODC. + self.replicate_account_to_rodc(dn) + + if not allowed_replication: + # If we don't want replicating secrets to be allowed for this + # account, disable it again. + samdb.modify(allowed_cleanup) + + self.check_revealed(dn, + rodc_dn, + revealed=revealed_to_rodc) + + if denied_replication: + # Deny replicating this account's secrets to the RODC. + self.add_to_group(dn, rodc_dn, 'msDS-NeverRevealGroup') + return creds def get_client_creds(self, -- 2.25.1 From 39933689093121f295294aed338289f7a51051ec Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 21:24:05 +1200 Subject: [PATCH 258/645] tests/krb5: Create RODC account for testing BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit ef5666bc51ca80e1acdadd525a9c61762756c8e3) --- python/samba/tests/krb5/kdc_base_test.py | 114 +++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 56102cfc4ea..892d3aaf41f 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -42,8 +42,10 @@ from samba.dsdb import ( UF_NO_AUTH_DATA_REQUIRED, UF_NORMAL_ACCOUNT, UF_NOT_DELEGATED, + UF_PARTIAL_SECRETS_ACCOUNT, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION ) +from samba.join import DCJoinContext from samba.ndr import ndr_pack, ndr_unpack from samba import net from samba.samdb import SamDB, dsdb_Dn @@ -105,6 +107,8 @@ class KDCBaseTest(RawKerberosTest): cls.account_cache = {} + cls._rodc_ctx = None + cls.ldb_cleanups = [] @classmethod @@ -121,6 +125,10 @@ class KDCBaseTest(RawKerberosTest): for dn in cls.accounts: delete_force(cls._ldb, dn) + + if cls._rodc_ctx is not None: + cls._rodc_ctx.cleanup_old_join(force=True) + super().tearDownClass() def setUp(self): @@ -171,6 +179,25 @@ class KDCBaseTest(RawKerberosTest): return dn + def get_mock_rodc_ctx(self): + if self._rodc_ctx is None: + admin_creds = self.get_admin_creds() + lp = self.get_lp() + + rodc_name = 'KRB5RODC' + site_name = 'Default-First-Site-Name' + + type(self)._rodc_ctx = DCJoinContext(server=self.dc_host, + creds=admin_creds, + lp=lp, + site=site_name, + netbios_name=rodc_name, + targetdir=None, + domain=None) + self.create_rodc(self._rodc_ctx) + + return self._rodc_ctx + def get_domain_functional_level(self, ldb): if self._functional_level is None: res = ldb.search(base='', @@ -259,6 +286,49 @@ class KDCBaseTest(RawKerberosTest): return (creds, dn) + def create_rodc(self, ctx): + ctx.nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] + ctx.full_nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] + ctx.krbtgt_dn = f'CN=krbtgt_{ctx.myname},CN=Users,{ctx.base_dn}' + + ctx.never_reveal_sid = [f'', + f'', + f'', + f'', + f''] + ctx.reveal_sid = f'' + + mysid = ctx.get_mysid() + admin_dn = f'' + ctx.managedby = admin_dn + + ctx.userAccountControl = (UF_WORKSTATION_TRUST_ACCOUNT | + UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | + UF_PARTIAL_SECRETS_ACCOUNT) + + ctx.connection_dn = f'CN=RODC Connection (FRS),{ctx.ntds_dn}' + ctx.secure_channel_type = misc.SEC_CHAN_RODC + ctx.RODC = True + ctx.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC | + drsuapi.DRSUAPI_DRS_PER_SYNC | + drsuapi.DRSUAPI_DRS_GET_ANC | + drsuapi.DRSUAPI_DRS_NEVER_SYNCED | + drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) + ctx.domain_replica_flags = ctx.replica_flags | drsuapi.DRSUAPI_DRS_CRITICAL_ONLY + + ctx.build_nc_lists() + + ctx.cleanup_old_join() + + try: + ctx.join_add_objects() + except Exception: + # cleanup the failed join (checking we still have a live LDB + # connection to the remote DC first) + ctx.refresh_ldb_connection() + ctx.cleanup_old_join() + raise + def replicate_account_to_rodc(self, dn): samdb = self.get_samdb() rodc_samdb = self.get_rodc_samdb() @@ -705,6 +775,50 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=download_rodc_krbtgt_creds) return c + def get_mock_rodc_krbtgt_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + + def create_rodc_krbtgt_account(): + samdb = self.get_samdb() + + rodc_ctx = self.get_mock_rodc_ctx() + + krbtgt_dn = rodc_ctx.new_krbtgt_dn + + res = samdb.search(base=ldb.Dn(samdb, krbtgt_dn), + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber', + 'msDS-SecondaryKrbTgtNumber']) + dn = res[0].dn + username = str(rodc_ctx.krbtgt_name) + + creds = KerberosCredentials() + creds.set_domain(self.env_get_var('DOMAIN', 'RODC_KRBTGT')) + creds.set_realm(self.env_get_var('REALM', 'RODC_KRBTGT')) + creds.set_username(username) + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + krbtgt_number = int(res[0]['msDS-SecondaryKrbTgtNumber'][0]) + + rodc_kvno = krbtgt_number << 16 | kvno + creds.set_kvno(rodc_kvno) + creds.set_dn(dn) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + return creds + + c = self._get_krb5_creds(prefix='MOCK_RODC_KRBTGT', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key, + fallback_creds_fn=create_rodc_krbtgt_account) + return c + def get_krbtgt_creds(self, require_keys=True, require_strongest_key=False): -- 2.25.1 From 9c742a5d6c45e80058eccd2f6dbce8ce0c7553a0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 13 Sep 2021 21:24:31 +1200 Subject: [PATCH 259/645] tests/krb5: Allow replicating accounts to the created RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall (cherry picked from commit 35292bd32225b39ad7a03c3aa53027458f0671eb) --- python/samba/tests/krb5/kdc_base_test.py | 50 ++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 892d3aaf41f..0e138352b06 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -378,6 +378,16 @@ class KDCBaseTest(RawKerberosTest): exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) + def reveal_account_to_mock_rodc(self, dn): + samdb = self.get_samdb() + rodc_ctx = self.get_mock_rodc_ctx() + + self.get_secrets( + samdb, + dn, + destination_dsa_guid=rodc_ctx.ntds_guid, + source_dsa_invocation_id=misc.GUID(samdb.invocation_id)) + def check_revealed(self, dn, rodc_dn, revealed=True): samdb = self.get_samdb() @@ -555,8 +565,11 @@ class KDCBaseTest(RawKerberosTest): opts_default = { 'allowed_replication': False, + 'allowed_replication_mock': False, 'denied_replication': False, + 'denied_replication_mock': False, 'revealed_to_rodc': False, + 'revealed_to_mock_rodc': False, 'no_auth_data_required': False, 'supported_enctypes': None, 'not_delegated': False, @@ -583,8 +596,11 @@ class KDCBaseTest(RawKerberosTest): def create_account_opts(self, *, machine_account, allowed_replication, + allowed_replication_mock, denied_replication, + denied_replication_mock, revealed_to_rodc, + revealed_to_mock_rodc, no_auth_data_required, supported_enctypes, not_delegated, @@ -682,6 +698,40 @@ class KDCBaseTest(RawKerberosTest): # Deny replicating this account's secrets to the RODC. self.add_to_group(dn, rodc_dn, 'msDS-NeverRevealGroup') + # Handle secret replication to the mock RODC. + + if allowed_replication_mock or revealed_to_mock_rodc: + # Allow replicating this account's secrets if requested, or allow + # it only temporarily if we want to add the account to the mock + # RODC's msDS-RevealedUsers. + rodc_ctx = self.get_mock_rodc_ctx() + mock_rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) + + allowed_mock_cleanup = self.add_to_group( + dn, mock_rodc_dn, + 'msDS-RevealOnDemandGroup') + + if revealed_to_mock_rodc: + # Request replicating this account's secrets to the mock RODC, + # which updates msDS-RevealedUsers. + self.reveal_account_to_mock_rodc(dn) + + if not allowed_replication_mock: + # If we don't want replicating secrets to be allowed for this + # account, disable it again. + samdb.modify(allowed_mock_cleanup) + + self.check_revealed(dn, + mock_rodc_dn, + revealed=revealed_to_mock_rodc) + + if denied_replication_mock: + # Deny replicating this account's secrets to the mock RODC. + rodc_ctx = self.get_mock_rodc_ctx() + mock_rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) + + self.add_to_group(dn, mock_rodc_dn, 'msDS-NeverRevealGroup') + return creds def get_client_creds(self, -- 2.25.1 From 74fc6a23a88a59a9fc6eaa80723ed502a4caf958 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 1 Sep 2021 15:42:28 +1200 Subject: [PATCH 260/645] python: Don't leak file handles Signed-off-by: Joseph Sutton Reviewed-by: Noel Power Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit cde38d36b98f1d40e7b58cd4c4b4bedfab76c390) --- python/samba/__init__.py | 12 +++++++----- python/samba/ms_schema.py | 6 +++--- python/samba/schema.py | 9 +++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/python/samba/__init__.py b/python/samba/__init__.py index d851bf3606c..e87e9c1b371 100644 --- a/python/samba/__init__.py +++ b/python/samba/__init__.py @@ -218,7 +218,8 @@ class Ldb(_Ldb): :param ldif_path: Path to LDIF file. """ - self.add_ldif(open(ldif_path, 'r').read()) + with open(ldif_path, 'r') as ldif_file: + self.add_ldif(ldif_file.read()) def add_ldif(self, ldif, controls=None): """Add data based on a LDIF string. @@ -280,10 +281,11 @@ def read_and_sub_file(file_name, subst_vars): :param file_name: File to be read (typically from setup directory) param subst_vars: Optional variables to subsitute in the file. """ - data = open(file_name, 'r', encoding="utf-8").read() - if subst_vars is not None: - data = substitute_var(data, subst_vars) - check_all_substituted(data) + with open(file_name, 'r', encoding="utf-8") as data_file: + data = data_file.read() + if subst_vars is not None: + data = substitute_var(data, subst_vars) + check_all_substituted(data) return data diff --git a/python/samba/ms_schema.py b/python/samba/ms_schema.py index 4946636cbd4..09dfbdde0f7 100644 --- a/python/samba/ms_schema.py +++ b/python/samba/ms_schema.py @@ -296,9 +296,9 @@ def __parse_schema_file(filename, objectClass): out = [] from io import open - f = open(filename, "r", encoding='latin-1') - for entry in __read_raw_entries(f): - out.append(__write_ldif_one(__transform_entry(entry, objectClass))) + with open(filename, "r", encoding='latin-1') as f: + for entry in __read_raw_entries(f): + out.append(__write_ldif_one(__transform_entry(entry, objectClass))) return "\n\n".join(out) diff --git a/python/samba/schema.py b/python/samba/schema.py index caea7e358ae..083af5f44b0 100644 --- a/python/samba/schema.py +++ b/python/samba/schema.py @@ -110,8 +110,13 @@ class Schema(object): setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][0]), setup_path('ad-schema/%s' % Schema.base_schemas[base_schema][1])) + def read_file(file): + with open(file, 'rb') as data_file: + return data_file.read() + if files is not None: - self.schema_data = "".join(get_string(open(file, 'rb').read()) for file in files) + self.schema_data = "".join(get_string(read_file(file)) + for file in files) self.schema_data = substitute_var(self.schema_data, {"SCHEMADN": schemadn}) @@ -130,7 +135,7 @@ class Schema(object): if override_prefixmap is not None: self.prefixmap_data = override_prefixmap else: - self.prefixmap_data = open(setup_path("prefixMap.txt"), 'rb').read() + self.prefixmap_data = read_file(setup_path("prefixMap.txt")) if additional_prefixmap is not None: self.prefixmap_data += "".join("%s\n" % map for map in additional_prefixmap) -- 2.25.1 From efdae6a0a0cd2940aff7c7b27daf1b0321ffea83 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 10 Sep 2021 14:02:22 +1200 Subject: [PATCH 261/645] python/join: Check for correct msDS-KrbTgtLink attribute Previously, the wrong case was used when checking for this attribute, which meant krbtgt accounts were not being cleaned up. Signed-off-by: Joseph Sutton Reviewed-by: Noel Power Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 21a7717359082feaddfdf42788648c3d7574c28e) --- python/samba/join.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/samba/join.py b/python/samba/join.py index 0cffa3055df..4dab3ca2a9c 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -258,8 +258,9 @@ class DCJoinContext(object): ctx.del_noerror(res[0].dn, recursive=True) - if "msDS-Krbtgtlink" in res[0]: - ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0] + krbtgt_dn = res[0].get('msDS-KrbTgtLink', idx=0) + if krbtgt_dn is not None: + ctx.new_krbtgt_dn = krbtgt_dn ctx.del_noerror(ctx.new_krbtgt_dn) res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(), @@ -338,7 +339,7 @@ class DCJoinContext(object): attrs=["msDS-krbTgtLink", "userAccountControl", "serverReferenceBL", "rIDSetReferences"]) if len(res) == 0: raise Exception("Could not find domain member account '%s' to promote to a DC, use 'samba-tool domain join' instead'" % ctx.samname) - if "msDS-krbTgtLink" in res[0] or "serverReferenceBL" in res[0] or "rIDSetReferences" in res[0]: + if "msDS-KrbTgtLink" in res[0] or "serverReferenceBL" in res[0] or "rIDSetReferences" in res[0]: raise Exception("Account '%s' appears to be an active DC, use 'samba-tool domain join' if you must re-create this account" % ctx.samname) if (int(res[0]["userAccountControl"][0]) & (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT | samba.dsdb.UF_SERVER_TRUST_ACCOUNT) == 0): -- 2.25.1 From 42363348e89308e667daa8f934b0ba236403467d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 15 Sep 2021 20:56:28 +1200 Subject: [PATCH 262/645] tests/krb5: Add helper method for modifying PACs This method can remove or replace a PAC in an authorization-data container, while additionally returning the original PAC. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit a281ae09bcf35277c830c4112567c72233fd66b8) --- python/samba/tests/krb5/raw_testcase.py | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index cca38fb9480..b7df1ac0879 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -42,6 +42,8 @@ from samba.tests import TestCaseInTempDir import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( + AD_IF_RELEVANT, + AD_WIN2K_PAC, FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_GENERIC, KDC_ERR_PREAUTH_FAILED, @@ -2848,6 +2850,49 @@ class RawKerberosTest(TestCaseInTempDir): ticket_blob) self.assertEqual(expected_checksum, checksum) + def replace_pac(self, auth_data, new_pac, expect_pac=True): + if new_pac is not None: + self.assertElementEqual(new_pac, 'ad-type', AD_WIN2K_PAC) + self.assertElementPresent(new_pac, 'ad-data') + + new_auth_data = [] + + ad_relevant = None + old_pac = None + + for authdata_elem in auth_data: + if authdata_elem['ad-type'] == AD_IF_RELEVANT: + ad_relevant = self.der_decode( + authdata_elem['ad-data'], + asn1Spec=krb5_asn1.AD_IF_RELEVANT()) + + relevant_elems = [] + for relevant_elem in ad_relevant: + if relevant_elem['ad-type'] == AD_WIN2K_PAC: + self.assertIsNone(old_pac, 'Multiple PACs detected') + old_pac = relevant_elem['ad-data'] + + if new_pac is not None: + relevant_elems.append(new_pac) + else: + relevant_elems.append(relevant_elem) + if expect_pac: + self.assertIsNotNone(old_pac, 'Expected PAC') + + ad_relevant = self.der_encode( + relevant_elems, + asn1Spec=krb5_asn1.AD_IF_RELEVANT()) + + authdata_elem = self.AuthorizationData_create(AD_IF_RELEVANT, + ad_relevant) + + new_auth_data.append(authdata_elem) + + if expect_pac: + self.assertIsNotNone(ad_relevant, 'Expected AD-RELEVANT') + + return new_auth_data, old_pac + def get_outer_pa_dict(self, kdc_exchange_dict): return self.get_pa_dict(kdc_exchange_dict['req_padata']) -- 2.25.1 From b0620d798a733ef7abc4804777e3bb37777d3d4a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:22:28 +1200 Subject: [PATCH 263/645] tests/krb5: Check correct flags element BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 0061fa2c2a26d990ed2e47441bca8797fc9be356) --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b7df1ac0879..632f69794e6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2193,7 +2193,7 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertElementMissing(encpart_private, 'key-expiration') - self.assertElementFlags(ticket_private, 'flags', + self.assertElementFlags(encpart_private, 'flags', expected_flags, unexpected_flags) self.assertElementPresent(encpart_private, 'authtime') -- 2.25.1 From 31059ba8d7d6368ae34b0f21f40fe13ff1bf0cf2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:13:09 +1200 Subject: [PATCH 264/645] tests/krb5: Refactor tgs_req() to use _generic_kdc_exchange BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 2a4d53dc12aa785f696e53ae3376f67375ce455f) --- python/samba/tests/krb5/kdc_base_test.py | 78 +++++++++++++----------- python/samba/tests/krb5/kdc_tgs_tests.py | 3 +- python/samba/tests/krb5/raw_testcase.py | 1 - source4/selftest/tests.py | 18 ++++-- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 0e138352b06..6a370d3036e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -52,7 +52,11 @@ from samba.samdb import SamDB, dsdb_Dn from samba.tests import delete_force import samba.tests.krb5.kcrypto as kcrypto -from samba.tests.krb5.raw_testcase import KerberosCredentials, RawKerberosTest +from samba.tests.krb5.raw_testcase import ( + KerberosCredentials, + KerberosTicketCreds, + RawKerberosTest +) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( AD_IF_RELEVANT, @@ -66,7 +70,6 @@ from samba.tests.krb5.rfc4120_constants import ( KU_AS_REP_ENC_PART, KU_ENC_CHALLENGE_CLIENT, KU_PA_ENC_TIMESTAMP, - KU_TGS_REP_ENC_PART_SUB_KEY, KU_TICKET, NT_PRINCIPAL, NT_SRV_HST, @@ -1063,49 +1066,56 @@ class KDCBaseTest(RawKerberosTest): else: self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) - def tgs_req(self, cname, sname, realm, ticket, key, etypes): + def tgs_req(self, cname, sname, realm, ticket, key, etypes, + expected_error_mode=0): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' kdc_options = "0" - till = self.get_KerberosTime(offset=36000) - padata = [] subkey = self.RandomKey(key.etype) (ctime, cusec) = self.get_KerberosTimeWithUsec() - req = self.TGS_REQ_create(padata=padata, - cusec=cusec, - ctime=ctime, - ticket=ticket, - kdc_options=str(kdc_options), - cname=cname, - realm=realm, - sname=sname, - from_time=None, - till_time=till, - renew_time=None, - nonce=0x7ffffffe, - etypes=etypes, - addresses=None, - EncAuthorizationData=None, - EncAuthorizationData_key=None, - additional_tickets=None, - ticket_session_key=key, - authenticator_subkey=subkey) - rep = self.send_recv_transaction(req) - self.assertIsNotNone(rep) + tgt = KerberosTicketCreds(ticket, + key, + crealm=realm, + cname=cname) - msg_type = rep['msg-type'] - enc_part = None - if msg_type == KRB_TGS_REP: - enc_part = subkey.decrypt( - KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) - enc_part = self.der_decode( - enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) - return (rep, enc_part) + if not expected_error_mode: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + else: + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=realm, + expected_cname=cname, + expected_srealm=realm, + expected_sname=sname, + expected_error_mode=expected_error_mode, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=tgt, + authenticator_subkey=subkey, + kdc_options=str(kdc_options)) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=realm, + sname=sname, + etypes=etypes) + + if expected_error_mode: + enc_part = None + else: + ticket_creds = kdc_exchange_dict['rep_ticket_creds'] + enc_part = ticket_creds.encpart_private + + return rep, enc_part # Named tuple to contain values of interest when the PAC is decoded. PacData = namedtuple( diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 97f9dd41339..dad9e6b88df 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -84,7 +84,8 @@ class KdcTgsTests(KDCBaseTest): name_type=NT_PRINCIPAL, names=["host", samdb.host_dns_name()]) - (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype) + (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype, + expected_error_mode=KDC_ERR_BADMATCH) self.assertIsNone( enc_part, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 632f69794e6..7eba62b4022 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2039,7 +2039,6 @@ class RawKerberosTest(TestCaseInTempDir): error_code=0) ticket_private = None - self.assertIsNotNone(ticket_decryption_key) if ticket_decryption_key is not None: self.assertElementEqual(ticket_encpart, 'etype', ticket_decryption_key.etype) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 4de8f84f72e..86d018a0919 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -755,22 +755,26 @@ planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) for env in ["ad_dc", smbv1_disabled_testenv]: @@ -1324,7 +1328,8 @@ planpythontestsuite( "samba.tests.krb5.kdc_tgs_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) planpythontestsuite( "ad_dc", @@ -1339,7 +1344,8 @@ planpythontestsuite( "samba.tests.krb5.ms_kile_client_principal_lookup_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0' }) for env in [ -- 2.25.1 From 958fe28d64a5da1de17720f2a19cd535c59cf20f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:16:27 +1200 Subject: [PATCH 265/645] tests/krb5: Allow tgs_req() to send additional padata BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 1f0654b8facf3b9b2288d2569a573ff3a5ca4a82) --- python/samba/tests/krb5/kdc_base_test.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 6a370d3036e..57ef1bceb49 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1067,7 +1067,7 @@ class KDCBaseTest(RawKerberosTest): self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) def tgs_req(self, cname, sname, realm, ticket, key, etypes, - expected_error_mode=0): + expected_error_mode=0, padata=None): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1090,6 +1090,12 @@ class KDCBaseTest(RawKerberosTest): check_error_fn = self.generic_check_kdc_error check_rep_fn = None + def generate_padata(_kdc_exchange_dict, + _callback_dict, + req_body): + + return padata, req_body + kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=realm, expected_cname=cname, @@ -1099,6 +1105,7 @@ class KDCBaseTest(RawKerberosTest): check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, + generate_padata_fn=generate_padata if padata is not None else None, tgt=tgt, authenticator_subkey=subkey, kdc_options=str(kdc_options)) -- 2.25.1 From b006d59391e0a55d3742137b6bf42de8a59496d8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:18:12 +1200 Subject: [PATCH 266/645] tests/krb5: Allow tgs_req() to specify different kdc-options BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 1a3426da54463c3e454c1b76c3df4e96882e6aa9) --- python/samba/tests/krb5/kdc_base_test.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 57ef1bceb49..c448f127c0c 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1067,13 +1067,11 @@ class KDCBaseTest(RawKerberosTest): self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) def tgs_req(self, cname, sname, realm, ticket, key, etypes, - expected_error_mode=0, padata=None): + expected_error_mode=0, padata=None, kdc_options=0): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' - kdc_options = "0" - subkey = self.RandomKey(key.etype) (ctime, cusec) = self.get_KerberosTimeWithUsec() -- 2.25.1 From d029bd47d676bb3e688cd47ba5704b23fd9e0dfa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:25:01 +1200 Subject: [PATCH 267/645] tests/krb5: Allow tgs_req() to send requests to the RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 6403a09d94ab54f89d6e50601ae6b19ab7e6aae7) --- python/samba/tests/krb5/kdc_base_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index c448f127c0c..5ef08eb32fe 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1067,7 +1067,8 @@ class KDCBaseTest(RawKerberosTest): self.assertEqual(rep['error-code'], expected, "rep = {%s}" % rep) def tgs_req(self, cname, sname, realm, ticket, key, etypes, - expected_error_mode=0, padata=None, kdc_options=0): + expected_error_mode=0, padata=None, kdc_options=0, + to_rodc=False): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1106,7 +1107,8 @@ class KDCBaseTest(RawKerberosTest): generate_padata_fn=generate_padata if padata is not None else None, tgt=tgt, authenticator_subkey=subkey, - kdc_options=str(kdc_options)) + kdc_options=str(kdc_options), + to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, cname=None, -- 2.25.1 From c5ba5e622daa6b4e710f36df1e7ca20e89272661 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 11:52:46 +1200 Subject: [PATCH 268/645] tests/krb5: Allow as_req() to specify different kdc-options BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit a5e62d681d81a422bac7bd89dc27ef2314d77457) --- python/samba/tests/krb5/kdc_base_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 5ef08eb32fe..ae62c9d5fc6 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -913,12 +913,11 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=download_krbtgt_creds) return c - def as_req(self, cname, sname, realm, etypes, padata=None): + def as_req(self, cname, sname, realm, etypes, padata=None, kdc_options=0): '''Send a Kerberos AS_REQ, returns the undecoded response ''' till = self.get_KerberosTime(offset=36000) - kdc_options = 0 req = self.AS_REQ_create(padata=padata, kdc_options=str(kdc_options), -- 2.25.1 From c4f351933c14fcf04b2165df0b40eb1cc8a51e58 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 12:06:51 +1200 Subject: [PATCH 269/645] tests/krb5: Use PAC buffer type constants from krb5pac.idl BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 3504e99dc5bcc206ca2964012b7fdca541555416) --- python/samba/tests/krb5/kdc_base_test.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index ae62c9d5fc6..2cebd9ef0cf 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1127,13 +1127,6 @@ class KDCBaseTest(RawKerberosTest): PacData = namedtuple( "PacData", "account_name account_sid logon_name upn domain_name") - PAC_LOGON_INFO = 1 - PAC_CREDENTIAL_INFO = 2 - PAC_SRV_CHECKSUM = 6 - PAC_KDC_CHECKSUM = 7 - PAC_LOGON_NAME = 10 - PAC_CONSTRAINED_DELEGATION = 11 - PAC_UPN_DNS_INFO = 12 def get_pac_data(self, authorization_data): '''Decode the PAC element contained in the authorization-data element @@ -1154,15 +1147,15 @@ class KDCBaseTest(RawKerberosTest): for ad in (x for x in buf if x['ad-type'] == AD_WIN2K_PAC): pb = ndr_unpack(krb5pac.PAC_DATA, ad['ad-data']) for pac in pb.buffers: - if pac.type == self.PAC_LOGON_INFO: + if pac.type == krb5pac.PAC_TYPE_LOGON_INFO: account_name = ( pac.info.info.info3.base.account_name) user_sid = ( str(pac.info.info.info3.base.domain_sid) + "-" + str(pac.info.info.info3.base.rid)) - elif pac.type == self.PAC_LOGON_NAME: + elif pac.type == krb5pac.PAC_TYPE_LOGON_NAME: logon_name = pac.info.account_name - elif pac.type == self.PAC_UPN_DNS_INFO: + elif pac.type == krb5pac.PAC_TYPE_UPN_DNS_INFO: upn = pac.info.upn_name domain_name = pac.info.dns_domain_name -- 2.25.1 From c49a273df367f21fda9a045fa70e997a18606796 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 12:13:51 +1200 Subject: [PATCH 270/645] tests/krb5: Don't manually create PAC request and options in fast_tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit c226029655ca361560d93298a6729a021f2f6b75) --- python/samba/tests/krb5/fast_tests.py | 17 +++++++++-------- python/samba/tests/krb5/raw_testcase.py | 5 ----- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 8024b92f445..dedf7a57a4b 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1553,10 +1553,7 @@ class FAST_Tests(KDCBaseTest): 'canonicalize,' 'renewable-ok')) - pac_request = self.get_pa_pac_request() - pac_options = self.get_pa_pac_options('1') # supports claims - - padata = [pac_request, pac_options] + pac_options = '1' # supports claims rep, kdc_exchange_dict = self._test_as_exchange( cname=cname, @@ -1571,10 +1568,12 @@ class FAST_Tests(KDCBaseTest): expected_sname=sname, expected_salt=salt, etypes=etype, - padata=padata, + padata=None, kdc_options=kdc_options, preauth_key=None, - ticket_decryption_key=ticket_decryption_key) + ticket_decryption_key=ticket_decryption_key, + pac_request=True, + pac_options=pac_options) self.check_pre_authentication(rep) etype_info2 = kdc_exchange_dict['preauth_etype_info2'] @@ -1585,7 +1584,7 @@ class FAST_Tests(KDCBaseTest): ts_enc_padata = self.get_enc_timestamp_pa_data(creds, rep) - padata = [ts_enc_padata, pac_request, pac_options] + padata = [ts_enc_padata] expected_realm = realm.upper() @@ -1608,7 +1607,9 @@ class FAST_Tests(KDCBaseTest): padata=padata, kdc_options=kdc_options, preauth_key=preauth_key, - ticket_decryption_key=ticket_decryption_key) + ticket_decryption_key=ticket_decryption_key, + pac_request=True, + pac_options=pac_options) self.check_as_reply(rep) tgt = rep['ticket'] diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 7eba62b4022..39821240941 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1177,11 +1177,6 @@ class RawKerberosTest(TestCaseInTempDir): pa_data = self.PA_DATA_create(PADATA_PAC_REQUEST, pa_pac) return pa_data - def get_pa_pac_request(self, request_pac=True): - pac_request = self.KERB_PA_PAC_REQUEST_create(request_pac) - - return pac_request - def get_pa_pac_options(self, options): pac_options = self.PA_PAC_OPTIONS_create(options) pac_options = self.der_encode(pac_options, -- 2.25.1 From 62f94eb04b8fecdbf7e2126eaf29fd73380bc49d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 12:19:28 +1200 Subject: [PATCH 271/645] tests/krb5: Set DN of created accounts to ldb.Dn type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 7645dfa5bedee7ef3f7debbf0fa7600bd1c4bd79) --- python/samba/tests/krb5/kdc_base_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 2cebd9ef0cf..e510ccbe46e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -228,7 +228,7 @@ class KDCBaseTest(RawKerberosTest): return default_enctypes - def create_account(self, ldb, name, machine_account=False, + def create_account(self, samdb, name, machine_account=False, spn=None, upn=None, additional_details=None, ou=None, account_control=0): '''Create an account for testing. @@ -239,13 +239,13 @@ class KDCBaseTest(RawKerberosTest): guid = (DS_GUID_COMPUTERS_CONTAINER if machine_account else DS_GUID_USERS_CONTAINER) - ou = ldb.get_wellknown_dn(ldb.get_default_basedn(), guid) + ou = samdb.get_wellknown_dn(samdb.get_default_basedn(), guid) dn = "CN=%s,%s" % (name, ou) # remove the account if it exists, this will happen if a previous test # run failed - delete_force(ldb, dn) + delete_force(samdb, dn) if machine_account: object_class = "computer" account_name = "%s$" % name @@ -270,19 +270,19 @@ class KDCBaseTest(RawKerberosTest): details["userPrincipalName"] = upn if additional_details is not None: details.update(additional_details) - ldb.add(details) + samdb.add(details) creds = KerberosCredentials() creds.guess(self.get_lp()) - creds.set_realm(ldb.domain_dns_name().upper()) - creds.set_domain(ldb.domain_netbios_name().upper()) + creds.set_realm(samdb.domain_dns_name().upper()) + creds.set_domain(samdb.domain_netbios_name().upper()) creds.set_password(password) creds.set_username(account_name) if machine_account: creds.set_workstation(name) else: creds.set_workstation('') - creds.set_dn(dn) + creds.set_dn(ldb.Dn(samdb, dn)) # # Save the account name so it can be deleted in tearDownClass self.accounts.add(dn) -- 2.25.1 From e959c9d2f559f35dbf050e80a6b407addb7dd104 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 12:38:38 +1200 Subject: [PATCH 272/645] tests/krb5: Allow get_service_ticket() to get tickets from the RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 5d3a135c2326edc9ca8f56bea24d2f52320f4fd6) --- python/samba/tests/krb5/fast_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index dedf7a57a4b..74fe11c5a90 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1497,7 +1497,7 @@ class FAST_Tests(KDCBaseTest): self.assertTrue( security.KERB_ENCTYPE_CLAIMS_SUPPORTED & krbtgt_etypes) - def get_service_ticket(self, tgt, target_creds, service='host'): + def get_service_ticket(self, tgt, target_creds, service='host', to_rodc=False): etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) key = tgt.session_key @@ -1510,7 +1510,7 @@ class FAST_Tests(KDCBaseTest): sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[service, target_name]) - rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype) + rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, to_rodc=to_rodc) service_ticket = rep['ticket'] -- 2.25.1 From 761fb0a654fa64d39facdd04aa21d93f99b80d10 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 12:41:46 +1200 Subject: [PATCH 273/645] tests/krb5: Allow get_tgt() to get tickets from the RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 2d69805b1e3a8022f1418605e5f29ae0bbaa4a06) --- python/samba/tests/krb5/fast_tests.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 74fe11c5a90..9109a63d704 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1530,7 +1530,7 @@ class FAST_Tests(KDCBaseTest): return service_ticket_creds - def get_tgt(self, creds): + def get_tgt(self, creds, to_rodc=False): user_name = creds.get_username() realm = creds.get_realm() @@ -1544,7 +1544,10 @@ class FAST_Tests(KDCBaseTest): till = self.get_KerberosTime(offset=36000) - krbtgt_creds = self.get_krbtgt_creds() + if to_rodc: + krbtgt_creds = self.get_rodc_krbtgt_creds() + else: + krbtgt_creds = self.get_krbtgt_creds() ticket_decryption_key = ( self.TicketDecryptionKey_from_creds(krbtgt_creds)) @@ -1573,7 +1576,8 @@ class FAST_Tests(KDCBaseTest): preauth_key=None, ticket_decryption_key=ticket_decryption_key, pac_request=True, - pac_options=pac_options) + pac_options=pac_options, + to_rodc=to_rodc) self.check_pre_authentication(rep) etype_info2 = kdc_exchange_dict['preauth_etype_info2'] @@ -1609,7 +1613,8 @@ class FAST_Tests(KDCBaseTest): preauth_key=preauth_key, ticket_decryption_key=ticket_decryption_key, pac_request=True, - pac_options=pac_options) + pac_options=pac_options, + to_rodc=to_rodc) self.check_as_reply(rep) tgt = rep['ticket'] -- 2.25.1 From 53e51cd904b13d0767e8a2e27c0d14bf95fe1403 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 13:14:06 +1200 Subject: [PATCH 274/645] tests/krb5: Allow get_tgt() to specify different kdc-options BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 4ecfa82e71b0dd5b71aa97973033c5c72257a0c3) --- python/samba/tests/krb5/fast_tests.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 9109a63d704..826c3536fb9 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1530,7 +1530,7 @@ class FAST_Tests(KDCBaseTest): return service_ticket_creds - def get_tgt(self, creds, to_rodc=False): + def get_tgt(self, creds, to_rodc=False, kdc_options=None): user_name = creds.get_username() realm = creds.get_realm() @@ -1551,10 +1551,12 @@ class FAST_Tests(KDCBaseTest): ticket_decryption_key = ( self.TicketDecryptionKey_from_creds(krbtgt_creds)) - kdc_options = str(krb5_asn1.KDCOptions('forwardable,' + if kdc_options is None: + kdc_options = krb5_asn1.KDCOptions('forwardable,' 'renewable,' 'canonicalize,' - 'renewable-ok')) + 'renewable-ok') + kdc_options = str(kdc_options) pac_options = '1' # supports claims -- 2.25.1 From c07bc41c2df7c371ed7a6928748b8f8a28c8c486 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 13:14:45 +1200 Subject: [PATCH 275/645] tests/krb5: Allow get_tgt() to specify expected and unexpected flags BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 035a8f198555ad1eedf8e2e6c565fbbbe4fbe7ce) --- python/samba/tests/krb5/fast_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 826c3536fb9..fd96c2b9c1a 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1530,7 +1530,8 @@ class FAST_Tests(KDCBaseTest): return service_ticket_creds - def get_tgt(self, creds, to_rodc=False, kdc_options=None): + def get_tgt(self, creds, to_rodc=False, kdc_options=None, + expected_flags=None, unexpected_flags=None): user_name = creds.get_username() realm = creds.get_realm() @@ -1572,6 +1573,8 @@ class FAST_Tests(KDCBaseTest): expected_srealm=realm, expected_sname=sname, expected_salt=salt, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, etypes=etype, padata=None, kdc_options=kdc_options, -- 2.25.1 From a5b85f330e8325da93e4f0c83dee24e6d748f75a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 13:24:46 +1200 Subject: [PATCH 276/645] tests/krb5: Move get_tgt() and get_service_ticket() to kdc_base_test BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 59c1043be25b92db75ab5676601cb15426ef37a3) --- python/samba/tests/krb5/fast_tests.py | 141 ---------------------- python/samba/tests/krb5/kdc_base_test.py | 144 +++++++++++++++++++++++ 2 files changed, 144 insertions(+), 141 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index fd96c2b9c1a..a74dc2a3cd0 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1497,147 +1497,6 @@ class FAST_Tests(KDCBaseTest): self.assertTrue( security.KERB_ENCTYPE_CLAIMS_SUPPORTED & krbtgt_etypes) - def get_service_ticket(self, tgt, target_creds, service='host', to_rodc=False): - etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) - - key = tgt.session_key - ticket = tgt.ticket - - cname = tgt.cname - realm = tgt.crealm - - target_name = target_creds.get_username()[:-1] - sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=[service, target_name]) - - rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, to_rodc=to_rodc) - - service_ticket = rep['ticket'] - - ticket_etype = service_ticket['enc-part']['etype'] - target_key = self.TicketDecryptionKey_from_creds(target_creds, - etype=ticket_etype) - - session_key = self.EncryptionKey_import(enc_part['key']) - - service_ticket_creds = KerberosTicketCreds(service_ticket, - session_key, - crealm=realm, - cname=cname, - srealm=realm, - sname=sname, - decryption_key=target_key) - - return service_ticket_creds - - def get_tgt(self, creds, to_rodc=False, kdc_options=None, - expected_flags=None, unexpected_flags=None): - user_name = creds.get_username() - 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]) - - till = self.get_KerberosTime(offset=36000) - - if to_rodc: - krbtgt_creds = self.get_rodc_krbtgt_creds() - else: - krbtgt_creds = self.get_krbtgt_creds() - ticket_decryption_key = ( - self.TicketDecryptionKey_from_creds(krbtgt_creds)) - - if kdc_options is None: - kdc_options = krb5_asn1.KDCOptions('forwardable,' - 'renewable,' - 'canonicalize,' - 'renewable-ok') - kdc_options = str(kdc_options) - - pac_options = '1' # supports claims - - rep, kdc_exchange_dict = self._test_as_exchange( - cname=cname, - realm=realm, - sname=sname, - till=till, - client_as_etypes=etype, - expected_error_mode=KDC_ERR_PREAUTH_REQUIRED, - expected_crealm=realm, - expected_cname=cname, - expected_srealm=realm, - expected_sname=sname, - expected_salt=salt, - expected_flags=expected_flags, - unexpected_flags=unexpected_flags, - etypes=etype, - padata=None, - kdc_options=kdc_options, - preauth_key=None, - ticket_decryption_key=ticket_decryption_key, - pac_request=True, - pac_options=pac_options, - to_rodc=to_rodc) - self.check_pre_authentication(rep) - - etype_info2 = kdc_exchange_dict['preauth_etype_info2'] - - preauth_key = self.PasswordKey_from_etype_info2(creds, - etype_info2[0], - creds.get_kvno()) - - ts_enc_padata = self.get_enc_timestamp_pa_data(creds, rep) - - padata = [ts_enc_padata] - - 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, - sname=sname, - till=till, - client_as_etypes=etype, - expected_error_mode=0, - expected_crealm=expected_realm, - expected_cname=cname, - expected_srealm=expected_realm, - expected_sname=expected_sname, - expected_salt=salt, - etypes=etype, - padata=padata, - kdc_options=kdc_options, - preauth_key=preauth_key, - ticket_decryption_key=ticket_decryption_key, - pac_request=True, - pac_options=pac_options, - to_rodc=to_rodc) - self.check_as_reply(rep) - - tgt = rep['ticket'] - - enc_part = self.get_as_rep_enc_data(preauth_key, rep) - session_key = self.EncryptionKey_import(enc_part['key']) - - ticket_creds = KerberosTicketCreds( - tgt, - session_key, - crealm=realm, - cname=cname, - srealm=realm, - sname=sname, - decryption_key=ticket_decryption_key) - - return ticket_creds, enc_part - def get_mach_tgt(self): if self.mach_tgt is None: mach_creds = self.get_mach_creds() diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e510ccbe46e..fbcc89a9b31 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -73,6 +73,7 @@ from samba.tests.krb5.rfc4120_constants import ( KU_TICKET, NT_PRINCIPAL, NT_SRV_HST, + NT_SRV_INST, PADATA_ENCRYPTED_CHALLENGE, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO2, @@ -1123,6 +1124,149 @@ class KDCBaseTest(RawKerberosTest): return rep, enc_part + def get_service_ticket(self, tgt, target_creds, service='host', + to_rodc=False): + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + key = tgt.session_key + ticket = tgt.ticket + + cname = tgt.cname + realm = tgt.crealm + + target_name = target_creds.get_username()[:-1] + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[service, target_name]) + + rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, + to_rodc=to_rodc) + + service_ticket = rep['ticket'] + + ticket_etype = service_ticket['enc-part']['etype'] + target_key = self.TicketDecryptionKey_from_creds(target_creds, + etype=ticket_etype) + + session_key = self.EncryptionKey_import(enc_part['key']) + + service_ticket_creds = KerberosTicketCreds(service_ticket, + session_key, + crealm=realm, + cname=cname, + srealm=realm, + sname=sname, + decryption_key=target_key) + + return service_ticket_creds + + def get_tgt(self, creds, to_rodc=False, kdc_options=None, + expected_flags=None, unexpected_flags=None): + user_name = creds.get_username() + 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]) + + till = self.get_KerberosTime(offset=36000) + + if to_rodc: + krbtgt_creds = self.get_rodc_krbtgt_creds() + else: + krbtgt_creds = self.get_krbtgt_creds() + ticket_decryption_key = ( + self.TicketDecryptionKey_from_creds(krbtgt_creds)) + + if kdc_options is None: + kdc_options = krb5_asn1.KDCOptions('forwardable,' + 'renewable,' + 'canonicalize,' + 'renewable-ok') + kdc_options = str(kdc_options) + + pac_options = '1' # supports claims + + rep, kdc_exchange_dict = self._test_as_exchange( + cname=cname, + realm=realm, + sname=sname, + till=till, + client_as_etypes=etype, + expected_error_mode=KDC_ERR_PREAUTH_REQUIRED, + expected_crealm=realm, + expected_cname=cname, + expected_srealm=realm, + expected_sname=sname, + expected_salt=salt, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, + etypes=etype, + padata=None, + kdc_options=kdc_options, + preauth_key=None, + ticket_decryption_key=ticket_decryption_key, + pac_request=True, + pac_options=pac_options, + to_rodc=to_rodc) + self.check_pre_authentication(rep) + + etype_info2 = kdc_exchange_dict['preauth_etype_info2'] + + preauth_key = self.PasswordKey_from_etype_info2(creds, + etype_info2[0], + creds.get_kvno()) + + ts_enc_padata = self.get_enc_timestamp_pa_data(creds, rep) + + padata = [ts_enc_padata] + + 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, + sname=sname, + till=till, + client_as_etypes=etype, + expected_error_mode=0, + expected_crealm=expected_realm, + expected_cname=cname, + expected_srealm=expected_realm, + expected_sname=expected_sname, + expected_salt=salt, + etypes=etype, + padata=padata, + kdc_options=kdc_options, + preauth_key=preauth_key, + ticket_decryption_key=ticket_decryption_key, + pac_request=True, + pac_options=pac_options, + to_rodc=to_rodc) + self.check_as_reply(rep) + + tgt = rep['ticket'] + + enc_part = self.get_as_rep_enc_data(preauth_key, rep) + session_key = self.EncryptionKey_import(enc_part['key']) + + ticket_creds = KerberosTicketCreds( + tgt, + session_key, + crealm=realm, + cname=cname, + srealm=realm, + sname=sname, + decryption_key=ticket_decryption_key) + + return ticket_creds, enc_part + # Named tuple to contain values of interest when the PAC is decoded. PacData = namedtuple( "PacData", -- 2.25.1 From 5296cd043628dec4c10549074fe685a4779fbf01 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 11:51:05 +1200 Subject: [PATCH 277/645] tests/krb5: Return encpart from get_tgt() as part of KerberosTicketCreds The encpart is already contained in ticket_creds, so it no longer needs to be returned as a separate value. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 6193f7433b15579aa32b26a146287923c9d3844d) --- python/samba/tests/krb5/fast_tests.py | 8 ++------ python/samba/tests/krb5/kdc_base_test.py | 16 ++-------------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index a74dc2a3cd0..42e75e7513c 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -67,11 +67,9 @@ class FAST_Tests(KDCBaseTest): super().setUpClass() cls.user_tgt = None - cls.user_enc_part = None cls.user_service_ticket = None cls.mach_tgt = None - cls.mach_enc_part = None cls.mach_service_ticket = None def setUp(self): @@ -1500,16 +1498,14 @@ class FAST_Tests(KDCBaseTest): def get_mach_tgt(self): if self.mach_tgt is None: mach_creds = self.get_mach_creds() - type(self).mach_tgt, type(self).mach_enc_part = ( - self.get_tgt(mach_creds)) + type(self).mach_tgt = self.get_tgt(mach_creds) return self.mach_tgt def get_user_tgt(self): if self.user_tgt is None: user_creds = self.get_client_creds() - type(self).user_tgt, type(self).user_enc_part = ( - self.get_tgt(user_creds)) + type(self).user_tgt = self.get_tgt(user_creds) return self.user_tgt diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index fbcc89a9b31..28d34210fce 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1251,21 +1251,9 @@ class KDCBaseTest(RawKerberosTest): to_rodc=to_rodc) self.check_as_reply(rep) - tgt = rep['ticket'] + ticket_creds = kdc_exchange_dict['rep_ticket_creds'] - enc_part = self.get_as_rep_enc_data(preauth_key, rep) - session_key = self.EncryptionKey_import(enc_part['key']) - - ticket_creds = KerberosTicketCreds( - tgt, - session_key, - crealm=realm, - cname=cname, - srealm=realm, - sname=sname, - decryption_key=ticket_decryption_key) - - return ticket_creds, enc_part + return ticket_creds # Named tuple to contain values of interest when the PAC is decoded. PacData = namedtuple( -- 2.25.1 From 9599359b2315d5170e05efd4459e04ef07918f5b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 11:51:20 +1200 Subject: [PATCH 278/645] tests/krb5: Cache obtained tickets Now tickets obtained with get_tgt() and get_service_ticket() make use of a cache so they can be reused, unless the 'fresh' parameter is specified as true. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit 419e4061ced466ec7e5e23f815823b540ef4751c) --- python/samba/tests/krb5/kdc_base_test.py | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 28d34210fce..59175c7bb2f 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -110,6 +110,7 @@ class KDCBaseTest(RawKerberosTest): cls.accounts = set() cls.account_cache = {} + cls.tkt_cache = {} cls._rodc_ctx = None @@ -1125,7 +1126,17 @@ class KDCBaseTest(RawKerberosTest): return rep, enc_part def get_service_ticket(self, tgt, target_creds, service='host', - to_rodc=False): + to_rodc=False, fresh=False): + user_name = tgt.cname['name-string'][0] + target_name = target_creds.get_username() + cache_key = (user_name, target_name, service, to_rodc) + + if not fresh: + ticket = self.tkt_cache.get(cache_key) + + if ticket is not None: + return ticket + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) key = tgt.session_key @@ -1157,11 +1168,23 @@ class KDCBaseTest(RawKerberosTest): sname=sname, decryption_key=target_key) + self.tkt_cache[cache_key] = service_ticket_creds + return service_ticket_creds def get_tgt(self, creds, to_rodc=False, kdc_options=None, - expected_flags=None, unexpected_flags=None): + expected_flags=None, unexpected_flags=None, + fresh=False): user_name = creds.get_username() + cache_key = (user_name, to_rodc, kdc_options, + expected_flags, unexpected_flags) + + if not fresh: + tgt = self.tkt_cache.get(cache_key) + + if tgt is not None: + return tgt + realm = creds.get_realm() salt = creds.get_salt() @@ -1253,6 +1276,8 @@ class KDCBaseTest(RawKerberosTest): ticket_creds = kdc_exchange_dict['rep_ticket_creds'] + self.tkt_cache[cache_key] = ticket_creds + return ticket_creds # Named tuple to contain values of interest when the PAC is decoded. -- 2.25.1 From d2c32b1339ec778925cb153ce16b8b497b5695cf Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 16:54:57 +1200 Subject: [PATCH 279/645] tests/krb5: Add methods for creating zeroed checksums and verifying checksums Creating a zeroed checksum is needed for signing a PAC. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett (cherry picked from commit a562882b15125902c5d89f094b8c9b1150f5d010) --- python/samba/tests/krb5/raw_testcase.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 39821240941..be49f16b1f7 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -232,12 +232,29 @@ class Krb5EncryptionKey: plaintext = kcrypto.decrypt(self.key, usage, ciphertext) return plaintext + def make_zeroed_checksum(self, ctype=None): + if ctype is None: + ctype = self.ctype + + checksum_len = kcrypto.checksum_len(ctype) + return bytes(checksum_len) + def make_checksum(self, usage, plaintext, ctype=None): if ctype is None: ctype = self.ctype cksum = kcrypto.make_checksum(ctype, self.key, usage, plaintext) return cksum + def verify_checksum(self, usage, plaintext, ctype, cksum): + if self.ctype != ctype: + raise AssertionError(f'{self.ctype} != {ctype}') + + kcrypto.verify_checksum(ctype, + self.key, + usage, + plaintext, + cksum) + def export_obj(self): EncryptionKey_obj = { 'keytype': self.etype, -- 2.25.1 From 6a5c5a0647cbd91bace9022e8f61b21bc294c85c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 16 Sep 2021 17:20:22 +1200 Subject: [PATCH 280/645] tests/krb5: Add RodcPacEncryptionKey type allowing for RODC PAC signatures Signatures created by an RODC have an RODCIdentifier appended to them identifying the RODC's krbtgt account. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Isaac Boukris Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Tue Sep 21 23:55:39 UTC 2021 on sn-devel-184 (cherry picked from commit ec95b3042bf2649c0600cafb12818c27242b5098) --- python/samba/tests/krb5/raw_testcase.py | 45 +++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index be49f16b1f7..e213b5eef9b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -263,6 +263,45 @@ class Krb5EncryptionKey: return EncryptionKey_obj +class RodcPacEncryptionKey(Krb5EncryptionKey): + def __init__(self, key, kvno, rodc_id=None): + super().__init__(key, kvno) + + if rodc_id is None: + kvno = self.kvno + if kvno is not None: + kvno >>= 16 + kvno &= (1 << 16) - 1 + + rodc_id = kvno or None + + if rodc_id is not None: + self.rodc_id = rodc_id.to_bytes(2, byteorder='little') + else: + self.rodc_id = b'' + + def make_zeroed_checksum(self, ctype=None): + checksum = super().make_zeroed_checksum(ctype) + return checksum + bytes(len(self.rodc_id)) + + def make_checksum(self, usage, plaintext, ctype=None): + checksum = super().make_checksum(usage, plaintext, ctype) + return checksum + self.rodc_id + + def verify_checksum(self, usage, plaintext, ctype, cksum): + if self.rodc_id: + cksum, cksum_rodc_id = cksum[:-2], cksum[-2:] + + if self.rodc_id != cksum_rodc_id: + raise AssertionError(f'{self.rodc_id.hex()} != ' + f'{cksum_rodc_id.hex()}') + + super().verify_checksum(usage, + plaintext, + ctype, + cksum) + + class KerberosCredentials(Credentials): def __init__(self): super(KerberosCredentials, self).__init__() @@ -325,7 +364,7 @@ class KerberosCredentials(Credentials): etype = int(etype) contents = binascii.a2b_hex(hexkey) key = kcrypto.Key(etype, contents) - self.forced_keys[etype] = Krb5EncryptionKey(key, self.kvno) + self.forced_keys[etype] = RodcPacEncryptionKey(key, self.kvno) def get_forced_key(self, etype): etype = int(etype) @@ -982,13 +1021,13 @@ class RawKerberosTest(TestCaseInTempDir): def SessionKey_create(self, etype, contents, kvno=None): key = kcrypto.Key(etype, contents) - return Krb5EncryptionKey(key, kvno) + return RodcPacEncryptionKey(key, kvno) def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None): self.assertIsNotNone(pwd) self.assertIsNotNone(salt) key = kcrypto.string_to_key(etype, pwd, salt) - return Krb5EncryptionKey(key, kvno) + return RodcPacEncryptionKey(key, kvno) def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): e = etype_info2['etype'] -- 2.25.1 From 88ef693cc9286eeba9f0da14e9a3ee04f7d6addd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 17 Sep 2021 14:56:51 +1200 Subject: [PATCH 281/645] tests/krb5: Add method to verify ticket PAC checksums BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 12b5e72a35d632516980f6c051a5d83f913079e7) --- python/samba/tests/krb5/raw_testcase.py | 118 +++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e213b5eef9b..265789cdb26 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -34,8 +34,9 @@ from pyasn1.codec.native.encoder import encode as pyasn1_native_encode from pyasn1.codec.ber.encoder import BitStringEncoder from samba.credentials import Credentials -from samba.dcerpc import security +from samba.dcerpc import krb5pac, security from samba.gensec import FEATURE_SEAL +from samba.ndr import ndr_pack, ndr_unpack import samba.tests from samba.tests import TestCaseInTempDir @@ -418,6 +419,10 @@ class KerberosTicketCreds: class RawKerberosTest(TestCaseInTempDir): """A raw Kerberos Test case.""" + pac_checksum_types = {krb5pac.PAC_TYPE_SRV_CHECKSUM, + krb5pac.PAC_TYPE_KDC_CHECKSUM, + krb5pac.PAC_TYPE_TICKET_CHECKSUM} + etypes_to_test = ( {"value": -1111, "name": "dummy", }, {"value": kcrypto.Enctype.AES256, "name": "aes128", }, @@ -2900,6 +2905,114 @@ class RawKerberosTest(TestCaseInTempDir): ticket_blob) self.assertEqual(expected_checksum, checksum) + def verify_ticket(self, ticket, krbtgt_key, expect_pac=True): + # Check if the ticket is a TGT. + sname = ticket.ticket['sname'] + is_tgt = sname['name-string'][0] == b'krbtgt' + + # Decrypt the ticket. + + key = ticket.decryption_key + enc_part = ticket.ticket['enc-part'] + + self.assertElementEqual(enc_part, 'etype', key.etype) + self.assertElementKVNO(enc_part, 'kvno', key.kvno) + + enc_part = key.decrypt(KU_TICKET, enc_part['cipher']) + enc_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncTicketPart()) + + # Fetch the authorization data from the ticket. + auth_data = enc_part.get('authorization-data') + if expect_pac: + self.assertIsNotNone(auth_data) + elif auth_data is None: + return + + # Get a copy of the authdata with an empty PAC, and the existing PAC + # (if present). + empty_pac = self.get_empty_pac() + auth_data, pac_data = self.replace_pac(auth_data, + empty_pac, + expect_pac=expect_pac) + if not expect_pac: + return + + # Unpack the PAC as both PAC_DATA and PAC_DATA_RAW types. We use the + # raw type to create a new PAC with zeroed signatures for + # verification. This is because on Windows, the resource_groups field + # is added to PAC_LOGON_INFO after the info3 field has been created, + # which results in a different ordering of pointer values than Samba + # (see commit 0e201ecdc53). Using the raw type avoids changing + # PAC_LOGON_INFO, so verification against Windows can work. We still + # need the PAC_DATA type to retrieve the actual checksums, because the + # signatures in the raw type may contain padding bytes. + pac = ndr_unpack(krb5pac.PAC_DATA, + pac_data) + raw_pac = ndr_unpack(krb5pac.PAC_DATA_RAW, + pac_data) + + checksums = {} + + for pac_buffer, raw_pac_buffer in zip(pac.buffers, raw_pac.buffers): + buffer_type = pac_buffer.type + if buffer_type in self.pac_checksum_types: + self.assertNotIn(buffer_type, checksums, + f'Duplicate checksum type {buffer_type}') + + # Fetch the checksum and the checksum type from the PAC buffer. + checksum = pac_buffer.info.signature + ctype = pac_buffer.info.type + if ctype & 1 << 31: + ctype |= -1 << 31 + + checksums[buffer_type] = checksum, ctype + + if buffer_type != krb5pac.PAC_TYPE_TICKET_CHECKSUM: + # Zero the checksum field so that we can later verify the + # checksums. The ticket checksum field is not zeroed. + + signature = ndr_unpack( + krb5pac.PAC_SIGNATURE_DATA, + raw_pac_buffer.info.remaining) + signature.signature = bytes(len(checksum)) + raw_pac_buffer.info.remaining = ndr_pack( + signature) + + # Re-encode the PAC. + pac_data = ndr_pack(raw_pac) + + # Verify the signatures. + + server_checksum, server_ctype = checksums[ + krb5pac.PAC_TYPE_SRV_CHECKSUM] + Krb5EncryptionKey.verify_checksum(key, + KU_NON_KERB_CKSUM_SALT, + pac_data, + server_ctype, + server_checksum) + + kdc_checksum, kdc_ctype = checksums[ + krb5pac.PAC_TYPE_KDC_CHECKSUM] + krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, + server_checksum, + kdc_ctype, + kdc_checksum) + + if is_tgt: + self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums) + else: + ticket_checksum, ticket_ctype = checksums[ + krb5pac.PAC_TYPE_TICKET_CHECKSUM] + enc_part['authorization-data'] = auth_data + enc_part = self.der_encode(enc_part, + asn1Spec=krb5_asn1.EncTicketPart()) + + krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, + enc_part, + ticket_ctype, + ticket_checksum) + def replace_pac(self, auth_data, new_pac, expect_pac=True): if new_pac is not None: self.assertElementEqual(new_pac, 'ad-type', AD_WIN2K_PAC) @@ -2943,6 +3056,9 @@ class RawKerberosTest(TestCaseInTempDir): return new_auth_data, old_pac + def get_empty_pac(self): + return self.AuthorizationData_create(AD_WIN2K_PAC, bytes(1)) + def get_outer_pa_dict(self, kdc_exchange_dict): return self.get_pa_dict(kdc_exchange_dict['req_padata']) -- 2.25.1 From dac48491e0b0cdb63c9881ee4c793ce0d2960b74 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 17 Sep 2021 15:26:12 +1200 Subject: [PATCH 282/645] tests/krb5: Add method for modifying a ticket and creating PAC checksums BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 1fcde7cb6ce50e0a08097841e92476f320560664) --- python/samba/tests/krb5/raw_testcase.py | 234 ++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 265789cdb26..4ac7698ffab 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3013,6 +3013,240 @@ class RawKerberosTest(TestCaseInTempDir): ticket_ctype, ticket_checksum) + def modified_ticket(self, + ticket, *, + new_ticket_key=None, + modify_fn=None, + modify_pac_fn=None, + exclude_pac=False, + update_pac_checksums=True, + checksum_keys=None, + include_checksums=None): + if checksum_keys is None: + # A dict containing a key for each checksum type to be created in + # the PAC. + checksum_keys = {} + + if include_checksums is None: + # A dict containing a value for each checksum type; True if the + # checksum type is to be included in the PAC, False if it is to be + # excluded, or None/not present if the checksum is to be included + # based on its presence in the original PAC. + include_checksums = {} + + # Check that the values passed in by the caller make sense. + + self.assertLessEqual(checksum_keys.keys(), self.pac_checksum_types) + self.assertLessEqual(include_checksums.keys(), self.pac_checksum_types) + + if exclude_pac: + self.assertIsNone(modify_pac_fn) + + update_pac_checksums = False + + if not update_pac_checksums: + self.assertFalse(checksum_keys) + self.assertFalse(include_checksums) + + expect_pac = update_pac_checksums or modify_pac_fn is not None + + key = ticket.decryption_key + + if new_ticket_key is None: + # Use the same key to re-encrypt the ticket. + new_ticket_key = key + + if krb5pac.PAC_TYPE_SRV_CHECKSUM not in checksum_keys: + # If the server signature key is not present, fall back to the key + # used to encrypt the ticket. + checksum_keys[krb5pac.PAC_TYPE_SRV_CHECKSUM] = new_ticket_key + + if krb5pac.PAC_TYPE_TICKET_CHECKSUM not in checksum_keys: + # If the ticket signature key is not present, fall back to the key + # used for the KDC signature. + kdc_checksum_key = checksum_keys.get(krb5pac.PAC_TYPE_KDC_CHECKSUM) + if kdc_checksum_key is not None: + checksum_keys[krb5pac.PAC_TYPE_TICKET_CHECKSUM] = ( + kdc_checksum_key) + + # Decrypt the ticket. + + enc_part = ticket.ticket['enc-part'] + + self.assertElementEqual(enc_part, 'etype', key.etype) + self.assertElementKVNO(enc_part, 'kvno', key.kvno) + + enc_part = key.decrypt(KU_TICKET, enc_part['cipher']) + enc_part = self.der_decode( + enc_part, asn1Spec=krb5_asn1.EncTicketPart()) + + # Modify the ticket here. + if modify_fn is not None: + enc_part = modify_fn(enc_part) + + auth_data = enc_part.get('authorization-data') + if expect_pac: + self.assertIsNotNone(auth_data) + if auth_data is not None: + new_pac = None + if not exclude_pac: + # Get a copy of the authdata with an empty PAC, and the + # existing PAC (if present). + empty_pac = self.get_empty_pac() + empty_pac_auth_data, pac_data = self.replace_pac(auth_data, + empty_pac) + + if expect_pac: + self.assertIsNotNone(pac_data) + if pac_data is not None: + pac = ndr_unpack(krb5pac.PAC_DATA, pac_data) + + # Modify the PAC here. + if modify_pac_fn is not None: + pac = modify_pac_fn(pac) + + if update_pac_checksums: + # Get the enc-part with an empty PAC, which is needed + # to create a ticket signature. + enc_part_to_sign = enc_part.copy() + enc_part_to_sign['authorization-data'] = ( + empty_pac_auth_data) + enc_part_to_sign = self.der_encode( + enc_part_to_sign, + asn1Spec=krb5_asn1.EncTicketPart()) + + self.update_pac_checksums(pac, + checksum_keys, + include_checksums, + enc_part_to_sign) + + # Re-encode the PAC. + pac_data = ndr_pack(pac) + new_pac = self.AuthorizationData_create(AD_WIN2K_PAC, + pac_data) + + # Replace the PAC in the authorization data and re-add it to the + # ticket enc-part. + auth_data, _ = self.replace_pac(auth_data, new_pac) + enc_part['authorization-data'] = auth_data + + # Re-encrypt the ticket enc-part with the new key. + enc_part_new = self.der_encode(enc_part, + asn1Spec=krb5_asn1.EncTicketPart()) + enc_part_new = self.EncryptedData_create(new_ticket_key, + KU_TICKET, + enc_part_new) + + # Create a copy of the ticket with the new enc-part. + new_ticket = ticket.ticket.copy() + new_ticket['enc-part'] = enc_part_new + + new_ticket_creds = KerberosTicketCreds( + new_ticket, + session_key=ticket.session_key, + crealm=ticket.crealm, + cname=ticket.cname, + srealm=ticket.srealm, + sname=ticket.sname, + decryption_key=new_ticket_key, + ticket_private=enc_part, + encpart_private=ticket.encpart_private) + + return new_ticket_creds + + def update_pac_checksums(self, + pac, + checksum_keys, + include_checksums, + enc_part=None): + pac_buffers = pac.buffers + checksum_buffers = {} + + # Find the relevant PAC checksum buffers. + for pac_buffer in pac_buffers: + buffer_type = pac_buffer.type + if buffer_type in self.pac_checksum_types: + self.assertNotIn(buffer_type, checksum_buffers, + f'Duplicate checksum type {buffer_type}') + + checksum_buffers[buffer_type] = pac_buffer + + # Create any additional buffers that were requested but not + # present. Conversely, remove any buffers that were requested to be + # removed. + for buffer_type in self.pac_checksum_types: + if buffer_type in checksum_buffers: + if include_checksums.get(buffer_type) is False: + checksum_buffer = checksum_buffers.pop(buffer_type) + + pac.num_buffers -= 1 + pac_buffers.remove(checksum_buffer) + + elif include_checksums.get(buffer_type) is True: + info = krb5pac.PAC_SIGNATURE_DATA() + + checksum_buffer = krb5pac.PAC_BUFFER() + checksum_buffer.type = buffer_type + checksum_buffer.info = info + + pac_buffers.append(checksum_buffer) + pac.num_buffers += 1 + + checksum_buffers[buffer_type] = checksum_buffer + + # Fill the relevant checksum buffers. + for buffer_type, checksum_buffer in checksum_buffers.items(): + checksum_key = checksum_keys[buffer_type] + ctype = checksum_key.ctype & ((1 << 32) - 1) + + if buffer_type == krb5pac.PAC_TYPE_TICKET_CHECKSUM: + self.assertIsNotNone(enc_part) + + signature = checksum_key.make_checksum( + KU_NON_KERB_CKSUM_SALT, + enc_part) + + elif buffer_type == krb5pac.PAC_TYPE_SRV_CHECKSUM: + signature = Krb5EncryptionKey.make_zeroed_checksum( + checksum_key) + + else: + signature = checksum_key.make_zeroed_checksum() + + checksum_buffer.info.signature = signature + checksum_buffer.info.type = ctype + + # Add the new checksum buffers to the PAC. + pac.buffers = pac_buffers + + # Calculate the server and KDC checksums and insert them into the PAC. + + server_checksum_buffer = checksum_buffers.get( + krb5pac.PAC_TYPE_SRV_CHECKSUM) + if server_checksum_buffer is not None: + server_checksum_key = checksum_keys[krb5pac.PAC_TYPE_SRV_CHECKSUM] + + pac_data = ndr_pack(pac) + server_checksum = Krb5EncryptionKey.make_checksum( + server_checksum_key, + KU_NON_KERB_CKSUM_SALT, + pac_data) + + server_checksum_buffer.info.signature = server_checksum + + kdc_checksum_buffer = checksum_buffers.get( + krb5pac.PAC_TYPE_KDC_CHECKSUM) + if kdc_checksum_buffer is not None: + self.assertIsNotNone(server_checksum_buffer) + + kdc_checksum_key = checksum_keys[krb5pac.PAC_TYPE_KDC_CHECKSUM] + + kdc_checksum = kdc_checksum_key.make_checksum( + KU_NON_KERB_CKSUM_SALT, + server_checksum) + + kdc_checksum_buffer.info.signature = kdc_checksum + def replace_pac(self, auth_data, new_pac, expect_pac=True): if new_pac is not None: self.assertElementEqual(new_pac, 'ad-type', AD_WIN2K_PAC) -- 2.25.1 From bda0b16d5e482c8d7a6bf159f5cc69f629717abb Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 13:33:16 +1200 Subject: [PATCH 283/645] tests/krb5: Simplify adding authdata to ticket by using modified_ticket() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 4c67a53cdca206a118e82b356db0faf0ddc011ab) --- python/samba/tests/krb5/fast_tests.py | 49 +++++-------------------- python/samba/tests/krb5/raw_testcase.py | 8 ++++ 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 42e75e7513c..d8ccfaee325 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -25,10 +25,7 @@ import collections import ldb from samba.dcerpc import security -from samba.tests.krb5.raw_testcase import ( - KerberosTicketCreds, - Krb5EncryptionKey -) +from samba.tests.krb5.raw_testcase import Krb5EncryptionKey from samba.tests.krb5.kdc_base_test import KDCBaseTest from samba.tests.krb5.rfc4120_constants import ( AD_FX_FAST_ARMOR, @@ -45,7 +42,6 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, KRB_AS_REP, KRB_TGS_REP, - KU_TICKET, NT_PRINCIPAL, NT_SRV_INST, PADATA_FX_COOKIE, @@ -1428,44 +1424,19 @@ class FAST_Tests(KDCBaseTest): def gen_tgt_fast_armor_auth_data(self): user_tgt = self.get_user_tgt() - ticket_decryption_key = user_tgt.decryption_key + auth_data = self.generate_fast_armor_auth_data() + + def modify_fn(enc_part): + enc_part['authorization-data'].append(auth_data) - tgt_encpart = self.getElementValue(user_tgt.ticket, 'enc-part') - self.assertElementEqual(tgt_encpart, 'etype', - ticket_decryption_key.etype) - self.assertElementKVNO(tgt_encpart, 'kvno', - ticket_decryption_key.kvno) - tgt_cipher = self.getElementValue(tgt_encpart, 'cipher') - tgt_decpart = ticket_decryption_key.decrypt(KU_TICKET, tgt_cipher) - tgt_private = self.der_decode(tgt_decpart, - asn1Spec=krb5_asn1.EncTicketPart()) + return enc_part - auth_data = self.generate_fast_armor_auth_data() - tgt_private['authorization-data'].append(auth_data) - - # Re-encrypt the user TGT. - tgt_private_new = self.der_encode( - tgt_private, - asn1Spec=krb5_asn1.EncTicketPart()) - tgt_encpart = self.EncryptedData_create(ticket_decryption_key, - KU_TICKET, - tgt_private_new) - user_ticket = user_tgt.ticket.copy() - user_ticket['enc-part'] = tgt_encpart - - user_tgt = KerberosTicketCreds( - user_ticket, - session_key=user_tgt.session_key, - crealm=user_tgt.crealm, - cname=user_tgt.cname, - srealm=user_tgt.srealm, - sname=user_tgt.sname, - decryption_key=user_tgt.decryption_key, - ticket_private=tgt_private, - encpart_private=user_tgt.encpart_private) + checksum_keys = self.get_krbtgt_checksum_key() # Use our modifed TGT to replace the one in the request. - return user_tgt + return self.modified_ticket(user_tgt, + modify_fn=modify_fn, + checksum_keys=checksum_keys) def create_fast_cookie(self, cookie): self.assertIsNotNone(cookie) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4ac7698ffab..57013caafb1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3290,6 +3290,14 @@ class RawKerberosTest(TestCaseInTempDir): return new_auth_data, old_pac + def get_krbtgt_checksum_key(self): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + return { + krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key + } + def get_empty_pac(self): return self.AuthorizationData_create(AD_WIN2K_PAC, bytes(1)) -- 2.25.1 From 32c964973908026a4c5ebcb40f70f67c6b51d79e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 17:01:12 +1200 Subject: [PATCH 284/645] tests/krb5: Make get_default_enctypes() return a set of enctype constants This is often more convenient than a bitfield. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 7cedd383bcc1b5652ea65817b464d6e0485c7b8b) --- python/samba/tests/krb5/kdc_base_test.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 59175c7bb2f..3d2d20cb65b 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -222,11 +222,11 @@ class KDCBaseTest(RawKerberosTest): functional_level = self.get_domain_functional_level(samdb) # RC4 should always be supported - default_enctypes = security.KERB_ENCTYPE_RC4_HMAC_MD5 + default_enctypes = {kcrypto.Enctype.RC4} if functional_level >= DS_DOMAIN_FUNCTION_2008: # AES is only supported at functional level 2008 or higher - default_enctypes |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 - default_enctypes |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + default_enctypes.add(kcrypto.Enctype.AES256) + default_enctypes.add(kcrypto.Enctype.AES128) return default_enctypes @@ -513,12 +513,7 @@ class KDCBaseTest(RawKerberosTest): default_enctypes = self.get_default_enctypes() - if default_enctypes & security.KERB_ENCTYPE_RC4_HMAC_MD5: - self.assertIn(kcrypto.Enctype.RC4, keys) - if default_enctypes & security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96: - self.assertIn(kcrypto.Enctype.AES256, keys) - if default_enctypes & security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96: - self.assertIn(kcrypto.Enctype.AES128, keys) + self.assertCountEqual(default_enctypes, keys) return keys -- 2.25.1 From 85034fb361104d57bd89058fbb6d5cdf5d0de4ee Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 21:01:46 +1200 Subject: [PATCH 285/645] tests/krb5: Add methods to convert between enctypes and bitfields These methods are useful for converting a collection of encryption types into msDS-SupportedEncryptionTypes bit flags, and vice versa. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 432eba9e09849e74f4c0f2d7826d45cbd2b7ce42) --- python/samba/tests/krb5/kdc_base_test.py | 6 +-- python/samba/tests/krb5/raw_testcase.py | 51 +++++++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 3d2d20cb65b..10ad9e6961f 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -633,10 +633,8 @@ class KDCBaseTest(RawKerberosTest): enctypes = supported_enctypes if fast_support: - fast_bits = (security.KERB_ENCTYPE_FAST_SUPPORTED | - security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | - security.KERB_ENCTYPE_CLAIMS_SUPPORTED) - enctypes = (enctypes or 0) | fast_bits + enctypes = enctypes or 0 + enctypes |= KerberosCredentials.fast_supported_bits if enctypes is not None: details['msDS-SupportedEncryptionTypes'] = str(enctypes) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 57013caafb1..57579126f8a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -304,6 +304,11 @@ class RodcPacEncryptionKey(Krb5EncryptionKey): class KerberosCredentials(Credentials): + + fast_supported_bits = (security.KERB_ENCTYPE_FAST_SUPPORTED | + security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED | + security.KERB_ENCTYPE_CLAIMS_SUPPORTED) + def __init__(self): super(KerberosCredentials, self).__init__() all_enc_types = 0 @@ -331,26 +336,52 @@ class KerberosCredentials(Credentials): def set_ap_supported_enctypes(self, value): self.ap_supported_enctypes = int(value) - def _get_krb5_etypes(self, supported_enctypes): + etype_map = collections.OrderedDict([ + (kcrypto.Enctype.AES256, + security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96), + (kcrypto.Enctype.AES128, + security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96), + (kcrypto.Enctype.RC4, + security.KERB_ENCTYPE_RC4_HMAC_MD5), + (kcrypto.Enctype.DES_MD5, + security.KERB_ENCTYPE_DES_CBC_MD5), + (kcrypto.Enctype.DES_CRC, + security.KERB_ENCTYPE_DES_CBC_CRC) + ]) + + @classmethod + def etypes_to_bits(self, etypes): + bits = 0 + for etype in etypes: + bit = self.etype_map[etype] + if bits & bit: + raise ValueError(f'Got duplicate etype: {etype}') + bits |= bit + + return bits + + @classmethod + def bits_to_etypes(self, bits): etypes = () + for etype, bit in self.etype_map.items(): + if bit & bits: + bits &= ~bit + etypes += (etype,) - if supported_enctypes & security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96: - etypes += (kcrypto.Enctype.AES256,) - if supported_enctypes & security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96: - etypes += (kcrypto.Enctype.AES128,) - if supported_enctypes & security.KERB_ENCTYPE_RC4_HMAC_MD5: - etypes += (kcrypto.Enctype.RC4,) + bits &= ~self.fast_supported_bits + if bits != 0: + raise ValueError(f'Unsupported etype bits: {bits}') return etypes def get_as_krb5_etypes(self): - return self._get_krb5_etypes(self.as_supported_enctypes) + return self.bits_to_etypes(self.as_supported_enctypes) def get_tgs_krb5_etypes(self): - return self._get_krb5_etypes(self.tgs_supported_enctypes) + return self.bits_to_etypes(self.tgs_supported_enctypes) def get_ap_krb5_etypes(self): - return self._get_krb5_etypes(self.ap_supported_enctypes) + return self.bits_to_etypes(self.ap_supported_enctypes) def set_kvno(self, kvno): # Sign-extend from 32 bits. -- 2.25.1 From 8cbe4a35f37b3de85d41a702926bc9192ffa7b0e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 17:10:49 +1200 Subject: [PATCH 286/645] tests/krb5: Get supported enctypes for credentials from database Look up the account's msDS-SupportedEncryptionTypes attribute to get the encryption types that it supports. Move the fallback to RC4 to when the ticket decryption key is obtained. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit b6eaf2cf44fb66d8f302d4cab050827a67de3ea4) --- python/samba/tests/krb5/as_req_tests.py | 4 +- python/samba/tests/krb5/kdc_base_test.py | 52 +++++++++++++++++------- python/samba/tests/krb5/raw_testcase.py | 5 ++- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 35f88a0c920..8d9b90fee69 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -60,7 +60,7 @@ class AsReqKerberosTests(KDCBaseTest): initial_kdc_options=None): client_creds = self.get_client_creds() client_account = client_creds.get_username() - client_as_etypes = client_creds.get_as_krb5_etypes() + 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() @@ -114,7 +114,7 @@ class AsReqKerberosTests(KDCBaseTest): def test_as_req_enc_timestamp(self): client_creds = self.get_client_creds() client_account = client_creds.get_username() - client_as_etypes = client_creds.get_as_krb5_etypes() + client_as_etypes = self.get_default_enctypes() client_kvno = client_creds.get_kvno() krbtgt_creds = self.get_krbtgt_creds(require_strongest_key=True) krbtgt_account = krbtgt_creds.get_username() diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 10ad9e6961f..cdaeaf9f3e1 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -289,6 +289,8 @@ class KDCBaseTest(RawKerberosTest): # Save the account name so it can be deleted in tearDownClass self.accounts.add(dn) + self.creds_set_enctypes(creds) + return (creds, dn) def create_rodc(self, ctx): @@ -522,13 +524,28 @@ class KDCBaseTest(RawKerberosTest): for enctype, key in keys.items(): creds.set_forced_key(enctype, key) - supported_enctypes = 0 - if kcrypto.Enctype.AES256 in keys: - supported_enctypes |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 - if kcrypto.Enctype.AES128 in keys: - supported_enctypes |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 - if kcrypto.Enctype.RC4 in keys: - supported_enctypes |= security.KERB_ENCTYPE_RC4_HMAC_MD5 + def creds_set_enctypes(self, creds): + samdb = self.get_samdb() + + res = samdb.search(creds.get_dn(), + scope=ldb.SCOPE_BASE, + attrs=['msDS-SupportedEncryptionTypes']) + supported_enctypes = res[0].get('msDS-SupportedEncryptionTypes', idx=0) + + if supported_enctypes is None: + supported_enctypes = 0 + + creds.set_as_supported_enctypes(supported_enctypes) + creds.set_tgs_supported_enctypes(supported_enctypes) + creds.set_ap_supported_enctypes(supported_enctypes) + + def creds_set_default_enctypes(self, creds, fast_support=False): + default_enctypes = self.get_default_enctypes() + supported_enctypes = KerberosCredentials.etypes_to_bits( + default_enctypes) + + if fast_support: + supported_enctypes |= KerberosCredentials.fast_supported_bits creds.set_as_supported_enctypes(supported_enctypes) creds.set_tgs_supported_enctypes(supported_enctypes) @@ -662,14 +679,6 @@ class KDCBaseTest(RawKerberosTest): keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) - if machine_account: - if supported_enctypes is not None: - tgs_enctypes = supported_enctypes - else: - tgs_enctypes = security.KERB_ENCTYPE_RC4_HMAC_MD5 - - creds.set_tgs_supported_enctypes(tgs_enctypes) - # Handle secret replication to the RODC. if allowed_replication or revealed_to_rodc: @@ -814,6 +823,11 @@ class KDCBaseTest(RawKerberosTest): keys = self.get_keys(samdb, krbtgt_dn) self.creds_set_keys(creds, keys) + # The RODC krbtgt account should support the default enctypes, + # although it might not have the msDS-SupportedEncryptionTypes + # attribute. + self.creds_set_default_enctypes(creds) + return creds c = self._get_krb5_creds(prefix='RODC_KRBTGT', @@ -858,6 +872,8 @@ class KDCBaseTest(RawKerberosTest): keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) + self.creds_set_enctypes(creds) + return creds c = self._get_krb5_creds(prefix='MOCK_RODC_KRBTGT', @@ -898,6 +914,12 @@ class KDCBaseTest(RawKerberosTest): keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) + # The krbtgt account should support the default enctypes, although + # it might not (on Samba) have the msDS-SupportedEncryptionTypes + # attribute. + self.creds_set_default_enctypes(creds, + fast_support=self.kdc_fast_support) + return creds c = self._get_krb5_creds(prefix='KRBTGT', diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 57579126f8a..8d7778602f5 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1082,7 +1082,10 @@ class RawKerberosTest(TestCaseInTempDir): if etype is None: etypes = creds.get_tgs_krb5_etypes() - etype = etypes[0] + if etypes: + etype = etypes[0] + else: + etype = kcrypto.Enctype.RC4 forced_key = creds.get_forced_key(etype) if forced_key is not None: -- 2.25.1 From 3de4e99cbdacbfeb7e92d66b8c36626010460b7f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 17:11:28 +1200 Subject: [PATCH 287/645] tests/krb5: Correctly check PA-SUPPORTED-ENCTYPES BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 14cd933a9d6af08deb680c9f688b166138d45ed9) --- python/samba/tests/krb5/fast_tests.py | 4 ++++ python/samba/tests/krb5/kdc_base_test.py | 3 +++ python/samba/tests/krb5/raw_testcase.py | 24 +++++++++++++++--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index d8ccfaee325..431b48f00d6 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1126,6 +1126,7 @@ class FAST_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) krbtgt_decryption_key = self.TicketDecryptionKey_from_creds( krbtgt_creds) + krbtgt_etypes = krbtgt_creds.tgs_supported_enctypes target_username = target_creds.get_username()[:-1] target_realm = target_creds.get_realm() @@ -1134,6 +1135,7 @@ class FAST_Tests(KDCBaseTest): name_type=NT_SRV_INST, names=[target_service, target_username]) target_decryption_key = self.TicketDecryptionKey_from_creds( target_creds) + target_etypes = target_creds.tgs_supported_enctypes fast_cookie = None preauth_etype_info2 = None @@ -1322,6 +1324,7 @@ class FAST_Tests(KDCBaseTest): expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, + expected_supported_etypes=krbtgt_etypes, expected_flags=expected_flags, unexpected_flags=unexpected_flags, ticket_decryption_key=krbtgt_decryption_key, @@ -1355,6 +1358,7 @@ class FAST_Tests(KDCBaseTest): expected_anon=expected_anon, expected_srealm=expected_srealm, expected_sname=expected_sname, + expected_supported_etypes=target_etypes, expected_flags=expected_flags, unexpected_flags=unexpected_flags, ticket_decryption_key=target_decryption_key, diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index cdaeaf9f3e1..646859e85b3 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1267,6 +1267,8 @@ class KDCBaseTest(RawKerberosTest): expected_sname = self.PrincipalName_create( name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) + expected_etypes = krbtgt_creds.tgs_supported_enctypes + rep, kdc_exchange_dict = self._test_as_exchange( cname=cname, realm=realm, @@ -1279,6 +1281,7 @@ class KDCBaseTest(RawKerberosTest): expected_srealm=expected_realm, expected_sname=expected_sname, expected_salt=salt, + expected_supported_etypes=expected_etypes, etypes=etype, padata=padata, kdc_options=kdc_options, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8d7778602f5..c6bc3e553ad 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1879,6 +1879,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_supported_etypes=None, expected_flags=None, unexpected_flags=None, ticket_decryption_key=None, @@ -1923,6 +1924,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, @@ -1963,6 +1965,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_supported_etypes=None, expected_flags=None, unexpected_flags=None, ticket_decryption_key=None, @@ -2006,6 +2009,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, @@ -2312,19 +2316,19 @@ class RawKerberosTest(TestCaseInTempDir): if canonicalize: self.assertIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) + expected_supported_etypes = kdc_exchange_dict[ + 'expected_supported_etypes'] + expected_supported_etypes |= ( + security.KERB_ENCTYPE_DES_CBC_CRC | + security.KERB_ENCTYPE_DES_CBC_MD5 | + security.KERB_ENCTYPE_RC4_HMAC_MD5) + (supported_etypes,) = struct.unpack( ' Date: Mon, 20 Sep 2021 13:54:39 +1200 Subject: [PATCH 288/645] tests/krb5: Set key version number for all accounts created with create_account() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 054ec1a8cc4ae42918c7c06ef9c66c8a81242655) --- python/samba/tests/krb5/kdc_base_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 646859e85b3..91034a10e15 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -291,6 +291,12 @@ class KDCBaseTest(RawKerberosTest): self.creds_set_enctypes(creds) + res = samdb.search(base=dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + return (creds, dn) def create_rodc(self, ctx): @@ -670,12 +676,6 @@ class KDCBaseTest(RawKerberosTest): additional_details=details, account_control=user_account_control) - res = samdb.search(base=dn, - scope=ldb.SCOPE_BASE, - attrs=['msDS-KeyVersionNumber']) - kvno = int(res[0]['msDS-KeyVersionNumber'][0]) - creds.set_kvno(kvno) - keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) -- 2.25.1 From 80db36f0c5dc5d60828fd73acad39fad6a0edaec Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 13:59:24 +1200 Subject: [PATCH 289/645] tests/krb5: Allow tgs_req() to check the returned ticket enc-part BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 38b4b334caf1b32f1479db3ada48b2028946f5e6) --- python/samba/tests/krb5/kdc_base_test.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 91034a10e15..914112fdfc7 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1084,7 +1084,7 @@ class KDCBaseTest(RawKerberosTest): def tgs_req(self, cname, sname, realm, ticket, key, etypes, expected_error_mode=0, padata=None, kdc_options=0, - to_rodc=False): + to_rodc=False, service_creds=None): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1098,6 +1098,12 @@ class KDCBaseTest(RawKerberosTest): crealm=realm, cname=cname) + if service_creds is not None: + decryption_key = self.TicketDecryptionKey_from_creds( + service_creds) + else: + decryption_key = None + if not expected_error_mode: check_error_fn = None check_rep_fn = self.generic_check_kdc_rep @@ -1120,6 +1126,7 @@ class KDCBaseTest(RawKerberosTest): check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, + ticket_decryption_key=decryption_key, generate_padata_fn=generate_padata if padata is not None else None, tgt=tgt, authenticator_subkey=subkey, -- 2.25.1 From dba52655b9f2c7421198457c4550c7110979f23d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 13:58:09 +1200 Subject: [PATCH 290/645] tests/krb5: Add method to get DC credentials BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 9d01043042f1caac98a23cf4d9aa9a02a31a9239) --- python/samba/tests/krb5/kdc_base_test.py | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 914112fdfc7..5de9907d02b 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -930,6 +930,48 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=download_krbtgt_creds) return c + def get_dc_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + + def download_dc_creds(): + samdb = self.get_samdb() + + dc_rid = 1000 + dc_sid = '%s-%d' % (samdb.get_domain_sid(), dc_rid) + + res = samdb.search(base='' % dc_sid, + scope=ldb.SCOPE_BASE, + attrs=['sAMAccountName', + 'msDS-KeyVersionNumber']) + dn = res[0].dn + username = str(res[0]['sAMAccountName']) + + creds = KerberosCredentials() + creds.set_domain(self.env_get_var('DOMAIN', 'DC')) + creds.set_realm(self.env_get_var('REALM', 'DC')) + creds.set_username(username) + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + creds.set_dn(dn) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + self.creds_set_enctypes(creds) + + return creds + + c = self._get_krb5_creds(prefix='DC', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key, + fallback_creds_fn=download_dc_creds) + return c + def as_req(self, cname, sname, realm, etypes, padata=None, kdc_options=0): '''Send a Kerberos AS_REQ, returns the undecoded response ''' -- 2.25.1 From b5bba9c3a89a3e980ec391f5920039e7352c61ac Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 14:08:16 +1200 Subject: [PATCH 291/645] tests/krb5: Fix checking for presence of authorization data BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit f9284d8517edd9ffd96f0c24166a16366f97de8f) --- python/samba/tests/krb5/kdc_base_test.py | 3 ++- .../ms_kile_client_principal_lookup_tests.py | 6 ++++-- python/samba/tests/krb5/raw_testcase.py | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 5de9907d02b..b4d3739aa11 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1126,7 +1126,7 @@ class KDCBaseTest(RawKerberosTest): def tgs_req(self, cname, sname, realm, ticket, key, etypes, expected_error_mode=0, padata=None, kdc_options=0, - to_rodc=False, service_creds=None): + to_rodc=False, service_creds=None, expect_pac=True): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1173,6 +1173,7 @@ class KDCBaseTest(RawKerberosTest): tgt=tgt, authenticator_subkey=subkey, kdc_options=str(kdc_options), + expect_pac=expect_pac, to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 99c842701ea..64ebe15ad70 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -321,7 +321,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + expect_pac=False) self.check_tgs_reply(rep) # Check the contents of the service ticket @@ -695,7 +696,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + expect_pac=False) self.check_tgs_reply(rep) # Check the contents of the service ticket diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c6bc3e553ad..b531e33041d 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -944,12 +944,15 @@ class RawKerberosTest(TestCaseInTempDir): v = self.getElementValue(obj, elem) self.assertIsNone(v) - def assertElementPresent(self, obj, elem): + def assertElementPresent(self, obj, elem, expect_empty=False): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) if self.strict_checking: if isinstance(v, collections.abc.Container): - self.assertNotEqual(0, len(v)) + if expect_empty: + self.assertEqual(0, len(v)) + else: + self.assertNotEqual(0, len(v)) def assertElementEqual(self, obj, elem, value): v = self.getElementValue(obj, elem) @@ -1907,6 +1910,7 @@ class RawKerberosTest(TestCaseInTempDir): outer_req=None, pac_request=None, pac_options=None, + expect_pac=True, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -1952,6 +1956,7 @@ class RawKerberosTest(TestCaseInTempDir): 'outer_req': outer_req, 'pac_request': pac_request, 'pac_options': pac_options, + 'expect_pac': expect_pac, 'to_rodc': to_rodc } if callback_dict is None: @@ -1992,6 +1997,7 @@ class RawKerberosTest(TestCaseInTempDir): outer_req=None, pac_request=None, pac_options=None, + expect_pac=True, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2036,6 +2042,7 @@ class RawKerberosTest(TestCaseInTempDir): 'outer_req': outer_req, 'pac_request': pac_request, 'pac_options': pac_options, + 'expect_pac': expect_pac, 'to_rodc': to_rodc } if callback_dict is None: @@ -2236,6 +2243,8 @@ class RawKerberosTest(TestCaseInTempDir): armor_key = kdc_exchange_dict['armor_key'] self.verify_ticket_checksum(ticket, ticket_checksum, armor_key) + expect_pac = kdc_exchange_dict['expect_pac'] + ticket_session_key = None if ticket_private is not None: self.assertElementFlags(ticket_private, 'flags', @@ -2265,7 +2274,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementMissing(ticket_private, 'renew-till') if self.strict_checking: self.assertElementEqual(ticket_private, 'caddr', []) - self.assertElementPresent(ticket_private, 'authorization-data') + self.assertElementPresent(ticket_private, 'authorization-data', + expect_empty=not expect_pac) encpart_session_key = None if encpart_private is not None: -- 2.25.1 From 446ce3918ac15c60867b09bd9db76c63770af9b2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 22 Sep 2021 11:41:45 +1200 Subject: [PATCH 292/645] tests/krb5: Provide ticket enc-part key to tgs_req() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit f2f1f3a1e9269f0e7b93006bba2368a6ffbecc7c) --- python/samba/tests/krb5/kdc_base_test.py | 3 +- python/samba/tests/krb5/kdc_tgs_tests.py | 6 ++-- .../ms_kile_client_principal_lookup_tests.py | 28 ++++++++++++------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b4d3739aa11..b71ae66bf54 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1215,7 +1215,8 @@ class KDCBaseTest(RawKerberosTest): names=[service, target_name]) rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, - to_rodc=to_rodc) + to_rodc=to_rodc, + service_creds=target_creds) service_ticket = rep['ticket'] diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index dad9e6b88df..0904233b01f 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -132,7 +132,8 @@ class KdcTgsTests(KDCBaseTest): names=["ldap", samdb.host_dns_name()]) (rep, _) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=self.get_dc_creds()) self.check_tgs_reply(rep) @@ -175,7 +176,8 @@ class KdcTgsTests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the service ticket diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 64ebe15ad70..ce796f63ac2 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -126,7 +126,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -185,7 +186,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, mc.get_realm(), ticket, key, etype) + cname, sname, mc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -247,7 +249,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the service ticket @@ -322,7 +325,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): (rep, enc_part) = self.tgs_req( cname, sname, uc.get_realm(), ticket, key, etype, - expect_pac=False) + service_creds=mc, expect_pac=False) self.check_tgs_reply(rep) # Check the contents of the service ticket @@ -390,7 +393,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -492,7 +496,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -555,7 +560,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -619,7 +625,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket @@ -697,7 +704,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): (rep, enc_part) = self.tgs_req( cname, sname, uc.get_realm(), ticket, key, etype, - expect_pac=False) + service_creds=mc, expect_pac=False) self.check_tgs_reply(rep) # Check the contents of the service ticket @@ -767,7 +774,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): names=[mc.get_username()]) (rep, enc_part) = self.tgs_req( - cname, sname, uc.get_realm(), ticket, key, etype) + cname, sname, uc.get_realm(), ticket, key, etype, + service_creds=mc) self.check_tgs_reply(rep) # Check the contents of the pac, and the ticket -- 2.25.1 From 6ea3eb76d1dd9d8145c888c10a1357786a11a9d7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 14:05:58 +1200 Subject: [PATCH 293/645] tests/krb5: Simplify account creation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 394e8db261b10d130c5e5730989bf68f9bf4f85f) --- .../ms_kile_client_principal_lookup_tests.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index ce796f63ac2..501bc4892f4 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -282,15 +282,11 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(samdb, user_name) + (uc, dn) = self.create_account(samdb, user_name, + account_control=UF_DONT_REQUIRE_PREAUTH) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) - self.modify_attribute( - samdb, - dn, - "userAccountControl", - str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) mach_name = "mskilemac" (mc, _) = self.create_account(samdb, mach_name, machine_account=True) @@ -660,15 +656,11 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): samdb = self.get_samdb() user_name = "mskileusr" alt_name = "mskilealtsec" - (uc, dn) = self.create_account(samdb, user_name) + (uc, dn) = self.create_account(samdb, user_name, + account_control=UF_DONT_REQUIRE_PREAUTH) realm = uc.get_realm().lower() alt_sec = "Kerberos:%s@%s" % (alt_name, realm) self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) - self.modify_attribute( - samdb, - dn, - "userAccountControl", - str(UF_NORMAL_ACCOUNT | UF_DONT_REQUIRE_PREAUTH)) ename = alt_name + "@" + realm mach_name = "mskilemac" -- 2.25.1 From 8967c3dc5ad280f34c55988ca1e1b1e832f59312 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 21 Sep 2021 13:54:47 +1200 Subject: [PATCH 294/645] tests/krb5: Add get_rodc_krbtgt_creds() to RawKerberosTest BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 1458cd9065de34c42bd5ec63feb2f66c25103982) --- python/samba/tests/krb5/raw_testcase.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b531e33041d..59882e44173 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -750,6 +750,17 @@ class RawKerberosTest(TestCaseInTempDir): c.set_gensec_features(c.get_gensec_features() | FEATURE_SEAL) return c + def get_rodc_krbtgt_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + c = self._get_krb5_creds(prefix='RODC_KRBTGT', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key) + return c + def get_krbtgt_creds(self, require_keys=True, require_strongest_key=False): -- 2.25.1 From 60ec7c93e121afdbfeda3cbdbb32406f91e3cf5b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 14:10:07 +1200 Subject: [PATCH 295/645] tests/krb5: Verify checksums of tickets obtained from the KDC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ea7b550a500d9e458498d37688b67dafd3d9509d) --- python/samba/tests/krb5/raw_testcase.py | 34 +++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 59882e44173..985792887ca 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2254,6 +2254,13 @@ class RawKerberosTest(TestCaseInTempDir): armor_key = kdc_exchange_dict['armor_key'] self.verify_ticket_checksum(ticket, ticket_checksum, armor_key) + to_rodc = kdc_exchange_dict['to_rodc'] + if to_rodc: + krbtgt_creds = self.get_rodc_krbtgt_creds() + else: + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + expect_pac = kdc_exchange_dict['expect_pac'] ticket_session_key = None @@ -2386,6 +2393,9 @@ class RawKerberosTest(TestCaseInTempDir): ticket_private=ticket_private, encpart_private=encpart_private) + if ticket_decryption_key is not None: + self.verify_ticket(ticket_creds, krbtgt_key, expect_pac=expect_pac) + kdc_exchange_dict['rep_ticket_creds'] = ticket_creds def check_pac_options_claims_support(self, pac_options): @@ -3061,16 +3071,20 @@ class RawKerberosTest(TestCaseInTempDir): if is_tgt: self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums) else: - ticket_checksum, ticket_ctype = checksums[ - krb5pac.PAC_TYPE_TICKET_CHECKSUM] - enc_part['authorization-data'] = auth_data - enc_part = self.der_encode(enc_part, - asn1Spec=krb5_asn1.EncTicketPart()) - - krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, - enc_part, - ticket_ctype, - ticket_checksum) + ticket_checksum, ticket_ctype = checksums.get( + krb5pac.PAC_TYPE_TICKET_CHECKSUM, + (None, None)) + if self.strict_checking: + self.assertIsNotNone(ticket_checksum) + if ticket_checksum is not None: + enc_part['authorization-data'] = auth_data + enc_part = self.der_encode(enc_part, + asn1Spec=krb5_asn1.EncTicketPart()) + + krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, + enc_part, + ticket_ctype, + ticket_checksum) def modified_ticket(self, ticket, *, -- 2.25.1 From 7a78066fb53fb52ed4e30f7890bad6311617e165 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 15:06:18 +1200 Subject: [PATCH 296/645] tests/krb5: Add method to determine if principal is krbtgt BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit c0b81f0dd54d0d71b5d0f5a870b505e82d0e85b8) --- python/samba/tests/krb5/raw_testcase.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 985792887ca..cadf2b50dc9 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2977,7 +2977,7 @@ class RawKerberosTest(TestCaseInTempDir): def verify_ticket(self, ticket, krbtgt_key, expect_pac=True): # Check if the ticket is a TGT. sname = ticket.ticket['sname'] - is_tgt = sname['name-string'][0] == b'krbtgt' + is_tgt = self.is_tgs(sname) # Decrypt the ticket. @@ -3371,6 +3371,10 @@ class RawKerberosTest(TestCaseInTempDir): krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key } + def is_tgs(self, principal): + name = principal['name-string'][0] + return name in ('krbtgt', b'krbtgt') + def get_empty_pac(self): return self.AuthorizationData_create(AD_WIN2K_PAC, bytes(1)) -- 2.25.1 From a6bc99e5377ab5165b965c29ee18ce25a57a3f27 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 15:10:35 +1200 Subject: [PATCH 297/645] tests/krb5: Add classes for testing invalid checksums BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Thu Sep 23 19:28:44 UTC 2021 on sn-devel-184 (cherry picked from commit 5b331443d0698256ee7fcc040a1ab8137efe925d) --- python/samba/tests/krb5/raw_testcase.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index cadf2b50dc9..579d52b3e92 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -303,6 +303,29 @@ class RodcPacEncryptionKey(Krb5EncryptionKey): cksum) +class ZeroedChecksumKey(Krb5EncryptionKey): + def make_checksum(self, usage, plaintext, ctype=None): + return self.make_zeroed_checksum(ctype) + + +class WrongLengthChecksumKey(Krb5EncryptionKey): + def __init__(self, key, kvno, length): + super().__init__(key, kvno) + + self._length = length + + def make_checksum(self, usage, plaintext, ctype=None): + checksum = super().make_checksum(usage, plaintext, ctype) + + diff = self._length - len(checksum) + if diff > 0: + checksum += bytes(diff) + elif diff < 0: + checksum = checksum[:self._length] + + return checksum + + class KerberosCredentials(Credentials): fast_supported_bits = (security.KERB_ENCTYPE_FAST_SUPPORTED | -- 2.25.1 From 9d36344e03555125db679400f83d56b606afe71f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:16:24 +1300 Subject: [PATCH 298/645] tests/krb5: Rename method parameter For class methods, the name given to the first parameter is generally 'cls' rather than 'self'. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit d501ddca3b7b9c39c0b3eccf19176e3122cf5b9d) --- python/samba/tests/krb5/raw_testcase.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 579d52b3e92..11c0e308e3d 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -373,10 +373,10 @@ class KerberosCredentials(Credentials): ]) @classmethod - def etypes_to_bits(self, etypes): + def etypes_to_bits(cls, etypes): bits = 0 for etype in etypes: - bit = self.etype_map[etype] + bit = cls.etype_map[etype] if bits & bit: raise ValueError(f'Got duplicate etype: {etype}') bits |= bit @@ -384,14 +384,14 @@ class KerberosCredentials(Credentials): return bits @classmethod - def bits_to_etypes(self, bits): + def bits_to_etypes(cls, bits): etypes = () - for etype, bit in self.etype_map.items(): + for etype, bit in cls.etype_map.items(): if bit & bits: bits &= ~bit etypes += (etype,) - bits &= ~self.fast_supported_bits + bits &= ~cls.fast_supported_bits if bits != 0: raise ValueError(f'Unsupported etype bits: {bits}') -- 2.25.1 From c91e9118a70fad0f17483bd586ac0933c04c1eaa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:16:51 +1300 Subject: [PATCH 299/645] tests/krb5: Remove unused parameter BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 8e4b21590836dab02c1864f6ac12b3879c4bd69c) --- python/samba/tests/krb5/raw_testcase.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 11c0e308e3d..1119c9926d7 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2169,7 +2169,6 @@ class RawKerberosTest(TestCaseInTempDir): self.check_rep_padata(kdc_exchange_dict, callback_dict, - rep, fast_response['padata'], error_code=0) @@ -2509,7 +2508,6 @@ class RawKerberosTest(TestCaseInTempDir): etype_info2 = self.check_rep_padata(kdc_exchange_dict, callback_dict, - rep, rep_padata, error_code) @@ -2520,7 +2518,6 @@ class RawKerberosTest(TestCaseInTempDir): def check_rep_padata(self, kdc_exchange_dict, callback_dict, - rep, rep_padata, error_code): rep_msg_type = kdc_exchange_dict['rep_msg_type'] -- 2.25.1 From cda6cb3e1ef28d554a583bde521e03fd8ef3eedd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:23:17 +1300 Subject: [PATCH 300/645] tests/krb5: Allow for missing msDS-KeyVersionNumber attribute BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ce433ff868d3cdf8e8a6e4995d89d6e036335fb6) --- python/samba/tests/krb5/kdc_base_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b71ae66bf54..bb92bbd65e5 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -294,8 +294,10 @@ class KDCBaseTest(RawKerberosTest): res = samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=['msDS-KeyVersionNumber']) - kvno = int(res[0]['msDS-KeyVersionNumber'][0]) - creds.set_kvno(kvno) + kvno = res[0].get('msDS-KeyVersionNumber', idx=0) + if kvno is not None: + self.assertEqual(int(kvno), 1) + creds.set_kvno(1) return (creds, dn) -- 2.25.1 From 857aaa6bb2546256864c4dfbcbf25a1a15858532 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 30 Sep 2021 10:51:01 +1300 Subject: [PATCH 301/645] tests/krb5: Fix sending PA-PAC-OPTIONS and PA-PAC-REQUEST These padata were not being sent if other FAST padata was not specified. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 (cherry picked from commit 6f1282e8d34073d8499ce919908b39645b017cb8) --- python/samba/tests/krb5/raw_testcase.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 1119c9926d7..ceff1b6220e 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1801,8 +1801,6 @@ class RawKerberosTest(TestCaseInTempDir): fast_padata, req_body = generate_fast_padata_fn(kdc_exchange_dict, callback_dict, req_body) - - fast_padata += additional_padata else: fast_padata = [] @@ -1847,6 +1845,7 @@ class RawKerberosTest(TestCaseInTempDir): KU_FAST_REQ_CHKSUM, checksum_blob) + fast_padata += additional_padata fast = generate_fast_fn(kdc_exchange_dict, callback_dict, inner_req_body, -- 2.25.1 From 24f19e865fc7a9a259408180d1a803087e236945 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 30 Sep 2021 10:54:33 +1300 Subject: [PATCH 302/645] tests/krb5: Fix PA-PAC-OPTIONS checking Make the check work correctly if bits other than the claims bit are specified. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 1fd00135fa4dff4331d86b228ccc01f834476997) --- python/samba/tests/krb5/raw_testcase.py | 44 +++++++++++++------------ 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index ceff1b6220e..0217674ed2d 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2354,10 +2354,10 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertElementEqual(encpart_private, 'caddr', []) - sent_claims = self.sent_claims(kdc_exchange_dict) + sent_pac_options = self.get_sent_pac_options(kdc_exchange_dict) if self.strict_checking: - if sent_claims or canonicalize: + if canonicalize or '1' in sent_pac_options: self.assertElementPresent(encpart_private, 'encrypted-pa-data') enc_pa_dict = self.get_pa_dict( @@ -2381,12 +2381,15 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertNotIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) - # ClaimsCompIdFASTSupported registry key - if sent_claims: + if '1' in sent_pac_options: self.assertIn(PADATA_PAC_OPTIONS, enc_pa_dict) - self.check_pac_options_claims_support( - enc_pa_dict[PADATA_PAC_OPTIONS]) + pac_options = self.der_decode( + enc_pa_dict[PADATA_PAC_OPTIONS], + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) + + self.assertElementEqual(pac_options, 'options', + sent_pac_options) else: self.assertNotIn(PADATA_PAC_OPTIONS, enc_pa_dict) else: @@ -2419,11 +2422,6 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['rep_ticket_creds'] = ticket_creds - def check_pac_options_claims_support(self, pac_options): - pac_options = self.der_decode(pac_options, - asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) - self.assertEqual('1', pac_options['options'][0]) # claims bit - def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -2565,8 +2563,9 @@ class RawKerberosTest(TestCaseInTempDir): if not sent_fast and error_code != 0: expected_patypes += (PADATA_PW_SALT,) else: - sent_claims = self.sent_claims(kdc_exchange_dict) - if sent_claims and error_code not in (0, KDC_ERR_GENERIC): + sent_pac_options = self.get_sent_pac_options(kdc_exchange_dict) + if ('1' in sent_pac_options + and error_code not in (0, KDC_ERR_GENERIC)): expected_patypes += (PADATA_PAC_OPTIONS,) elif error_code != KDC_ERR_GENERIC: if expect_etype_info: @@ -2656,8 +2655,9 @@ class RawKerberosTest(TestCaseInTempDir): continue if patype == PADATA_PAC_OPTIONS: self.assertIsNone(pac_options) - pac_options = pavalue - self.assertIsNotNone(pac_options) + pac_options = self.der_decode( + pavalue, + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) continue if patype == PADATA_PW_SALT: self.assertIsNone(pw_salt) @@ -2677,7 +2677,7 @@ class RawKerberosTest(TestCaseInTempDir): inner=True) if pac_options is not None: - self.check_pac_options_claims_support(pac_options) + self.assertElementEqual(pac_options, 'options', sent_pac_options) if pw_salt is not None: self.assertEqual(12, len(pw_salt)) @@ -3418,19 +3418,21 @@ class RawKerberosTest(TestCaseInTempDir): return PADATA_ENCRYPTED_CHALLENGE in fast_pa_dict - def sent_claims(self, kdc_exchange_dict): + def get_sent_pac_options(self, kdc_exchange_dict): fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict) if PADATA_PAC_OPTIONS not in fast_pa_dict: - return False + return '' pac_options = self.der_decode(fast_pa_dict[PADATA_PAC_OPTIONS], asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) pac_options = pac_options['options'] - claims_pos = len(tuple(krb5_asn1.PACOptionFlags('claims'))) - 1 - return (claims_pos < len(pac_options) - and pac_options[claims_pos] == '1') + # Mask out unsupported bits. + pac_options, remaining = pac_options[:4], pac_options[4:] + pac_options += '0' * len(remaining) + + return pac_options def get_krbtgt_sname(self): krbtgt_creds = self.get_krbtgt_creds() -- 2.25.1 From 0bdecfb6781b8476b706544b8df73b799c7e449a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:47:39 +1300 Subject: [PATCH 303/645] tests/krb5: Rename allowed_to_delegate_to parameter for clarity This helps to distinguish resourced-based and non-resource-based constrained delegation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 31817c383c2014224b1397fde610624663313246) --- python/samba/tests/krb5/kdc_base_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index bb92bbd65e5..e6639270f69 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -598,7 +598,7 @@ class KDCBaseTest(RawKerberosTest): 'no_auth_data_required': False, 'supported_enctypes': None, 'not_delegated': False, - 'allowed_to_delegate_to': None, + 'delegation_to_spn': None, 'trusted_to_auth_for_delegation': False, 'fast_support': False } @@ -629,13 +629,13 @@ class KDCBaseTest(RawKerberosTest): no_auth_data_required, supported_enctypes, not_delegated, - allowed_to_delegate_to, + delegation_to_spn, trusted_to_auth_for_delegation, fast_support): if machine_account: self.assertFalse(not_delegated) else: - self.assertIsNone(allowed_to_delegate_to) + self.assertIsNone(delegation_to_spn) self.assertFalse(trusted_to_auth_for_delegation) samdb = self.get_samdb() @@ -664,8 +664,8 @@ class KDCBaseTest(RawKerberosTest): if enctypes is not None: details['msDS-SupportedEncryptionTypes'] = str(enctypes) - if allowed_to_delegate_to: - details['msDS-AllowedToDelegateTo'] = allowed_to_delegate_to + if delegation_to_spn: + details['msDS-AllowedToDelegateTo'] = delegation_to_spn if machine_account: spn = 'host/' + user_name -- 2.25.1 From 5d1eb011c25b4ef750f1042bc04197538ff246f4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:50:36 +1300 Subject: [PATCH 304/645] tests/krb5: Allow created accounts to use resource-based constrained delegation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit bba8cb8dce19e47a7b813efd9a7527e38856435e) --- python/samba/tests/krb5/kdc_base_test.py | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e6639270f69..918e04a1dbe 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -301,6 +301,30 @@ class KDCBaseTest(RawKerberosTest): return (creds, dn) + def get_security_descriptor(self, dn): + samdb = self.get_samdb() + + sid = self.get_objectSid(samdb, dn) + + owner_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) + + ace = security.ace() + ace.access_mask = security.SEC_ADS_GENERIC_ALL + + ace.trustee = security.dom_sid(sid) + + dacl = security.acl() + dacl.revision = security.SECURITY_ACL_REVISION_ADS + dacl.aces = [ace] + dacl.num_aces = 1 + + security_desc = security.descriptor() + security_desc.type |= security.SEC_DESC_DACL_PRESENT + security_desc.owner_sid = owner_sid + security_desc.dacl = dacl + + return ndr_pack(security_desc) + def create_rodc(self, ctx): ctx.nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] ctx.full_nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] @@ -599,6 +623,7 @@ class KDCBaseTest(RawKerberosTest): 'supported_enctypes': None, 'not_delegated': False, 'delegation_to_spn': None, + 'delegation_from_dn': None, 'trusted_to_auth_for_delegation': False, 'fast_support': False } @@ -630,12 +655,14 @@ class KDCBaseTest(RawKerberosTest): supported_enctypes, not_delegated, delegation_to_spn, + delegation_from_dn, trusted_to_auth_for_delegation, fast_support): if machine_account: self.assertFalse(not_delegated) else: self.assertIsNone(delegation_to_spn) + self.assertIsNone(delegation_from_dn) self.assertFalse(trusted_to_auth_for_delegation) samdb = self.get_samdb() @@ -667,6 +694,12 @@ class KDCBaseTest(RawKerberosTest): if delegation_to_spn: details['msDS-AllowedToDelegateTo'] = delegation_to_spn + if delegation_from_dn: + security_descriptor = self.get_security_descriptor( + delegation_from_dn) + details['msDS-AllowedToActOnBehalfOfOtherIdentity'] = ( + security_descriptor) + if machine_account: spn = 'host/' + user_name else: -- 2.25.1 From 8c4f4546e8b0d7e6072ecbd2b6acc868baf6b9f7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:52:17 +1300 Subject: [PATCH 305/645] tests/krb5: Add assertion to make failures clearer These failures may occur if tests are not run against an RODC. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit cda50b5c505072989abf84c209e16ff4efe2e628) --- python/samba/tests/krb5/kdc_base_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 918e04a1dbe..25433ba1069 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -590,6 +590,7 @@ class KDCBaseTest(RawKerberosTest): scope=ldb.SCOPE_BASE, attrs=[group_attr]) orig_msg = res[0] + self.assertIn(group_attr, orig_msg) members = list(orig_msg[group_attr]) members.append(account_dn) -- 2.25.1 From 17e7e82a827d265efab05c7db8efc06dd7bc7258 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:54:49 +1300 Subject: [PATCH 306/645] tests/krb5: Introduce helper method for creating invalid length checksums BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 9d142dc3a452b0f06efc66f422402ee6e553ee7c) --- python/samba/tests/krb5/raw_testcase.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0217674ed2d..6107442409f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -314,17 +314,20 @@ class WrongLengthChecksumKey(Krb5EncryptionKey): self._length = length - def make_checksum(self, usage, plaintext, ctype=None): - checksum = super().make_checksum(usage, plaintext, ctype) - - diff = self._length - len(checksum) + @classmethod + def _adjust_to_length(cls, checksum, length): + diff = length - len(checksum) if diff > 0: checksum += bytes(diff) elif diff < 0: - checksum = checksum[:self._length] + checksum = checksum[:length] return checksum + def make_checksum(self, usage, plaintext, ctype=None): + checksum = super().make_checksum(usage, plaintext, ctype) + return self._adjust_to_length(checksum, self._length) + class KerberosCredentials(Credentials): -- 2.25.1 From 52173654df92620e82b79f59a8f83dab71845f20 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:56:21 +1300 Subject: [PATCH 307/645] tests/krb5: Fix method for creating invalid length zeroed checksum Previously the base class method was being used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ae09219c3a1c6d47817f51baf3784e8986c7478d) --- python/samba/tests/krb5/raw_testcase.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 6107442409f..a3f17e4dc4a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -324,6 +324,9 @@ class WrongLengthChecksumKey(Krb5EncryptionKey): return checksum + def make_zeroed_checksum(self, ctype=None): + return bytes(self._length) + def make_checksum(self, usage, plaintext, ctype=None): checksum = super().make_checksum(usage, plaintext, ctype) return self._adjust_to_length(checksum, self._length) -- 2.25.1 From 7e9af82d21d4600303d0a97020775e2fb68b121a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 11:59:42 +1300 Subject: [PATCH 308/645] tests/krb5: Fix checksum generation and verification The KDC and server checksums may be generated using the same key, but only the KDC checksum should have an RODCIdentifier. To fix this, instead of overriding the existing methods, add additional ones for RODC-specific signatures, so that both types of signatures can be generated or verified. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit a927cecafdd5ad6dc5189fa98cb42684c9c3b033) --- python/samba/tests/krb5/raw_testcase.py | 57 ++++++++++++++----------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a3f17e4dc4a..aefbdd6d761 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -281,15 +281,15 @@ class RodcPacEncryptionKey(Krb5EncryptionKey): else: self.rodc_id = b'' - def make_zeroed_checksum(self, ctype=None): + def make_rodc_zeroed_checksum(self, ctype=None): checksum = super().make_zeroed_checksum(ctype) return checksum + bytes(len(self.rodc_id)) - def make_checksum(self, usage, plaintext, ctype=None): + def make_rodc_checksum(self, usage, plaintext, ctype=None): checksum = super().make_checksum(usage, plaintext, ctype) return checksum + self.rodc_id - def verify_checksum(self, usage, plaintext, ctype, cksum): + def verify_rodc_checksum(self, usage, plaintext, ctype, cksum): if self.rodc_id: cksum, cksum_rodc_id = cksum[:-2], cksum[-2:] @@ -303,12 +303,15 @@ class RodcPacEncryptionKey(Krb5EncryptionKey): cksum) -class ZeroedChecksumKey(Krb5EncryptionKey): +class ZeroedChecksumKey(RodcPacEncryptionKey): def make_checksum(self, usage, plaintext, ctype=None): return self.make_zeroed_checksum(ctype) + def make_rodc_checksum(self, usage, plaintext, ctype=None): + return self.make_rodc_zeroed_checksum(ctype) -class WrongLengthChecksumKey(Krb5EncryptionKey): + +class WrongLengthChecksumKey(RodcPacEncryptionKey): def __init__(self, key, kvno, length): super().__init__(key, kvno) @@ -331,6 +334,13 @@ class WrongLengthChecksumKey(Krb5EncryptionKey): checksum = super().make_checksum(usage, plaintext, ctype) return self._adjust_to_length(checksum, self._length) + def make_rodc_zeroed_checksum(self, ctype=None): + return bytes(self._length) + + def make_rodc_checksum(self, usage, plaintext, ctype=None): + checksum = super().make_rodc_checksum(usage, plaintext, ctype) + return self._adjust_to_length(checksum, self._length) + class KerberosCredentials(Credentials): @@ -3080,18 +3090,17 @@ class RawKerberosTest(TestCaseInTempDir): server_checksum, server_ctype = checksums[ krb5pac.PAC_TYPE_SRV_CHECKSUM] - Krb5EncryptionKey.verify_checksum(key, - KU_NON_KERB_CKSUM_SALT, - pac_data, - server_ctype, - server_checksum) + key.verify_checksum(KU_NON_KERB_CKSUM_SALT, + pac_data, + server_ctype, + server_checksum) kdc_checksum, kdc_ctype = checksums[ krb5pac.PAC_TYPE_KDC_CHECKSUM] - krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, - server_checksum, - kdc_ctype, - kdc_checksum) + krbtgt_key.verify_rodc_checksum(KU_NON_KERB_CKSUM_SALT, + server_checksum, + kdc_ctype, + kdc_checksum) if is_tgt: self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums) @@ -3106,10 +3115,10 @@ class RawKerberosTest(TestCaseInTempDir): enc_part = self.der_encode(enc_part, asn1Spec=krb5_asn1.EncTicketPart()) - krbtgt_key.verify_checksum(KU_NON_KERB_CKSUM_SALT, - enc_part, - ticket_ctype, - ticket_checksum) + krbtgt_key.verify_rodc_checksum(KU_NON_KERB_CKSUM_SALT, + enc_part, + ticket_ctype, + ticket_checksum) def modified_ticket(self, ticket, *, @@ -3300,16 +3309,15 @@ class RawKerberosTest(TestCaseInTempDir): if buffer_type == krb5pac.PAC_TYPE_TICKET_CHECKSUM: self.assertIsNotNone(enc_part) - signature = checksum_key.make_checksum( + signature = checksum_key.make_rodc_checksum( KU_NON_KERB_CKSUM_SALT, enc_part) elif buffer_type == krb5pac.PAC_TYPE_SRV_CHECKSUM: - signature = Krb5EncryptionKey.make_zeroed_checksum( - checksum_key) + signature = checksum_key.make_zeroed_checksum() else: - signature = checksum_key.make_zeroed_checksum() + signature = checksum_key.make_rodc_zeroed_checksum() checksum_buffer.info.signature = signature checksum_buffer.info.type = ctype @@ -3325,8 +3333,7 @@ class RawKerberosTest(TestCaseInTempDir): server_checksum_key = checksum_keys[krb5pac.PAC_TYPE_SRV_CHECKSUM] pac_data = ndr_pack(pac) - server_checksum = Krb5EncryptionKey.make_checksum( - server_checksum_key, + server_checksum = server_checksum_key.make_checksum( KU_NON_KERB_CKSUM_SALT, pac_data) @@ -3339,7 +3346,7 @@ class RawKerberosTest(TestCaseInTempDir): kdc_checksum_key = checksum_keys[krb5pac.PAC_TYPE_KDC_CHECKSUM] - kdc_checksum = kdc_checksum_key.make_checksum( + kdc_checksum = kdc_checksum_key.make_rodc_checksum( KU_NON_KERB_CKSUM_SALT, server_checksum) -- 2.25.1 From dc86b79ffe1fc1fffe076006aab70fbc5199f879 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 12:03:33 +1300 Subject: [PATCH 309/645] tests/krb5: Allow excluding the PAC server checksum BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit dcf45a151a198f7165cd332a26db78a5d8e8f8c5) --- python/samba/tests/krb5/raw_testcase.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index aefbdd6d761..4c1aedbca0f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3342,7 +3342,10 @@ class RawKerberosTest(TestCaseInTempDir): kdc_checksum_buffer = checksum_buffers.get( krb5pac.PAC_TYPE_KDC_CHECKSUM) if kdc_checksum_buffer is not None: - self.assertIsNotNone(server_checksum_buffer) + if server_checksum_buffer is None: + # There's no server signature to make the checksum over, so + # just make the checksum over an empty bytes object. + server_checksum = bytes() kdc_checksum_key = checksum_keys[krb5pac.PAC_TYPE_KDC_CHECKSUM] -- 2.25.1 From 8883c324d0b7cbbe87fdc7dcbd16d445ee968a04 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 12:06:03 +1300 Subject: [PATCH 310/645] tests/krb5: Fix handling authdata with missing PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit a4bc712ee02f32c2d04dfc2d99d58931344e5ceb) --- python/samba/tests/krb5/raw_testcase.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4c1aedbca0f..b9895e547c4 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3200,11 +3200,11 @@ class RawKerberosTest(TestCaseInTempDir): # Get a copy of the authdata with an empty PAC, and the # existing PAC (if present). empty_pac = self.get_empty_pac() - empty_pac_auth_data, pac_data = self.replace_pac(auth_data, - empty_pac) + empty_pac_auth_data, pac_data = self.replace_pac( + auth_data, + empty_pac, + expect_pac=expect_pac) - if expect_pac: - self.assertIsNotNone(pac_data) if pac_data is not None: pac = ndr_unpack(krb5pac.PAC_DATA, pac_data) @@ -3234,7 +3234,8 @@ class RawKerberosTest(TestCaseInTempDir): # Replace the PAC in the authorization data and re-add it to the # ticket enc-part. - auth_data, _ = self.replace_pac(auth_data, new_pac) + auth_data, _ = self.replace_pac(auth_data, new_pac, + expect_pac=expect_pac) enc_part['authorization-data'] = auth_data # Re-encrypt the ticket enc-part with the new key. -- 2.25.1 From ec182e7a0eabf089be55056977aa176df3301311 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 12:16:58 +1300 Subject: [PATCH 311/645] tests/krb5: Fix status code checking The type used to encode the status code is actually KERB-ERROR-DATA, rather than PA-DATA. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 012b6fcd1976c6570e9b92c133d8c21e543e5a4f) --- python/samba/tests/krb5/raw_testcase.py | 89 +++++++++----------- python/samba/tests/krb5/rfc4120_constants.py | 6 ++ 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b9895e547c4..db7db28cac5 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -49,6 +49,7 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_GENERIC, KDC_ERR_PREAUTH_FAILED, KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, + KERB_ERR_TYPE_EXTENDED, KRB_AP_REQ, KRB_AS_REP, KRB_AS_REQ, @@ -85,7 +86,6 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, PADATA_PK_AS_REP_19, - PADATA_PW_SALT, PADATA_SUPPORTED_ETYPES ) import samba.tests.krb5.kcrypto as kcrypto @@ -2497,34 +2497,51 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(edata) if edata is not None: if rep_msg_type == KRB_TGS_REP and not sent_fast: - rep_padata = [self.der_decode(edata, - asn1Spec=krb5_asn1.PA_DATA())] + error_data = self.der_decode( + edata, + asn1Spec=krb5_asn1.KERB_ERROR_DATA()) + self.assertEqual(KERB_ERR_TYPE_EXTENDED, + error_data['data-type']) + + extended_error = error_data['data-value'] + + self.assertEqual(12, len(extended_error)) + + status = int.from_bytes(extended_error[:4], 'little') + flags = int.from_bytes(extended_error[8:], 'little') + + expected_status = kdc_exchange_dict['expected_status'] + self.assertEqual(expected_status, status) + + self.assertEqual(3, flags) else: + self.assertIsNone(kdc_exchange_dict['expected_status']) + rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA()) - self.assertGreater(len(rep_padata), 0) + self.assertGreater(len(rep_padata), 0) - if sent_fast: - self.assertEqual(1, len(rep_padata)) - rep_pa_dict = self.get_pa_dict(rep_padata) - self.assertIn(PADATA_FX_FAST, rep_pa_dict) + if sent_fast: + self.assertEqual(1, len(rep_padata)) + rep_pa_dict = self.get_pa_dict(rep_padata) + self.assertIn(PADATA_FX_FAST, rep_pa_dict) - armor_key = kdc_exchange_dict['armor_key'] - self.assertIsNotNone(armor_key) - fast_response = self.check_fx_fast_data( - kdc_exchange_dict, - rep_pa_dict[PADATA_FX_FAST], - armor_key, - expect_strengthen_key=False) + armor_key = kdc_exchange_dict['armor_key'] + self.assertIsNotNone(armor_key) + fast_response = self.check_fx_fast_data( + kdc_exchange_dict, + rep_pa_dict[PADATA_FX_FAST], + armor_key, + expect_strengthen_key=False) - rep_padata = fast_response['padata'] + rep_padata = fast_response['padata'] - etype_info2 = self.check_rep_padata(kdc_exchange_dict, - callback_dict, - rep_padata, - error_code) + etype_info2 = self.check_rep_padata(kdc_exchange_dict, + callback_dict, + rep_padata, + error_code) - kdc_exchange_dict['preauth_etype_info2'] = etype_info2 + kdc_exchange_dict['preauth_etype_info2'] = etype_info2 return rep @@ -2576,13 +2593,10 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_FX_COOKIE,) if rep_msg_type == KRB_TGS_REP: - if not sent_fast and error_code != 0: - expected_patypes += (PADATA_PW_SALT,) - else: - sent_pac_options = self.get_sent_pac_options(kdc_exchange_dict) - if ('1' in sent_pac_options - and error_code not in (0, KDC_ERR_GENERIC)): - expected_patypes += (PADATA_PAC_OPTIONS,) + sent_pac_options = self.get_sent_pac_options(kdc_exchange_dict) + if ('1' in sent_pac_options + and error_code not in (0, KDC_ERR_GENERIC)): + expected_patypes += (PADATA_PAC_OPTIONS,) elif error_code != KDC_ERR_GENERIC: if expect_etype_info: self.assertGreater(len(expect_etype_info2), 0) @@ -2621,7 +2635,6 @@ class RawKerberosTest(TestCaseInTempDir): fast_error = None fx_fast = None pac_options = None - pw_salt = None for pa in rep_padata: patype = self.getElementValue(pa, 'padata-type') pavalue = self.getElementValue(pa, 'padata-value') @@ -2675,11 +2688,6 @@ class RawKerberosTest(TestCaseInTempDir): pavalue, asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) continue - if patype == PADATA_PW_SALT: - self.assertIsNone(pw_salt) - pw_salt = pavalue - self.assertIsNotNone(pw_salt) - continue if fast_cookie is not None: kdc_exchange_dict['fast_cookie'] = fast_cookie @@ -2695,19 +2703,6 @@ class RawKerberosTest(TestCaseInTempDir): if pac_options is not None: self.assertElementEqual(pac_options, 'options', sent_pac_options) - if pw_salt is not None: - self.assertEqual(12, len(pw_salt)) - - status = int.from_bytes(pw_salt[:4], 'little') - flags = int.from_bytes(pw_salt[8:], 'little') - - expected_status = kdc_exchange_dict['expected_status'] - self.assertEqual(expected_status, status) - - self.assertEqual(3, flags) - else: - self.assertIsNone(kdc_exchange_dict.get('expected_status')) - if enc_challenge is not None: if not sent_enc_challenge: self.assertEqual(len(enc_challenge), 0) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index ac2bac4d91e..76f2b75d94e 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -78,6 +78,12 @@ KDC_ERR_SKEW = 37 KDC_ERR_GENERIC = 60 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 +# Extended error types +KERB_AP_ERR_TYPE_SKEW_RECOVERY = int( + krb5_asn1.KerbErrorDataTypeValues('kERB-AP-ERR-TYPE-SKEW-RECOVERY')) +KERB_ERR_TYPE_EXTENDED = int( + krb5_asn1.KerbErrorDataTypeValues('kERB-ERR-TYPE-EXTENDED')) + # Name types NT_UNKNOWN = int(krb5_asn1.NameTypeValues('kRB5-NT-UNKNOWN')) NT_PRINCIPAL = int(krb5_asn1.NameTypeValues('kRB5-NT-PRINCIPAL')) -- 2.25.1 From b261076fd8141f372ad90ff4d762c536b360f25d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 13:01:30 +1300 Subject: [PATCH 312/645] tests/krb5: Make expected_sname checking more explicit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit 8f6d369d709614e2f5c0684882c62f0476bcafa2 as Samba 4.14 as the test which crashes older MIT KDC versions is omitted] --- python/samba/tests/krb5/fast_tests.py | 39 ++++++++++--------------- python/samba/tests/krb5/raw_testcase.py | 6 +--- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 431b48f00d6..5180eb57563 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -99,11 +99,7 @@ class FAST_Tests(KDCBaseTest): ]) def test_simple_no_sname(self): - krbtgt_creds = self.get_krbtgt_creds() - krbtgt_username = krbtgt_creds.get_username() - krbtgt_realm = krbtgt_creds.get_realm() - expected_sname = self.PrincipalName_create( - name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + expected_sname = self.get_krbtgt_sname() self._run_test_sequence([ { @@ -116,11 +112,7 @@ class FAST_Tests(KDCBaseTest): ]) def test_simple_tgs_no_sname(self): - krbtgt_creds = self.get_krbtgt_creds() - krbtgt_username = krbtgt_creds.get_username() - krbtgt_realm = krbtgt_creds.get_realm() - expected_sname = self.PrincipalName_create( - name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + expected_sname = self.get_krbtgt_sname() self._run_test_sequence([ { @@ -134,11 +126,7 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_no_sname(self): - krbtgt_creds = self.get_krbtgt_creds() - krbtgt_username = krbtgt_creds.get_username() - krbtgt_realm = krbtgt_creds.get_realm() - expected_sname = self.PrincipalName_create( - name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + expected_sname = self.get_krbtgt_sname() self._run_test_sequence([ { @@ -153,11 +141,7 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_tgs_no_sname(self): - krbtgt_creds = self.get_krbtgt_creds() - krbtgt_username = krbtgt_creds.get_username() - krbtgt_realm = krbtgt_creds.get_realm() - expected_sname = self.PrincipalName_create( - name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm]) + expected_sname = self.get_krbtgt_sname() self._run_test_sequence([ { @@ -830,6 +814,8 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_ad_fx_fast_armor(self): + expected_sname = self.get_krbtgt_sname() + # If the authenticator or TGT authentication data contains the # AD-fx-fast-armor authdata type, the KDC must reject the request # (RFC6113 5.4.1.1). @@ -849,7 +835,8 @@ class FAST_Tests(KDCBaseTest): 'use_fast': True, 'gen_authdata_fn': self.generate_fast_armor_auth_data, 'gen_tgt_fn': self.get_user_tgt, - 'fast_armor': None + 'fast_armor': None, + 'expected_sname': expected_sname } ]) @@ -877,6 +864,8 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_ad_fx_fast_armor_ticket(self): + expected_sname = self.get_krbtgt_sname() + # If the authenticator or TGT authentication data contains the # AD-fx-fast-armor authdata type, the KDC must reject the request # (RFC6113 5.4.2). @@ -896,7 +885,8 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': KDC_ERR_GENERIC, 'use_fast': True, 'gen_tgt_fn': self.gen_tgt_fast_armor_auth_data, - 'fast_armor': None + 'fast_armor': None, + 'expected_sname': expected_sname } ]) @@ -956,6 +946,8 @@ class FAST_Tests(KDCBaseTest): ]) def test_fast_tgs_no_subkey(self): + expected_sname = self.get_krbtgt_sname() + # Show that omitting the subkey in the TGS-REQ authenticator fails # (RFC6113 5.4.2). self._run_test_sequence([ @@ -965,7 +957,8 @@ class FAST_Tests(KDCBaseTest): 'use_fast': True, 'gen_tgt_fn': self.get_user_tgt, 'fast_armor': None, - 'include_subkey': False + 'include_subkey': False, + 'expected_sname': expected_sname } ]) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index db7db28cac5..f6aeb00dc8f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2475,11 +2475,7 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertElementMissing(rep, 'cname') self.assertElementEqualUTF8(rep, 'realm', expected_srealm) - if sent_fast and error_code == KDC_ERR_GENERIC: - self.assertElementEqualPrincipal(rep, 'sname', - self.get_krbtgt_sname()) - else: - self.assertElementEqualPrincipal(rep, 'sname', expected_sname) + self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') if (error_code == KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS or (rep_msg_type == KRB_TGS_REP -- 2.25.1 From 983c62901ba0bd734334e603993959889f4ec71f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 13:03:49 +1300 Subject: [PATCH 313/645] tests/krb5: Fix assertElementFlags() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 788b3a29eea62f9f38ca8865c7cb7860bdc94bec) --- python/samba/tests/krb5/fast_tests.py | 4 ++-- python/samba/tests/krb5/raw_testcase.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 5180eb57563..cf9b9d718bb 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -1305,10 +1305,10 @@ class FAST_Tests(KDCBaseTest): expected_flags = kdc_dict.pop('expected_flags', None) if expected_flags is not None: - expected_flags = krb5_asn1.KDCOptions(expected_flags) + expected_flags = krb5_asn1.TicketFlags(expected_flags) unexpected_flags = kdc_dict.pop('unexpected_flags', None) if unexpected_flags is not None: - unexpected_flags = krb5_asn1.KDCOptions(unexpected_flags) + unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags) if rep_type == KRB_AS_REP: kdc_exchange_dict = self.as_exchange_dict( diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f6aeb00dc8f..a24faf1d060 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1053,14 +1053,14 @@ class RawKerberosTest(TestCaseInTempDir): v = self.getElementValue(obj, elem) self.assertIsNotNone(v) if expected is not None: - self.assertIsInstance(expected, krb5_asn1.KDCOptions) + self.assertIsInstance(expected, krb5_asn1.TicketFlags) for i, flag in enumerate(expected): if flag == 1: self.assertEqual('1', v[i], f"'{expected.namedValues[i]}' " f"expected in {v}") if unexpected is not None: - self.assertIsInstance(unexpected, krb5_asn1.KDCOptions) + self.assertIsInstance(unexpected, krb5_asn1.TicketFlags) for i, flag in enumerate(unexpected): if flag == 1: self.assertEqual('0', v[i], -- 2.25.1 From 657dc0e53342e67842808c9c9a7f548305869083 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 14:02:37 +1300 Subject: [PATCH 314/645] tests/krb5: Remove unneeded parameters from ticket cache key BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 7fba83c6c6309a525742c38e904d3e473db99ef1) --- python/samba/tests/krb5/kdc_base_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 25433ba1069..7ddaa53b541 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1278,8 +1278,7 @@ class KDCBaseTest(RawKerberosTest): expected_flags=None, unexpected_flags=None, fresh=False): user_name = creds.get_username() - cache_key = (user_name, to_rodc, kdc_options, - expected_flags, unexpected_flags) + cache_key = (user_name, to_rodc, kdc_options) if not fresh: tgt = self.tkt_cache.get(cache_key) -- 2.25.1 From a3ab83fdfcff1f24e637b787ae4d6d4cfd0c0852 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 15:48:58 +1300 Subject: [PATCH 315/645] tests/krb5: Fix checking for presence of error data BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ab92dc16d20b0996b8c46714652c15019c795095) --- python/samba/tests/krb5/fast_tests.py | 39 +++++++++++++++++------- python/samba/tests/krb5/kdc_base_test.py | 4 ++- python/samba/tests/krb5/kdc_tgs_tests.py | 3 +- python/samba/tests/krb5/raw_testcase.py | 27 ++++++++-------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index cf9b9d718bb..28fe0686335 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -107,7 +107,8 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN), 'use_fast': False, 'sname': None, - 'expected_sname': expected_sname + 'expected_sname': expected_sname, + 'expect_edata': False } ]) @@ -121,7 +122,8 @@ class FAST_Tests(KDCBaseTest): 'use_fast': False, 'gen_tgt_fn': self.get_user_tgt, 'sname': None, - 'expected_sname': expected_sname + 'expected_sname': expected_sname, + 'expect_edata': False } ]) @@ -172,6 +174,7 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': KDC_ERR_NOT_US, 'use_fast': False, 'gen_tgt_fn': self.get_user_service_ticket, + 'expect_edata': False } ]) @@ -182,6 +185,7 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': KDC_ERR_NOT_US, 'use_fast': False, 'gen_tgt_fn': self.get_mach_service_ticket, + 'expect_edata': False } ]) @@ -294,7 +298,8 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP, 'use_fast': False, 'gen_tgt_fn': self.get_mach_tgt, - 'etypes': () + 'etypes': (), + 'expect_edata': False } ]) @@ -342,7 +347,8 @@ class FAST_Tests(KDCBaseTest): 'use_fast': True, 'gen_fast_fn': self.generate_empty_fast, 'fast_armor': None, - 'gen_armor_tgt_fn': self.get_mach_tgt + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'expect_edata': False } ]) @@ -365,7 +371,8 @@ class FAST_Tests(KDCBaseTest): 'expected_error_mode': KDC_ERR_GENERIC, 'use_fast': True, 'fast_armor': None, # no armor, - 'gen_armor_tgt_fn': self.get_mach_tgt + 'gen_armor_tgt_fn': self.get_mach_tgt, + 'expect_edata': False } ]) @@ -809,7 +816,8 @@ class FAST_Tests(KDCBaseTest): # should be KRB_APP_ERR_MODIFIED 'use_fast': False, 'gen_authdata_fn': self.generate_fast_used_auth_data, - 'gen_tgt_fn': self.get_user_tgt + 'gen_tgt_fn': self.get_user_tgt, + 'expect_edata': False } ]) @@ -836,7 +844,8 @@ class FAST_Tests(KDCBaseTest): 'gen_authdata_fn': self.generate_fast_armor_auth_data, 'gen_tgt_fn': self.get_user_tgt, 'fast_armor': None, - 'expected_sname': expected_sname + 'expected_sname': expected_sname, + 'expect_edata': False } ]) @@ -886,7 +895,8 @@ class FAST_Tests(KDCBaseTest): 'use_fast': True, 'gen_tgt_fn': self.gen_tgt_fast_armor_auth_data, 'fast_armor': None, - 'expected_sname': expected_sname + 'expected_sname': expected_sname, + 'expect_edata': False } ]) @@ -958,7 +968,8 @@ class FAST_Tests(KDCBaseTest): 'gen_tgt_fn': self.get_user_tgt, 'fast_armor': None, 'include_subkey': False, - 'expected_sname': expected_sname + 'expected_sname': expected_sname, + 'expect_edata': False } ]) @@ -1209,6 +1220,10 @@ class FAST_Tests(KDCBaseTest): else: tgt_cname = client_cname + expect_edata = kdc_dict.pop('expect_edata', None) + if expect_edata is not None: + self.assertTrue(expected_error_mode) + expected_cname = kdc_dict.pop('expected_cname', tgt_cname) expected_anon = kdc_dict.pop('expected_anon', False) @@ -1343,7 +1358,8 @@ class FAST_Tests(KDCBaseTest): inner_req=inner_req, outer_req=outer_req, pac_request=True, - pac_options=pac_options) + pac_options=pac_options, + expect_edata=expect_edata) else: # KRB_TGS_REP kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=expected_crealm, @@ -1376,7 +1392,8 @@ class FAST_Tests(KDCBaseTest): inner_req=inner_req, outer_req=outer_req, pac_request=None, - pac_options=pac_options) + pac_options=pac_options, + expect_edata=expect_edata) repeat = kdc_dict.pop('repeat', 1) for _ in range(repeat): diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 7ddaa53b541..d25fc0b42b2 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1162,7 +1162,8 @@ class KDCBaseTest(RawKerberosTest): def tgs_req(self, cname, sname, realm, ticket, key, etypes, expected_error_mode=0, padata=None, kdc_options=0, - to_rodc=False, service_creds=None, expect_pac=True): + to_rodc=False, service_creds=None, expect_pac=True, + expect_edata=None): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1209,6 +1210,7 @@ class KDCBaseTest(RawKerberosTest): tgt=tgt, authenticator_subkey=subkey, kdc_options=str(kdc_options), + expect_edata=expect_edata, expect_pac=expect_pac, to_rodc=to_rodc) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 0904233b01f..2b55ba8a376 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -85,7 +85,8 @@ class KdcTgsTests(KDCBaseTest): names=["host", samdb.host_dns_name()]) (rep, enc_part) = self.tgs_req(cname, sname, realm, ticket, key, etype, - expected_error_mode=KDC_ERR_BADMATCH) + expected_error_mode=KDC_ERR_BADMATCH, + expect_edata=False) self.assertIsNone( enc_part, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a24faf1d060..1a3aedbd436 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1959,6 +1959,7 @@ class RawKerberosTest(TestCaseInTempDir): outer_req=None, pac_request=None, pac_options=None, + expect_edata=None, expect_pac=True, to_rodc=False): if expected_error_mode == 0: @@ -2005,6 +2006,7 @@ class RawKerberosTest(TestCaseInTempDir): 'outer_req': outer_req, 'pac_request': pac_request, 'pac_options': pac_options, + 'expect_edata': expect_edata, 'expect_pac': expect_pac, 'to_rodc': to_rodc } @@ -2046,6 +2048,7 @@ class RawKerberosTest(TestCaseInTempDir): outer_req=None, pac_request=None, pac_options=None, + expect_edata=None, expect_pac=True, to_rodc=False): if expected_error_mode == 0: @@ -2091,6 +2094,7 @@ class RawKerberosTest(TestCaseInTempDir): 'outer_req': outer_req, 'pac_request': pac_request, 'pac_options': pac_options, + 'expect_edata': expect_edata, 'expect_pac': expect_pac, 'to_rodc': to_rodc } @@ -2477,20 +2481,20 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementEqualUTF8(rep, 'realm', expected_srealm) self.assertElementEqualPrincipal(rep, 'sname', expected_sname) self.assertElementMissing(rep, 'e-text') - if (error_code == KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS - or (rep_msg_type == KRB_TGS_REP - and not sent_fast) - or (sent_fast and fast_armor_type is not None - and fast_armor_type != FX_FAST_ARMOR_AP_REQUEST) - or inner): + expected_status = kdc_exchange_dict['expected_status'] + expect_edata = kdc_exchange_dict['expect_edata'] + if expect_edata is None: + expect_edata = (error_code != KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS + and (not sent_fast or fast_armor_type is None + or fast_armor_type == FX_FAST_ARMOR_AP_REQUEST) + and not inner) + if not expect_edata: + self.assertIsNone(expected_status) self.assertElementMissing(rep, 'e-data') return rep edata = self.getElementValue(rep, 'e-data') if self.strict_checking: - if error_code != KDC_ERR_GENERIC: - # Predicting whether an ERR_GENERIC error contains e-data is - # more complicated. - self.assertIsNotNone(edata) + self.assertIsNotNone(edata) if edata is not None: if rep_msg_type == KRB_TGS_REP and not sent_fast: error_data = self.der_decode( @@ -2506,12 +2510,11 @@ class RawKerberosTest(TestCaseInTempDir): status = int.from_bytes(extended_error[:4], 'little') flags = int.from_bytes(extended_error[8:], 'little') - expected_status = kdc_exchange_dict['expected_status'] self.assertEqual(expected_status, status) self.assertEqual(3, flags) else: - self.assertIsNone(kdc_exchange_dict['expected_status']) + self.assertIsNone(expected_status) rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA()) -- 2.25.1 From 4e1288bdf6b2c88d8513491f9161ac6ebf6c6c45 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:10:07 +1300 Subject: [PATCH 316/645] tests/krb5: Add expect_claims parameter to kdc_exchange_dict BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 7cfc225b549108739bd86e222f2f35eb96af4ea3) --- python/samba/tests/krb5/raw_testcase.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 1a3aedbd436..0415f1ff6e6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1961,6 +1961,7 @@ class RawKerberosTest(TestCaseInTempDir): pac_options=None, expect_edata=None, expect_pac=True, + expect_claims=True, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2008,6 +2009,7 @@ class RawKerberosTest(TestCaseInTempDir): 'pac_options': pac_options, 'expect_edata': expect_edata, 'expect_pac': expect_pac, + 'expect_claims': expect_claims, 'to_rodc': to_rodc } if callback_dict is None: @@ -2050,6 +2052,7 @@ class RawKerberosTest(TestCaseInTempDir): pac_options=None, expect_edata=None, expect_pac=True, + expect_claims=True, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2096,6 +2099,7 @@ class RawKerberosTest(TestCaseInTempDir): 'pac_options': pac_options, 'expect_edata': expect_edata, 'expect_pac': expect_pac, + 'expect_claims': expect_claims, 'to_rodc': to_rodc } if callback_dict is None: -- 2.25.1 From d4e0cfa7202607a12348840bdd273459ce0b0c29 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:15:26 +1300 Subject: [PATCH 317/645] tests/krb5: Check buffer types in PAC with STRICT_CHECKING=1 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit aa2e583fdea4fd93e4e71c54630e32a1035d1e2a) --- librpc/idl/krb5pac.idl | 3 ++ python/samba/tests/krb5/raw_testcase.py | 52 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index 3239d7656b6..515150ab9cd 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -113,6 +113,9 @@ interface krb5pac PAC_TYPE_LOGON_NAME = 10, PAC_TYPE_CONSTRAINED_DELEGATION = 11, PAC_TYPE_UPN_DNS_INFO = 12, + PAC_TYPE_CLIENT_CLAIMS_INFO = 13, + PAC_TYPE_DEVICE_INFO = 14, + PAC_TYPE_DEVICE_CLAIMS_INFO = 15, PAC_TYPE_TICKET_CHECKSUM = 16 } PAC_TYPE; diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0415f1ff6e6..320de0a4dbe 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2340,6 +2340,13 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(ticket_private, 'authorization-data', expect_empty=not expect_pac) + if expect_pac: + authorization_data = self.getElementValue(ticket_private, + 'authorization-data') + pac_data = self.get_pac(authorization_data) + + self.check_pac_buffers(pac_data, kdc_exchange_dict) + encpart_session_key = None if encpart_private is not None: self.assertElementPresent(encpart_private, 'key') @@ -2446,6 +2453,47 @@ class RawKerberosTest(TestCaseInTempDir): kdc_exchange_dict['rep_ticket_creds'] = ticket_creds + def check_pac_buffers(self, pac_data, kdc_exchange_dict): + pac = ndr_unpack(krb5pac.PAC_DATA, pac_data) + + rep_msg_type = kdc_exchange_dict['rep_msg_type'] + armor_tgt = kdc_exchange_dict['armor_tgt'] + + expected_sname = kdc_exchange_dict['expected_sname'] + expect_claims = kdc_exchange_dict['expect_claims'] + + expected_types = [krb5pac.PAC_TYPE_LOGON_INFO, + krb5pac.PAC_TYPE_SRV_CHECKSUM, + krb5pac.PAC_TYPE_KDC_CHECKSUM, + krb5pac.PAC_TYPE_LOGON_NAME, + krb5pac.PAC_TYPE_UPN_DNS_INFO] + + kdc_options = kdc_exchange_dict['kdc_options'] + pos = len(tuple(krb5_asn1.KDCOptions('cname-in-addl-tkt'))) - 1 + constrained_delegation = (pos < len(kdc_options) + and kdc_options[pos] == '1') + if constrained_delegation: + expected_types.append(krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION) + + if self.kdc_fast_support: + if expect_claims: + expected_types.append(krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO) + + if (rep_msg_type == KRB_TGS_REP + and armor_tgt is not None): + expected_types.append(krb5pac.PAC_TYPE_DEVICE_INFO) + expected_types.append(krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO) + + if not self.is_tgs(expected_sname): + expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + + if self.strict_checking: + buffer_types = [pac_buffer.type + for pac_buffer in pac.buffers] + self.assertCountEqual(expected_types, buffer_types, + f'expected: {expected_types} ' + f'got: {buffer_types}') + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -3397,6 +3445,10 @@ class RawKerberosTest(TestCaseInTempDir): return new_auth_data, old_pac + def get_pac(self, auth_data, expect_pac=True): + _, pac = self.replace_pac(auth_data, None, expect_pac) + return pac + def get_krbtgt_checksum_key(self): krbtgt_creds = self.get_krbtgt_creds() krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) -- 2.25.1 From b7253d1e97f31d65aae006b81e8a5fbe5970c5e3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:26:54 +1300 Subject: [PATCH 318/645] tests/krb5: Check constrained delegation PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 0e232fa1c9e5760ae6b9a99b5e7aa5513b84aa8b) --- python/samba/tests/krb5/raw_testcase.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 320de0a4dbe..8144bd37b2f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2053,6 +2053,8 @@ class RawKerberosTest(TestCaseInTempDir): expect_edata=None, expect_pac=True, expect_claims=True, + expected_proxy_target=None, + expected_transited_services=None, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2100,6 +2102,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_edata': expect_edata, 'expect_pac': expect_pac, 'expect_claims': expect_claims, + 'expected_proxy_target': expected_proxy_target, + 'expected_transited_services': expected_transited_services, 'to_rodc': to_rodc } if callback_dict is None: @@ -2494,6 +2498,23 @@ class RawKerberosTest(TestCaseInTempDir): f'expected: {expected_types} ' f'got: {buffer_types}') + for pac_buffer in pac.buffers: + if pac_buffer.type == krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION: + expected_proxy_target = kdc_exchange_dict[ + 'expected_proxy_target'] + expected_transited_services = kdc_exchange_dict[ + 'expected_transited_services'] + + delegation_info = pac_buffer.info.info + + self.assertEqual(expected_proxy_target, + str(delegation_info.proxy_target)) + + transited_services = list(map( + str, delegation_info.transited_services)) + self.assertEqual(expected_transited_services, + transited_services) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, -- 2.25.1 From 99a1c42203abac4e91dbb9e88f3416e7f6ddc49f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:41:23 +1300 Subject: [PATCH 319/645] tests/krb5: Save account SPN This is useful for testing delegation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit bb58b4b58c66a6ada79e886dd0c44401e1c5878c) --- python/samba/tests/krb5/kdc_base_test.py | 1 + python/samba/tests/krb5/raw_testcase.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index d25fc0b42b2..70ab14786da 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -285,6 +285,7 @@ class KDCBaseTest(RawKerberosTest): else: creds.set_workstation('') creds.set_dn(ldb.Dn(samdb, dn)) + creds.set_spn(spn) # # Save the account name so it can be deleted in tearDownClass self.accounts.add(dn) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8144bd37b2f..c34ffb848e1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -365,6 +365,7 @@ class KerberosCredentials(Credentials): self.forced_salt = None self.dn = None + self.spn = None def set_as_supported_enctypes(self, value): self.as_supported_enctypes = int(value) @@ -467,6 +468,12 @@ class KerberosCredentials(Credentials): def get_dn(self): return self.dn + def set_spn(self, spn): + self.spn = spn + + def get_spn(self): + return self.spn + class KerberosTicketCreds: def __init__(self, ticket, session_key, -- 2.25.1 From d23d778af263754725d2f7ab38f9c8fe388265fa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:48:50 +1300 Subject: [PATCH 320/645] tests/krb5: Allow specifying options and expected flags when obtaining a ticket BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 34020766bb7094d1ab5d4fc4c0ee89ccb81f39f1) --- python/samba/tests/krb5/kdc_base_test.py | 31 +++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 70ab14786da..34a23b3b876 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1164,7 +1164,7 @@ class KDCBaseTest(RawKerberosTest): def tgs_req(self, cname, sname, realm, ticket, key, etypes, expected_error_mode=0, padata=None, kdc_options=0, to_rodc=False, service_creds=None, expect_pac=True, - expect_edata=None): + expect_edata=None, expected_flags=None, unexpected_flags=None): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' @@ -1203,6 +1203,8 @@ class KDCBaseTest(RawKerberosTest): expected_srealm=realm, expected_sname=sname, expected_error_mode=expected_error_mode, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, @@ -1230,10 +1232,12 @@ class KDCBaseTest(RawKerberosTest): return rep, enc_part def get_service_ticket(self, tgt, target_creds, service='host', - to_rodc=False, fresh=False): + to_rodc=False, kdc_options=None, + expected_flags=None, unexpected_flags=None, + fresh=False): user_name = tgt.cname['name-string'][0] target_name = target_creds.get_username() - cache_key = (user_name, target_name, service, to_rodc) + cache_key = (user_name, target_name, service, to_rodc, kdc_options) if not fresh: ticket = self.tkt_cache.get(cache_key) @@ -1243,6 +1247,10 @@ class KDCBaseTest(RawKerberosTest): etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + if kdc_options is None: + kdc_options = '0' + kdc_options = krb5_asn1.KDCOptions(kdc_options) + key = tgt.session_key ticket = tgt.ticket @@ -1255,7 +1263,10 @@ class KDCBaseTest(RawKerberosTest): rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, to_rodc=to_rodc, - service_creds=target_creds) + service_creds=target_creds, + kdc_options=kdc_options, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags) service_ticket = rep['ticket'] @@ -1309,11 +1320,11 @@ class KDCBaseTest(RawKerberosTest): self.TicketDecryptionKey_from_creds(krbtgt_creds)) if kdc_options is None: - kdc_options = krb5_asn1.KDCOptions('forwardable,' - 'renewable,' - 'canonicalize,' - 'renewable-ok') - kdc_options = str(kdc_options) + kdc_options = ('forwardable,' + 'renewable,' + 'canonicalize,' + 'renewable-ok') + kdc_options = krb5_asn1.KDCOptions(kdc_options) pac_options = '1' # supports claims @@ -1370,6 +1381,8 @@ class KDCBaseTest(RawKerberosTest): expected_srealm=expected_realm, expected_sname=expected_sname, expected_salt=salt, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, expected_supported_etypes=expected_etypes, etypes=etype, padata=padata, -- 2.25.1 From 13342a91ce4a24115014c1e999ec86746b196577 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 16:52:01 +1300 Subject: [PATCH 321/645] tests/krb5: Supply supported account enctypes in tgs_req() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 248249dc0acac89d1495c3572cbd2cbe8bdca362) --- python/samba/tests/krb5/kdc_base_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 34a23b3b876..93951586cc7 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1181,8 +1181,10 @@ class KDCBaseTest(RawKerberosTest): if service_creds is not None: decryption_key = self.TicketDecryptionKey_from_creds( service_creds) + expected_supported_etypes = service_creds.tgs_supported_enctypes else: decryption_key = None + expected_supported_etypes = None if not expected_error_mode: check_error_fn = None @@ -1205,6 +1207,7 @@ class KDCBaseTest(RawKerberosTest): expected_error_mode=expected_error_mode, expected_flags=expected_flags, unexpected_flags=unexpected_flags, + expected_supported_etypes=expected_supported_etypes, check_error_fn=check_error_fn, check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, -- 2.25.1 From 1d7c6fc782654943c44d2d6399fa290da31e628e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 30 Sep 2021 16:53:35 +1300 Subject: [PATCH 322/645] tests/krb5: Add parameter to enforce presence of ticket checksums This allows existing tests to pass before this functionality is implemented. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ef24fe982d750a42be81808379b0254d8488c559) --- python/samba/tests/krb5/raw_testcase.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c34ffb848e1..72a39b23b0e 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1942,6 +1942,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_flags=None, unexpected_flags=None, ticket_decryption_key=None, + expect_ticket_checksum=None, generate_fast_fn=None, generate_fast_armor_fn=None, generate_fast_padata_fn=None, @@ -1990,6 +1991,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, + 'expect_ticket_checksum': expect_ticket_checksum, 'generate_fast_fn': generate_fast_fn, 'generate_fast_armor_fn': generate_fast_armor_fn, 'generate_fast_padata_fn': generate_fast_padata_fn, @@ -2034,6 +2036,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_flags=None, unexpected_flags=None, ticket_decryption_key=None, + expect_ticket_checksum=None, generate_fast_fn=None, generate_fast_armor_fn=None, generate_fast_padata_fn=None, @@ -2083,6 +2086,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, 'ticket_decryption_key': ticket_decryption_key, + 'expect_ticket_checksum': expect_ticket_checksum, 'generate_fast_fn': generate_fast_fn, 'generate_fast_armor_fn': generate_fast_armor_fn, 'generate_fast_padata_fn': generate_fast_padata_fn, @@ -2459,8 +2463,15 @@ class RawKerberosTest(TestCaseInTempDir): ticket_private=ticket_private, encpart_private=encpart_private) + # TODO: This parameter should be removed when all service tickets are + # issued with ticket checksums. + expect_ticket_checksum = kdc_exchange_dict['expect_ticket_checksum'] + if expect_ticket_checksum: + self.assertIsNotNone(ticket_decryption_key) + if ticket_decryption_key is not None: - self.verify_ticket(ticket_creds, krbtgt_key, expect_pac=expect_pac) + self.verify_ticket(ticket_creds, krbtgt_key, expect_pac=expect_pac, + expect_ticket_checksum=expect_ticket_checksum) kdc_exchange_dict['rep_ticket_creds'] = ticket_creds @@ -3083,7 +3094,8 @@ class RawKerberosTest(TestCaseInTempDir): ticket_blob) self.assertEqual(expected_checksum, checksum) - def verify_ticket(self, ticket, krbtgt_key, expect_pac=True): + def verify_ticket(self, ticket, krbtgt_key, expect_pac=True, + expect_ticket_checksum=True): # Check if the ticket is a TGT. sname = ticket.ticket['sname'] is_tgt = self.is_tgs(sname) @@ -3182,8 +3194,10 @@ class RawKerberosTest(TestCaseInTempDir): ticket_checksum, ticket_ctype = checksums.get( krb5pac.PAC_TYPE_TICKET_CHECKSUM, (None, None)) - if self.strict_checking: + if expect_ticket_checksum: self.assertIsNotNone(ticket_checksum) + elif expect_ticket_checksum is False: + self.assertIsNone(ticket_checksum) if ticket_checksum is not None: enc_part['authorization-data'] = auth_data enc_part = self.der_encode(enc_part, -- 2.25.1 From 20049b045673d48b5392e061b948d3facf262900 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 14 Oct 2021 16:43:05 +1300 Subject: [PATCH 323/645] tests/krb5: Add compatability tests for ticket checksums BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org: Backported from ec4b264bdf9ab64a728212580b344fbf35c3c673 to Samba 4.14 due to conflicts in knownfail as the test which crashes older MIT KDC versions is omitted] --- .../samba/tests/krb5/compatability_tests.py | 44 ++++++++++++++++++- selftest/knownfail_heimdal_kdc | 6 ++- source4/selftest/tests.py | 7 ++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index cd67549212a..0da72796894 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -23,7 +23,7 @@ import os sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" -from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.kdc_base_test import KDCBaseTest import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( AES128_CTS_HMAC_SHA1_96, @@ -50,7 +50,7 @@ MIT_ENC_AS_REP_PART_TYPE_TAG = 0x7A ENC_PA_REP_FLAG = 0x00010000 -class SimpleKerberosTests(RawKerberosTest): +class SimpleKerberosTests(KDCBaseTest): def setUp(self): super(SimpleKerberosTests, self).setUp() @@ -120,6 +120,46 @@ class SimpleKerberosTests(RawKerberosTest): self.fail( "(Heimdal) Salt populated for ARCFOUR_HMAC_MD5 encryption") + def test_heimdal_ticket_signature(self): + # Ensure that a DC correctly issues tickets signed with its krbtgt key. + user_creds = self.get_client_creds() + target_creds = self.get_service_creds() + + krbtgt_creds = self.get_krbtgt_creds() + key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + # Get a TGT from the DC. + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. + self.verify_ticket(tgt, key) + + # 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) + + def test_mit_ticket_signature(self): + # Ensure that a DC does not issue tickets signed with its krbtgt key. + user_creds = self.get_client_creds() + target_creds = self.get_service_creds() + + krbtgt_creds = self.get_krbtgt_creds() + key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + # Get a TGT from the DC. + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. + self.verify_ticket(tgt, key) + + # 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) + def as_pre_auth_req(self, creds, etypes): user = creds.get_username() realm = creds.get_realm() diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 80b8224f015..6eb667f8969 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -1,7 +1,7 @@ # # We expect all the MIT specific compatability tests to fail on heimdal # kerberos -^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_ +^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_(?!ticket_signature) # # Heimdal currently fails the following MS-KILE client principal lookup # tests @@ -121,3 +121,7 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc +# +# Heimdal currently does not generate ticket signatures +# +^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_heimdal_ticket_signature diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 86d018a0919..67024b4b200 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1321,7 +1321,12 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD' }) -planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests") +planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0', + }) planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") planpythontestsuite( "ad_dc", -- 2.25.1 From 30dd42bfef9c28a6f1c370ce6b727610ee7100e2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 14:37:03 +1300 Subject: [PATCH 324/645] tests/krb5: Use correct principal name type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 687c8f94c68af9f1e44771dfd7219eeb41382bba) --- python/samba/tests/krb5/fast_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/fast_tests.py b/python/samba/tests/krb5/fast_tests.py index 28fe0686335..1cdfd5e20c4 100755 --- a/python/samba/tests/krb5/fast_tests.py +++ b/python/samba/tests/krb5/fast_tests.py @@ -43,6 +43,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_AS_REP, KRB_TGS_REP, NT_PRINCIPAL, + NT_SRV_HST, NT_SRV_INST, PADATA_FX_COOKIE, PADATA_FX_FAST, @@ -1136,7 +1137,7 @@ class FAST_Tests(KDCBaseTest): target_realm = target_creds.get_realm() target_service = 'host' target_sname = self.PrincipalName_create( - name_type=NT_SRV_INST, names=[target_service, target_username]) + name_type=NT_SRV_HST, names=[target_service, target_username]) target_decryption_key = self.TicketDecryptionKey_from_creds( target_creds) target_etypes = target_creds.tgs_supported_enctypes -- 2.25.1 From ce29c39991ba0d4887f2c22406ca082db871dd83 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 14:39:26 +1300 Subject: [PATCH 325/645] tests/krb5: Clarify checksum type assertion message BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ee2b7e2c77f021984ec583fa0c4c756979197b0f) --- python/samba/tests/krb5/raw_testcase.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 72a39b23b0e..e52eb5ae5b9 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -248,7 +248,8 @@ class Krb5EncryptionKey: def verify_checksum(self, usage, plaintext, ctype, cksum): if self.ctype != ctype: - raise AssertionError(f'{self.ctype} != {ctype}') + raise AssertionError(f'key checksum type ({self.ctype}) != ' + f'checksum type ({ctype})') kcrypto.verify_checksum(ctype, self.key, -- 2.25.1 From 1e23d8607220acc978f393680d7f76cc5986a0f1 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 16:15:43 +1300 Subject: [PATCH 326/645] tests/krb5: Fix padata checking at functional level 2003 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 72265227e9c2037b63cdfb01a456a86ac8932f59) --- python/samba/tests/krb5/raw_testcase.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e52eb5ae5b9..bb9d414da5b 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2661,11 +2661,10 @@ class RawKerberosTest(TestCaseInTempDir): if kcrypto.Enctype.RC4 in proposed_etypes: expect_etype_info = True for etype in proposed_etypes: - if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): - expect_etype_info = False if etype not in client_as_etypes: continue if etype in (kcrypto.Enctype.AES256, kcrypto.Enctype.AES128): + expect_etype_info = False if etype > expected_aes_type: expected_aes_type = etype if etype in (kcrypto.Enctype.RC4,) and error_code != 0: @@ -2865,7 +2864,8 @@ class RawKerberosTest(TestCaseInTempDir): else: self.assertIsNone(etype_info2) if expect_etype_info: - self.assertIsNotNone(etype_info) + if self.strict_checking: + self.assertIsNotNone(etype_info) else: if self.strict_checking: self.assertIsNone(etype_info) -- 2.25.1 From 0e396c8eb342802d8580da10f5821fecba8e853c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 12 Oct 2021 11:34:59 +1300 Subject: [PATCH 327/645] tests/krb5: Add environment variable to specify KDC FAST support BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backportd from commit 238f52bad811688624e9fd4b1595266e2149094a because tests.py changed in more recent releases with new tests nearby] --- python/samba/tests/krb5/raw_testcase.py | 6 +++- source4/selftest/tests.py | 37 +++++++++++++++++-------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index bb9d414da5b..fbddb7f83b1 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -568,7 +568,11 @@ class RawKerberosTest(TestCaseInTempDir): # obtained. cls.creds_dict = {} - cls.kdc_fast_support = False + kdc_fast_support = samba.tests.env_get_var_value('FAST_SUPPORT', + allow_missing=True) + if kdc_fast_support is None: + kdc_fast_support = '0' + cls.kdc_fast_support = bool(int(kdc_fast_support)) def setUp(self): super().setUp() diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 67024b4b200..bdcbfcb4ab6 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -742,39 +742,47 @@ planoldpythontestsuite("nt4_dc", "samba.tests.netbios", extra_args=['-U"$USERNAM planoldpythontestsuite("ad_dc:local", "samba.tests.gpo", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$USERNAME%$PASSWORD"']) +have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", - environ={'SERVICE_USERNAME':'$SERVER'}) + environ={'SERVICE_USERNAME':'$SERVER', + 'FAST_SUPPORT': have_fast_support}) planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", environ={'SERVICE_USERNAME':'srv_account', 'SERVICE_PASSWORD':'$PASSWORD', - 'FOR_USER':'$USERNAME'}) + 'FOR_USER':'$USERNAME', + 'FAST_SUPPORT': have_fast_support}) -planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests") +planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests", + environ={'FAST_SUPPORT': have_fast_support}) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) for env in ["ad_dc", smbv1_disabled_testenv]: @@ -1299,6 +1307,7 @@ for env in ["fl2008r2dc", "fl2003dc"]: 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) @@ -1319,22 +1328,26 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD' + 'ADMIN_PASSWORD': '$PASSWORD', + 'FAST_SUPPORT': have_fast_support }) planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, }) -planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests") +planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests", + environ={'FAST_SUPPORT': have_fast_support}) planpythontestsuite( "ad_dc", "samba.tests.krb5.kdc_tgs_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) planpythontestsuite( "ad_dc", @@ -1343,6 +1356,7 @@ planpythontestsuite( 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) planpythontestsuite( "ad_dc", @@ -1350,7 +1364,8 @@ planpythontestsuite( environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0' + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support }) for env in [ -- 2.25.1 From 2456b64448c4d195ee5cd734fa60ef90c5095a45 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 14:45:45 +1300 Subject: [PATCH 328/645] tests/krb5: Check padata types when STRICT_CHECKING=0 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit bd22dcd9cc4dfda827f892224eb2da4a16564176 to Samba 4.14 due to conflicts in knownfail as the test which crashes older MIT KDC versions is omitted] --- python/samba/tests/krb5/raw_testcase.py | 25 +++++++++++++++++++++---- selftest/knownfail_mit_kdc | 9 +++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index fbddb7f83b1..dbcff787f70 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1079,6 +1079,20 @@ class RawKerberosTest(TestCaseInTempDir): f"'{unexpected.namedValues[i]}' " f"unexpected in {v}") + def assertSequenceElementsEqual(self, expected, got, *, + require_strict=None): + if self.strict_checking: + self.assertEqual(expected, got) + else: + fail_msg = f'expected: {expected} got: {got}' + + if require_strict is not None: + fail_msg += f' (ignoring: {require_strict})' + expected = (x for x in expected if x not in require_strict) + got = (x for x in got if x not in require_strict) + + self.assertCountEqual(expected, got, fail_msg) + def get_KerberosTimeWithUsec(self, epoch=None, offset=None): if epoch is None: epoch = time.time() @@ -2714,10 +2728,13 @@ class RawKerberosTest(TestCaseInTempDir): expected_patypes += (PADATA_FX_FAST,) expected_patypes += (PADATA_FX_COOKIE,) - if self.strict_checking: - for i, patype in enumerate(expected_patypes): - self.assertElementEqual(rep_padata[i], 'padata-type', patype) - self.assertEqual(len(rep_padata), len(expected_patypes)) + got_patypes = tuple(pa['padata-type'] for pa in rep_padata) + self.assertSequenceElementsEqual(expected_patypes, got_patypes, + require_strict={PADATA_FX_COOKIE, + PADATA_FX_FAST, + PADATA_PAC_OPTIONS, + PADATA_PK_AS_REP_19, + PADATA_PK_AS_REQ}) etype_info2 = None etype_info = None diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index f167c2bf856..4e0b20c5c80 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -290,6 +290,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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_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_c ^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_6_c +# +# MIT currently fails some as_req_no_preauth tests. +# +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth.*aes.*rc4.*fl2003dc +^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth.*rc4.*aes.*fl2003dc # Differences in our KDC compared to windows # ^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally @@ -304,6 +309,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_authdata_fast_not_used.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_enc_timestamp.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_clock_skew.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_no_fast.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_encrypted_challenge_wrong_key_kdc.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_invalid_tgt_mach.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_armor.ad_dc @@ -318,5 +326,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc -- 2.25.1 From 8786673f77d5db2d2048a7b20db8e84a8d97ae77 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 14:48:03 +1300 Subject: [PATCH 329/645] tests/krb5: Check logon name in PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit e7c39cc44f2e16aecb01c0afc195911a474ef0b9) --- python/samba/tests/krb5/raw_testcase.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index dbcff787f70..b0cd2bfdf0f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2552,6 +2552,12 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(expected_transited_services, transited_services) + elif pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME: + expected_cname = kdc_exchange_dict['expected_cname'] + account_name = expected_cname['name-string'][0] + + self.assertEqual(account_name, pac_buffer.info.account_name) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, -- 2.25.1 From c90413bbca24b7c5ebe5da4dddf2d43fca6f8879 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 11 Oct 2021 14:49:34 +1300 Subject: [PATCH 330/645] tests/krb5: Simplify padata checking BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit cf3ca6ac4567d7c7954ea4ecc8cc9dd5effcc094) --- python/samba/tests/krb5/raw_testcase.py | 169 ++++++------------------ 1 file changed, 41 insertions(+), 128 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b0cd2bfdf0f..b51ad499192 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2742,73 +2742,32 @@ class RawKerberosTest(TestCaseInTempDir): PADATA_PK_AS_REP_19, PADATA_PK_AS_REQ}) - etype_info2 = None - etype_info = None - enc_timestamp = None - enc_challenge = None - pk_as_req = None - pk_as_rep19 = None - fast_cookie = None - fast_error = None - fx_fast = None - pac_options = None - for pa in rep_padata: - patype = self.getElementValue(pa, 'padata-type') - pavalue = self.getElementValue(pa, 'padata-value') - if patype == PADATA_ETYPE_INFO2: - self.assertIsNone(etype_info2) - etype_info2 = self.der_decode(pavalue, - asn1Spec=krb5_asn1.ETYPE_INFO2()) - continue - if patype == PADATA_ETYPE_INFO: - self.assertIsNone(etype_info) - etype_info = self.der_decode(pavalue, - asn1Spec=krb5_asn1.ETYPE_INFO()) - continue - if patype == PADATA_ENC_TIMESTAMP: - self.assertIsNone(enc_timestamp) - enc_timestamp = pavalue - self.assertEqual(len(enc_timestamp), 0) - continue - if patype == PADATA_ENCRYPTED_CHALLENGE: - self.assertIsNone(enc_challenge) - enc_challenge = pavalue - continue - if patype == PADATA_PK_AS_REQ: - self.assertIsNone(pk_as_req) - pk_as_req = pavalue - self.assertEqual(len(pk_as_req), 0) - continue - if patype == PADATA_PK_AS_REP_19: - self.assertIsNone(pk_as_rep19) - pk_as_rep19 = pavalue - self.assertEqual(len(pk_as_rep19), 0) - continue - if patype == PADATA_FX_COOKIE: - self.assertIsNone(fast_cookie) - fast_cookie = pavalue - self.assertIsNotNone(fast_cookie) - continue - if patype == PADATA_FX_ERROR: - self.assertIsNone(fast_error) - fast_error = pavalue - self.assertIsNotNone(fast_error) - continue - if patype == PADATA_FX_FAST: - self.assertIsNone(fx_fast) - fx_fast = pavalue - self.assertEqual(len(fx_fast), 0) - continue - if patype == PADATA_PAC_OPTIONS: - self.assertIsNone(pac_options) - pac_options = self.der_decode( - pavalue, - asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) - continue + if not expected_patypes: + return None + + pa_dict = self.get_pa_dict(rep_padata) + + enc_timestamp = pa_dict.get(PADATA_ENC_TIMESTAMP) + if enc_timestamp is not None: + self.assertEqual(len(enc_timestamp), 0) + + pk_as_req = pa_dict.get(PADATA_PK_AS_REQ) + if pk_as_req is not None: + self.assertEqual(len(pk_as_req), 0) + + pk_as_rep19 = pa_dict.get(PADATA_PK_AS_REP_19) + if pk_as_rep19 is not None: + self.assertEqual(len(pk_as_rep19), 0) + fx_fast = pa_dict.get(PADATA_FX_FAST) + if fx_fast is not None: + self.assertEqual(len(fx_fast), 0) + + fast_cookie = pa_dict.get(PADATA_FX_COOKIE) if fast_cookie is not None: kdc_exchange_dict['fast_cookie'] = fast_cookie + fast_error = pa_dict.get(PADATA_FX_ERROR) if fast_error is not None: fast_error = self.der_decode(fast_error, asn1Spec=krb5_asn1.KRB_ERROR()) @@ -2817,9 +2776,14 @@ class RawKerberosTest(TestCaseInTempDir): fast_error, inner=True) + pac_options = pa_dict.get(PADATA_PAC_OPTIONS) if pac_options is not None: + pac_options = self.der_decode( + pac_options, + asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) self.assertElementEqual(pac_options, 'options', sent_pac_options) + enc_challenge = pa_dict.get(PADATA_ENCRYPTED_CHALLENGE) if enc_challenge is not None: if not sent_enc_challenge: self.assertEqual(len(enc_challenge), 0) @@ -2862,52 +2826,21 @@ class RawKerberosTest(TestCaseInTempDir): self.assertLess(current_time - 300, rep_time) self.assertLess(rep_time, current_time + 300) - if all(etype not in client_as_etypes or etype not in proposed_etypes - for etype in (kcrypto.Enctype.AES256, - kcrypto.Enctype.AES128, - kcrypto.Enctype.RC4)): - self.assertIsNone(etype_info2) - self.assertIsNone(etype_info) - if rep_msg_type == KRB_AS_REP: - if self.strict_checking: - if sent_fast: - self.assertIsNotNone(enc_challenge) - self.assertIsNone(enc_timestamp) - else: - self.assertIsNotNone(enc_timestamp) - self.assertIsNone(enc_challenge) - self.assertIsNotNone(pk_as_req) - self.assertIsNotNone(pk_as_rep19) - else: - self.assertIsNone(enc_timestamp) - self.assertIsNone(enc_challenge) - self.assertIsNone(pk_as_req) - self.assertIsNone(pk_as_rep19) - return None - - if error_code != KDC_ERR_GENERIC: - if self.strict_checking: - self.assertIsNotNone(etype_info2) - else: - self.assertIsNone(etype_info2) - if expect_etype_info: - if self.strict_checking: - self.assertIsNotNone(etype_info) - else: - if self.strict_checking: - self.assertIsNone(etype_info) - if unexpect_etype_info: - self.assertIsNone(etype_info) - - if error_code != KDC_ERR_GENERIC and self.strict_checking: + etype_info2 = pa_dict.get(PADATA_ETYPE_INFO2) + if etype_info2 is not None: + etype_info2 = self.der_decode(etype_info2, + asn1Spec=krb5_asn1.ETYPE_INFO2()) self.assertGreaterEqual(len(etype_info2), 1) - self.assertEqual(len(etype_info2), len(expect_etype_info2)) + if self.strict_checking: + self.assertEqual(len(etype_info2), len(expect_etype_info2)) for i in range(0, len(etype_info2)): e = self.getElementValue(etype_info2[i], 'etype') - self.assertEqual(e, expect_etype_info2[i]) + if self.strict_checking: + self.assertEqual(e, expect_etype_info2[i]) salt = self.getElementValue(etype_info2[i], 'salt') if e == kcrypto.Enctype.RC4: - self.assertIsNone(salt) + if self.strict_checking: + self.assertIsNone(salt) else: self.assertIsNotNone(salt) expected_salt = kdc_exchange_dict['expected_salt'] @@ -2916,7 +2849,11 @@ class RawKerberosTest(TestCaseInTempDir): s2kparams = self.getElementValue(etype_info2[i], 's2kparams') if self.strict_checking: self.assertIsNone(s2kparams) + + etype_info = pa_dict.get(PADATA_ETYPE_INFO) if etype_info is not None: + etype_info = self.der_decode(etype_info, + asn1Spec=krb5_asn1.ETYPE_INFO()) self.assertEqual(len(etype_info), 1) e = self.getElementValue(etype_info[0], 'etype') self.assertEqual(e, kcrypto.Enctype.RC4) @@ -2926,30 +2863,6 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(salt) self.assertEqual(len(salt), 0) - if error_code not in (KDC_ERR_PREAUTH_FAILED, - KDC_ERR_GENERIC): - if sent_fast: - self.assertIsNotNone(enc_challenge) - if self.strict_checking: - self.assertIsNone(enc_timestamp) - else: - self.assertIsNotNone(enc_timestamp) - if self.strict_checking: - self.assertIsNone(enc_challenge) - if not sent_enc_challenge: - if self.strict_checking: - self.assertIsNotNone(pk_as_req) - self.assertIsNotNone(pk_as_rep19) - else: - self.assertIsNone(pk_as_req) - self.assertIsNone(pk_as_rep19) - else: - if self.strict_checking: - self.assertIsNone(enc_timestamp) - self.assertIsNone(enc_challenge) - self.assertIsNone(pk_as_req) - self.assertIsNone(pk_as_rep19) - return etype_info2 def generate_simple_fast(self, -- 2.25.1 From 3986962be4a6b18b78ff9f6c70b07c291809a970 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 11:48:41 +1300 Subject: [PATCH 331/645] tests/krb5: Disable debugging output for tests This reduces the time spent running the tests in a testenv. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit dfd613661eec4b81e162f2d86a8fa9266c2fdc03) --- python/samba/tests/krb5/as_canonicalization_tests.py | 4 ++-- python/samba/tests/krb5/as_req_tests.py | 4 ++-- python/samba/tests/krb5/compatability_tests.py | 4 ++-- python/samba/tests/krb5/kdc_tests.py | 4 ++-- python/samba/tests/krb5/kdc_tgs_tests.py | 4 ++-- python/samba/tests/krb5/s4u_tests.py | 4 ++-- python/samba/tests/krb5/simple_tests.py | 4 ++-- python/samba/tests/krb5/test_ccache.py | 4 ++-- python/samba/tests/krb5/test_ldap.py | 4 ++-- python/samba/tests/krb5/test_rpc.py | 4 ++-- python/samba/tests/krb5/test_smb.py | 4 ++-- python/samba/tests/krb5/xrealm_tests.py | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 29d8cf418f5..9538d0ae3cf 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -427,8 +427,8 @@ class KerberosASCanonicalizationTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 8d9b90fee69..7d7baaebf24 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -198,8 +198,8 @@ class AsReqKerberosTests(KDCBaseTest): self.assertIsNotNone(as_rep) if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py index 0da72796894..ed2dc565b6d 100755 --- a/python/samba/tests/krb5/compatability_tests.py +++ b/python/samba/tests/krb5/compatability_tests.py @@ -261,7 +261,7 @@ class SimpleKerberosTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/kdc_tests.py b/python/samba/tests/krb5/kdc_tests.py index 928f3c25c0f..b7c8566a1ec 100755 --- a/python/samba/tests/krb5/kdc_tests.py +++ b/python/samba/tests/krb5/kdc_tests.py @@ -222,7 +222,7 @@ class KdcTests(RawKerberosTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 2b55ba8a376..3075cc6b0a9 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -211,7 +211,7 @@ class KdcTgsTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 57575f0595d..bbddef4d6e0 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -197,7 +197,7 @@ class S4UKerberosTests(RawKerberosTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/simple_tests.py b/python/samba/tests/krb5/simple_tests.py index 795d753b4f7..3cd3b17bb31 100755 --- a/python/samba/tests/krb5/simple_tests.py +++ b/python/samba/tests/krb5/simple_tests.py @@ -179,7 +179,7 @@ class SimpleKerberosTests(RawKerberosTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index feb7a7bd9be..c44ea02d504 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -129,7 +129,7 @@ class CcacheTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index d304fb9d71e..95b2d24221a 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -90,7 +90,7 @@ class LdapTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index 324b57f2847..40ac6df7a35 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -73,7 +73,7 @@ class RpcTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 45d4fe5e0c1..eebc9a9d4fe 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -104,7 +104,7 @@ class SmbTests(KDCBaseTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() diff --git a/python/samba/tests/krb5/xrealm_tests.py b/python/samba/tests/krb5/xrealm_tests.py index 073cb755b46..73a6b3cf52d 100755 --- a/python/samba/tests/krb5/xrealm_tests.py +++ b/python/samba/tests/krb5/xrealm_tests.py @@ -181,7 +181,7 @@ class XrealmKerberosTests(RawKerberosTest): if __name__ == "__main__": - global_asn1_print = True - global_hexdump = True + global_asn1_print = False + global_hexdump = False import unittest unittest.main() -- 2.25.1 From deafb219706916382dce66539979a835079581a9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 5 Oct 2021 19:47:22 +1300 Subject: [PATCH 332/645] tests/krb5: Provide clearer assertion messages for test failures BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 5233f002000f196875af488b4f4d1df26fca90de) --- python/samba/tests/krb5/raw_testcase.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b51ad499192..188a54451d3 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1942,7 +1942,12 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNone(check_error_fn) self.assertEqual(0, len(expected_error_mode)) self.assertIsNotNone(expected_msg_type) - self.assertEqual(msg_type, expected_msg_type) + if msg_type == KRB_ERROR: + error_code = self.getElementValue(rep, 'error-code') + fail_msg = f'Got unexpected error: {error_code}' + else: + fail_msg = f'Expected to fail with error: {expected_error_mode}' + self.assertEqual(msg_type, expected_msg_type, fail_msg) if msg_type == KRB_ERROR: return check_error_fn(kdc_exchange_dict, -- 2.25.1 From e9ab0e3aaea2b2c7a91ac5f3dfb19654224424df Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 5 Oct 2021 16:32:01 +1300 Subject: [PATCH 333/645] tests/krb5: Fix sha1 checksum type Previously, sha1 signatures were being designated as rsa-md5-des3 signatures. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ebe729786806c69e95b26ffc410e887e203accb8) --- python/samba/tests/krb5/kcrypto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index 2a72969de00..a919b785ad1 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -81,8 +81,8 @@ class Cksumtype(object): MD4_DES = 3 MD5 = 7 MD5_DES = 8 - SHA1 = 9 SHA1_DES3 = 12 + SHA1 = 14 SHA1_AES128 = 15 SHA1_AES256 = 16 HMAC_MD5 = -138 -- 2.25.1 From 5abe1c669c8c242cc2712897af3ab169f5e4d868 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 13 Oct 2021 12:26:22 +1300 Subject: [PATCH 334/645] selftest/dbcheck: Fix up RODC one-way links Test accounts were replicated to the RODC and then deleted, causing state links to remain in the database. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 40e5db4aabcd32834ee524857b77d36921f6bdfe) --- testprogs/blackbox/dbcheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testprogs/blackbox/dbcheck.sh b/testprogs/blackbox/dbcheck.sh index caf89ca402b..e2ba987e2de 100755 --- a/testprogs/blackbox/dbcheck.sh +++ b/testprogs/blackbox/dbcheck.sh @@ -19,7 +19,7 @@ dbcheck() { # This list of attributes can be freely extended dbcheck_fix_one_way_links() { - $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes fix_all_old_dn_string_component_mismatch --attrs="lastKnownParent defaultObjectCategory fromServer rIDSetReferences" --cross-ncs $ARGS + $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes fix_all_old_dn_string_component_mismatch --attrs="lastKnownParent defaultObjectCategory fromServer rIDSetReferences msDS-RevealOnDemandGroup msDS-NeverRevealGroup" --cross-ncs $ARGS } # This list of attributes can be freely extended -- 2.25.1 From d5cc39effca0dd2f5305e8bcd122f8e928465c06 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 14 Oct 2021 16:58:15 +1300 Subject: [PATCH 335/645] tests/krb5: Add TKT_SIG_SUPPORT environment variable This lets us indicate that service tickets should be issued with ticket checksums in the PAC. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit ae2c57fb0332f94ac44d0886c5edbed707ef52fe due to changes in other tests nearby in tests.py] --- python/samba/tests/krb5/raw_testcase.py | 6 ++++ source4/selftest/tests.py | 41 +++++++++++++++++-------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 188a54451d3..1f7c51c07a5 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -574,6 +574,12 @@ class RawKerberosTest(TestCaseInTempDir): kdc_fast_support = '0' cls.kdc_fast_support = bool(int(kdc_fast_support)) + tkt_sig_support = samba.tests.env_get_var_value('TKT_SIG_SUPPORT', + allow_missing=True) + if tkt_sig_support is None: + tkt_sig_support = '0' + cls.tkt_sig_support = bool(int(tkt_sig_support)) + def setUp(self): super().setUp() self.do_asn1_print = False diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index bdcbfcb4ab6..2fa725e837c 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -743,46 +743,54 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.gpo", extra_args=['-U"$USERNA planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$USERNAME%$PASSWORD"']) have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) +tkt_sig_support = 0 planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", environ={'SERVICE_USERNAME':'$SERVER', - 'FAST_SUPPORT': have_fast_support}) + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support}) planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", environ={'SERVICE_USERNAME':'srv_account', 'SERVICE_PASSWORD':'$PASSWORD', 'FOR_USER':'$USERNAME', - 'FAST_SUPPORT': have_fast_support}) + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support}) planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests", - environ={'FAST_SUPPORT': have_fast_support}) + environ={'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support}) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) for env in ["ad_dc", smbv1_disabled_testenv]: @@ -1307,7 +1315,8 @@ for env in ["fl2008r2dc", "fl2003dc"]: 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) @@ -1329,7 +1338,8 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", environ={ @@ -1337,9 +1347,11 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests", - environ={'FAST_SUPPORT': have_fast_support}) + environ={'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support}) planpythontestsuite( "ad_dc", "samba.tests.krb5.kdc_tgs_tests", @@ -1347,7 +1359,8 @@ planpythontestsuite( 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planpythontestsuite( "ad_dc", @@ -1356,7 +1369,8 @@ planpythontestsuite( 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) planpythontestsuite( "ad_dc", @@ -1365,7 +1379,8 @@ planpythontestsuite( 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support }) for env in [ -- 2.25.1 From 14917591b7161d9cf12ca5bf6342b0469a2f03ee Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 5 Oct 2021 15:39:11 +1300 Subject: [PATCH 336/645] tests/krb5: Require ticket checksums if decryption key is available We perform this check conditionally, because MIT doesn't currently add ticket checksums. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit bf63221722903665e7b20991021fb5cdf4e4327e) --- python/samba/tests/krb5/raw_testcase.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 1f7c51c07a5..2e289c90ce7 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2493,15 +2493,14 @@ class RawKerberosTest(TestCaseInTempDir): ticket_private=ticket_private, encpart_private=encpart_private) - # TODO: This parameter should be removed when all service tickets are - # issued with ticket checksums. expect_ticket_checksum = kdc_exchange_dict['expect_ticket_checksum'] if expect_ticket_checksum: self.assertIsNotNone(ticket_decryption_key) if ticket_decryption_key is not None: self.verify_ticket(ticket_creds, krbtgt_key, expect_pac=expect_pac, - expect_ticket_checksum=expect_ticket_checksum) + expect_ticket_checksum=expect_ticket_checksum + or self.tkt_sig_support) kdc_exchange_dict['rep_ticket_creds'] = ticket_creds -- 2.25.1 From fd49684ff5dc90603fd7a5baf418e08b45d4a993 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 6 Oct 2021 16:35:47 +1300 Subject: [PATCH 337/645] tests/krb5: Verify tickets obtained with get_service_ticket() We only require the ticket checksum with Heimdal, because MIT currently doesn't add it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit d86eee2fd0fb72e52d878ceba0c476ca58abe6cf) --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 93951586cc7..8a5e12bbed4 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1287,6 +1287,14 @@ class KDCBaseTest(RawKerberosTest): sname=sname, decryption_key=target_key) + if to_rodc: + krbtgt_creds = self.get_rodc_krbtgt_creds() + else: + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + self.verify_ticket(service_ticket_creds, krbtgt_key, + expect_ticket_checksum=self.tkt_sig_support) + self.tkt_cache[cache_key] = service_ticket_creds return service_ticket_creds -- 2.25.1 From cb7d9d9bb38754331d91d8582cf9872ea0f27910 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 30 Sep 2021 15:03:04 +1300 Subject: [PATCH 338/645] tests/krb5: Add constrained delegation tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 56ccdba54e0c7cf3409d8430ea1012e5d3d9b092) --- python/samba/tests/krb5/rfc4120_constants.py | 5 + python/samba/tests/krb5/rodc_tests.py | 73 ++ python/samba/tests/krb5/s4u_tests.py | 958 ++++++++++++++++++- python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 29 + source4/selftest/tests.py | 11 +- 6 files changed, 1070 insertions(+), 7 deletions(-) create mode 100755 python/samba/tests/krb5/rodc_tests.py diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 76f2b75d94e..39bb2db8e32 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -69,12 +69,17 @@ PADATA_SUPPORTED_ETYPES = int( KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 KDC_ERR_S_PRINCIPAL_UNKNOWN = 7 KDC_ERR_POLICY = 12 +KDC_ERR_BADOPTION = 13 KDC_ERR_ETYPE_NOSUPP = 14 +KDC_ERR_SUMTYPE_NOSUPP = 15 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 +KDC_ERR_BAD_INTEGRITY = 31 KDC_ERR_NOT_US = 35 KDC_ERR_BADMATCH = 36 KDC_ERR_SKEW = 37 +KDC_ERR_MODIFIED = 41 +KDC_ERR_INAPP_CKSUM = 50 KDC_ERR_GENERIC = 60 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 diff --git a/python/samba/tests/krb5/rodc_tests.py b/python/samba/tests/krb5/rodc_tests.py new file mode 100755 index 00000000000..4579f9eb552 --- /dev/null +++ b/python/samba/tests/krb5/rodc_tests.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import os + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class RodcKerberosTests(KDCBaseTest): + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + # Ensure that an RODC correctly issues tickets signed with its krbtgt key + # and including the RODCIdentifier. + def test_rodc_ticket_signature(self): + user_creds = self.get_cached_creds( + machine_account=False, + opts={ + 'revealed_to_rodc': True + }) + target_creds = self.get_cached_creds( + machine_account=True, + opts={ + 'revealed_to_rodc': True + }) + + krbtgt_creds = self.get_rodc_krbtgt_creds() + rodc_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + # Get a TGT from the RODC. + tgt = self.get_tgt(user_creds, to_rodc=True) + + # Ensure the PAC contains the expected checksums. + self.verify_ticket(tgt, rodc_key) + + # 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) + + +if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index bbddef4d6e0..9a25256081a 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -18,17 +18,34 @@ import sys import os +import functools sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" +from samba import ntstatus +from samba.dcerpc import krb5pac, lsa + from samba.tests import env_get_var_value -from samba.tests.krb5.kcrypto import Cksumtype -from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.kcrypto import Cksumtype, Enctype +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.raw_testcase import ( + RodcPacEncryptionKey, + ZeroedChecksumKey +) from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_BADOPTION, + KDC_ERR_BAD_INTEGRITY, + KDC_ERR_GENERIC, + KDC_ERR_INAPP_CKSUM, + KDC_ERR_MODIFIED, + KDC_ERR_SUMTYPE_NOSUPP, KU_PA_ENC_TIMESTAMP, KU_AS_REP_ENC_PART, KU_TGS_REP_ENC_PART_SUB_KEY, + NT_PRINCIPAL ) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 @@ -36,7 +53,7 @@ global_asn1_print = False global_hexdump = False -class S4UKerberosTests(RawKerberosTest): +class S4UKerberosTests(KDCBaseTest): def setUp(self): super(S4UKerberosTests, self).setUp() @@ -119,8 +136,14 @@ class S4UKerberosTests(RawKerberosTest): self.assertEqual(msg_type, 11) enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) - enc_part2 = self.der_decode( - enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + # MIT KDC encodes both EncASRepPart and EncTGSRepPart with + # application tag 26 + try: + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) + except Exception: + enc_part2 = self.der_decode( + enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # S4U2Self Request sname = cname @@ -195,6 +218,931 @@ class S4UKerberosTests(RawKerberosTest): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.CRC32) self.assertEqual(msg_type, 30) + def _run_s4u2self_test(self, kdc_dict): + client_opts = kdc_dict.pop('client_opts', None) + client_creds = self.get_cached_creds(machine_account=False, + opts=client_opts) + + service_opts = kdc_dict.pop('service_opts', None) + service_creds = self.get_cached_creds(machine_account=True, + opts=service_opts) + + service_tgt = self.get_tgt(service_creds) + modify_service_tgt_fn = kdc_dict.pop('modify_service_tgt_fn', None) + if modify_service_tgt_fn is not None: + service_tgt = modify_service_tgt_fn(service_tgt) + + client_name = client_creds.get_username() + client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_name]) + + service_name = service_creds.get_username()[:-1] + service_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', service_name]) + + realm = client_creds.get_realm() + + expected_flags = kdc_dict.pop('expected_flags', None) + if expected_flags is not None: + expected_flags = krb5_asn1.TicketFlags(expected_flags) + + unexpected_flags = kdc_dict.pop('unexpected_flags', None) + if unexpected_flags is not None: + unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags) + + kdc_options = kdc_dict.pop('kdc_options', '0') + kdc_options = krb5_asn1.KDCOptions(kdc_options) + + service_decryption_key = self.TicketDecryptionKey_from_creds( + service_creds) + + authenticator_subkey = self.RandomKey(Enctype.AES256) + + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) + + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): + pa_s4u = self.PA_S4U2Self_create( + name=client_cname, + realm=realm, + tgt_session_key=service_tgt.session_key, + ctype=None) + + return [pa_s4u], req_body + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=realm, + expected_cname=client_cname, + expected_srealm=realm, + expected_sname=service_sname, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, + ticket_decryption_key=service_decryption_key, + expect_ticket_checksum=True, + generate_padata_fn=generate_s4u2self_padata, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=0, + tgt=service_tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=str(kdc_options), + expect_claims=False) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=realm, + sname=service_sname, + etypes=etypes) + + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + + # Test performing an S4U2Self operation with a forwardable ticket. The + # resulting ticket should have the 'forwardable' flag set. + def test_s4u2self_forwardable(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'expected_flags': 'forwardable' + }) + + # Test performing an S4U2Self operation without requesting a forwardable + # ticket. The resulting ticket should not have the 'forwardable' flag set. + def test_s4u2self_without_forwardable(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'unexpected_flags': 'forwardable' + }) + + # Do an S4U2Self with a non-forwardable TGT. The 'forwardable' flag should + # not be set on the ticket. + def test_s4u2self_not_forwardable(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=False), + 'unexpected_flags': 'forwardable' + }) + + # Do an S4U2Self with the not_delegated flag set on the client. The + # 'forwardable' flag should not be set on the ticket. + def test_s4u2self_client_not_delegated(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': True + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'unexpected_flags': 'forwardable' + }) + + # Do an S4U2Self with a service not trusted to authenticate for delegation, + # but having an empty msDS-AllowedToDelegateTo attribute. The 'forwardable' + # flag should be set on the ticket. + def test_s4u2self_not_trusted_empty_allowed(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'service_opts': { + 'trusted_to_auth_for_delegation': False, + 'delegation_to_spn': () + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'expected_flags': 'forwardable' + }) + + # Do an S4U2Self with a service not trusted to authenticate for delegation + # and having a non-empty msDS-AllowedToDelegateTo attribute. The + # 'forwardable' flag should not be set on the ticket. + def test_s4u2self_not_trusted_nonempty_allowed(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'service_opts': { + 'trusted_to_auth_for_delegation': False, + 'delegation_to_spn': ('test',) + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'unexpected_flags': 'forwardable' + }) + + # Do an S4U2Self with a service trusted to authenticate for delegation and + # having an empty msDS-AllowedToDelegateTo attribute. The 'forwardable' + # flag should be set on the ticket. + def test_s4u2self_trusted_empty_allowed(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'service_opts': { + 'trusted_to_auth_for_delegation': True, + 'delegation_to_spn': () + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': functools.partial( + self.set_ticket_forwardable, flag=True), + 'expected_flags': 'forwardable' + }) + + # Do an S4U2Self with a service trusted to authenticate for delegation and + # having a non-empty msDS-AllowedToDelegateTo attribute. The 'forwardable' + # flag should be set on the ticket. + def test_s4u2self_trusted_nonempty_allowed(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'service_opts': { + 'trusted_to_auth_for_delegation': True, + 'delegation_to_spn': ('test',) + }, + '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(machine_account=False, + opts=client_opts) + + service1_opts = kdc_dict.pop('service1_opts', {}) + service2_opts = kdc_dict.pop('service2_opts', {}) + + allow_delegation = kdc_dict.pop('allow_delegation', False) + allow_rbcd = kdc_dict.pop('allow_rbcd', False) + self.assertFalse(allow_delegation and allow_rbcd) + + if allow_rbcd: + service1_creds = self.get_cached_creds(machine_account=True, + opts=service1_opts) + + self.assertNotIn('delegation_from_dn', service2_opts) + service2_opts['delegation_from_dn'] = str(service1_creds.get_dn()) + + service2_creds = self.get_cached_creds(machine_account=True, + opts=service2_opts) + else: + service2_creds = self.get_cached_creds(machine_account=True, + opts=service2_opts) + + if allow_delegation: + self.assertNotIn('delegation_to_spn', service1_opts) + service1_opts['delegation_to_spn'] = service2_creds.get_spn() + + service1_creds = self.get_cached_creds(machine_account=True, + opts=service1_opts) + + client_tkt_options = kdc_dict.pop('client_tkt_options', 'forwardable') + expected_flags = krb5_asn1.TicketFlags(client_tkt_options) + + client_tgt = self.get_tgt(client_creds, + kdc_options=client_tkt_options, + expected_flags=expected_flags) + client_service_tkt = self.get_service_ticket( + client_tgt, + service1_creds, + kdc_options=client_tkt_options, + expected_flags=expected_flags) + + service1_tgt = self.get_tgt(service1_creds) + + modify_client_tkt_fn = kdc_dict.pop('modify_client_tkt_fn', None) + if modify_client_tkt_fn is not None: + client_service_tkt = modify_client_tkt_fn(client_service_tkt) + + additional_tickets = [client_service_tkt.ticket] + + modify_service_tgt_fn = kdc_dict.pop('modify_service_tgt_fn', None) + if modify_service_tgt_fn is not None: + service1_tgt = modify_service_tgt_fn(service1_tgt) + + kdc_options = kdc_dict.pop('kdc_options', None) + if kdc_options is None: + kdc_options = str(krb5_asn1.KDCOptions('cname-in-addl-tkt')) + + client_username = client_creds.get_username() + client_realm = client_creds.get_realm() + client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_username]) + + service1_name = service1_creds.get_username()[:-1] + service1_realm = service1_creds.get_realm() + + service2_name = service2_creds.get_username()[:-1] + service2_realm = service2_creds.get_realm() + service2_service = 'host' + service2_sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[service2_service, + service2_name]) + service2_decryption_key = self.TicketDecryptionKey_from_creds( + service2_creds) + service2_etypes = service2_creds.tgs_supported_enctypes + + expected_error_mode = kdc_dict.pop('expected_error_mode') + expected_status = kdc_dict.pop('expected_status', None) + if expected_error_mode: + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + + self.assertIsNone(expected_status) + + expect_edata = kdc_dict.pop('expect_edata', None) + if expect_edata is not None: + self.assertTrue(expected_error_mode) + + pac_options = kdc_dict.pop('pac_options', None) + + authenticator_subkey = self.RandomKey(Enctype.AES256) + + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) + + expected_proxy_target = service2_creds.get_spn() + + expected_transited_services = kdc_dict.pop( + 'expected_transited_services', []) + + transited_service = f'host/{service1_name}@{service1_realm}' + expected_transited_services.append(transited_service) + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=client_realm, + expected_cname=client_cname, + expected_srealm=service2_realm, + expected_sname=service2_sname, + expected_supported_etypes=service2_etypes, + ticket_decryption_key=service2_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, + expected_status=expected_status, + callback_dict={}, + tgt=service1_tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=kdc_options, + pac_options=pac_options, + expect_edata=expect_edata, + expected_proxy_target=expected_proxy_target, + expected_transited_services=expected_transited_services) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=service2_realm, + sname=service2_sname, + etypes=etypes, + additional_tickets=additional_tickets) + + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + + def test_constrained_delegation(self): + # Test constrained delegation. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True + }) + + def test_constrained_delegation_existing_delegation_info(self): + # Test constrained delegation with an existing S4U_DELEGATION_INFO + # structure in the PAC. + + services = ['service1', 'service2', 'service3'] + + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 'modify_client_tkt_fn': functools.partial( + self.add_delegation_info, services=services), + 'expected_transited_services': services + }) + + def test_constrained_delegation_not_allowed(self): + # Test constrained delegation when the delegating service does not + # allow it. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_delegation': False + }) + + def test_constrained_delegation_no_client_pac(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC. + self._run_delegation_test( + { + 'expected_error_mode': (KDC_ERR_BADOPTION, + KDC_ERR_MODIFIED), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False + }) + + def test_constrained_delegation_no_service_pac(self): + # Test constrained delegation when the service TGT does not contain a + # PAC. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 'modify_service_tgt_fn': self.remove_ticket_pac + }) + + def test_constrained_delegation_non_forwardable(self): + # Test constrained delegation with a non-forwardable ticket. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_ACCOUNT_RESTRICTION, + 'allow_delegation': True, + 'modify_client_tkt_fn': functools.partial( + self.set_ticket_forwardable, flag=False) + }) + + def test_constrained_delegation_pac_options_rbcd(self): + # Test constrained delegation, but with the RBCD bit set in the PAC + # options. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'pac_options': '0001', # supports RBCD + 'allow_delegation': True + }) + + def test_rbcd_existing_delegation_info(self): + # Test constrained delegation with an existing S4U_DELEGATION_INFO + # structure in the PAC. + + services = ['service1', 'service2', 'service3'] + + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': functools.partial( + self.add_delegation_info, services=services), + 'expected_transited_services': services + }) + + def test_rbcd_not_allowed(self): + # Test resource-based constrained delegation when the target service + # does not allow it. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_NOT_FOUND, + 'allow_rbcd': False, + 'pac_options': '0001' # supports RBCD + }) + + def test_rbcd_no_client_pac_a(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC, and an empty msDS-AllowedToDelegateTo attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': self.remove_ticket_pac + }) + + def test_rbcd_no_client_pac_b(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC, and a non-empty msDS-AllowedToDelegateTo attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': ntstatus.NT_STATUS_NO_MATCH, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'service1_opts': { + 'delegation_to_spn': ('host/test') + } + }) + + def test_rbcd_no_service_pac(self): + # Test constrained delegation when the service TGT does not contain a + # PAC. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': + ntstatus.NT_STATUS_NOT_FOUND, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': self.remove_ticket_pac + }) + + def test_rbcd_non_forwardable(self): + # Test resource-based constrained delegation with a non-forwardable + # ticket. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_ACCOUNT_RESTRICTION, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': functools.partial( + self.set_ticket_forwardable, flag=False) + }) + + def test_rbcd_no_pac_options_a(self): + # Test resource-based constrained delegation without the RBCD bit set + # in the PAC options, and an empty msDS-AllowedToDelegateTo attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '1' # does not support RBCD + }) + + def test_rbcd_no_pac_options_b(self): + # Test resource-based constrained delegation without the RBCD bit set + # in the PAC options, and a non-empty msDS-AllowedToDelegateTo + # attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': ntstatus.NT_STATUS_NO_MATCH, + 'allow_rbcd': True, + 'pac_options': '1', # does not support RBCD + 'service1_opts': { + 'delegation_to_spn': ('host/test') + } + }) + + def test_bronze_bit_constrained_delegation_old_checksum(self): + # Attempt to modify the ticket without updating the PAC checksums. + self._run_delegation_test( + { + 'expected_error_mode': (KDC_ERR_MODIFIED, + KDC_ERR_BAD_INTEGRITY), + 'allow_delegation': True, + 'client_tkt_options': '0', # non-forwardable ticket + 'modify_client_tkt_fn': functools.partial( + self.set_ticket_forwardable, + flag=True, update_pac_checksums=False), + 'expect_edata': False + }) + + def test_bronze_bit_rbcd_old_checksum(self): + # Attempt to modify the ticket without updating the PAC checksums. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'client_tkt_options': '0', # non-forwardable ticket + 'modify_client_tkt_fn': functools.partial( + self.set_ticket_forwardable, + flag=True, update_pac_checksums=False) + }) + + def test_constrained_delegation_missing_client_checksum(self): + # Present a user ticket without the required checksums. + 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) + else: + expected_error_mode = KDC_ERR_GENERIC + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'allow_delegation': True, + 'modify_client_tkt_fn': functools.partial( + self.remove_pac_checksum, checksum=checksum), + 'expect_edata': False + }) + + def test_constrained_delegation_missing_service_checksum(self): + # Present the service's ticket without the required checksums. + for checksum in filter(lambda x: x != krb5pac.PAC_TYPE_TICKET_CHECKSUM, + self.pac_checksum_types): + with self.subTest(checksum=checksum): + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_GENERIC, + 'expected_status': + ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES, + 'allow_delegation': True, + 'modify_service_tgt_fn': functools.partial( + self.remove_pac_checksum, checksum=checksum) + }) + + def test_rbcd_missing_client_checksum(self): + # Present a user ticket without the required checksums. + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + if checksum == krb5pac.PAC_TYPE_TICKET_CHECKSUM: + expected_error_mode = KDC_ERR_MODIFIED + else: + expected_error_mode = KDC_ERR_GENERIC + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': + ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': functools.partial( + self.remove_pac_checksum, checksum=checksum) + }) + + def test_rbcd_missing_service_checksum(self): + # Present the service's ticket without the required checksums. + for checksum in filter(lambda x: x != krb5pac.PAC_TYPE_TICKET_CHECKSUM, + self.pac_checksum_types): + with self.subTest(checksum=checksum): + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_GENERIC, + 'expected_status': + ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': functools.partial( + self.remove_pac_checksum, checksum=checksum) + }) + + def test_constrained_delegation_zeroed_client_checksum(self): + # Present a user ticket with invalid checksums. + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + self._run_delegation_test( + { + 'expected_error_mode': (KDC_ERR_MODIFIED, + KDC_ERR_BAD_INTEGRITY), + 'allow_delegation': True, + 'modify_client_tkt_fn': functools.partial( + self.zeroed_pac_checksum, checksum=checksum), + 'expect_edata': False + }) + + def test_constrained_delegation_zeroed_service_checksum(self): + # Present the service's ticket with invalid checksums. + 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_status = ntstatus.NT_STATUS_WRONG_PASSWORD + else: + expected_error_mode = 0 + expected_status = None + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, + 'allow_delegation': True, + 'modify_service_tgt_fn': functools.partial( + self.zeroed_pac_checksum, checksum=checksum) + }) + + def test_rbcd_zeroed_client_checksum(self): + # Present a user ticket with invalid checksums. + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': + ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': functools.partial( + self.zeroed_pac_checksum, checksum=checksum) + }) + + def test_rbcd_zeroed_service_checksum(self): + # Present the service's ticket with invalid checksums. + 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_status = ntstatus.NT_STATUS_WRONG_PASSWORD + else: + expected_error_mode = 0 + expected_status = None + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': functools.partial( + self.zeroed_pac_checksum, checksum=checksum) + }) + + unkeyed_ctypes = {Cksumtype.MD5, Cksumtype.SHA1, Cksumtype.CRC32} + + def test_constrained_delegation_unkeyed_client_checksum(self): + # Present a user ticket with invalid checksums. + for checksum in self.pac_checksum_types: + for ctype in self.unkeyed_ctypes: + with self.subTest(checksum=checksum, ctype=ctype): + if (checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM + and ctype == Cksumtype.SHA1): + expected_error_mode = (KDC_ERR_SUMTYPE_NOSUPP, + KDC_ERR_INAPP_CKSUM) + else: + expected_error_mode = (KDC_ERR_GENERIC, + KDC_ERR_INAPP_CKSUM) + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'allow_delegation': True, + 'modify_client_tkt_fn': functools.partial( + self.unkeyed_pac_checksum, + checksum=checksum, ctype=ctype), + 'expect_edata': False + }) + + def test_constrained_delegation_unkeyed_service_checksum(self): + # Present the service's ticket with invalid checksums. + for checksum in self.pac_checksum_types: + for ctype in self.unkeyed_ctypes: + 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_INAPP_CKSUM) + expected_status = ntstatus.NT_STATUS_LOGON_FAILURE + else: + expected_error_mode = (KDC_ERR_GENERIC, + KDC_ERR_INAPP_CKSUM) + expected_status = ( + ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES) + else: + expected_error_mode = 0 + expected_status = None + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, + 'allow_delegation': True, + 'modify_service_tgt_fn': functools.partial( + self.unkeyed_pac_checksum, + checksum=checksum, ctype=ctype) + }) + + def test_rbcd_unkeyed_client_checksum(self): + # Present a user ticket with invalid checksums. + for checksum in self.pac_checksum_types: + for ctype in self.unkeyed_ctypes: + with self.subTest(checksum=checksum, ctype=ctype): + if (checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM + and ctype == Cksumtype.SHA1): + expected_error_mode = KDC_ERR_SUMTYPE_NOSUPP + else: + expected_error_mode = KDC_ERR_GENERIC + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': + ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': functools.partial( + self.unkeyed_pac_checksum, + checksum=checksum, ctype=ctype) + }) + + def test_rbcd_unkeyed_service_checksum(self): + # Present the service's ticket with invalid checksums. + for checksum in self.pac_checksum_types: + for ctype in self.unkeyed_ctypes: + 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_status = ntstatus.NT_STATUS_LOGON_FAILURE + else: + expected_error_mode = KDC_ERR_GENERIC + expected_status = ( + ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES) + else: + expected_error_mode = 0 + expected_status = None + + self._run_delegation_test( + { + 'expected_error_mode': expected_error_mode, + 'expected_status': expected_status, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': functools.partial( + self.unkeyed_pac_checksum, + checksum=checksum, ctype=ctype) + }) + + def remove_pac_checksum(self, ticket, checksum): + checksum_keys = self.get_krbtgt_checksum_key() + + return self.modified_ticket(ticket, + checksum_keys=checksum_keys, + include_checksums={checksum: False}) + + def zeroed_pac_checksum(self, ticket, checksum): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + server_key = ticket.decryption_key + + checksum_keys = { + krb5pac.PAC_TYPE_SRV_CHECKSUM: server_key, + krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, + krb5pac.PAC_TYPE_TICKET_CHECKSUM: krbtgt_key, + } + + if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM: + zeroed_key = server_key + else: + zeroed_key = krbtgt_key + + checksum_keys[checksum] = ZeroedChecksumKey(zeroed_key.key, + zeroed_key.kvno) + + return self.modified_ticket(ticket, + checksum_keys=checksum_keys, + include_checksums={checksum: True}) + + def unkeyed_pac_checksum(self, ticket, checksum, ctype): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + server_key = ticket.decryption_key + + checksum_keys = { + krb5pac.PAC_TYPE_SRV_CHECKSUM: server_key, + krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, + krb5pac.PAC_TYPE_TICKET_CHECKSUM: krbtgt_key, + } + + # Make a copy of the existing key and change the ctype. + key = checksum_keys[checksum] + new_key = RodcPacEncryptionKey(key.key, key.kvno) + new_key.ctype = ctype + checksum_keys[checksum] = new_key + + return self.modified_ticket(ticket, + checksum_keys=checksum_keys, + include_checksums={checksum: True}) + + def add_delegation_info(self, ticket, services=None): + def modify_pac_fn(pac): + pac_buffers = pac.buffers + self.assertNotIn(krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION, + (buffer.type for buffer in pac_buffers)) + + transited_services = list(map(lsa.String, services)) + + delegation = krb5pac.PAC_CONSTRAINED_DELEGATION() + delegation.proxy_target = lsa.String('test_proxy_target') + delegation.transited_services = transited_services + delegation.num_transited_services = len(transited_services) + + info = krb5pac.PAC_CONSTRAINED_DELEGATION_CTR() + info.info = delegation + + pac_buffer = krb5pac.PAC_BUFFER() + pac_buffer.type = krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION + pac_buffer.info = info + + pac_buffers.append(pac_buffer) + + pac.buffers = pac_buffers + pac.num_buffers += 1 + + return pac + + checksum_keys = self.get_krbtgt_checksum_key() + + return self.modified_ticket(ticket, + checksum_keys=checksum_keys, + 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 + + if update_pac_checksums: + checksum_keys = self.get_krbtgt_checksum_key() + else: + checksum_keys = None + + return self.modified_ticket(ticket, + modify_fn=modify_fn, + checksum_keys=checksum_keys, + update_pac_checksums=update_pac_checksums) + + def remove_ticket_pac(self, ticket): + return self.modified_ticket(ticket, + exclude_pac=True) + if __name__ == "__main__": global_asn1_print = False diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 29990ec9511..e1711b532d7 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -102,6 +102,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py', 'python/samba/tests/krb5/as_req_tests.py', 'python/samba/tests/krb5/fast_tests.py', + 'python/samba/tests/krb5/rodc_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 6eb667f8969..0b8e83f1f3f 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -125,3 +125,32 @@ # Heimdal currently does not generate ticket signatures # ^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_heimdal_ticket_signature +# +# 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_missing_client_checksum +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_client_checksum +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_service_checksum +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_zeroed_client_checksum +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_zeroed_service_checksum +^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_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_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_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 +# +# RODC tests +# +^samba.tests.krb5.rodc_tests.samba.tests.krb5.rodc_tests.RodcKerberosTests.test_rodc_ticket_signature diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 2fa725e837c..1f8554155bf 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -750,9 +750,16 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support}) planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", - environ={'SERVICE_USERNAME':'srv_account', - 'SERVICE_PASSWORD':'$PASSWORD', + environ={'ADMIN_USERNAME':'$USERNAME', + 'ADMIN_PASSWORD':'$PASSWORD', 'FOR_USER':'$USERNAME', + 'STRICT_CHECKING':'0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support}) +planoldpythontestsuite("rodc:local", "samba.tests.krb5.rodc_tests", + environ={'ADMIN_USERNAME':'$USERNAME', + 'ADMIN_PASSWORD':'$PASSWORD', + 'STRICT_CHECKING':'0', 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support}) -- 2.25.1 From a29f0ec3eb891dde69a19727a3c0e3fea900d1e4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 29 Sep 2021 12:07:40 +1300 Subject: [PATCH 339/645] tests/krb5: Don't include empty AD-IF-RELEVANT BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 1a08399cd8169a525cc9e7aed99da84ef20e5b9c) --- python/samba/tests/krb5/raw_testcase.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 2e289c90ce7..e008223eb23 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3424,14 +3424,19 @@ class RawKerberosTest(TestCaseInTempDir): if expect_pac: self.assertIsNotNone(old_pac, 'Expected PAC') - ad_relevant = self.der_encode( - relevant_elems, - asn1Spec=krb5_asn1.AD_IF_RELEVANT()) - - authdata_elem = self.AuthorizationData_create(AD_IF_RELEVANT, - ad_relevant) + if relevant_elems: + ad_relevant = self.der_encode( + relevant_elems, + asn1Spec=krb5_asn1.AD_IF_RELEVANT()) + + authdata_elem = self.AuthorizationData_create( + AD_IF_RELEVANT, + ad_relevant) + else: + authdata_elem = None - new_auth_data.append(authdata_elem) + if authdata_elem is not None: + new_auth_data.append(authdata_elem) if expect_pac: self.assertIsNotNone(ad_relevant, 'Expected AD-RELEVANT') -- 2.25.1 From 56038c91e0a6d04240c55bb24179258e769adf8d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:41:35 +1300 Subject: [PATCH 340/645] tests/krb5: Allow bypassing cache when creating accounts BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 3948701f1d0f3ccd06f6dad56ca72833d66b1d84) --- python/samba/tests/krb5/kdc_base_test.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 8a5e12bbed4..87160f675ae 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -610,7 +610,8 @@ class KDCBaseTest(RawKerberosTest): def get_cached_creds(self, *, machine_account, - opts=None): + opts=None, + use_cache=True): if opts is None: opts = {} @@ -638,9 +639,13 @@ class KDCBaseTest(RawKerberosTest): cache_key = tuple(sorted(account_opts.items())) - creds = self.account_cache.get(cache_key) - if creds is None: - creds = self.create_account_opts(**account_opts) + if use_cache: + creds = self.account_cache.get(cache_key) + if creds is not None: + return creds + + creds = self.create_account_opts(**account_opts) + if use_cache: self.account_cache[cache_key] = creds return creds -- 2.25.1 From 1bf1dbecf6c52222c7ccba39bd71be2fcd19649a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:40:39 +1300 Subject: [PATCH 341/645] tests/krb5: Fix duplicate account creation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 3dede18c5a1801023a60cc55b99022b033428350) --- .../krb5/ms_kile_client_principal_lookup_tests.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 501bc4892f4..2ee3d4a2a83 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -150,18 +150,15 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # Create a machine account for the test. # samdb = self.get_samdb() - user_name = "mskilemac" - (mc, dn) = self.create_account(samdb, user_name, machine_account=True) - realm = mc.get_realm().lower() - mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, dn) = self.create_account(samdb, mach_name, machine_account=True) + realm = mc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required # response etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) cname = self.PrincipalName_create( - name_type=NT_PRINCIPAL, names=[user_name]) + name_type=NT_PRINCIPAL, names=[mach_name]) sname = self.PrincipalName_create( name_type=NT_SRV_INST, names=["krbtgt", realm]) @@ -180,7 +177,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): key = self.EncryptionKey_import(enc_part2['key']) cname = self.PrincipalName_create( name_type=NT_PRINCIPAL, - names=[user_name]) + names=[mach_name]) sname = self.PrincipalName_create( name_type=NT_PRINCIPAL, names=[mc.get_username()]) @@ -197,7 +194,7 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # check the crealm and cname cname = enc_part['cname'] self.assertEqual(NT_PRINCIPAL, cname['name-type']) - self.assertEqual(user_name.encode('UTF8'), cname['name-string'][0]) + self.assertEqual(mach_name.encode('UTF8'), cname['name-string'][0]) self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) def test_nt_principal_step_3(self): -- 2.25.1 From d717239fc6ec70488f01d2839b5afc573ae30c26 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 16:06:58 +1300 Subject: [PATCH 342/645] s4:kdc: Simplify samba_kdc_update_pac_blob() to take ldb_context as parameter BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 7149eeaceb426470b1b8181749d2d081c2fb83a4) --- source4/kdc/mit_samba.c | 7 +------ source4/kdc/pac-glue.c | 5 ++--- source4/kdc/pac-glue.h | 3 +-- source4/kdc/wdc-samba4.c | 2 +- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 54dcd545ea1..2936fe2d18a 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -482,7 +482,6 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, DATA_BLOB *deleg_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; bool is_in_db = false; bool is_untrusted = false; size_t num_types = 0; @@ -513,9 +512,6 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, if (server == NULL) { return EINVAL; } - server_skdc_entry = - talloc_get_type_abort(server->e_data, - struct samba_kdc_entry); if (krbtgt == NULL) { return EINVAL; @@ -575,8 +571,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, nt_status = samba_kdc_update_pac_blob(tmp_ctx, context, - krbtgt_skdc_entry, - server_skdc_entry, + krbtgt_skdc_entry->kdc_db_ctx->samdb, *pac, pac_blob, pac_srv_sig, diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 04fbc5cf487..88bcb734fc5 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -747,8 +747,7 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, - struct samba_kdc_entry *krbtgt, - struct samba_kdc_entry *server, + struct ldb_context *samdb, const krb5_pac pac, DATA_BLOB *pac_blob, struct PAC_SIGNATURE_DATA *pac_srv_sig, struct PAC_SIGNATURE_DATA *pac_kdc_sig) @@ -768,7 +767,7 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, * as the token might be generated by a trusted domain. */ nt_status = authsam_update_user_info_dc(mem_ctx, - krbtgt->kdc_db_ctx->samdb, + samdb, user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 2eb7fd3b755..7b51b0389f5 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -51,8 +51,7 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, - struct samba_kdc_entry *krbtgt, - struct samba_kdc_entry *server, + struct ldb_context *samdb, const krb5_pac pac, DATA_BLOB *pac_blob, struct PAC_SIGNATURE_DATA *pac_srv_sig, struct PAC_SIGNATURE_DATA *pac_kdc_sig); diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index a7d8de1f417..68c8a8aa572 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -186,7 +186,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, } nt_status = samba_kdc_update_pac_blob(mem_ctx, context, - krbtgt_skdc_entry, p, + krbtgt_skdc_entry->kdc_db_ctx->samdb, *pac, pac_blob, pac_srv_sig, pac_kdc_sig); if (!NT_STATUS_IS_OK(nt_status)) { -- 2.25.1 From d354015ccb3a1c3982b299b8b5d973071253c088 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 6 Oct 2021 16:40:21 +1300 Subject: [PATCH 343/645] s4:kdc: Fix debugging messages BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit c14c61748b5a2d2a4f4de00615c476fcf381309e) --- source4/kdc/wdc-samba4.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index 68c8a8aa572..037db40ce46 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -238,10 +238,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, switch (types[i]) { case PAC_TYPE_LOGON_INFO: if (logon_info_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("logon info type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + logon_info_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; @@ -250,10 +250,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, break; case PAC_TYPE_CONSTRAINED_DELEGATION: if (delegation_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("constrained delegation type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + delegation_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; @@ -262,10 +262,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, break; case PAC_TYPE_LOGON_NAME: if (logon_name_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("logon name type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + logon_name_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; @@ -274,10 +274,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, break; case PAC_TYPE_UPN_DNS_INFO: if (upn_dns_info_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("upn dns info type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + upn_dns_info_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; @@ -286,10 +286,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, break; case PAC_TYPE_SRV_CHECKSUM: if (srv_checksum_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("server checksum type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + srv_checksum_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; @@ -298,10 +298,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, break; case PAC_TYPE_KDC_CHECKSUM: if (kdc_checksum_idx != -1) { - DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n", - (int)types[i], - (int)logon_info_idx, - (int)i)); + DEBUG(1, ("kdc checksum type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + kdc_checksum_idx, + i)); SAFE_FREE(types); talloc_free(mem_ctx); return EINVAL; -- 2.25.1 From 9d622a07c77f4ce402f9c3ac3118d6a130cb529a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:42:29 +1300 Subject: [PATCH 344/645] s4/torture: Expect ticket checksum PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit d5002c34ce1ffef795dc83af3175ca0e04d17dfd due to missing tests in Samba 4.14 that crashed the MIT KDC] --- selftest/knownfail_heimdal_kdc | 41 ++++++++++++++++++++++++++++++++ selftest/knownfail_mit_kdc | 41 ++++++++++++++++++++++++++++++++ source4/torture/rpc/remote_pac.c | 14 +++++++++-- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 0b8e83f1f3f..31572067ad4 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -154,3 +154,44 @@ # RODC tests # ^samba.tests.krb5.rodc_tests.samba.tests.krb5.rodc_tests.RodcKerberosTests.test_rodc_ticket_signature +# +# PAC tests +# +^netr-bdc-arcfour.verify-sig-arcfour +^netr-bdc-arcfour.verify-sig-arcfour +^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 a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 4e0b20c5c80..09efbc7b590 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -329,3 +329,44 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc +# +# PAC tests +# +^netr-bdc-arcfour.verify-sig-arcfour +^netr-bdc-arcfour.verify-sig-arcfour +^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 a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index c74746123fe..14c23f674f1 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/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 = 4; + num_pac_buffers = 5; if (expect_pac_upn_dns_info) { num_pac_buffers += 1; } @@ -317,6 +317,12 @@ static bool test_PACVerify(struct torture_context *tctx, pac_buf->info != NULL, "PAC_TYPE_KDC_CHECKSUM info"); + pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_TICKET_CHECKSUM); + torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_TICKET_CHECKSUM"); + torture_assert(tctx, + pac_buf->info != NULL, + "PAC_TYPE_TICKET_CHECKSUM info"); + ok = netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name, negotiate_flags, pac_data, session_info); @@ -1076,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 = 6; + 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"); @@ -1101,6 +1107,10 @@ static bool test_S4U2Proxy(struct torture_context *tctx, torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_KDC_CHECKSUM"); torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_KDC_CHECKSUM info"); + pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_TICKET_CHECKSUM); + torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_TICKET_CHECKSUM"); + torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_TICKET_CHECKSUM info"); + pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_CONSTRAINED_DELEGATION); torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_CONSTRAINED_DELEGATION"); torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_CONSTRAINED_DELEGATION info"); -- 2.25.1 From fcb21e818cdd214b07c4ac81a473f9b75657b554 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 28 Dec 2020 22:07:10 +0200 Subject: [PATCH 345/645] kdc: remove KRB5SignedPath, to be replaced with PAC KRB5SignedPath was a Heimdal-specific authorization data element used to protect the authenticity of evidence tickets when used in constrained delegation (without a Windows PAC). Remove this, to be replaced with the Windows PAC which itself now supports signing the entire ticket in the TGS key. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Backported from Heimdal commit bb1d8f2a8c2545bccdf2c9179ce9259bf1050086 - Removed tests - Removed auditing hook (only present in Heimdal master) - Added knownfails ] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit ccabc7f16cca5b0dcb46233e934e708167f1071b) --- selftest/knownfail_heimdal_kdc | 6 + source4/heimdal/kdc/kerberos5.c | 12 -- source4/heimdal/kdc/krb5tgs.c | 297 ----------------------------- source4/heimdal/lib/asn1/krb5.asn1 | 21 -- 4 files changed, 6 insertions(+), 330 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 31572067ad4..f0263133eee 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -130,6 +130,7 @@ # ^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_missing_client_checksum +^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_unkeyed_client_checksum ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_service_checksum ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_zeroed_client_checksum @@ -195,3 +196,8 @@ ^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 +# +# The lack of KRB5SignedPath means we no longer return +# KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case +# +^samba4.krb5.kdc with machine account.as-req-pac-request.fl2000dc:local diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 0fa336e871c..a400b21a652 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -1744,18 +1744,6 @@ _kdc_as_rep(krb5_context context, _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, et.endtime, et.renew_till); - /* do this as the last thing since this signs the EncTicketPart */ - ret = _kdc_add_KRB5SignedPath(context, - config, - server, - setype, - client->entry.principal, - NULL, - NULL, - &et); - if (ret) - goto out; - log_as_req(context, config, reply_key->keytype, setype, b); ret = _kdc_encode_reply(context, config, diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ef337ea4faf..fcdebede3a9 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -47,230 +47,6 @@ get_krbtgt_realm(const PrincipalName *p) return NULL; } -/* - * The KDC might add a signed path to the ticket authorization data - * field. This is to avoid server impersonating clients and the - * request constrained delegation. - * - * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single - * entry of type KRB5SignedPath. - */ - -static krb5_error_code -find_KRB5SignedPath(krb5_context context, - const AuthorizationData *ad, - krb5_data *data) -{ - AuthorizationData child; - krb5_error_code ret; - int pos; - - if (ad == NULL || ad->len == 0) - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - - pos = ad->len - 1; - - if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT) - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - - ret = decode_AuthorizationData(ad->val[pos].ad_data.data, - ad->val[pos].ad_data.length, - &child, - NULL); - if (ret) { - krb5_set_error_message(context, ret, "Failed to decode " - "IF_RELEVANT with %d", ret); - return ret; - } - - if (child.len != 1) { - free_AuthorizationData(&child); - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - } - - if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) { - free_AuthorizationData(&child); - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - } - - if (data) - ret = der_copy_octet_string(&child.val[0].ad_data, data); - free_AuthorizationData(&child); - return ret; -} - -krb5_error_code -_kdc_add_KRB5SignedPath(krb5_context context, - krb5_kdc_configuration *config, - hdb_entry_ex *krbtgt, - krb5_enctype enctype, - krb5_principal client, - krb5_const_principal server, - krb5_principals principals, - EncTicketPart *tkt) -{ - krb5_error_code ret; - KRB5SignedPath sp; - krb5_data data; - krb5_crypto crypto = NULL; - size_t size = 0; - - if (server && principals) { - ret = add_Principals(principals, server); - if (ret) - return ret; - } - - { - KRB5SignedPathData spd; - - spd.client = client; - spd.authtime = tkt->authtime; - spd.delegated = principals; - spd.method_data = NULL; - - ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, - &spd, &size, ret); - if (ret) - return ret; - if (data.length != size) - krb5_abortx(context, "internal asn.1 encoder error"); - } - - { - Key *key; - ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key); - if (ret == 0) - ret = krb5_crypto_init(context, &key->key, 0, &crypto); - if (ret) { - free(data.data); - return ret; - } - } - - /* - * Fill in KRB5SignedPath - */ - - sp.etype = enctype; - sp.delegated = principals; - sp.method_data = NULL; - - ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0, - data.data, data.length, &sp.cksum); - krb5_crypto_destroy(context, crypto); - free(data.data); - if (ret) - return ret; - - ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret); - free_Checksum(&sp.cksum); - if (ret) - return ret; - if (data.length != size) - krb5_abortx(context, "internal asn.1 encoder error"); - - - /* - * Add IF-RELEVANT(KRB5SignedPath) to the last slot in - * authorization data field. - */ - - ret = _kdc_tkt_add_if_relevant_ad(context, tkt, - KRB5_AUTHDATA_SIGNTICKET, &data); - krb5_data_free(&data); - - return ret; -} - -static krb5_error_code -check_KRB5SignedPath(krb5_context context, - krb5_kdc_configuration *config, - hdb_entry_ex *krbtgt, - krb5_principal cp, - EncTicketPart *tkt, - krb5_principals *delegated, - int *signedpath) -{ - krb5_error_code ret; - krb5_data data; - krb5_crypto crypto = NULL; - - if (delegated) - *delegated = NULL; - - ret = find_KRB5SignedPath(context, tkt->authorization_data, &data); - if (ret == 0) { - KRB5SignedPathData spd; - KRB5SignedPath sp; - size_t size = 0; - - ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL); - krb5_data_free(&data); - if (ret) - return ret; - - spd.client = cp; - spd.authtime = tkt->authtime; - spd.delegated = sp.delegated; - spd.method_data = sp.method_data; - - ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, - &spd, &size, ret); - if (ret) { - free_KRB5SignedPath(&sp); - return ret; - } - if (data.length != size) - krb5_abortx(context, "internal asn.1 encoder error"); - - { - Key *key; - ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key); - if (ret == 0) - ret = krb5_crypto_init(context, &key->key, 0, &crypto); - if (ret) { - free(data.data); - free_KRB5SignedPath(&sp); - return ret; - } - } - ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, - data.data, data.length, - &sp.cksum); - krb5_crypto_destroy(context, crypto); - free(data.data); - if (ret) { - free_KRB5SignedPath(&sp); - kdc_log(context, config, 5, - "KRB5SignedPath not signed correctly, not marking as signed"); - return 0; - } - - if (delegated && sp.delegated) { - - *delegated = malloc(sizeof(*sp.delegated)); - if (*delegated == NULL) { - free_KRB5SignedPath(&sp); - return ENOMEM; - } - - ret = copy_Principals(*delegated, sp.delegated); - if (ret) { - free_KRB5SignedPath(&sp); - free(*delegated); - *delegated = NULL; - return ret; - } - } - free_KRB5SignedPath(&sp); - - *signedpath = 1; - } - - return 0; -} - /* * */ @@ -738,7 +514,6 @@ tgs_make_reply(krb5_context context, krb5_principal client_principal, hdb_entry_ex *krbtgt, krb5_enctype krbtgt_etype, - krb5_principals spp, const krb5_data *rspac, const METHOD_DATA *enc_pa_data, const char **e_text, @@ -903,20 +678,6 @@ tgs_make_reply(krb5_context context, goto out; } } - - /* Filter out type KRB5SignedPath */ - ret = find_KRB5SignedPath(context, et.authorization_data, NULL); - if (ret == 0) { - if (et.authorization_data->len == 1) { - free_AuthorizationData(et.authorization_data); - free(et.authorization_data); - et.authorization_data = NULL; - } else { - AuthorizationData *ad = et.authorization_data; - free_AuthorizationDataElement(&ad->val[ad->len - 1]); - ad->len--; - } - } } ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key); @@ -945,24 +706,6 @@ tgs_make_reply(krb5_context context, _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, et.endtime, et.renew_till); - /* Don't sign cross realm tickets, they can't be checked anyway */ - { - char *r = get_krbtgt_realm(&ek.sname); - - if (r == NULL || strcmp(r, ek.srealm) == 0) { - ret = _kdc_add_KRB5SignedPath(context, - config, - krbtgt, - krbtgt_etype, - client_principal, - NULL, - spp, - &et); - if (ret) - goto out; - } - } - if (enc_pa_data->len) { rep.padata = calloc(1, sizeof(*rep.padata)); if (rep.padata == NULL) { @@ -1517,7 +1260,6 @@ tgs_build_reply(krb5_context context, HDB *clientdb, *s4u2self_impersonated_clientdb; krb5_realm ref_realm = NULL; EncTicketPart *tgt = &ticket->ticket; - krb5_principals spp = NULL; const EncryptionKey *ekey; krb5_keyblock sessionkey; krb5_kvno kvno; @@ -1891,23 +1633,6 @@ server_lookup: goto out; } - /* also check the krbtgt for signature */ - ret = check_KRB5SignedPath(context, - config, - krbtgt, - cp, - tgt, - &spp, - &signedpath); - if (ret) { - const char *msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 0, - "KRB5SignedPath check failed for %s (%s) from %s with %s", - spn, cpn, from, msg); - krb5_free_error_message(context, msg); - goto out; - } - /* * Process request */ @@ -2183,27 +1908,6 @@ server_lookup: goto out; } - /* - * Check that the KDC issued the user's ticket. - */ - ret = check_KRB5SignedPath(context, - config, - krbtgt, - cp, - &adtkt, - NULL, - &ad_signedpath); - if (ret) { - const char *msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 0, - "KRB5SignedPath check from service %s failed " - "for delegation to %s for client %s (%s)" - "from %s failed with %s", - spn, tpn, dpn, cpn, from, msg); - krb5_free_error_message(context, msg); - goto out; - } - if (!ad_signedpath) { ret = KRB5KDC_ERR_BADOPTION; kdc_log(context, config, 0, @@ -2301,7 +2005,6 @@ server_lookup: cp, krbtgt_out, krbtgt_etype, - spp, &rspac, &enc_pa_data, e_text, diff --git a/source4/heimdal/lib/asn1/krb5.asn1 b/source4/heimdal/lib/asn1/krb5.asn1 index c2f40c0ecd6..155d51d4ac8 100644 --- a/source4/heimdal/lib/asn1/krb5.asn1 +++ b/source4/heimdal/lib/asn1/krb5.asn1 @@ -43,9 +43,6 @@ EXPORTS KRB-PRIV, KRB-SAFE, KRB-SAFE-BODY, - KRB5SignedPath, - KRB5SignedPathData, - KRB5SignedPathPrincipals, KerberosString, KerberosTime, KrbCredInfo, @@ -713,24 +710,6 @@ PA-S4U2Self ::= SEQUENCE { auth[3] GeneralString } --- never encoded on the wire, just used to checksum over -KRB5SignedPathData ::= SEQUENCE { - client[0] Principal OPTIONAL, - authtime[1] KerberosTime, - delegated[2] Principals OPTIONAL, - method_data[3] METHOD-DATA OPTIONAL -} - -KRB5SignedPath ::= SEQUENCE { - -- DERcoded KRB5SignedPathData - -- krbtgt key (etype), KeyUsage = XXX - etype[0] ENCTYPE, - cksum[1] Checksum, - -- srvs delegated though - delegated[2] Principals OPTIONAL, - method_data[3] METHOD-DATA OPTIONAL -} - AD-LoginAlias ::= SEQUENCE { -- ad-type number TBD -- login-alias [0] PrincipalName, checksum [1] Checksum -- 2.25.1 From 989131b928431f19061b2a26ac68261e37a3700a Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Fri, 13 Aug 2021 12:44:37 +0300 Subject: [PATCH 346/645] kdc: sign ticket using Windows PAC Split Windows PAC signing and verification logic, as the signing has to be when the ticket is ready. Create sign and verify the PAC KDC signature if the plugin did not, allowing for S4U2Proxy to work, instead of KRB5SignedPath. Use the header key to verify PAC server signature, as the same key used to encrypt/decrypt the ticket should be used for PAC server signature, like U2U tickets are signed witht the tgt session-key and not with the longterm key, and so krbtgt should be no different and the header key should be used. Lookup the delegated client in DB instead of passing the delegator DB entry. Add PAC ticket-signatures and related functions. Note: due to the change from KRB5SignedPath to PAC, S4U2Proxy requests against new KDC will not work if the evidence ticket was acquired from an old KDC, and vide versa. Closes: #767 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Backported from Heimdal commit 2ffaba9401d19c718764d4bd24180960290238e9 - Removed tests - Adapted to Samba's version of Heimdal - Addressed build failures with -O3 - Added knownfails ] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org backported from commit d7b03394a9012960d71489e775d40d10fd6f5232 due to conflicts in knownfail due to missing tests that crash the MIT KDC] --- selftest/knownfail_heimdal_kdc | 54 +-- source4/heimdal/kdc/kerberos5.c | 69 +--- source4/heimdal/kdc/krb5tgs.c | 354 +++++++++--------- source4/heimdal/kdc/windc.c | 15 +- source4/heimdal/kdc/windc_plugin.h | 5 +- source4/heimdal/lib/krb5/authdata.c | 124 +++++++ source4/heimdal/lib/krb5/pac.c | 376 ++++++++++++++++++-- source4/heimdal/lib/krb5/version-script.map | 5 + source4/heimdal_build/wscript_build | 2 +- source4/selftest/tests.py | 2 +- 10 files changed, 687 insertions(+), 319 deletions(-) create mode 100644 source4/heimdal/lib/krb5/authdata.c diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index f0263133eee..4ec682c01d0 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -1,7 +1,7 @@ # # We expect all the MIT specific compatability tests to fail on heimdal # kerberos -^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_(?!ticket_signature) +^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_ # # Heimdal currently fails the following MS-KILE client principal lookup # tests @@ -122,14 +122,9 @@ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc # -# Heimdal currently does not generate ticket signatures -# -^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_heimdal_ticket_signature -# # 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_missing_client_checksum ^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_unkeyed_client_checksum ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_service_checksum @@ -143,60 +138,13 @@ ^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_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 # # RODC tests # ^samba.tests.krb5.rodc_tests.samba.tests.krb5.rodc_tests.RodcKerberosTests.test_rodc_ticket_signature # -# PAC tests -# -^netr-bdc-arcfour.verify-sig-arcfour -^netr-bdc-arcfour.verify-sig-arcfour -^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 -# # The lack of KRB5SignedPath means we no longer return # KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case # diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index a400b21a652..7b17d2539ce 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -1712,6 +1712,7 @@ _kdc_as_rep(krb5_context context, if (send_pac_p(context, req)) { krb5_pac p = NULL; krb5_data data; + uint16_t rodc_id; ret = _kdc_pac_generate(context, client, pk_reply_key, &p); if (ret) { @@ -1720,10 +1721,13 @@ _kdc_as_rep(krb5_context context, goto out; } if (p != NULL) { + rodc_id = server->entry.kvno >> 16; + ret = _krb5_pac_sign(context, p, et.authtime, client->entry.principal, &skey->key, /* Server key */ &skey->key, /* FIXME: should be krbtgt key */ + rodc_id, &data); krb5_pac_free(context, p); if (ret) { @@ -1732,9 +1736,7 @@ _kdc_as_rep(krb5_context context, goto out; } - ret = _kdc_tkt_add_if_relevant_ad(context, &et, - KRB5_AUTHDATA_WIN2K_PAC, - &data); + ret = _kdc_tkt_insert_pac(context, &et, &data); krb5_data_free(&data); if (ret) goto out; @@ -1888,64 +1890,3 @@ prepare_enc_data(krb5_context context, return TRUE; } - -/* - * Add the AuthorizationData `data´ of `type´ to the last element in - * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT - */ - -krb5_error_code -_kdc_tkt_add_if_relevant_ad(krb5_context context, - EncTicketPart *tkt, - int type, - const krb5_data *data) -{ - krb5_error_code ret; - size_t size = 0; - - if (tkt->authorization_data == NULL) { - tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); - if (tkt->authorization_data == NULL) { - krb5_set_error_message(context, ENOMEM, "out of memory"); - return ENOMEM; - } - } - - /* add the entry to the last element */ - { - AuthorizationData ad = { 0, NULL }; - AuthorizationDataElement ade; - - ade.ad_type = type; - ade.ad_data = *data; - - ret = add_AuthorizationData(&ad, &ade); - if (ret) { - krb5_set_error_message(context, ret, "add AuthorizationData failed"); - return ret; - } - - ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; - - ASN1_MALLOC_ENCODE(AuthorizationData, - ade.ad_data.data, ade.ad_data.length, - &ad, &size, ret); - free_AuthorizationData(&ad); - if (ret) { - krb5_set_error_message(context, ret, "ASN.1 encode of " - "AuthorizationData failed"); - return ret; - } - if (ade.ad_data.length != size) - krb5_abortx(context, "internal asn.1 encoder error"); - - ret = add_AuthorizationData(tkt->authorization_data, &ade); - der_free_octet_string(&ade.ad_data); - if (ret) { - krb5_set_error_message(context, ret, "add AuthorizationData failed"); - return ret; - } - } - - return 0; -} diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index fcdebede3a9..e8bbb42465f 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -59,85 +59,64 @@ check_PAC(krb5_context context, hdb_entry_ex *client, hdb_entry_ex *server, hdb_entry_ex *krbtgt, + hdb_entry_ex *ticket_server, const EncryptionKey *server_check_key, - const EncryptionKey *server_sign_key, - const EncryptionKey *krbtgt_sign_key, + const EncryptionKey *krbtgt_check_key, EncTicketPart *tkt, - krb5_data *rspac, - int *signedpath) + krb5_boolean *kdc_issued, + krb5_pac *ppac) { - AuthorizationData *ad = tkt->authorization_data; - unsigned i, j; + krb5_pac pac = NULL; krb5_error_code ret; + krb5_boolean signedticket; - if (ad == NULL || ad->len == 0) - return 0; - - for (i = 0; i < ad->len; i++) { - AuthorizationData child; - - if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT) - continue; - - ret = decode_AuthorizationData(ad->val[i].ad_data.data, - ad->val[i].ad_data.length, - &child, - NULL); - if (ret) { - krb5_set_error_message(context, ret, "Failed to decode " - "IF_RELEVANT with %d", ret); - return ret; - } - for (j = 0; j < child.len; j++) { - - if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) { - int signed_pac = 0; - krb5_pac pac; - - /* Found PAC */ - ret = krb5_pac_parse(context, - child.val[j].ad_data.data, - child.val[j].ad_data.length, - &pac); - free_AuthorizationData(&child); - if (ret) - return ret; + *kdc_issued = FALSE; + *ppac = NULL; - ret = krb5_pac_verify(context, pac, tkt->authtime, - client_principal, - server_check_key, NULL); - if (ret) { - krb5_pac_free(context, pac); - return ret; - } + ret = _krb5_kdc_pac_ticket_parse(context, tkt, &signedticket, &pac); + if (ret || pac == NULL) + return ret; - ret = _kdc_pac_verify(context, client_principal, - delegated_proxy_principal, - client, server, krbtgt, &pac, &signed_pac); - if (ret) { - krb5_pac_free(context, pac); - return ret; - } + /* Verify the server signature. */ + ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal, + server_check_key, NULL); + if (ret) { + krb5_pac_free(context, pac); + return ret; + } - /* - * Only re-sign PAC if we could verify it with the PAC - * function. The no-verify case happens when we get in - * a PAC from cross realm from a Windows domain and - * that there is no PAC verification function. - */ - if (signed_pac) { - *signedpath = 1; - ret = _krb5_pac_sign(context, pac, tkt->authtime, - client_principal, - server_sign_key, krbtgt_sign_key, rspac); - } + /* Verify the KDC signatures. */ + ret = _kdc_pac_verify(context, client_principal, delegated_proxy_principal, + client, server, krbtgt, &pac); + if (ret == KRB5_PLUGIN_NO_HANDLE) { + /* + * We can't verify the KDC signatures if the ticket was issued by + * another realm's KDC. + */ + if (krb5_realm_compare(context, server->entry.principal, + ticket_server->entry.principal)) { + ret = krb5_pac_verify(context, pac, 0, NULL, NULL, + krbtgt_check_key); + if (ret) { krb5_pac_free(context, pac); - return ret; } } - free_AuthorizationData(&child); + /* Discard the PAC if the plugin didn't handle it */ + krb5_pac_free(context, pac); + ret = krb5_pac_init(context, &pac); + if (ret) + return ret; + } else if (ret) { + krb5_pac_free(context, pac); + return ret; } + + *kdc_issued = signedticket || + krb5_principal_is_krbtgt(context, + ticket_server->entry.principal); + *ppac = pac; + return 0; } @@ -499,11 +478,12 @@ static krb5_error_code tgs_make_reply(krb5_context context, krb5_kdc_configuration *config, KDC_REQ_BODY *b, - krb5_const_principal tgt_name, + krb5_principal tgt_name, const EncTicketPart *tgt, const krb5_keyblock *replykey, int rk_is_subkey, const EncryptionKey *serverkey, + const EncryptionKey *krbtgtkey, const krb5_keyblock *sessionkey, krb5_kvno kvno, AuthorizationData *auth_data, @@ -513,8 +493,9 @@ tgs_make_reply(krb5_context context, hdb_entry_ex *client, krb5_principal client_principal, hdb_entry_ex *krbtgt, - krb5_enctype krbtgt_etype, - const krb5_data *rspac, + krb5_pac mspac, + uint16_t rodc_id, + krb5_boolean add_ticket_sig, const METHOD_DATA *enc_pa_data, const char **e_text, krb5_data *reply) @@ -647,17 +628,6 @@ tgs_make_reply(krb5_context context, if (!server->entry.flags.proxiable) et.flags.proxiable = 0; - if(rspac->length) { - /* - * No not need to filter out the any PAC from the - * auth_data since it's signed by the KDC. - */ - ret = _kdc_tkt_add_if_relevant_ad(context, &et, - KRB5_AUTHDATA_WIN2K_PAC, rspac); - if (ret) - goto out; - } - if (auth_data) { unsigned int i = 0; @@ -724,6 +694,11 @@ tgs_make_reply(krb5_context context, is_weak = 1; } + /* The PAC should be the last change to the ticket. */ + ret = _krb5_kdc_pac_sign_ticket(context, mspac, tgt_name, serverkey, + krbtgtkey, rodc_id, add_ticket_sig, &et); + if (ret) + goto out; /* It is somewhat unclear where the etype in the following encryption should come from. What we have is a session @@ -910,6 +885,7 @@ tgs_parse_request(krb5_context context, int **cusec, AuthorizationData **auth_data, krb5_keyblock **replykey, + Key **header_key, int *rk_is_subkey) { static char failed[] = ""; @@ -1047,6 +1023,8 @@ tgs_parse_request(krb5_context context, goto out; } + *header_key = tkey; + { krb5_authenticator auth; @@ -1236,6 +1214,57 @@ eout: return ENOMEM; } +static krb5_error_code +db_fetch_client(krb5_context context, + krb5_kdc_configuration *config, + int flags, + krb5_principal cp, + const char *cpn, + const char *krbtgt_realm, + HDB **clientdb, + hdb_entry_ex **client_out) +{ + krb5_error_code ret; + hdb_entry_ex *client = NULL; + + *client_out = NULL; + + ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags, + NULL, clientdb, &client); + if (ret == HDB_ERR_NOT_FOUND_HERE) { + /* + * This is OK, we are just trying to find out if they have + * been disabled or deleted in the meantime; missing secrets + * are OK. + */ + } else if (ret) { + /* + * If the client belongs to the same realm as our TGS, it + * should exist in the local database. + */ + const char *msg; + + if (strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) { + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + kdc_log(context, config, 4, "Client no longer in database: %s", cpn); + return ret; + } + + msg = krb5_get_error_message(context, ret); + kdc_log(context, config, 4, "Client not found in database: %s", msg); + krb5_free_error_message(context, msg); + } else if (client->entry.flags.invalid || !client->entry.flags.client) { + kdc_log(context, config, 4, "Client has invalid bit set"); + _kdc_free_ent(context, client); + return KRB5KDC_ERR_POLICY; + } + + *client_out = client; + + return 0; +} + static krb5_error_code tgs_build_reply(krb5_context context, krb5_kdc_configuration *config, @@ -1243,6 +1272,7 @@ tgs_build_reply(krb5_context context, KDC_REQ_BODY *b, hdb_entry_ex *krbtgt, krb5_enctype krbtgt_etype, + Key *tkey_check, const krb5_keyblock *replykey, int rk_is_subkey, krb5_ticket *ticket, @@ -1263,7 +1293,9 @@ tgs_build_reply(krb5_context context, const EncryptionKey *ekey; krb5_keyblock sessionkey; krb5_kvno kvno; - krb5_data rspac; + krb5_pac mspac = NULL; + uint16_t rodc_id; + krb5_boolean add_ticket_sig = FALSE; hdb_entry_ex *krbtgt_out = NULL; @@ -1274,15 +1306,13 @@ tgs_build_reply(krb5_context context, int nloop = 0; EncTicketPart adtkt; char opt_str[128]; - int signedpath = 0; + krb5_boolean kdc_issued = FALSE; - Key *tkey_check; Key *tkey_sign; int flags = HDB_F_FOR_TGS_REQ; memset(&sessionkey, 0, sizeof(sessionkey)); memset(&adtkt, 0, sizeof(adtkt)); - krb5_data_zero(&rspac); memset(&enc_pa_data, 0, sizeof(enc_pa_data)); s = b->sname; @@ -1517,18 +1547,6 @@ server_lookup: * backward. */ - /* - * Validate authoriation data - */ - - ret = hdb_enctype2key(context, &krbtgt->entry, - krbtgt_etype, &tkey_check); - if(ret) { - kdc_log(context, config, 0, - "Failed to find key for krbtgt PAC check"); - goto out; - } - /* Now refetch the primary krbtgt, and get the current kvno (the * sign check may have been on an old kvno, and the server may * have been an incoming trust) */ @@ -1589,41 +1607,14 @@ server_lookup: goto out; } - ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags, - NULL, &clientdb, &client); - if(ret == HDB_ERR_NOT_FOUND_HERE) { - /* This is OK, we are just trying to find out if they have - * been disabled or deleted in the meantime, missing secrets - * is OK */ - } else if(ret){ - const char *krbtgt_realm, *msg; - - /* - * If the client belongs to the same realm as our krbtgt, it - * should exist in the local database. - * - */ - - krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal); - - if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) { - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - kdc_log(context, config, 1, "Client no longer in database: %s", - cpn); - goto out; - } - - msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 1, "Client not found in database: %s", msg); - krb5_free_error_message(context, msg); - } + ret = db_fetch_client(context, config, flags, cp, cpn, + krb5_principal_get_realm(context, krbtgt_out->entry.principal), + &clientdb, &client); + if (ret) + goto out; - ret = check_PAC(context, config, cp, NULL, - client, server, krbtgt, - &tkey_check->key, - ekey, &tkey_sign->key, - tgt, &rspac, &signedpath); + ret = check_PAC(context, config, cp, NULL, client, server, krbtgt, krbtgt, + &tkey_check->key, &tkey_check->key, tgt, &kdc_issued, &mspac); if (ret) { const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, @@ -1743,27 +1734,15 @@ server_lookup: goto out; /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ - if(rspac.data) { - krb5_pac p = NULL; - krb5_data_free(&rspac); - ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p); + if (mspac) { + krb5_pac_free(context, mspac); + mspac = NULL; + ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &mspac); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", tpn); goto out; } - if (p != NULL) { - ret = _krb5_pac_sign(context, p, ticket->ticket.authtime, - s4u2self_impersonated_client->entry.principal, - ekey, &tkey_sign->key, - &rspac); - krb5_pac_free(context, p); - if (ret) { - kdc_log(context, config, 0, "PAC signing failed for -- %s", - tpn); - goto out; - } - } } /* @@ -1806,22 +1785,25 @@ server_lookup: && b->additional_tickets->len != 0 && b->kdc_options.enc_tkt_in_skey == 0) { - int ad_signedpath = 0; + hdb_entry_ex *adclient = NULL; + krb5_boolean ad_kdc_issued = FALSE; Key *clientkey; Ticket *t; /* - * Require that the KDC have issued the service's krbtgt (not - * self-issued ticket with kimpersonate(1). + * We require that the service's krbtgt has a PAC. */ - if (!signedpath) { + if (mspac == NULL) { ret = KRB5KDC_ERR_BADOPTION; kdc_log(context, config, 0, - "Constrained delegation done on service ticket %s/%s", + "Constrained delegation without PAC %s/%s", cpn, spn); goto out; } + krb5_pac_free(context, mspac); + mspac = NULL; + t = &b->additional_tickets->val[0]; ret = hdb_enctype2key(context, &client->entry, @@ -1885,19 +1867,32 @@ server_lookup: goto out; } - krb5_data_free(&rspac); + /* Try lookup the delegated client in DB */ + ret = db_fetch_client(context, config, flags, tp, tpn, + krb5_principal_get_realm(context, krbtgt_out->entry.principal), + NULL, &adclient); + if (ret) + goto out; + + if (adclient != NULL) { + ret = kdc_check_flags(context, config, + adclient, tpn, + server, spn, + FALSE); + if (ret) { + _kdc_free_ent(context, adclient); + goto out; + } + } /* - * generate the PAC for the user. - * * TODO: pass in t->sname and t->realm and build * a S4U_DELEGATION_INFO blob to the PAC. */ - ret = check_PAC(context, config, tp, dp, - client, server, krbtgt, - &clientkey->key, - ekey, &tkey_sign->key, - &adtkt, &rspac, &ad_signedpath); + ret = check_PAC(context, config, tp, dp, adclient, server, krbtgt, client, + &clientkey->key, &tkey_check->key, &adtkt, &ad_kdc_issued, &mspac); + if (adclient) + _kdc_free_ent(context, adclient); if (ret) { const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, @@ -1908,13 +1903,12 @@ server_lookup: goto out; } - if (!ad_signedpath) { + if (mspac == NULL || !ad_kdc_issued) { ret = KRB5KDC_ERR_BADOPTION; kdc_log(context, config, 0, - "Ticket not signed with PAC nor SignedPath service %s failed " - "for delegation to %s for client %s (%s)" - "from %s", - spn, tpn, dpn, cpn, from); + "Ticket not signed with PAC; service %s failed for " + "for delegation to %s for client %s (%s) from %s; (%s).", + spn, tpn, dpn, cpn, from, mspac ? "Ticket unsigned" : "No PAC"); goto out; } @@ -1983,6 +1977,25 @@ server_lookup: } } + /* + * Only add ticket signature if the requested server is not krbtgt, and + * either the header server is krbtgt or, in the case of renewal/validation + * if it was signed with PAC ticket signature and we verified it. + * Currently Heimdal only allows renewal of krbtgt anyway but that might + * change one day (see issue #763) so make sure to check for it. + */ + + if (kdc_issued && + !krb5_principal_is_krbtgt(context, server->entry.principal)) + add_ticket_sig = TRUE; + + /* + * Active-Directory implementations use the high part of the kvno as the + * read-only-dc identifier, we need to embed it in the PAC KDC signatures. + */ + + rodc_id = krbtgt_out->entry.kvno >> 16; + /* * */ @@ -1995,6 +2008,7 @@ server_lookup: replykey, rk_is_subkey, ekey, + &tkey_sign->key, &sessionkey, kvno, *auth_data, @@ -2004,8 +2018,9 @@ server_lookup: client, cp, krbtgt_out, - krbtgt_etype, - &rspac, + mspac, + rodc_id, + add_ticket_sig, &enc_pa_data, e_text, reply); @@ -2018,7 +2033,6 @@ out: if (dpn) free(dpn); - krb5_data_free(&rspac); krb5_free_keyblock_contents(context, &sessionkey); if(krbtgt_out) _kdc_free_ent(context, krbtgt_out); @@ -2043,6 +2057,9 @@ out: free_EncTicketPart(&adtkt); + if (mspac) + krb5_pac_free(context, mspac); + return ret; } @@ -2063,6 +2080,7 @@ _kdc_tgs_rep(krb5_context context, krb5_error_code ret; int i = 0; const PA_DATA *tgs_req; + Key *header_key = NULL; hdb_entry_ex *krbtgt = NULL; krb5_ticket *ticket = NULL; @@ -2100,6 +2118,7 @@ _kdc_tgs_rep(krb5_context context, &csec, &cusec, &auth_data, &replykey, + &header_key, &rk_is_subkey); if (ret == HDB_ERR_NOT_FOUND_HERE) { /* kdc_log() is called in tgs_parse_request() */ @@ -2117,6 +2136,7 @@ _kdc_tgs_rep(krb5_context context, &req->req_body, krbtgt, krbtgt_etype, + header_key, replykey, rk_is_subkey, ticket, diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index fb1c8a6a993..43dc89e2bc0 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -77,8 +77,14 @@ _kdc_pac_generate(krb5_context context, krb5_pac *pac) { *pac = NULL; - if (windcft == NULL) + if (krb5_config_get_bool_default(context, NULL, FALSE, "realms", + client->entry.principal->realm, + "disable_pac", NULL)) return 0; + if (windcft == NULL) { + return krb5_pac_init(context, pac); + } + if (windcft->pac_pk_generate != NULL && pk_reply_key != NULL) return (windcft->pac_pk_generate)(windcctx, context, client, pk_reply_key, pac); @@ -92,20 +98,17 @@ _kdc_pac_verify(krb5_context context, hdb_entry_ex *client, hdb_entry_ex *server, hdb_entry_ex *krbtgt, - krb5_pac *pac, - int *verified) + krb5_pac *pac) { krb5_error_code ret; if (windcft == NULL) - return 0; + return KRB5_PLUGIN_NO_HANDLE; ret = windcft->pac_verify(windcctx, context, client_principal, delegated_proxy_principal, client, server, krbtgt, pac); - if (ret == 0) - *verified = 1; return ret; } diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index bf90826cb06..dda258da3d1 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -43,8 +43,9 @@ * krb5_pac_init and fill in the PAC structure for the principal using * krb5_pac_add_buffer. * - * The PAC verify function should verify all components in the PAC - * using krb5_pac_get_types and krb5_pac_get_buffer for all types. + * The PAC verify function should verify the PAC KDC signatures by fetching + * the right KDC key and calling krb5_pac_verify() with that KDC key. + * Optionally, update the PAC buffers upon success. * * Check client access function check if the client is authorized. */ diff --git a/source4/heimdal/lib/krb5/authdata.c b/source4/heimdal/lib/krb5/authdata.c new file mode 100644 index 00000000000..ac426618f6e --- /dev/null +++ b/source4/heimdal/lib/krb5/authdata.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1997-2021 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Copyright (c) 2021 Isaac Boukris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +/* + * Add the AuthorizationData `data´ of `type´ to the last element in + * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_kdc_tkt_add_if_relevant_ad(krb5_context context, + EncTicketPart *tkt, + int type, + const krb5_data *data) +{ + krb5_error_code ret; + size_t size = 0; + + if (tkt->authorization_data == NULL) { + tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); + if (tkt->authorization_data == NULL) { + return krb5_enomem(context); + } + } + + /* add the entry to the last element */ + { + AuthorizationData ad = { 0, NULL }; + AuthorizationDataElement ade; + + ade.ad_type = type; + ade.ad_data = *data; + + ret = add_AuthorizationData(&ad, &ade); + if (ret) { + krb5_set_error_message(context, ret, "add AuthorizationData failed"); + return ret; + } + + ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; + + ASN1_MALLOC_ENCODE(AuthorizationData, + ade.ad_data.data, ade.ad_data.length, + &ad, &size, ret); + free_AuthorizationData(&ad); + if (ret) { + krb5_set_error_message(context, ret, "ASN.1 encode of " + "AuthorizationData failed"); + return ret; + } + if (ade.ad_data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + ret = add_AuthorizationData(tkt->authorization_data, &ade); + der_free_octet_string(&ade.ad_data); + if (ret) { + krb5_set_error_message(context, ret, "add AuthorizationData failed"); + return ret; + } + } + + return 0; +} + +/* + * Insert a PAC wrapped in AD-IF-RELEVANT container as the first AD element, + * as some clients such as Windows may fail to parse it otherwise. + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_kdc_tkt_insert_pac(krb5_context context, + EncTicketPart *tkt, + const krb5_data *data) +{ + AuthorizationDataElement ade; + unsigned int i; + krb5_error_code ret; + + ret = _kdc_tkt_add_if_relevant_ad(context, tkt, KRB5_AUTHDATA_WIN2K_PAC, + data); + if (ret) + return ret; + + heim_assert(tkt->authorization_data->len != 0, "No authorization_data!"); + ade = tkt->authorization_data->val[tkt->authorization_data->len - 1]; + for (i = 0; i < tkt->authorization_data->len - 1; i++) { + tkt->authorization_data->val[i + 1] = tkt->authorization_data->val[i]; + } + tkt->authorization_data->val[0] = ade; + + return 0; +} diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 26aae107b32..eec1e84c7bd 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -53,6 +53,8 @@ struct krb5_pac_data { struct PAC_INFO_BUFFER *server_checksum; struct PAC_INFO_BUFFER *privsvr_checksum; struct PAC_INFO_BUFFER *logon_name; + struct PAC_INFO_BUFFER *ticket_checksum; + krb5_data ticket_sign_data; }; #define PAC_ALIGNMENT 8 @@ -64,6 +66,7 @@ struct krb5_pac_data { #define PAC_PRIVSVR_CHECKSUM 7 #define PAC_LOGON_NAME 10 #define PAC_CONSTRAINED_DELEGATION 11 +#define PAC_TICKET_CHECKSUM 16 #define CHECK(r,f,l) \ do { \ @@ -142,13 +145,13 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, CHECK(ret, krb5_ret_uint32(sp, &tmp2), out); if (tmp < 1) { ret = EINVAL; /* Too few buffers */ - krb5_set_error_message(context, ret, N_("PAC have too few buffer", "")); + krb5_set_error_message(context, ret, N_("PAC has too few buffers", "")); goto out; } if (tmp2 != 0) { ret = EINVAL; /* Wrong version */ krb5_set_error_message(context, ret, - N_("PAC have wrong version %d", ""), + N_("PAC has wrong version %d", ""), (int)tmp2); goto out; } @@ -191,7 +194,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, if (p->pac->buffers[i].offset_lo > len) { ret = EINVAL; krb5_set_error_message(context, ret, - N_("PAC offset off end", "")); + N_("PAC offset overflow", "")); goto out; } if (p->pac->buffers[i].offset_lo < header_end) { @@ -204,7 +207,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, } if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){ ret = EINVAL; - krb5_set_error_message(context, ret, N_("PAC length off end", "")); + krb5_set_error_message(context, ret, N_("PAC length overflow", "")); goto out; } @@ -213,7 +216,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, if (p->server_checksum) { ret = EINVAL; krb5_set_error_message(context, ret, - N_("PAC have two server checksums", "")); + N_("PAC has multiple server checksums", "")); goto out; } p->server_checksum = &p->pac->buffers[i]; @@ -221,7 +224,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, if (p->privsvr_checksum) { ret = EINVAL; krb5_set_error_message(context, ret, - N_("PAC have two KDC checksums", "")); + N_("PAC has multiple KDC checksums", "")); goto out; } p->privsvr_checksum = &p->pac->buffers[i]; @@ -229,10 +232,18 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, if (p->logon_name) { ret = EINVAL; krb5_set_error_message(context, ret, - N_("PAC have two logon names", "")); + N_("PAC has multiple logon names", "")); goto out; } p->logon_name = &p->pac->buffers[i]; + } else if (p->pac->buffers[i].type == PAC_TICKET_CHECKSUM) { + if (p->ticket_checksum) { + ret = EINVAL; + krb5_set_error_message(context, ret, + N_("PAC has multiple ticket checksums", "")); + goto out; + } + p->ticket_checksum = &p->pac->buffers[i]; } } @@ -425,6 +436,7 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_pac_free(krb5_context context, krb5_pac pac) { krb5_data_free(&pac->data); + krb5_data_free(&pac->ticket_sign_data); free(pac->pac); free(pac); } @@ -444,6 +456,7 @@ verify_checksum(krb5_context context, uint32_t type; krb5_error_code ret; Checksum cksum; + size_t cksumsize; memset(&cksum, 0, sizeof(cksum)); @@ -456,8 +469,17 @@ verify_checksum(krb5_context context, CHECK(ret, krb5_ret_uint32(sp, &type), out); cksum.cksumtype = type; - cksum.checksum.length = - sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR); + + ret = krb5_checksumsize(context, type, &cksumsize); + if (ret) + goto out; + + /* Allow for RODCIdentifier trailer, see MS-PAC 2.8 */ + if (cksumsize > (sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR))) { + ret = EINVAL; + goto out; + } + cksum.checksum.length = cksumsize; cksum.checksum.data = malloc(cksum.checksum.length); if (cksum.checksum.data == NULL) { ret = krb5_enomem(context); @@ -804,7 +826,6 @@ out: return ret; } - /** * Verify the PAC. * @@ -844,18 +865,22 @@ krb5_pac_verify(krb5_context context, return EINVAL; } - ret = verify_logonname(context, - pac->logon_name, - &pac->data, - authtime, - principal); - if (ret) - return ret; + if (principal != NULL) { + ret = verify_logonname(context, pac->logon_name, &pac->data, authtime, + principal); + if (ret) + return ret; + } + + if (pac->server_checksum->buffersize < 4 || + pac->privsvr_checksum->buffersize < 4) + return EINVAL; /* * in the service case, clean out data option of the privsvr and * server checksum before checking the checksum. */ + if (server != NULL) { krb5_data *copy; @@ -897,6 +922,20 @@ krb5_pac_verify(krb5_context context, privsvr); if (ret) return ret; + + if (pac->ticket_sign_data.length != 0) { + if (pac->ticket_checksum == NULL) { + krb5_set_error_message(context, EINVAL, + "PAC missing ticket checksum"); + return EINVAL; + } + + ret = verify_checksum(context, pac->ticket_checksum, &pac->data, + pac->ticket_sign_data.data, + pac->ticket_sign_data.length, privsvr); + if (ret) + return ret; + } } return 0; @@ -965,13 +1004,14 @@ _krb5_pac_sign(krb5_context context, krb5_principal principal, const krb5_keyblock *server_key, const krb5_keyblock *priv_key, + uint16_t rodc_id, krb5_data *data) { krb5_error_code ret; krb5_storage *sp = NULL, *spdata = NULL; uint32_t end; size_t server_size, priv_size; - uint32_t server_offset = 0, priv_offset = 0; + uint32_t server_offset = 0, priv_offset = 0, ticket_offset = 0; uint32_t server_cksumtype = 0, priv_cksumtype = 0; int num = 0; size_t i; @@ -985,9 +1025,9 @@ _krb5_pac_sign(krb5_context context, p->server_checksum = &p->pac->buffers[i]; } if (p->server_checksum != &p->pac->buffers[i]) { - ret = EINVAL; + ret = KRB5KDC_ERR_BADOPTION; krb5_set_error_message(context, ret, - N_("PAC have two server checksums", "")); + N_("PAC has multiple server checksums", "")); goto out; } } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { @@ -995,9 +1035,9 @@ _krb5_pac_sign(krb5_context context, p->privsvr_checksum = &p->pac->buffers[i]; } if (p->privsvr_checksum != &p->pac->buffers[i]) { - ret = EINVAL; + ret = KRB5KDC_ERR_BADOPTION; krb5_set_error_message(context, ret, - N_("PAC have two KDC checksums", "")); + N_("PAC has multiple KDC checksums", "")); goto out; } } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { @@ -1005,9 +1045,19 @@ _krb5_pac_sign(krb5_context context, p->logon_name = &p->pac->buffers[i]; } if (p->logon_name != &p->pac->buffers[i]) { - ret = EINVAL; + ret = KRB5KDC_ERR_BADOPTION; + krb5_set_error_message(context, ret, + N_("PAC has multiple logon names", "")); + goto out; + } + } else if (p->pac->buffers[i].type == PAC_TICKET_CHECKSUM) { + if (p->ticket_checksum == NULL) { + p->ticket_checksum = &p->pac->buffers[i]; + } + if (p->ticket_checksum != &p->pac->buffers[i]) { + ret = KRB5KDC_ERR_BADOPTION; krb5_set_error_message(context, ret, - N_("PAC have two logon names", "")); + N_("PAC has multiple ticket checksums", "")); goto out; } } @@ -1019,6 +1069,8 @@ _krb5_pac_sign(krb5_context context, num++; if (p->privsvr_checksum == NULL) num++; + if (p->ticket_sign_data.length != 0 && p->ticket_checksum == NULL) + num++; if (num) { void *ptr; @@ -1044,6 +1096,11 @@ _krb5_pac_sign(krb5_context context, memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; } + if (p->ticket_sign_data.length != 0 && p->ticket_checksum == NULL) { + p->ticket_checksum = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->ticket_checksum, 0, sizeof(*p->privsvr_checksum)); + p->ticket_checksum->type = PAC_TICKET_CHECKSUM; + } } /* Calculate LOGON NAME */ @@ -1055,6 +1112,7 @@ _krb5_pac_sign(krb5_context context, ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); if (ret) goto out; + ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); if (ret) goto out; @@ -1095,10 +1153,24 @@ _krb5_pac_sign(krb5_context context, priv_offset = end + 4; CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); CHECK(ret, fill_zeros(context, spdata, priv_size), out); + if (rodc_id != 0) { + len += sizeof(rodc_id); + CHECK(ret, fill_zeros(context, spdata, sizeof(rodc_id)), out); + } + } else if (p->ticket_sign_data.length != 0 && + p->pac->buffers[i].type == PAC_TICKET_CHECKSUM) { + len = priv_size + 4; + ticket_offset = end + 4; + CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); + CHECK(ret, fill_zeros(context, spdata, priv_size), out); + if (rodc_id != 0) { + len += sizeof(rodc_id); + CHECK(ret, krb5_store_uint16(spdata, rodc_id), out); + } } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { len = krb5_storage_write(spdata, logon.data, logon.length); if (logon.length != len) { - ret = EINVAL; + ret = KRB5KDC_ERR_BADOPTION; goto out; } } else { @@ -1156,6 +1228,16 @@ _krb5_pac_sign(krb5_context context, } /* sign */ + if (p->ticket_sign_data.length) { + ret = create_checksum(context, priv_key, priv_cksumtype, + p->ticket_sign_data.data, + p->ticket_sign_data.length, + (char *)d.data + ticket_offset, priv_size); + if (ret) { + krb5_data_free(&d); + goto out; + } + } ret = create_checksum(context, server_key, server_cksumtype, d.data, d.length, (char *)d.data + server_offset, server_size); @@ -1171,6 +1253,32 @@ _krb5_pac_sign(krb5_context context, goto out; } + if (rodc_id != 0) { + krb5_data rd; + krb5_storage *rs = krb5_storage_emem(); + if (rs == NULL) { + krb5_data_free(&d); + ret = krb5_enomem(context); + goto out; + } + krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE); + ret = krb5_store_uint16(rs, rodc_id); + if (ret) { + krb5_storage_free(rs); + krb5_data_free(&d); + goto out; + } + ret = krb5_storage_to_data(rs, &rd); + krb5_storage_free(rs); + if (ret) { + krb5_data_free(&d); + goto out; + } + heim_assert(rd.length == sizeof(rodc_id), "invalid length"); + memcpy((char *)d.data + priv_offset + priv_size, rd.data, rd.length); + krb5_data_free(&rd); + } + /* done */ *data = d; @@ -1187,3 +1295,221 @@ out: krb5_storage_free(spdata); return ret; } + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_pac_get_kdc_checksum_info(krb5_context context, + krb5_pac pac, + krb5_cksumtype *cstype, + uint16_t *rodc_id) +{ + krb5_error_code ret; + krb5_storage *sp = NULL; + const struct PAC_INFO_BUFFER *sig; + size_t cksumsize, prefix; + uint32_t type = 0; + + *cstype = 0; + *rodc_id = 0; + + sig = pac->privsvr_checksum; + if (sig == NULL) { + krb5_set_error_message(context, KRB5KDC_ERR_BADOPTION, + "PAC missing kdc checksum"); + return KRB5KDC_ERR_BADOPTION; + } + + sp = krb5_storage_from_mem((char *)pac->data.data + sig->offset_lo, + sig->buffersize); + if (sp == NULL) + return krb5_enomem(context); + + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + ret = krb5_ret_uint32(sp, &type); + if (ret) + goto out; + + ret = krb5_checksumsize(context, type, &cksumsize); + if (ret) + goto out; + + prefix = krb5_storage_seek(sp, 0, SEEK_CUR); + + if ((sig->buffersize - prefix) >= cksumsize + 2) { + krb5_storage_seek(sp, cksumsize, SEEK_CUR); + ret = krb5_ret_uint16(sp, rodc_id); + if (ret) + goto out; + } + + *cstype = type; + +out: + krb5_storage_free(sp); + + return ret; +} + +static unsigned char single_zero = '\0'; +static krb5_data single_zero_pac = { 1, &single_zero }; + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_kdc_pac_ticket_parse(krb5_context context, + EncTicketPart *tkt, + krb5_boolean *signedticket, + krb5_pac *ppac) +{ + AuthorizationData *ad = tkt->authorization_data; + krb5_boolean pac_found = FALSE; + krb5_pac pac = NULL; + unsigned i, j; + size_t len = 0; + krb5_error_code ret; + + *signedticket = FALSE; + *ppac = NULL; + + if (ad == NULL || ad->len == 0) + return 0; + + for (i = 0; i < ad->len; i++) { + AuthorizationData child; + + if (ad->val[i].ad_type == KRB5_AUTHDATA_WIN2K_PAC) + return KRB5KDC_ERR_BADOPTION; + + if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT) + continue; + + ret = decode_AuthorizationData(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_message(context, ret, "Failed to decode " + "AD-IF-RELEVANT with %d", ret); + return ret; + } + + for (j = 0; j < child.len; j++) { + if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) { + krb5_data adifr_data = ad->val[i].ad_data; + krb5_data pac_data = child.val[j].ad_data; + krb5_data recoded_adifr; + + if (pac_found) { + free_AuthorizationData(&child); + return KRB5KDC_ERR_BADOPTION; + } + pac_found = TRUE; + + ret = krb5_pac_parse(context, + pac_data.data, + pac_data.length, + &pac); + if (ret) { + free_AuthorizationData(&child); + return ret; + } + + if (pac->ticket_checksum == NULL) { + free_AuthorizationData(&child); + *ppac = pac; + continue; + } + + /* + * Encode the ticket with the PAC replaced with a single zero + * byte, to be used as input data to the ticket signature. + */ + + child.val[j].ad_data = single_zero_pac; + + ASN1_MALLOC_ENCODE(AuthorizationData, recoded_adifr.data, + recoded_adifr.length, &child, &len, ret); + if (recoded_adifr.length != len) + krb5_abortx(context, "Internal error in ASN.1 encoder"); + + child.val[j].ad_data = pac_data; + free_AuthorizationData(&child); + + if (ret) { + krb5_pac_free(context, pac); + return ret; + } + + ad->val[i].ad_data = recoded_adifr; + + ASN1_MALLOC_ENCODE(EncTicketPart, + pac->ticket_sign_data.data, + pac->ticket_sign_data.length, tkt, &len, + ret); + if(pac->ticket_sign_data.length != len) + krb5_abortx(context, "Internal error in ASN.1 encoder"); + + ad->val[i].ad_data = adifr_data; + krb5_data_free(&recoded_adifr); + + if (ret) { + krb5_pac_free(context, pac); + return ret; + } + + *signedticket = TRUE; + *ppac = pac; + } + } + free_AuthorizationData(&child); + } + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_kdc_pac_sign_ticket(krb5_context context, + const krb5_pac pac, + krb5_principal client, + const krb5_keyblock *server_key, + const krb5_keyblock *kdc_key, + uint16_t rodc_id, + krb5_boolean add_ticket_sig, + EncTicketPart *tkt) +{ + krb5_error_code ret; + krb5_data tkt_data; + krb5_data rspac; + + krb5_data_zero(&rspac); + krb5_data_zero(&tkt_data); + + krb5_data_free(&pac->ticket_sign_data); + + if (add_ticket_sig) { + size_t len = 0; + + ret = _kdc_tkt_insert_pac(context, tkt, &single_zero_pac); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EncTicketPart, tkt_data.data, tkt_data.length, + tkt, &len, ret); + if(tkt_data.length != len) + krb5_abortx(context, "Internal error in ASN.1 encoder"); + if (ret) + return ret; + + ret = remove_AuthorizationData(tkt->authorization_data, 0); + if (ret) { + krb5_data_free(&tkt_data); + return ret; + } + + pac->ticket_sign_data = tkt_data; + } + + ret = _krb5_pac_sign(context, pac, tkt->authtime, client, server_key, + kdc_key, rodc_id, &rspac); + if (ret) + return ret; + + return _kdc_tkt_insert_pac(context, tkt, &rspac); +} diff --git a/source4/heimdal/lib/krb5/version-script.map b/source4/heimdal/lib/krb5/version-script.map index ddae2a06764..91eb3543003 100644 --- a/source4/heimdal/lib/krb5/version-script.map +++ b/source4/heimdal/lib/krb5/version-script.map @@ -751,6 +751,11 @@ HEIMDAL_KRB5_2.0 { _krb5_get_host_realm_int; _krb5_get_int; _krb5_pac_sign; + _krb5_kdc_pac_sign_ticket; + _krb5_kdc_pac_ticket_parse; + _krb5_pac_get_kdc_checksum_info; + _kdc_tkt_insert_pac; + _kdc_tkt_add_if_relevant_ad; _krb5_parse_moduli; _krb5_pk_kdf; _krb5_pk_load_id; diff --git a/source4/heimdal_build/wscript_build b/source4/heimdal_build/wscript_build index 9904b245218..f151788dcfd 100644 --- a/source4/heimdal_build/wscript_build +++ b/source4/heimdal_build/wscript_build @@ -606,7 +606,7 @@ if not bld.CONFIG_SET("USING_SYSTEM_KRB5"): KRB5_SOURCE = [os.path.join('lib/krb5/', x) for x in to_list( '''acache.c add_et_list.c addr_families.c appdefault.c - asn1_glue.c auth_context.c + asn1_glue.c auth_context.c authdata.c build_ap_req.c build_auth.c cache.c changepw.c codec.c config_file.c constants.c convert_creds.c diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 1f8554155bf..2d2d0af658f 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -743,7 +743,7 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.gpo", extra_args=['-U"$USERNA planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$USERNAME%$PASSWORD"']) have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) -tkt_sig_support = 0 +tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", environ={'SERVICE_USERNAME':'$SERVER', -- 2.25.1 From f41ef3e67c5e3e2334df05e8bac418de89ca9e80 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 19 Sep 2021 15:04:14 +0300 Subject: [PATCH 347/645] krb5: allow NULL parameter to krb5_pac_free() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Cherry-picked from Heimdal commit b295167208a96e68515902138f6ce93972892ec5] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 2d09de5c41e729bccc2d7949d8a3568a95e80e76) --- source4/heimdal/kdc/krb5tgs.c | 3 +-- source4/heimdal/lib/krb5/pac.c | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index e8bbb42465f..24a4f261766 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -2057,8 +2057,7 @@ out: free_EncTicketPart(&adtkt); - if (mspac) - krb5_pac_free(context, mspac); + krb5_pac_free(context, mspac); return ret; } diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index eec1e84c7bd..18f385fac1f 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -435,6 +435,8 @@ krb5_pac_get_types(krb5_context context, KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_pac_free(krb5_context context, krb5_pac pac) { + if (pac == NULL) + return; krb5_data_free(&pac->data); krb5_data_free(&pac->ticket_sign_data); free(pac->pac); -- 2.25.1 From b1e56013e2d2cf685d63a1fc9a297fccdcd5ce72 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 19 Sep 2021 15:16:58 +0300 Subject: [PATCH 348/645] krb5: rework PAC validation loop Avoid allocating the PAC on error. Closes: #836 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Cherry-picked from Heimdal commit 6df8be5091363a1c9a9165465ab8292f817bec81] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 2773379603a5a625c5d1c6e62f29c442942ff570) --- source4/heimdal/lib/krb5/pac.c | 132 +++++++++++++++++---------------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 18f385fac1f..922a8710eda 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -1362,11 +1362,10 @@ _krb5_kdc_pac_ticket_parse(krb5_context context, krb5_pac *ppac) { AuthorizationData *ad = tkt->authorization_data; - krb5_boolean pac_found = FALSE; krb5_pac pac = NULL; unsigned i, j; size_t len = 0; - krb5_error_code ret; + krb5_error_code ret = 0; *signedticket = FALSE; *ppac = NULL; @@ -1377,8 +1376,10 @@ _krb5_kdc_pac_ticket_parse(krb5_context context, for (i = 0; i < ad->len; i++) { AuthorizationData child; - if (ad->val[i].ad_type == KRB5_AUTHDATA_WIN2K_PAC) - return KRB5KDC_ERR_BADOPTION; + if (ad->val[i].ad_type == KRB5_AUTHDATA_WIN2K_PAC) { + ret = KRB5KDC_ERR_BADOPTION; + goto out; + } if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT) continue; @@ -1390,79 +1391,84 @@ _krb5_kdc_pac_ticket_parse(krb5_context context, if (ret) { krb5_set_error_message(context, ret, "Failed to decode " "AD-IF-RELEVANT with %d", ret); - return ret; + goto out; } for (j = 0; j < child.len; j++) { - if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) { - krb5_data adifr_data = ad->val[i].ad_data; - krb5_data pac_data = child.val[j].ad_data; - krb5_data recoded_adifr; - - if (pac_found) { - free_AuthorizationData(&child); - return KRB5KDC_ERR_BADOPTION; - } - pac_found = TRUE; - - ret = krb5_pac_parse(context, - pac_data.data, - pac_data.length, - &pac); - if (ret) { - free_AuthorizationData(&child); - return ret; - } - - if (pac->ticket_checksum == NULL) { - free_AuthorizationData(&child); - *ppac = pac; - continue; - } - - /* - * Encode the ticket with the PAC replaced with a single zero - * byte, to be used as input data to the ticket signature. - */ - - child.val[j].ad_data = single_zero_pac; - - ASN1_MALLOC_ENCODE(AuthorizationData, recoded_adifr.data, - recoded_adifr.length, &child, &len, ret); - if (recoded_adifr.length != len) - krb5_abortx(context, "Internal error in ASN.1 encoder"); - - child.val[j].ad_data = pac_data; + krb5_data adifr_data = ad->val[i].ad_data; + krb5_data pac_data = child.val[j].ad_data; + krb5_data recoded_adifr; + + if (child.val[j].ad_type != KRB5_AUTHDATA_WIN2K_PAC) + continue; + + if (pac != NULL) { + free_AuthorizationData(&child); + ret = KRB5KDC_ERR_BADOPTION; + goto out; + } + + ret = krb5_pac_parse(context, + pac_data.data, + pac_data.length, + &pac); + if (ret) { free_AuthorizationData(&child); + goto out; + } - if (ret) { - krb5_pac_free(context, pac); - return ret; - } + if (pac->ticket_checksum == NULL) + continue; - ad->val[i].ad_data = recoded_adifr; + /* + * Encode the ticket with the PAC replaced with a single zero + * byte, to be used as input data to the ticket signature. + */ - ASN1_MALLOC_ENCODE(EncTicketPart, - pac->ticket_sign_data.data, - pac->ticket_sign_data.length, tkt, &len, - ret); - if(pac->ticket_sign_data.length != len) - krb5_abortx(context, "Internal error in ASN.1 encoder"); + child.val[j].ad_data = single_zero_pac; - ad->val[i].ad_data = adifr_data; - krb5_data_free(&recoded_adifr); + ASN1_MALLOC_ENCODE(AuthorizationData, recoded_adifr.data, + recoded_adifr.length, &child, &len, ret); + if (recoded_adifr.length != len) + krb5_abortx(context, "Internal error in ASN.1 encoder"); - if (ret) { - krb5_pac_free(context, pac); - return ret; - } + child.val[j].ad_data = pac_data; - *signedticket = TRUE; - *ppac = pac; + if (ret) { + free_AuthorizationData(&child); + goto out; } + + ad->val[i].ad_data = recoded_adifr; + + ASN1_MALLOC_ENCODE(EncTicketPart, + pac->ticket_sign_data.data, + pac->ticket_sign_data.length, tkt, &len, + ret); + if (pac->ticket_sign_data.length != len) + krb5_abortx(context, "Internal error in ASN.1 encoder"); + + ad->val[i].ad_data = adifr_data; + krb5_data_free(&recoded_adifr); + + if (ret) { + free_AuthorizationData(&child); + goto out; + } + + *signedticket = TRUE; } free_AuthorizationData(&child); } + +out: + if (ret) { + krb5_pac_free(context, pac); + return ret; + } + + *ppac = pac; + return 0; } -- 2.25.1 From 36cbb8e043b10aa0f589edf3a2e435690f90d482 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 17 Sep 2021 13:57:57 +1000 Subject: [PATCH 349/645] krb5: return KRB5KRB_AP_ERR_INAPP_CKSUM if PAC checksum fails Return KRB5KRB_AP_ERR_INAPP_CKSUM instead of EINVAL when verifying a PAC, if the checksum is absent or unkeyed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Cherry-picked from Heimdal commit c4b99b48c4b18f30d504b427bc1961d7a71f631e] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit d6a472e953545ec3858ca969c1a4191e4f27ba63) --- source4/heimdal/lib/krb5/pac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 922a8710eda..3e45125d35e 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -489,13 +489,13 @@ verify_checksum(krb5_context context, } ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length); if (ret != (int)cksum.checksum.length) { - ret = EINVAL; + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; krb5_set_error_message(context, ret, "PAC checksum missing checksum"); goto out; } if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) { - ret = EINVAL; + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; krb5_set_error_message(context, ret, "Checksum type %d not keyed", cksum.cksumtype); goto out; -- 2.25.1 From e74e78903ab3293be7b48a8c85357527c527da25 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 6 Jan 2019 17:54:58 +1100 Subject: [PATCH 350/645] kdc: only set HDB_F_GET_KRBTGT when requesting TGS principal BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Backported from Heimdal commit f1dd2b818aa0866960945edea02a6bc782ed697c - Removed change to _kdc_find_etype() use_strongest_session_key parameter since Samba's Heimdal version uses different logic ] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit db30b71f79864a20b38a1f812a5df833f3a92de8) --- source4/heimdal/kdc/kerberos5.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 7b17d2539ce..d1fd201113b 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -983,6 +983,7 @@ _kdc_as_rep(krb5_context context, pk_client_params *pkp = NULL; #endif const EncryptionKey *pk_reply_key = NULL; + krb5_boolean is_tgs; memset(&rep, 0, sizeof(rep)); memset(&session_key, 0, sizeof(session_key)); @@ -1033,6 +1034,8 @@ _kdc_as_rep(krb5_context context, kdc_log(context, config, 0, "AS-REQ %s from %s for %s", client_name, from, server_name); + is_tgs = krb5_principal_is_krbtgt(context, server_princ); + /* * */ @@ -1101,7 +1104,7 @@ _kdc_as_rep(krb5_context context, goto out; } ret = _kdc_db_fetch(context, config, server_princ, - HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags, + HDB_F_GET_SERVER | flags | (is_tgs ? HDB_F_GET_KRBTGT : 0), NULL, NULL, &server); if(ret == HDB_ERR_NOT_FOUND_HERE) { kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name); -- 2.25.1 From 718e18d8b683ba06b0ff1435da167435c54b0df7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 23 Sep 2021 14:39:35 +1000 Subject: [PATCH 351/645] kdc: use ticket client name when signing PAC The principal in the PAC_LOGON_NAME buffer is expected to match the client name in the ticket. Previously we were setting this to the canonical client name, which would have broken PAC validation if the client did not request name canonicalization BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Backported from Heimdal commit 3b0856cab2b25624deb1f6e0e67637ba96a647ac - Renamed variable to avoid shadowing existing variable ] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 75d1a7cd14b134506061ed64ddb9b99856231d2c) --- source4/heimdal/kdc/kerberos5.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index d1fd201113b..6dc945b134a 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -1716,6 +1716,7 @@ _kdc_as_rep(krb5_context context, krb5_pac p = NULL; krb5_data data; uint16_t rodc_id; + krb5_principal client_pac; ret = _kdc_pac_generate(context, client, pk_reply_key, &p); if (ret) { @@ -1726,12 +1727,21 @@ _kdc_as_rep(krb5_context context, if (p != NULL) { rodc_id = server->entry.kvno >> 16; + /* libkrb5 expects ticket and PAC client names to match */ + ret = _krb5_principalname2krb5_principal(context, &client_pac, + et.cname, et.crealm); + if (ret) { + krb5_pac_free(context, p); + goto out; + } + ret = _krb5_pac_sign(context, p, et.authtime, - client->entry.principal, + client_pac, &skey->key, /* Server key */ &skey->key, /* FIXME: should be krbtgt key */ rodc_id, &data); + krb5_free_principal(context, client_pac); krb5_pac_free(context, p); if (ret) { kdc_log(context, config, 0, "PAC signing failed for -- %s", -- 2.25.1 From dd2461de8e1030dd8096dd4d68dfc6b393ffe1a0 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 23 Sep 2021 17:51:51 +1000 Subject: [PATCH 352/645] kdc: correctly generate PAC TGS signature When generating an AS-REQ, the TGS signature was incorrectly generated using the server key, which would fail to validate if the server was not also the TGS. Fix this. Patch from Isaac Bourkis . BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Backported from Heimdal commit e7863e2af922809dad25a2e948e98c408944d551 - Samba's Heimdal version does not have the generate_pac() helper function. - Samba's Heimdal version does not use the 'r' context variable. ] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 91e684f5dcb48b76e6a322c15acb53cbce5c275a) --- source4/heimdal/kdc/kerberos5.c | 49 ++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 6dc945b134a..a131f1af08e 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -948,6 +948,33 @@ _kdc_is_anonymous(krb5_context context, krb5_principal principal) return 1; } +static krb5_error_code +get_local_tgs(krb5_context context, + krb5_kdc_configuration *config, + krb5_const_realm realm, + hdb_entry_ex **krbtgt) +{ + krb5_error_code ret; + krb5_principal tgs_name; + + *krbtgt = NULL; + + ret = krb5_make_principal(context, + &tgs_name, + realm, + KRB5_TGS_NAME, + realm, + NULL); + if (ret) + return ret; + + ret = _kdc_db_fetch(context, config, tgs_name, + HDB_F_GET_KRBTGT, NULL, NULL, krbtgt); + krb5_free_principal(context, tgs_name); + + return ret; +} + /* * */ @@ -984,6 +1011,8 @@ _kdc_as_rep(krb5_context context, #endif const EncryptionKey *pk_reply_key = NULL; krb5_boolean is_tgs; + hdb_entry_ex *krbtgt = NULL; + Key *krbtgt_key = NULL; memset(&rep, 0, sizeof(rep)); memset(&session_key, 0, sizeof(session_key)); @@ -1466,6 +1495,22 @@ _kdc_as_rep(krb5_context context, if(ret) goto out; + /* If server is not krbtgt, fetch local krbtgt key for signing authdata */ + if (is_tgs) { + krbtgt_key = skey; + } else { + ret = get_local_tgs(context, config, server_princ->realm, + &krbtgt); + if (ret) + goto out; + + ret = _kdc_get_preferred_key(context, config, krbtgt, + server_princ->realm, + NULL, &krbtgt_key); + if (ret) + goto out; + } + if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey || (f.request_anonymous && !config->allow_anonymous)) { ret = KRB5KDC_ERR_BADOPTION; @@ -1738,7 +1783,7 @@ _kdc_as_rep(krb5_context context, ret = _krb5_pac_sign(context, p, et.authtime, client_pac, &skey->key, /* Server key */ - &skey->key, /* FIXME: should be krbtgt key */ + &krbtgt_key->key, /* TGS key */ rodc_id, &data); krb5_free_principal(context, client_pac); @@ -1807,6 +1852,8 @@ out: _kdc_free_ent(context, client); if(server) _kdc_free_ent(context, server); + if (krbtgt) + _kdc_free_ent(context, krbtgt); return ret; } -- 2.25.1 From be38815a741c7e21ab0d88147735bcd3272043be Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 11 Aug 2021 13:27:11 +1200 Subject: [PATCH 353/645] s4/heimdal/lib/krb5/pac.c: Align PAC buffers to match Windows BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 28a5a586c8e9cd155d676dcfcb81a2587ace99d1) --- selftest/knownfail_heimdal_kdc | 1 + source4/heimdal/lib/krb5/pac.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 4ec682c01d0..20eea7f2d7e 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -124,6 +124,7 @@ # # S4U tests # +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_constrained_delegation_old_checksum ^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_service_pac ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_client_checksum diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 3e45125d35e..6535a9bdcc4 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -62,10 +62,12 @@ struct krb5_pac_data { #define PACTYPE_SIZE 8 #define PAC_INFO_BUFFER_SIZE 16 +#define PAC_LOGON_INFO 1 #define PAC_SERVER_CHECKSUM 6 #define PAC_PRIVSVR_CHECKSUM 7 #define PAC_LOGON_NAME 10 #define PAC_CONSTRAINED_DELEGATION 11 +#define PAC_UPN_DNS_INFO 12 #define PAC_TICKET_CHECKSUM 16 #define CHECK(r,f,l) \ @@ -1184,7 +1186,17 @@ _krb5_pac_sign(krb5_context context, ret = krb5_enomem(context); goto out; } - /* XXX if not aligned, fill_zeros */ + + if (p->pac->buffers[i].type == PAC_LOGON_INFO + || p->pac->buffers[i].type == PAC_UPN_DNS_INFO) + { + uint32_t rounded = (len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT + * PAC_ALIGNMENT; + uint32_t remaining = rounded - len; + CHECK(ret, fill_zeros(context, spdata, remaining), out); + + len = rounded; + } } /* write header */ -- 2.25.1 From b04cc9488bd674ab87dc392ea6e86946b922da3e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:43:41 +1300 Subject: [PATCH 354/645] heimdal: Make _krb5_pac_get_kdc_checksum_info() into a global function This lets us call it from Samba. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 3bdce12789af1e7a7aba56691f184625a432410d) --- source4/heimdal/lib/krb5/pac.c | 8 ++++---- source4/heimdal/lib/krb5/version-script.map | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 6535a9bdcc4..f6d38178a88 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -1311,10 +1311,10 @@ out: } KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -_krb5_pac_get_kdc_checksum_info(krb5_context context, - krb5_pac pac, - krb5_cksumtype *cstype, - uint16_t *rodc_id) +krb5_pac_get_kdc_checksum_info(krb5_context context, + krb5_pac pac, + krb5_cksumtype *cstype, + uint16_t *rodc_id) { krb5_error_code ret; krb5_storage *sp = NULL; diff --git a/source4/heimdal/lib/krb5/version-script.map b/source4/heimdal/lib/krb5/version-script.map index 91eb3543003..9ba00cd04f6 100644 --- a/source4/heimdal/lib/krb5/version-script.map +++ b/source4/heimdal/lib/krb5/version-script.map @@ -470,6 +470,7 @@ HEIMDAL_KRB5_2.0 { krb5_pac_add_buffer; krb5_pac_free; krb5_pac_get_buffer; + krb5_pac_get_kdc_checksum_info; krb5_pac_get_types; krb5_pac_init; krb5_pac_parse; @@ -753,7 +754,6 @@ HEIMDAL_KRB5_2.0 { _krb5_pac_sign; _krb5_kdc_pac_sign_ticket; _krb5_kdc_pac_ticket_parse; - _krb5_pac_get_kdc_checksum_info; _kdc_tkt_insert_pac; _kdc_tkt_add_if_relevant_ad; _krb5_parse_moduli; -- 2.25.1 From 1cc5fd1d6af0b0295a3a8c75bba7c5d905ac6831 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 16:08:39 +1300 Subject: [PATCH 355/645] s4:kdc: Check ticket signature BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 02fa69c6c73c01d82807be4370e838f3e7c66f35) --- selftest/knownfail_heimdal_kdc | 9 -- source4/kdc/wdc-samba4.c | 270 ++++++++++++++++++++++++++------- 2 files changed, 215 insertions(+), 64 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 20eea7f2d7e..683dbacb979 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -124,13 +124,8 @@ # # S4U tests # -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_constrained_delegation_old_checksum ^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_service_pac -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_client_checksum -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_unkeyed_service_checksum -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_zeroed_client_checksum -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_zeroed_service_checksum ^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 @@ -142,10 +137,6 @@ ^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 # -# RODC tests -# -^samba.tests.krb5.rodc_tests.samba.tests.krb5.rodc_tests.RodcKerberosTests.test_rodc_ticket_signature -# # The lack of KRB5SignedPath means we no longer return # KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case # diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index 037db40ce46..589df8a651d 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -23,7 +23,10 @@ #include "includes.h" #include "kdc/kdc-glue.h" +#include "kdc/db-glue.h" #include "kdc/pac-glue.h" +#include "sdb.h" +#include "sdb_hdb.h" /* * Given the right private pointer from hdb_samba4, @@ -94,15 +97,13 @@ static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context return samba_wdc_get_pac(priv, context, client, NULL, pac); } -/* Resign (and reform, including possibly new groups) a PAC */ - -static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, - const krb5_principal client_principal, - const krb5_principal delegated_proxy_principal, - struct hdb_entry_ex *client, - struct hdb_entry_ex *server, - struct hdb_entry_ex *krbtgt, - krb5_pac *pac) +static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + const krb5_principal delegated_proxy_principal, + struct hdb_entry_ex *client, + struct hdb_entry_ex *server, + struct hdb_entry_ex *krbtgt, + krb5_pac *pac, + krb5_cksumtype ctype) { struct samba_kdc_entry *p = talloc_get_type_abort(server->ctx, @@ -110,15 +111,13 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, struct samba_kdc_entry *krbtgt_skdc_entry = talloc_get_type_abort(krbtgt->ctx, struct samba_kdc_entry); - TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context"); + TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac2 context"); krb5_pac new_pac = NULL; DATA_BLOB *pac_blob = NULL; DATA_BLOB *upn_blob = NULL; DATA_BLOB *deleg_blob = NULL; krb5_error_code ret; NTSTATUS nt_status; - struct PAC_SIGNATURE_DATA *pac_srv_sig; - struct PAC_SIGNATURE_DATA *pac_kdc_sig; bool is_in_db, is_untrusted; size_t num_types = 0; uint32_t *types = NULL; @@ -130,6 +129,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, 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; if (!mem_ctx) { return ENOMEM; @@ -150,6 +150,71 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, return ret; } + if (delegated_proxy_principal != NULL) { + krb5_enctype etype; + Key *key = NULL; + + if (!is_in_db) { + /* + * The RODC-issued PAC was signed by a KDC entry that we + * don't have a key for. The server signature is not + * trustworthy, since it could have been created by the + * server we got the ticket from. We must not proceed as + * otherwise the ticket signature is unchecked. + */ + talloc_free(mem_ctx); + return HDB_ERR_NOT_FOUND_HERE; + } + + /* Fetch the correct key depending on the checksum type. */ + if (ctype == CKSUMTYPE_HMAC_MD5) { + etype = ENCTYPE_ARCFOUR_HMAC; + } else { + ret = krb5_cksumtype_to_enctype(context, + ctype, + &etype); + if (ret != 0) { + talloc_free(mem_ctx); + return ret; + } + } + ret = hdb_enctype2key(context, &krbtgt->entry, etype, &key); + if (ret != 0) { + return ret; + } + + /* Check the KDC and ticket signatures. */ + ret = krb5_pac_verify(context, + *pac, + 0, + NULL, + NULL, + &key->key); + if (ret != 0) { + DEBUG(1, ("PAC KDC signature failed to verify\n")); + talloc_free(mem_ctx); + return ret; + } + + deleg_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (!deleg_blob) { + talloc_free(mem_ctx); + return ENOMEM; + } + + nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, + context, *pac, + server->entry.principal, + delegated_proxy_principal, + deleg_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Building PAC failed: %s\n", + nt_errstr(nt_status))); + talloc_free(mem_ctx); + return EINVAL; + } + } + if (is_untrusted) { struct samba_kdc_entry *client_skdc_entry = NULL; @@ -173,52 +238,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, return ENOMEM; } - pac_srv_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); - if (!pac_srv_sig) { - talloc_free(mem_ctx); - return ENOMEM; - } - - pac_kdc_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); - if (!pac_kdc_sig) { - talloc_free(mem_ctx); - return ENOMEM; - } - nt_status = samba_kdc_update_pac_blob(mem_ctx, context, krbtgt_skdc_entry->kdc_db_ctx->samdb, *pac, pac_blob, - pac_srv_sig, pac_kdc_sig); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("Building PAC failed: %s\n", - nt_errstr(nt_status))); - talloc_free(mem_ctx); - return EINVAL; - } - - if (is_in_db) { - /* Now check the KDC signature, fetching the correct key based on the enc type */ - ret = kdc_check_pac(context, pac_srv_sig->signature, pac_kdc_sig, krbtgt); - if (ret != 0) { - DEBUG(1, ("PAC KDC signature failed to verify\n")); - talloc_free(mem_ctx); - return ret; - } - } - } - - if (delegated_proxy_principal) { - deleg_blob = talloc_zero(mem_ctx, DATA_BLOB); - if (!deleg_blob) { - talloc_free(mem_ctx); - return ENOMEM; - } - - nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, - context, *pac, - server->entry.principal, - delegated_proxy_principal, - deleg_blob); + NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Building PAC failed: %s\n", nt_errstr(nt_status))); @@ -308,6 +331,18 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, } kdc_checksum_idx = i; break; + case PAC_TYPE_TICKET_CHECKSUM: + if (tkt_checksum_idx != -1) { + DEBUG(1, ("ticket checksum type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + tkt_checksum_idx, + i)); + SAFE_FREE(types); + talloc_free(mem_ctx); + return EINVAL; + } + tkt_checksum_idx = i; + break; default: continue; } @@ -471,6 +506,131 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, return ret; } +/* Resign (and reform, including possibly new groups) a PAC */ + +static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + const krb5_principal client_principal, + const krb5_principal delegated_proxy_principal, + struct hdb_entry_ex *client, + struct hdb_entry_ex *server, + struct hdb_entry_ex *krbtgt, + krb5_pac *pac) +{ + struct samba_kdc_entry *krbtgt_skdc_entry = + talloc_get_type_abort(krbtgt->ctx, + struct samba_kdc_entry); + krb5_error_code ret; + krb5_cksumtype ctype = CKSUMTYPE_NONE; + struct hdb_entry_ex signing_krbtgt_hdb; + + if (delegated_proxy_principal) { + uint16_t rodc_id; + unsigned int my_krbtgt_number; + + /* + * We're using delegated_proxy_principal for the moment to + * indicate cases where the ticket was encrypted with the server + * key, and not a krbtgt key. This cannot be trusted, so we need + * to find a krbtgt key that signs the PAC in order to trust the + * ticket. + * + * The krbtgt passed in to this function refers to the krbtgt + * used to decrypt the ticket of the server requesting + * S4U2Proxy. + * + * When we implement service ticket renewal, we need to check + * the PAC, and this will need to be updated. + */ + ret = krb5_pac_get_kdc_checksum_info(context, + *pac, + &ctype, + &rodc_id); + if (ret != 0) { + DEBUG(1, ("Failed to get PAC checksum info\n")); + return ret; + } + + /* + * We need to check the KDC and ticket signatures, fetching the + * correct key based on the enctype. + */ + + my_krbtgt_number = krbtgt_skdc_entry->kdc_db_ctx->my_krbtgt_number; + + if (my_krbtgt_number != 0) { + /* + * If we are an RODC, and we are not the KDC that signed + * the evidence ticket, then we need to proxy the + * request. + */ + if (rodc_id != my_krbtgt_number) { + return HDB_ERR_NOT_FOUND_HERE; + } + } else { + /* + * If we are a DC, the ticket may have been signed by a + * different KDC than the one that issued the header + * ticket. + */ + if (rodc_id != krbtgt->entry.kvno >> 16) { + struct sdb_entry_ex signing_krbtgt_sdb; + + /* + * If we didn't sign the ticket, then return an + * error. + */ + if (rodc_id != 0) { + return KRB5KRB_AP_ERR_MODIFIED; + } + + /* + * Fetch our key from the database. To support + * key rollover, we're going to need to try + * multiple keys by trial and error. For now, + * krbtgt keys aren't assumed to change. + */ + ret = samba_kdc_fetch(context, + krbtgt_skdc_entry->kdc_db_ctx, + krbtgt->entry.principal, + SDB_F_GET_KRBTGT | SDB_F_CANON, + 0, + &signing_krbtgt_sdb); + if (ret != 0) { + return ret; + } + + ret = sdb_entry_ex_to_hdb_entry_ex(context, + &signing_krbtgt_sdb, + &signing_krbtgt_hdb); + sdb_free_entry(&signing_krbtgt_sdb); + if (ret != 0) { + return ret; + } + + /* + * Replace the krbtgt entry with our own entry + * for further processing. + */ + krbtgt = &signing_krbtgt_hdb; + } + } + } + + ret = samba_wdc_reget_pac2(context, + delegated_proxy_principal, + client, + server, + krbtgt, + pac, + ctype); + + if (krbtgt == &signing_krbtgt_hdb) { + hdb_free_entry(context, &signing_krbtgt_hdb); + } + + return ret; +} + static char *get_netbios_name(TALLOC_CTX *mem_ctx, HostAddresses *addrs) { char *nb_name = NULL; -- 2.25.1 From f2e296901932f98d3aba956b78bd31bd15ef1ec8 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Sun, 10 Oct 2021 21:55:59 -0500 Subject: [PATCH 356/645] krb5: Fix PAC signature leak affecting KDC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 [jsutton@samba.org Cherry-picked from Heimdal commit 54581d2d52443a9a07ed5980df331f660b397dcf] Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit f6adfefbbb41b9100736134d0f975f1ec0c33c42) --- source4/heimdal/lib/krb5/pac.c | 136 +++++++++++++++------------------ 1 file changed, 61 insertions(+), 75 deletions(-) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index f6d38178a88..05bcc523080 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -1018,9 +1018,10 @@ _krb5_pac_sign(krb5_context context, uint32_t server_offset = 0, priv_offset = 0, ticket_offset = 0; uint32_t server_cksumtype = 0, priv_cksumtype = 0; int num = 0; - size_t i; + size_t i, sz; krb5_data logon, d; + krb5_data_zero(&d); krb5_data_zero(&logon); for (i = 0; i < p->pac->numbuffers; i++) { @@ -1080,8 +1081,10 @@ _krb5_pac_sign(krb5_context context, void *ptr; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); - if (ptr == NULL) - return krb5_enomem(context); + if (ptr == NULL) { + ret = krb5_enomem(context); + goto out; + } p->pac = ptr; @@ -1109,30 +1112,33 @@ _krb5_pac_sign(krb5_context context, /* Calculate LOGON NAME */ ret = build_logon_name(context, authtime, principal, &logon); - if (ret) - goto out; /* Set lengths for checksum */ - ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); - if (ret) - goto out; + if (ret == 0) + ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); - ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); - if (ret) - goto out; + if (ret == 0) + ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); /* Encode PAC */ - sp = krb5_storage_emem(); - if (sp == NULL) - return krb5_enomem(context); - - krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + if (ret == 0) { + sp = krb5_storage_emem(); + if (sp == NULL) + ret = krb5_enomem(context); + } - spdata = krb5_storage_emem(); - if (spdata == NULL) { - krb5_storage_free(sp); - return krb5_enomem(context); + if (ret == 0) { + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + spdata = krb5_storage_emem(); + if (spdata == NULL) { + krb5_storage_free(sp); + ret = krb5_enomem(context); + } } + + if (ret) + goto out; + krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out); @@ -1222,77 +1228,56 @@ _krb5_pac_sign(krb5_context context, /* assert (server_offset != 0 && priv_offset != 0); */ /* export PAC */ - ret = krb5_storage_to_data(spdata, &d); - if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); - goto out; - } - ret = krb5_storage_write(sp, d.data, d.length); - if (ret != (int)d.length) { - krb5_data_free(&d); - ret = krb5_enomem(context); - goto out; + if (ret == 0) + ret = krb5_storage_to_data(spdata, &d); + if (ret == 0) { + sz = krb5_storage_write(sp, d.data, d.length); + if (sz != d.length) { + krb5_data_free(&d); + ret = krb5_enomem(context); + goto out; + } } krb5_data_free(&d); - ret = krb5_storage_to_data(sp, &d); - if (ret) { - ret = krb5_enomem(context); - goto out; - } + if (ret == 0) + ret = krb5_storage_to_data(sp, &d); /* sign */ - if (p->ticket_sign_data.length) { + if (ret == 0 && p->ticket_sign_data.length) ret = create_checksum(context, priv_key, priv_cksumtype, p->ticket_sign_data.data, p->ticket_sign_data.length, (char *)d.data + ticket_offset, priv_size); - if (ret) { - krb5_data_free(&d); - goto out; - } - } - ret = create_checksum(context, server_key, server_cksumtype, - d.data, d.length, - (char *)d.data + server_offset, server_size); - if (ret) { - krb5_data_free(&d); - goto out; - } - ret = create_checksum(context, priv_key, priv_cksumtype, - (char *)d.data + server_offset, server_size, - (char *)d.data + priv_offset, priv_size); - if (ret) { - krb5_data_free(&d); - goto out; - } - - if (rodc_id != 0) { + if (ret == 0) + ret = create_checksum(context, server_key, server_cksumtype, + d.data, d.length, + (char *)d.data + server_offset, server_size); + if (ret == 0) + ret = create_checksum(context, priv_key, priv_cksumtype, + (char *)d.data + server_offset, server_size, + (char *)d.data + priv_offset, priv_size); + if (ret == 0 && rodc_id != 0) { krb5_data rd; krb5_storage *rs = krb5_storage_emem(); - if (rs == NULL) { - krb5_data_free(&d); + if (rs == NULL) ret = krb5_enomem(context); - goto out; - } krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE); - ret = krb5_store_uint16(rs, rodc_id); - if (ret) { - krb5_storage_free(rs); - krb5_data_free(&d); - goto out; - } - ret = krb5_storage_to_data(rs, &rd); + if (ret == 0) + ret = krb5_store_uint16(rs, rodc_id); + if (ret == 0) + ret = krb5_storage_to_data(rs, &rd); krb5_storage_free(rs); - if (ret) { - krb5_data_free(&d); + if (ret) goto out; - } heim_assert(rd.length == sizeof(rodc_id), "invalid length"); memcpy((char *)d.data + priv_offset + priv_size, rd.data, rd.length); krb5_data_free(&rd); } + if (ret) + goto out; + /* done */ *data = d; @@ -1302,6 +1287,7 @@ _krb5_pac_sign(krb5_context context, return 0; out: + krb5_data_free(&d); krb5_data_free(&logon); if (sp) krb5_storage_free(sp); @@ -1528,8 +1514,8 @@ _krb5_kdc_pac_sign_ticket(krb5_context context, ret = _krb5_pac_sign(context, pac, tkt->authtime, client, server_key, kdc_key, rodc_id, &rspac); - if (ret) - return ret; - - return _kdc_tkt_insert_pac(context, tkt, &rspac); + if (ret == 0) + ret = _kdc_tkt_insert_pac(context, tkt, &rspac); + krb5_data_free(&rspac); + return ret; } -- 2.25.1 From 74564140a37bdcc046a48e8ae56e587cea94c2de Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 15 Oct 2021 13:09:20 +1300 Subject: [PATCH 357/645] selftest/dbcheck: Fix up RODC one-way links (use correct dbcheck rule) The previous commit was correct on intention, but it was not noticed as there is a race, that the incorrect rule was appended to. These links are removed by remove_plausible_deleted_DN_links not fix_all_old_dn_string_component_mismatch BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri Oct 15 10:00:47 UTC 2021 on sn-devel-184 (cherry picked from commit a7ad665e65f0701eb75cac5bc10a366ccd9689f4) --- testprogs/blackbox/dbcheck.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testprogs/blackbox/dbcheck.sh b/testprogs/blackbox/dbcheck.sh index e2ba987e2de..5462441005e 100755 --- a/testprogs/blackbox/dbcheck.sh +++ b/testprogs/blackbox/dbcheck.sh @@ -19,12 +19,12 @@ dbcheck() { # This list of attributes can be freely extended dbcheck_fix_one_way_links() { - $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes fix_all_old_dn_string_component_mismatch --attrs="lastKnownParent defaultObjectCategory fromServer rIDSetReferences msDS-RevealOnDemandGroup msDS-NeverRevealGroup" --cross-ncs $ARGS + $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes fix_all_old_dn_string_component_mismatch --attrs="lastKnownParent defaultObjectCategory fromServer rIDSetReferences" --cross-ncs $ARGS } # This list of attributes can be freely extended dbcheck_fix_stale_links() { - $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes remove_plausible_deleted_DN_links --attrs="member msDS-NC-Replica-Locations msDS-NC-RO-Replica-Locations" --cross-ncs $ARGS + $PYTHON $BINDIR/samba-tool dbcheck --quiet --fix --yes remove_plausible_deleted_DN_links --attrs="member msDS-NC-Replica-Locations msDS-NC-RO-Replica-Locations msDS-RevealOnDemandGroup msDS-NeverRevealGroup" --cross-ncs $ARGS } # This list of attributes can be freely extended -- 2.25.1 From a98c4af8f6343222ace072b304b9c8e9fba5a8f7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 15 Oct 2021 12:12:30 +1300 Subject: [PATCH 358/645] heimdal:kdc: Fix ticket signing without a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit d23d8e859357b0fac4d1f4a49f1dce6cf60d6216) --- source4/heimdal/kdc/krb5tgs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 24a4f261766..b0c873a4ffb 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -695,10 +695,12 @@ tgs_make_reply(krb5_context context, } /* The PAC should be the last change to the ticket. */ - ret = _krb5_kdc_pac_sign_ticket(context, mspac, tgt_name, serverkey, - krbtgtkey, rodc_id, add_ticket_sig, &et); + if (mspac != NULL) { + ret = _krb5_kdc_pac_sign_ticket(context, mspac, tgt_name, serverkey, + krbtgtkey, rodc_id, add_ticket_sig, &et); if (ret) goto out; + } /* It is somewhat unclear where the etype in the following encryption should come from. What we have is a session -- 2.25.1 From 8abcb3eb029d180f9ece17d0f17bf6f8688c74b5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 15 Oct 2021 14:26:40 +1300 Subject: [PATCH 359/645] tests/krb5: Allow get_tgt() to request including or omitting a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit e086c6193f6da6fcb5d0bcada2199e9bc7ad25f5) --- python/samba/tests/krb5/kdc_base_test.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 87160f675ae..1fc15315b0b 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1306,9 +1306,9 @@ class KDCBaseTest(RawKerberosTest): def get_tgt(self, creds, to_rodc=False, kdc_options=None, expected_flags=None, unexpected_flags=None, - fresh=False): + pac_request=True, expect_pac=True, fresh=False): user_name = creds.get_username() - cache_key = (user_name, to_rodc, kdc_options) + cache_key = (user_name, to_rodc, kdc_options, pac_request) if not fresh: tgt = self.tkt_cache.get(cache_key) @@ -1363,7 +1363,7 @@ class KDCBaseTest(RawKerberosTest): kdc_options=kdc_options, preauth_key=None, ticket_decryption_key=ticket_decryption_key, - pac_request=True, + pac_request=pac_request, pac_options=pac_options, to_rodc=to_rodc) self.check_pre_authentication(rep) @@ -1405,8 +1405,9 @@ class KDCBaseTest(RawKerberosTest): kdc_options=kdc_options, preauth_key=preauth_key, ticket_decryption_key=ticket_decryption_key, - pac_request=True, + pac_request=pac_request, pac_options=pac_options, + expect_pac=expect_pac, to_rodc=to_rodc) self.check_as_reply(rep) -- 2.25.1 From 2edd6f53eeb099c0094cb94028d2a7e856f79f6b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 15 Oct 2021 14:27:15 +1300 Subject: [PATCH 360/645] tests/krb5: Allow specifying whether to expect a PAC with _test_as_exchange() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 0dc69c1327f72384628a869a00482f6528b8671b) --- python/samba/tests/krb5/raw_testcase.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index e008223eb23..29dc5f397b6 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3530,6 +3530,7 @@ class RawKerberosTest(TestCaseInTempDir): ticket_decryption_key=None, pac_request=None, pac_options=None, + expect_pac=True, to_rodc=False): def _generate_padata_copy(_kdc_exchange_dict, @@ -3569,6 +3570,7 @@ class RawKerberosTest(TestCaseInTempDir): kdc_options=str(kdc_options), pac_request=pac_request, pac_options=pac_options, + expect_pac=expect_pac, to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, -- 2.25.1 From 6232ce9969aa2b77eddc9c5a9d2ddf332fc79a71 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 15 Oct 2021 14:27:25 +1300 Subject: [PATCH 361/645] tests/krb5: Add method to get the PAC from a ticket BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 288355896a2b6f460c42559ec46ff980ab57782e) --- python/samba/tests/krb5/raw_testcase.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 29dc5f397b6..0790ac13f99 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3447,6 +3447,15 @@ class RawKerberosTest(TestCaseInTempDir): _, pac = self.replace_pac(auth_data, None, expect_pac) return pac + def get_ticket_pac(self, ticket, expect_pac=True): + auth_data = ticket.ticket_private.get('authorization-data') + if expect_pac: + self.assertIsNotNone(auth_data) + elif auth_data is None: + return None + + return self.get_pac(auth_data, expect_pac=expect_pac) + def get_krbtgt_checksum_key(self): krbtgt_creds = self.get_krbtgt_creds() krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) -- 2.25.1 From eb582f10383de305abd590402b1af2ca0473c050 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 15 Oct 2021 14:29:26 +1300 Subject: [PATCH 362/645] tests/krb5: Add tests for requesting a service ticket without a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Sun Oct 17 23:40:33 UTC 2021 on sn-devel-184 [abartlet@samba.org backported from commit 9d3a691920205f8a9dc05d0e173e25e6a335f139 as the MIT KDC 1.16 seen on the reference Ubuntu 18.04 does not fail test_remove_pac] --- python/samba/tests/krb5/kdc_tgs_tests.py | 120 +++++++++++++++++++++++ selftest/knownfail_heimdal_kdc | 5 + selftest/knownfail_mit_kdc | 4 + 3 files changed, 129 insertions(+) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 3075cc6b0a9..9d846a2c3ad 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -23,15 +23,18 @@ import os sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" +import samba.tests.krb5.kcrypto as kcrypto from samba.tests.krb5.kdc_base_test import KDCBaseTest from samba.tests.krb5.rfc4120_constants import ( AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5, KRB_ERROR, + KRB_TGS_REP, KDC_ERR_BADMATCH, NT_PRINCIPAL, NT_SRV_INST, ) +import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 global_asn1_print = False global_hexdump = False @@ -209,6 +212,123 @@ class KdcTgsTests(KDCBaseTest): pac_data.account_sid, "rep = {%s},%s" % (rep, pac_data)) + def _make_tgs_request(self, client_creds, service_creds, tgt, + expect_pac=True): + 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) + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=expected_crealm, + expected_cname=expected_cname, + expected_srealm=expected_srealm, + expected_sname=expected_sname, + expected_supported_etypes=expected_supported_etypes, + ticket_decryption_key=target_decryption_key, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=0, + tgt=tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=kdc_options, + expect_pac=expect_pac) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=cname, + realm=realm, + sname=sname, + etypes=etypes) + self.check_reply(rep, KRB_TGS_REP) + + return kdc_exchange_dict['rep_ticket_creds'] + + def test_request_no_pac(self): + client_creds = self.get_client_creds() + service_creds = self.get_service_creds() + + tgt = self.get_tgt(client_creds, pac_request=False, + expect_pac=False) + + pac = self.get_ticket_pac(tgt, expect_pac=False) + self.assertIsNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_client_no_auth_data_required(self): + client_creds = self.get_cached_creds( + machine_account=False, + opts={'no_auth_data_required': True}) + service_creds = self.get_service_creds() + + tgt = self.get_tgt(client_creds) + + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_service_no_auth_data_required(self): + client_creds = self.get_client_creds() + service_creds = self.get_cached_creds( + machine_account=True, + opts={'no_auth_data_required': True}) + + tgt = self.get_tgt(client_creds) + + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_remove_pac(self): + client_creds = self.get_client_creds() + service_creds = self.get_service_creds() + + tgt = self.modified_ticket(self.get_tgt(client_creds), + exclude_pac=True) + + pac = self.get_ticket_pac(tgt, expect_pac=False) + self.assertIsNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + if __name__ == "__main__": global_asn1_print = False diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 683dbacb979..32cfa2afa88 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -141,3 +141,8 @@ # KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case # ^samba4.krb5.kdc with machine account.as-req-pac-request.fl2000dc:local +# +# TGS tests +# +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_client_no_auth_data_required +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 09efbc7b590..00f652db14a 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -276,6 +276,10 @@ 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_ldap_service_ticket\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) # +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_client_no_auth_data_required\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required\(ad_dc\) +# # MIT currently fails the following MS-KILE 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 -- 2.25.1 From fea85c12b88d4078bc328f4ef2d22dcfe2e33103 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 18 Oct 2021 15:21:50 +1300 Subject: [PATCH 363/645] kdc: Remove UF_NO_AUTH_DATA_REQUIRED from client principals Tests against Windows 2019 show that UF_NO_AUTH_DATA_REQUIRED applies to services only, not to clients. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher [abartlet@samba.org backported from commit 92e8ce18a79e88c9b961dc20e39436c4cf653013 as there was a knownfail conflict with the test_remove_pac case which succeeds on this branch] --- selftest/knownfail_heimdal_kdc | 1 - selftest/knownfail_mit_kdc | 1 - source4/kdc/mit_samba.c | 7 ------- source4/kdc/pac-glue.c | 5 ----- 4 files changed, 14 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 32cfa2afa88..4d058bad3da 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -144,5 +144,4 @@ # # TGS tests # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_client_no_auth_data_required ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 00f652db14a..0f845fb9b1c 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -276,7 +276,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_ldap_service_ticket\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_client_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required\(ad_dc\) # diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 2936fe2d18a..689e14e1c38 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -495,18 +495,11 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, ssize_t srv_checksum_idx = -1; ssize_t kdc_checksum_idx = -1; krb5_pac new_pac = NULL; - bool ok; if (client != NULL) { client_skdc_entry = talloc_get_type_abort(client->e_data, struct samba_kdc_entry); - - /* The user account may be set not to want the PAC */ - ok = samba_princ_needs_pac(client_skdc_entry); - if (!ok) { - return EINVAL; - } } if (server == NULL) { diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 88bcb734fc5..688103d8477 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -651,11 +651,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, } *_upn_info_blob = NULL; - /* The user account may be set not to want the PAC */ - if ( ! samba_princ_needs_pac(p)) { - return NT_STATUS_OK; - } - logon_blob = talloc_zero(mem_ctx, DATA_BLOB); if (logon_blob == NULL) { return NT_STATUS_NO_MEMORY; -- 2.25.1 From d660c179046a2e75da3382845f92646e524231b3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 18 Oct 2021 16:00:45 +1300 Subject: [PATCH 364/645] kdc: Correctly strip PAC, rather than error on UF_NO_AUTH_DATA_REQUIRED for servers UF_NO_AUTH_DATA_REQUIRED on a server/service account should cause the PAC to be stripped not to given an error if the PAC was still present. Tested against Windows 2019 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher (cherry picked from commit 031a8287642e3c4b9d0b7c6b51f3b1d79b227542) --- selftest/knownfail_heimdal_kdc | 4 ---- source4/kdc/wdc-samba4.c | 38 +++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 4d058bad3da..683dbacb979 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -141,7 +141,3 @@ # KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case # ^samba4.krb5.kdc with machine account.as-req-pac-request.fl2000dc:local -# -# TGS tests -# -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index 589df8a651d..ac9d7d51733 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -105,13 +105,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, krb5_pac *pac, krb5_cksumtype ctype) { - struct samba_kdc_entry *p = + struct samba_kdc_entry *server_skdc_entry = talloc_get_type_abort(server->ctx, struct samba_kdc_entry); struct samba_kdc_entry *krbtgt_skdc_entry = talloc_get_type_abort(krbtgt->ctx, struct samba_kdc_entry); - TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac2 context"); + TALLOC_CTX *mem_ctx = talloc_named(server_skdc_entry, + 0, + "samba_kdc_reget_pac2 context"); krb5_pac new_pac = NULL; DATA_BLOB *pac_blob = NULL; DATA_BLOB *upn_blob = NULL; @@ -135,12 +137,6 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, return ENOMEM; } - /* The user account may be set not to want the PAC */ - if (!samba_princ_needs_pac(p)) { - talloc_free(mem_ctx); - return EINVAL; - } - /* If the krbtgt was generated by an RODC, and we are not that * RODC, then we need to regenerate the PAC - we can't trust * it */ @@ -373,12 +369,28 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, return EINVAL; } - /* Build an updated PAC */ + /* + * The server account may be set not to want the PAC. + * + * While this is wasteful if the above cacluations were done + * and now thrown away, this is cleaner as we do any ticket + * signature checking etc always. + * + * UF_NO_AUTH_DATA_REQUIRED is the rare case and most of the + * time (eg not accepting a ticket from the RODC) we do not + * need to re-generate anything anyway. + */ + if (!samba_princ_needs_pac(server_skdc_entry)) { + ret = 0; + new_pac = NULL; + goto out; + } + + /* Otherwise build an updated PAC */ ret = krb5_pac_init(context, &new_pac); if (ret != 0) { - SAFE_FREE(types); - talloc_free(mem_ctx); - return ret; + new_pac = NULL; + goto out; } for (i = 0;;) { @@ -496,6 +508,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, } } +out: + SAFE_FREE(types); /* We now replace the pac */ -- 2.25.1 From 3846b5f445a8816eacfa02e3fb3b47454b8d86f0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 16:05:19 +1300 Subject: [PATCH 365/645] tests/krb5: Ensure PAC is not present if expect_pac is false BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit cc3d27596b9e8a8a46e8ba9c3c1a445477d458cf) --- python/samba/tests/krb5/raw_testcase.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0790ac13f99..0b9fe8e7a04 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2385,13 +2385,6 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementPresent(ticket_private, 'authorization-data', expect_empty=not expect_pac) - if expect_pac: - authorization_data = self.getElementValue(ticket_private, - 'authorization-data') - pac_data = self.get_pac(authorization_data) - - self.check_pac_buffers(pac_data, kdc_exchange_dict) - encpart_session_key = None if encpart_private is not None: self.assertElementPresent(encpart_private, 'key') @@ -2493,6 +2486,13 @@ class RawKerberosTest(TestCaseInTempDir): ticket_private=ticket_private, encpart_private=encpart_private) + if ticket_private is not None: + pac_data = self.get_ticket_pac(ticket_creds, expect_pac=expect_pac) + if expect_pac: + self.check_pac_buffers(pac_data, kdc_exchange_dict) + else: + self.assertIsNone(pac_data) + expect_ticket_checksum = kdc_exchange_dict['expect_ticket_checksum'] if expect_ticket_checksum: self.assertIsNotNone(ticket_decryption_key) -- 2.25.1 From 9f2a0bf4cfb2142526b96d7a6153d8bcbfee7918 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 16:07:11 +1300 Subject: [PATCH 366/645] tests/krb5: Add tests for constrained delegation to NO_AUTH_DATA_REQUIRED service BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 20 09:22:43 UTC 2021 on sn-devel-184 (cherry picked from commit 83a654a4efd39a6e792a6d49e0ecf586e9bc53ef) --- python/samba/tests/krb5/s4u_tests.py | 107 ++++++++++++++++++++++++++- selftest/knownfail_heimdal_kdc | 8 +- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 9a25256081a..bbb7135b55b 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -538,6 +538,8 @@ class S4UKerberosTests(KDCBaseTest): transited_service = f'host/{service1_name}@{service1_realm}' expected_transited_services.append(transited_service) + expect_pac = kdc_dict.pop('expect_pac', True) + kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=client_realm, expected_cname=client_cname, @@ -557,7 +559,8 @@ class S4UKerberosTests(KDCBaseTest): pac_options=pac_options, expect_edata=expect_edata, expected_proxy_target=expected_proxy_target, - expected_transited_services=expected_transited_services) + expected_transited_services=expected_transited_services, + expect_pac=expect_pac) self._generic_kdc_exchange(kdc_exchange_dict, cname=None, @@ -577,6 +580,18 @@ class S4UKerberosTests(KDCBaseTest): 'allow_delegation': True }) + def test_constrained_delegation_no_auth_data_required(self): + # Test constrained delegation. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 'service2_opts': { + 'no_auth_data_required': True + }, + 'expect_pac': False + }) + def test_constrained_delegation_existing_delegation_info(self): # Test constrained delegation with an existing S4U_DELEGATION_INFO # structure in the PAC. @@ -624,6 +639,35 @@ class S4UKerberosTests(KDCBaseTest): 'modify_service_tgt_fn': self.remove_ticket_pac }) + def test_constrained_delegation_no_client_pac_no_auth_data_required(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC. + self._run_delegation_test( + { + 'expected_error_mode': (KDC_ERR_BADOPTION, + KDC_ERR_MODIFIED), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False, + 'service2_opts': { + 'no_auth_data_required': True + } + }) + + def test_constrained_delegation_no_service_pac_no_auth_data_required(self): + # Test constrained delegation when the service TGT does not contain a + # PAC. + self._run_delegation_test( + { + 'expected_error_mode': (KDC_ERR_BADOPTION, + KDC_ERR_MODIFIED), + 'allow_delegation': True, + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True + } + }) + def test_constrained_delegation_non_forwardable(self): # Test constrained delegation with a non-forwardable ticket. self._run_delegation_test( @@ -645,6 +689,18 @@ class S4UKerberosTests(KDCBaseTest): 'allow_delegation': True }) + def test_rbcd_no_auth_data_required(self): + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'service2_opts': { + 'no_auth_data_required': True + }, + 'expect_pac': False + }) + def test_rbcd_existing_delegation_info(self): # Test constrained delegation with an existing S4U_DELEGATION_INFO # structure in the PAC. @@ -712,6 +768,55 @@ class S4UKerberosTests(KDCBaseTest): 'modify_service_tgt_fn': self.remove_ticket_pac }) + def test_rbcd_no_client_pac_no_auth_data_required_a(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC, and an empty msDS-AllowedToDelegateTo attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True + } + }) + + def test_rbcd_no_client_pac_no_auth_data_required_b(self): + # Test constrained delegation when the client service ticket does not + # contain a PAC, and a non-empty msDS-AllowedToDelegateTo attribute. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_MODIFIED, + 'expected_status': ntstatus.NT_STATUS_NO_MATCH, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'service1_opts': { + 'delegation_to_spn': ('host/test') + }, + 'service2_opts': { + 'no_auth_data_required': True + } + }) + + def test_rbcd_no_service_pac_no_auth_data_required(self): + # Test constrained delegation when the service TGT does not contain a + # PAC. + self._run_delegation_test( + { + 'expected_error_mode': KDC_ERR_BADOPTION, + 'expected_status': + ntstatus.NT_STATUS_NOT_FOUND, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True + } + }) + def test_rbcd_non_forwardable(self): # Test resource-based constrained delegation with a non-forwardable # ticket. diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 683dbacb979..b1d7a1ebe8f 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -125,7 +125,7 @@ # 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_service_pac +^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_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 @@ -141,3 +141,9 @@ # KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case # ^samba4.krb5.kdc with machine account.as-req-pac-request.fl2000dc:local +# +# +^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 +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_b -- 2.25.1 From eeb22695c5a61b56c25804700a934006da0c0c2f Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 10 Aug 2016 23:31:14 +0000 Subject: [PATCH 367/645] HEIMDAL:kdc: Fix transit path validation CVE-2017-6594 Commit f469fc6 (2010-10-02) inadvertently caused the previous hop realm to not be added to the transit path of issued tickets. This may, in some cases, enable bypass of capath policy in Heimdal versions 1.5 through 7.2. Note, this may break sites that rely on the bug. With the bug some incomplete [capaths] worked, that should not have. These may now break authentication in some cross-realm configurations. (similar to heimdal commit b1e699103f08d6a0ca46a122193c9da65f6cf837) BUG: https://bugzilla.samba.org/show_bug.cgi?id=12998 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 20 10:58:37 UTC 2021 on sn-devel-184 (cherry picked from commit 7e961f3f7a815960ae25377d5b7515184d439690) --- source4/heimdal/kdc/krb5tgs.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index b0c873a4ffb..33120a28d34 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -409,8 +409,12 @@ fix_transited_encoding(krb5_context context, "Decoding transited encoding"); return ret; } + + /* + * If the realm of the presented tgt is neither the client nor the server + * realm, it is a transit realm and must be added to transited set. + */ if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { - /* not us, so add the previous realm to transited set */ if (num_realms + 1 > UINT_MAX/sizeof(*realms)) { ret = ERANGE; goto free_realms; @@ -492,6 +496,7 @@ tgs_make_reply(krb5_context context, const char *server_name, hdb_entry_ex *client, krb5_principal client_principal, + const char *tgt_realm, hdb_entry_ex *krbtgt, krb5_pac mspac, uint16_t rodc_id, @@ -553,7 +558,7 @@ tgs_make_reply(krb5_context context, &tgt->transited, &et, krb5_principal_get_realm(context, client_principal), krb5_principal_get_realm(context, server->entry.principal), - krb5_principal_get_realm(context, krbtgt->entry.principal)); + tgt_realm); if(ret) goto out; @@ -1292,13 +1297,14 @@ tgs_build_reply(krb5_context context, HDB *clientdb, *s4u2self_impersonated_clientdb; krb5_realm ref_realm = NULL; EncTicketPart *tgt = &ticket->ticket; + const char *tgt_realm = /* Realm of TGT issuer */ + krb5_principal_get_realm(context, krbtgt->entry.principal); const EncryptionKey *ekey; krb5_keyblock sessionkey; krb5_kvno kvno; krb5_pac mspac = NULL; uint16_t rodc_id; krb5_boolean add_ticket_sig = FALSE; - hdb_entry_ex *krbtgt_out = NULL; METHOD_DATA enc_pa_data; @@ -2019,6 +2025,7 @@ server_lookup: spn, client, cp, + tgt_realm, krbtgt_out, mspac, rodc_id, -- 2.25.1 From 5292b7c26388e01afdf6b3ae13297a6d1425dc4e Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 8 Sep 2021 17:01:26 +1200 Subject: [PATCH 368/645] pytest/rodc_rwdc: try to avoid race. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14868 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Douglas Bagnall Reviewed-by: Stefan Metzmacher (cherry picked from commit a169e013e66bab15e594ce49b805edebfcd503cf) --- source4/dsdb/tests/python/rodc_rwdc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/dsdb/tests/python/rodc_rwdc.py b/source4/dsdb/tests/python/rodc_rwdc.py index 988eeaf8094..5de78605963 100644 --- a/source4/dsdb/tests/python/rodc_rwdc.py +++ b/source4/dsdb/tests/python/rodc_rwdc.py @@ -251,6 +251,10 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): res = ldb_system.search(userdn, attrs=['unicodePwd']) self.assertTrue('unicodePwd' in res[0]) + # force replication here to flush any pending preloads (this + # was a racy test). + self.force_replication() + newpass = userpass + '!' # Forcing replication should blank out password (when changed) -- 2.25.1 From dc3a26567ffbe94939cb29c399646bd7f4f90c89 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 20 Sep 2021 16:27:40 +1200 Subject: [PATCH 369/645] selftest: Increase account lockout windows to make test more realiable BUG: https://bugzilla.samba.org/show_bug.cgi?id=14868 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit 6292f0597f208d7953382341380921cf0fd0a8a8) --- source4/dsdb/tests/python/rodc_rwdc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/tests/python/rodc_rwdc.py b/source4/dsdb/tests/python/rodc_rwdc.py index 5de78605963..f8b21b8af21 100644 --- a/source4/dsdb/tests/python/rodc_rwdc.py +++ b/source4/dsdb/tests/python/rodc_rwdc.py @@ -289,14 +289,14 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): m = ldb.Message() m.dn = ldb.Dn(self.ldb, self.base_dn) - self.account_lockout_duration = 10 + self.account_lockout_duration = 15 account_lockout_duration_ticks = -int(self.account_lockout_duration * (1e7)) m["lockoutDuration"] = ldb.MessageElement(str(account_lockout_duration_ticks), ldb.FLAG_MOD_REPLACE, "lockoutDuration") - self.lockout_observation_window = 10 + self.lockout_observation_window = 15 lockout_observation_window_ticks = -int(self.lockout_observation_window * (1e7)) m["lockOutObservationWindow"] = ldb.MessageElement(str(lockout_observation_window_ticks), -- 2.25.1 From b4e069a14f10ec67814551b4fa5619eee72d8ea1 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 6 Aug 2021 11:08:10 +1200 Subject: [PATCH 370/645] pytest: dynamic tests optionally add __doc__ BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Douglas Bagnall Reviewed-by: Stefan Metzmacher (cherry picked from commit aacb18f920349e13b562c7c97901a0be7b273137) --- python/samba/tests/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index 9d5128bab0e..d7abffe4060 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -71,7 +71,7 @@ class TestCase(unittest.TestCase): """A Samba test case.""" @classmethod - def generate_dynamic_test(cls, fnname, suffix, *args): + def generate_dynamic_test(cls, fnname, suffix, *args, doc=None): """ fnname is something like "test_dynamic_sum" suffix is something like "1plus2" @@ -84,6 +84,7 @@ class TestCase(unittest.TestCase): """ def fn(self): getattr(self, "_%s_with_args" % fnname)(*args) + fn.__doc__ = doc setattr(cls, "%s_%s" % (fnname, suffix), fn) @classmethod -- 2.25.1 From 63c549855fa8968185c4137e02403b3bb3f4d4ee Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:40:09 +1300 Subject: [PATCH 371/645] selftest: krb5 account creation: clarify account type as an enum This makes the code clearer with a symbolic constant rather than a True/False boolean. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit 49306f74eb29a2192019fab9260f9d242f9d5fd9) --- .../tests/krb5/as_canonicalization_tests.py | 7 ++- python/samba/tests/krb5/kdc_base_test.py | 63 ++++++++++++------- python/samba/tests/krb5/kdc_tgs_tests.py | 7 ++- .../ms_kile_client_principal_lookup_tests.py | 36 +++++++---- python/samba/tests/krb5/rodc_tests.py | 4 +- python/samba/tests/krb5/s4u_tests.py | 35 ++++++----- python/samba/tests/krb5/test_ccache.py | 11 ++-- 7 files changed, 100 insertions(+), 63 deletions(-) diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 9538d0ae3cf..674fcb37101 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -171,9 +171,10 @@ class KerberosASCanonicalizationTests(KDCBaseTest): def machine_account_creds(self): if self.machine_creds is None: samdb = self.get_samdb() - self.machine_creds, _ = self.create_account(samdb, - MACHINE_NAME, - machine_account=True) + self.machine_creds, _ = self.create_account( + samdb, + MACHINE_NAME, + account_type=self.AccountType.COMPUTER) self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) self.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1fc15315b0b..7cd3c5255f2 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -23,6 +23,7 @@ import tempfile import binascii import collections import secrets +from enum import Enum, auto from collections import namedtuple import ldb @@ -90,6 +91,10 @@ class KDCBaseTest(RawKerberosTest): """ Base class for KDC tests. """ + class AccountType(Enum): + USER = auto() + COMPUTER = auto() + @classmethod def setUpClass(cls): super().setUpClass() @@ -230,7 +235,7 @@ class KDCBaseTest(RawKerberosTest): return default_enctypes - def create_account(self, samdb, name, machine_account=False, + def create_account(self, samdb, name, account_type=AccountType.USER, spn=None, upn=None, additional_details=None, ou=None, account_control=0): '''Create an account for testing. @@ -238,8 +243,10 @@ class KDCBaseTest(RawKerberosTest): which is used by tearDownClass to clean up the created accounts. ''' if ou is None: - guid = (DS_GUID_COMPUTERS_CONTAINER if machine_account - else DS_GUID_USERS_CONTAINER) + if account_type is account_type.COMPUTER: + guid = DS_GUID_COMPUTERS_CONTAINER + else: + guid = DS_GUID_USERS_CONTAINER ou = samdb.get_wellknown_dn(samdb.get_default_basedn(), guid) @@ -248,14 +255,17 @@ class KDCBaseTest(RawKerberosTest): # remove the account if it exists, this will happen if a previous test # run failed delete_force(samdb, dn) - if machine_account: - object_class = "computer" - account_name = "%s$" % name - account_control |= UF_WORKSTATION_TRUST_ACCOUNT - else: + if account_type is self.AccountType.USER: object_class = "user" account_name = name account_control |= UF_NORMAL_ACCOUNT + else: + object_class = "computer" + account_name = "%s$" % name + if account_type is self.AccountType.COMPUTER: + account_control |= UF_WORKSTATION_TRUST_ACCOUNT + else: + self.fail() password = generate_random_password(32, 32) utf16pw = ('"%s"' % password).encode('utf-16-le') @@ -267,6 +277,10 @@ class KDCBaseTest(RawKerberosTest): "userAccountControl": str(account_control), "unicodePwd": utf16pw} if spn is not None: + if isinstance(spn, str): + spn = spn.format(account=account_name) + else: + spn = tuple(s.format(account=account_name) for s in spn) details["servicePrincipalName"] = spn if upn is not None: details["userPrincipalName"] = upn @@ -280,10 +294,10 @@ class KDCBaseTest(RawKerberosTest): creds.set_domain(samdb.domain_netbios_name().upper()) creds.set_password(password) creds.set_username(account_name) - if machine_account: - creds.set_workstation(name) - else: + if account_type is self.AccountType.USER: creds.set_workstation('') + else: + creds.set_workstation(name) creds.set_dn(ldb.Dn(samdb, dn)) creds.set_spn(spn) # @@ -609,13 +623,14 @@ class KDCBaseTest(RawKerberosTest): return cleanup def get_cached_creds(self, *, - machine_account, + account_type, opts=None, use_cache=True): if opts is None: opts = {} opts_default = { + 'spn': None, 'allowed_replication': False, 'allowed_replication_mock': False, 'denied_replication': False, @@ -632,7 +647,7 @@ class KDCBaseTest(RawKerberosTest): } account_opts = { - 'machine_account': machine_account, + 'account_type': account_type, **opts_default, **opts } @@ -651,7 +666,8 @@ class KDCBaseTest(RawKerberosTest): return creds def create_account_opts(self, *, - machine_account, + account_type, + spn, allowed_replication, allowed_replication_mock, denied_replication, @@ -665,12 +681,13 @@ class KDCBaseTest(RawKerberosTest): delegation_from_dn, trusted_to_auth_for_delegation, fast_support): - if machine_account: - self.assertFalse(not_delegated) - else: + if account_type is self.AccountType.USER: + self.assertIsNone(spn) self.assertIsNone(delegation_to_spn) self.assertIsNone(delegation_from_dn) self.assertFalse(trusted_to_auth_for_delegation) + else: + self.assertFalse(not_delegated) samdb = self.get_samdb() rodc_samdb = self.get_rodc_samdb() @@ -707,13 +724,11 @@ class KDCBaseTest(RawKerberosTest): details['msDS-AllowedToActOnBehalfOfOtherIdentity'] = ( security_descriptor) - if machine_account: + if spn is None and account_type is not self.AccountType.USER: spn = 'host/' + user_name - else: - spn = None creds, dn = self.create_account(samdb, user_name, - machine_account=machine_account, + account_type=account_type, spn=spn, additional_details=details, account_control=user_account_control) @@ -787,7 +802,7 @@ class KDCBaseTest(RawKerberosTest): allow_missing_password=False, allow_missing_keys=True): def create_client_account(): - return self.get_cached_creds(machine_account=False) + return self.get_cached_creds(account_type=self.AccountType.USER) c = self._get_krb5_creds(prefix='CLIENT', allow_missing_password=allow_missing_password, @@ -799,7 +814,7 @@ class KDCBaseTest(RawKerberosTest): allow_missing_password=False, allow_missing_keys=True): def create_mach_account(): - return self.get_cached_creds(machine_account=True, + return self.get_cached_creds(account_type=self.AccountType.COMPUTER, opts={'fast_support': True}) c = self._get_krb5_creds(prefix='MAC', @@ -813,7 +828,7 @@ class KDCBaseTest(RawKerberosTest): allow_missing_keys=True): def create_service_account(): return self.get_cached_creds( - machine_account=True, + account_type=self.AccountType.COMPUTER, opts={ 'trusted_to_auth_for_delegation': True, 'fast_support': True diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 9d846a2c3ad..f36704f998c 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -148,7 +148,8 @@ class KdcTgsTests(KDCBaseTest): samdb = self.get_samdb() user_name = "tsttktusr" (uc, dn) = self.create_account(samdb, user_name) - (mc, _) = self.create_account(samdb, "tsttktmac", machine_account=True) + (mc, _) = self.create_account(samdb, "tsttktmac", + account_type=self.AccountType.COMPUTER) realm = uc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required @@ -282,7 +283,7 @@ class KdcTgsTests(KDCBaseTest): def test_client_no_auth_data_required(self): client_creds = self.get_cached_creds( - machine_account=False, + account_type=self.AccountType.USER, opts={'no_auth_data_required': True}) service_creds = self.get_service_creds() @@ -299,7 +300,7 @@ class KdcTgsTests(KDCBaseTest): def test_service_no_auth_data_required(self): client_creds = self.get_client_creds() service_creds = self.get_cached_creds( - machine_account=True, + account_type=self.AccountType.COMPUTER, opts={'no_auth_data_required': True}) tgt = self.get_tgt(client_creds) diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py index 2ee3d4a2a83..0aa3309b814 100755 --- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py @@ -95,7 +95,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -151,7 +152,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): # samdb = self.get_samdb() mach_name = "mskilemac" - (mc, dn) = self.create_account(samdb, mach_name, machine_account=True) + (mc, dn) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) realm = mc.get_realm().lower() # Do the initial AS-REQ, should get a pre-authentication required @@ -215,7 +217,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -286,7 +289,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH # we should get a valid AS-RESP @@ -351,7 +355,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -420,7 +425,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): self.add_attribute(samdb, dn, "altSecurityIdentities", alt_sec) mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -459,7 +465,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -523,7 +530,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ename = user_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -586,7 +594,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): realm = uc.get_realm().lower() mach_name = "mskilemac" - (mc, dn) = self.create_account(samdb, mach_name, machine_account=True) + (mc, dn) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) ename = mach_name + "@" + realm uname = mach_name + "$@" + realm @@ -661,7 +670,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ename = alt_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, as we've set UF_DONT_REQUIRE_PREAUTH # we should get a valid AS-RESP @@ -728,7 +738,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): uname = user_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response @@ -798,7 +809,8 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): ename = alt_name + "@" + realm mach_name = "mskilemac" - (mc, _) = self.create_account(samdb, mach_name, machine_account=True) + (mc, _) = self.create_account(samdb, mach_name, + account_type=self.AccountType.COMPUTER) # Do the initial AS-REQ, should get a pre-authentication required # response diff --git a/python/samba/tests/krb5/rodc_tests.py b/python/samba/tests/krb5/rodc_tests.py index 4579f9eb552..302ae865cf1 100755 --- a/python/samba/tests/krb5/rodc_tests.py +++ b/python/samba/tests/krb5/rodc_tests.py @@ -39,12 +39,12 @@ class RodcKerberosTests(KDCBaseTest): # and including the RODCIdentifier. def test_rodc_ticket_signature(self): user_creds = self.get_cached_creds( - machine_account=False, + account_type=self.AccountType.USER, opts={ 'revealed_to_rodc': True }) target_creds = self.get_cached_creds( - machine_account=True, + account_type=self.AccountType.COMPUTER, opts={ 'revealed_to_rodc': True }) diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index bbb7135b55b..ea629d29706 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -220,12 +220,14 @@ class S4UKerberosTests(KDCBaseTest): def _run_s4u2self_test(self, kdc_dict): client_opts = kdc_dict.pop('client_opts', None) - client_creds = self.get_cached_creds(machine_account=False, - opts=client_opts) + client_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts=client_opts) service_opts = kdc_dict.pop('service_opts', None) - service_creds = self.get_cached_creds(machine_account=True, - opts=service_opts) + service_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts=service_opts) service_tgt = self.get_tgt(service_creds) modify_service_tgt_fn = kdc_dict.pop('modify_service_tgt_fn', None) @@ -432,8 +434,9 @@ class S4UKerberosTests(KDCBaseTest): def _run_delegation_test(self, kdc_dict): client_opts = kdc_dict.pop('client_opts', None) - client_creds = self.get_cached_creds(machine_account=False, - opts=client_opts) + client_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts=client_opts) service1_opts = kdc_dict.pop('service1_opts', {}) service2_opts = kdc_dict.pop('service2_opts', {}) @@ -443,24 +446,28 @@ class S4UKerberosTests(KDCBaseTest): self.assertFalse(allow_delegation and allow_rbcd) if allow_rbcd: - service1_creds = self.get_cached_creds(machine_account=True, - opts=service1_opts) + service1_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts=service1_opts) self.assertNotIn('delegation_from_dn', service2_opts) service2_opts['delegation_from_dn'] = str(service1_creds.get_dn()) - service2_creds = self.get_cached_creds(machine_account=True, - opts=service2_opts) + service2_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts=service2_opts) else: - service2_creds = self.get_cached_creds(machine_account=True, - opts=service2_opts) + service2_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts=service2_opts) if allow_delegation: self.assertNotIn('delegation_to_spn', service1_opts) service1_opts['delegation_to_spn'] = service2_creds.get_spn() - service1_creds = self.get_cached_creds(machine_account=True, - opts=service1_opts) + service1_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts=service1_opts) client_tkt_options = kdc_dict.pop('client_tkt_options', 'forwardable') expected_flags = krb5_asn1.TicketFlags(client_tkt_options) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index c44ea02d504..6a2b78398ac 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -55,11 +55,12 @@ class CcacheTests(KDCBaseTest): (user_credentials, _) = self.create_account(samdb, user_name) # Create the machine account. - (mach_credentials, _) = self.create_account(samdb, - mach_name, - machine_account=True, - spn="%s/%s" % (service, - mach_name)) + (mach_credentials, _) = self.create_account( + samdb, + mach_name, + account_type=self.AccountType.COMPUTER, + spn="%s/%s" % (service, + mach_name)) # 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 -- 2.25.1 From 763f74719b0486878c8ecd612b988ae9b86f46d4 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:39:05 +1300 Subject: [PATCH 372/645] tests/krb5: Decrease length of test account prefix This allows us more room to test with different account names. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit a5a6296e57cab2b53617d997c37b4e92d4124cc7) --- python/samba/tests/krb5/kdc_base_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 7cd3c5255f2..8f453b464fd 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -108,7 +108,7 @@ class KDCBaseTest(RawKerberosTest): # An identifier to ensure created accounts have unique names. Windows # caches accounts based on usernames, so account names being different # across test runs avoids previous test runs affecting the results. - cls.account_base = f'krb5_{secrets.token_hex(5)}_' + cls.account_base = f'{secrets.token_hex(4)}_' cls.account_id = 0 # A set containing DNs of accounts created as part of testing. -- 2.25.1 From 16dd9e13a86715ddab6959af19b37469d0d2964f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:41:39 +1300 Subject: [PATCH 373/645] tests/krb5: Allow specifying prefix or suffix for test account names BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit 7e39994ed341883ac4c8c257220c19dbf70c7bc5) --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 8f453b464fd..d8f3969d228 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -630,6 +630,8 @@ class KDCBaseTest(RawKerberosTest): opts = {} opts_default = { + 'name_prefix': None, + 'name_suffix': None, 'spn': None, 'allowed_replication': False, 'allowed_replication_mock': False, @@ -667,6 +669,8 @@ class KDCBaseTest(RawKerberosTest): def create_account_opts(self, *, account_type, + name_prefix, + name_suffix, spn, allowed_replication, allowed_replication_mock, @@ -696,6 +700,10 @@ class KDCBaseTest(RawKerberosTest): user_name = self.account_base + str(self.account_id) type(self).account_id += 1 + if name_prefix is not None: + user_name = name_prefix + user_name + if name_suffix is not None: + user_name += name_suffix user_account_control = 0 if trusted_to_auth_for_delegation: -- 2.25.1 From 8a0ee0ba0da50cf1d5d9e4299794df78fb87dc51 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:44:19 +1300 Subject: [PATCH 374/645] tests/krb5: Allow creating machine accounts without a trailing dollar BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit f4785ccfefe7c89f84ad847ca3c12f604172b321) --- python/samba/tests/krb5/kdc_base_test.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index d8f3969d228..35f168a3c83 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -237,7 +237,7 @@ 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): + ou=None, account_control=0, add_dollar=True): '''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. @@ -255,13 +255,14 @@ class KDCBaseTest(RawKerberosTest): # remove the account if it exists, this will happen if a previous test # run failed delete_force(samdb, dn) + account_name = name if account_type is self.AccountType.USER: object_class = "user" - account_name = name account_control |= UF_NORMAL_ACCOUNT else: object_class = "computer" - account_name = "%s$" % name + if add_dollar: + account_name += '$' if account_type is self.AccountType.COMPUTER: account_control |= UF_WORKSTATION_TRUST_ACCOUNT else: @@ -632,6 +633,7 @@ class KDCBaseTest(RawKerberosTest): opts_default = { 'name_prefix': None, 'name_suffix': None, + 'add_dollar': True, 'spn': None, 'allowed_replication': False, 'allowed_replication_mock': False, @@ -671,6 +673,7 @@ class KDCBaseTest(RawKerberosTest): account_type, name_prefix, name_suffix, + add_dollar, spn, allowed_replication, allowed_replication_mock, @@ -739,7 +742,8 @@ class KDCBaseTest(RawKerberosTest): account_type=account_type, spn=spn, additional_details=details, - account_control=user_account_control) + account_control=user_account_control, + add_dollar=add_dollar) keys = self.get_keys(samdb, dn) self.creds_set_keys(creds, keys) -- 2.25.1 From 999c64a0342aab023a59449e21428745ceffe037 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:45:08 +1300 Subject: [PATCH 375/645] tests/krb5: Allow specifying the UPN for test accounts BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit 889476d1754f8ce2a41557ed3bf5242c1293584e) --- python/samba/tests/krb5/kdc_base_test.py | 4 ++++ python/samba/tests/krb5/raw_testcase.py | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 35f168a3c83..b24c6376ab0 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -300,6 +300,7 @@ class KDCBaseTest(RawKerberosTest): else: creds.set_workstation(name) creds.set_dn(ldb.Dn(samdb, dn)) + creds.set_upn(upn) creds.set_spn(spn) # # Save the account name so it can be deleted in tearDownClass @@ -634,6 +635,7 @@ class KDCBaseTest(RawKerberosTest): 'name_prefix': None, 'name_suffix': None, 'add_dollar': True, + 'upn': None, 'spn': None, 'allowed_replication': False, 'allowed_replication_mock': False, @@ -674,6 +676,7 @@ class KDCBaseTest(RawKerberosTest): name_prefix, name_suffix, add_dollar, + upn, spn, allowed_replication, allowed_replication_mock, @@ -740,6 +743,7 @@ class KDCBaseTest(RawKerberosTest): creds, dn = self.create_account(samdb, user_name, account_type=account_type, + upn=upn, spn=spn, additional_details=details, account_control=user_account_control, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 0b9fe8e7a04..619a8d006b2 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -366,6 +366,7 @@ class KerberosCredentials(Credentials): self.forced_salt = None self.dn = None + self.upn = None self.spn = None def set_as_supported_enctypes(self, value): @@ -475,6 +476,12 @@ class KerberosCredentials(Credentials): def get_spn(self): return self.spn + def set_upn(self, upn): + self.upn = upn + + def get_upn(self): + return self.upn + class KerberosTicketCreds: def __init__(self, ticket, session_key, -- 2.25.1 From fb10201c25b0655484c6aa63a140c2e347b0ef3f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:45:47 +1300 Subject: [PATCH 376/645] tests/krb5: Fix account salt calculation to match Windows BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit 25bdf4c994e4fdb74abbacb1e22237f3f2cc37fe) --- python/samba/tests/krb5/raw_testcase.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 619a8d006b2..f352615db1f 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -454,13 +454,22 @@ class KerberosCredentials(Credentials): if self.forced_salt is not None: return self.forced_salt + upn = self.get_upn() + if upn is not None: + salt_name = upn.rsplit('@', 1)[0].replace('/', '') + else: + salt_name = self.get_username() + if self.get_workstation(): + salt_name = self.get_username().lower() + if salt_name[-1] == '$': + salt_name = salt_name[:-1] salt_string = '%shost%s.%s' % ( self.get_realm().upper(), - self.get_username().lower().rsplit('$', 1)[0], + salt_name, self.get_realm().lower()) else: - salt_string = self.get_realm().upper() + self.get_username() + salt_string = self.get_realm().upper() + salt_name return salt_string.encode('utf-8') -- 2.25.1 From 2458093a609444b2f25fc0270082694a8da9b6ca Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 12:46:36 +1300 Subject: [PATCH 377/645] tests/krb5: Add tests for account salt calculation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher [abartlet@samba.org backported from commit 46039baa81377df10e5b134e4bb064ed246795e4 as the no_preauth side of the testsuite shows differences in enctypes in Samba 4.14. The change is only in salt calculation so this is not vital] --- python/samba/tests/krb5/as_req_tests.py | 10 + python/samba/tests/krb5/salt_tests.py | 327 ++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail.d/kdc-salt | 12 + selftest/knownfail_heimdal_kdc | 108 ++++++++ source4/selftest/tests.py | 8 + 6 files changed, 466 insertions(+) create mode 100755 python/samba/tests/krb5/salt_tests.py create mode 100644 selftest/knownfail.d/kdc-salt diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 7d7baaebf24..08081928363 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -113,6 +113,13 @@ class AsReqKerberosTests(KDCBaseTest): 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) + + def _run_as_req_enc_timestamp(self, client_creds): client_account = client_creds.get_username() client_as_etypes = self.get_default_enctypes() client_kvno = client_creds.get_kvno() @@ -197,6 +204,9 @@ class AsReqKerberosTests(KDCBaseTest): pac_request=True) self.assertIsNotNone(as_rep) + return etype_info2 + + if __name__ == "__main__": global_asn1_print = False global_hexdump = False diff --git a/python/samba/tests/krb5/salt_tests.py b/python/samba/tests/krb5/salt_tests.py new file mode 100755 index 00000000000..ecbf618e40e --- /dev/null +++ b/python/samba/tests/krb5/salt_tests.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# +# 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 sys +import os + +import ldb + +from samba.tests.krb5.as_req_tests import AsReqKerberosTests +import samba.tests.krb5.kcrypto as kcrypto + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +class SaltTests(AsReqKerberosTests): + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def _get_creds(self, *, + account_type, + opts=None): + try: + return self.get_cached_creds( + account_type=account_type, + opts=opts) + except ldb.LdbError: + self.fail() + + def _run_salt_test(self, client_creds): + expected_salt = self.get_salt(client_creds) + self.assertIsNotNone(expected_salt) + + etype_info2 = self._run_as_req_enc_timestamp(client_creds) + + self.assertEqual(etype_info2[0]['etype'], kcrypto.Enctype.AES256) + self.assertEqual(etype_info2[0]['salt'], expected_salt) + + def test_salt_at_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'foo@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_case_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'Foo@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_case_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'Foo@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_double_at_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'foo@@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_double_at_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo@@bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_start_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_prefix': '@foo'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_start_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_prefix': '@foo'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_end_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'foo@'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_end_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo@'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_at_end_no_dollar_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo@', + 'add_dollar': False}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_no_dollar_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'add_dollar': False}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_dollar_mid_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo$bar', + 'add_dollar': False}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_dollar_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'foo$bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_dollar_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo$bar'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_dollar_end_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'name_suffix': 'foo$'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_dollar_end_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'name_suffix': 'foo$'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo0'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo1'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'host/foo2'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'host/foo3'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo4@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo5@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'host/foo6@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'host/foo7@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_dollar_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo8$@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_dollar_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo9$@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_dollar_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'host/foo10$@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_dollar_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'host/foo11$@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_other_realm_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo12@other.realm'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_other_realm_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo13@other.realm'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_other_realm_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'host/foo14@other.realm'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_other_realm_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'host/foo15@other.realm'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_case_user(self): + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'Foo16'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_case_mac(self): + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'Foo17'}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_dollar_mid_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo$18@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_dollar_mid_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo$19@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_dollar_mid_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'host/foo$20@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_host_dollar_mid_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'host/foo$21@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_at_realm_user(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.USER, + opts={'upn': 'foo22@bar@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + def test_salt_upn_at_realm_mac(self): + realm = self.get_samdb().domain_dns_name() + client_creds = self._get_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'foo23@bar@' + realm}) + self._run_as_req_enc_timestamp(client_creds) + + +if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index e1711b532d7..4b68a2b798c 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -103,6 +103,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/as_req_tests.py', 'python/samba/tests/krb5/fast_tests.py', 'python/samba/tests/krb5/rodc_tests.py', + 'python/samba/tests/krb5/salt_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail.d/kdc-salt b/selftest/knownfail.d/kdc-salt new file mode 100644 index 00000000000..1a4ecd44624 --- /dev/null +++ b/selftest/knownfail.d/kdc-salt @@ -0,0 +1,12 @@ +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_case_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_case_user +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_no_dollar_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_user +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_start_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_start_user +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_user +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_double_at_mac +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_double_at_user +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_upn_at_realm_user diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index b1d7a1ebe8f..b39b11c3c53 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -71,6 +71,114 @@ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_dummy_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_dummy_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_aes256_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_aes128_pac_True.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_False.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_None.fl2008r2dc +^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_as_req_no_preauth_rc4_dummy_aes256_pac_True.fl2008r2dc # # FAST tests # diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 2d2d0af658f..e7ec2f363d2 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1326,6 +1326,14 @@ for env in ["fl2008r2dc", "fl2003dc"]: 'TKT_SIG_SUPPORT': tkt_sig_support }) +planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support + }) for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: if env == "rodc": -- 2.25.1 From 2e21127d8826d3a2884be40a4e937e17cea4aa2f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 19 Oct 2021 16:01:36 +1300 Subject: [PATCH 378/645] dsdb: Allow special chars like "@" in samAccountName when generating the salt BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 20 12:54:54 UTC 2021 on sn-devel-184 (cherry picked from commit 5eeb441b771a1ffe1ba1c69b72e8795f525a58ed) --- auth/credentials/credentials_krb5.c | 12 +- lib/krb5_wrap/krb5_samba.c | 192 +++++++++++++++--- lib/krb5_wrap/krb5_samba.h | 13 +- selftest/knownfail.d/kdc-salt | 11 - source3/passdb/machine_account_secrets.c | 10 +- .../dsdb/samdb/ldb_modules/password_hash.c | 23 ++- 6 files changed, 195 insertions(+), 66 deletions(-) diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index 20e677e521a..61e55f7032d 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -1199,12 +1199,12 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, break; } - ret = smb_krb5_salt_principal(realm, - username, /* sAMAccountName */ - upn, /* userPrincipalName */ - uac_flags, - mem_ctx, - &salt_principal); + ret = smb_krb5_salt_principal_str(realm, + username, /* sAMAccountName */ + upn, /* userPrincipalName */ + uac_flags, + mem_ctx, + &salt_principal); if (ret) { talloc_free(mem_ctx); return ret; diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index ee7055ea7b8..7655dab8ec6 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -456,19 +456,20 @@ int smb_krb5_get_pw_salt(krb5_context context, * * @see smb_krb5_salt_principal2data */ -int smb_krb5_salt_principal(const char *realm, +int smb_krb5_salt_principal(krb5_context krb5_ctx, + const char *realm, const char *sAMAccountName, const char *userPrincipalName, uint32_t uac_flags, - TALLOC_CTX *mem_ctx, - char **_salt_principal) + krb5_principal *salt_princ) { TALLOC_CTX *frame = talloc_stackframe(); char *upper_realm = NULL; const char *principal = NULL; int principal_len = 0; + krb5_error_code krb5_ret; - *_salt_principal = NULL; + *salt_princ = NULL; if (sAMAccountName == NULL) { TALLOC_FREE(frame); @@ -512,7 +513,6 @@ int smb_krb5_salt_principal(const char *realm, */ if (uac_flags & UF_TRUST_ACCOUNT_MASK) { int computer_len = 0; - char *tmp = NULL; computer_len = strlen(sAMAccountName); if (sAMAccountName[computer_len-1] == '$') { @@ -520,60 +520,186 @@ int smb_krb5_salt_principal(const char *realm, } if (uac_flags & UF_INTERDOMAIN_TRUST_ACCOUNT) { - principal = talloc_asprintf(frame, "krbtgt/%*.*s", - computer_len, computer_len, - sAMAccountName); - if (principal == NULL) { + const char *krbtgt = "krbtgt"; + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + strlen(krbtgt), + krbtgt, + computer_len, + sAMAccountName, + 0); + if (krb5_ret != 0) { TALLOC_FREE(frame); - return ENOMEM; + return krb5_ret; } } else { - - tmp = talloc_asprintf(frame, "host/%*.*s.%s", - computer_len, computer_len, - sAMAccountName, realm); + const char *host = "host"; + char *tmp = NULL; + char *tmp_lower = NULL; + + tmp = talloc_asprintf(frame, "%*.*s.%s", + computer_len, + computer_len, + sAMAccountName, + realm); if (tmp == NULL) { TALLOC_FREE(frame); return ENOMEM; } - principal = strlower_talloc(frame, tmp); - TALLOC_FREE(tmp); - if (principal == NULL) { + tmp_lower = strlower_talloc(frame, tmp); + if (tmp_lower == NULL) { TALLOC_FREE(frame); return ENOMEM; } - } - principal_len = strlen(principal); + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + strlen(host), + host, + strlen(tmp_lower), + tmp_lower, + 0); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } + } } else if (userPrincipalName != NULL) { - char *p; + /* + * We parse the name not only to allow an easy + * replacement of the realm (no matter the realm in + * the UPN, the salt comes from the upper-case real + * realm, but also to correctly provide a salt when + * the UPN is host/foo.bar + * + * This can fail for a UPN of the form foo@bar@REALM + * (which is accepted by windows) however. + */ + krb5_ret = krb5_parse_name(krb5_ctx, + userPrincipalName, + salt_princ); - principal = userPrincipalName; - p = strchr(principal, '@'); - if (p != NULL) { - principal_len = PTR_DIFF(p, principal); - } else { - principal_len = strlen(principal); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } + + /* + * No matter what realm (including none) in the UPN, + * the realm is replaced with our upper-case realm + */ + smb_krb5_principal_set_realm(krb5_ctx, + *salt_princ, + upper_realm); + if (krb5_ret != 0) { + krb5_free_principal(krb5_ctx, *salt_princ); + TALLOC_FREE(frame); + return krb5_ret; } } else { principal = sAMAccountName; principal_len = strlen(principal); - } - *_salt_principal = talloc_asprintf(mem_ctx, "%*.*s@%s", - principal_len, principal_len, - principal, upper_realm); - if (*_salt_principal == NULL) { - TALLOC_FREE(frame); - return ENOMEM; + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + principal_len, + principal, + 0); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } } TALLOC_FREE(frame); return 0; } +/** + * @brief This constructs the salt principal used by active directory + * + * Most Kerberos encryption types require a salt in order to + * calculate the long term private key for user/computer object + * based on a password. + * + * The returned _salt_principal is a string in forms like this: + * - host/somehost.example.com@EXAMPLE.COM + * - SomeAccount@EXAMPLE.COM + * - SomePrincipal@EXAMPLE.COM + * + * This is not the form that's used as salt, it's just + * the human readable form. It needs to be converted by + * smb_krb5_salt_principal2data(). + * + * @param[in] realm The realm the user/computer is added too. + * + * @param[in] sAMAccountName The sAMAccountName attribute of the object. + * + * @param[in] userPrincipalName The userPrincipalName attribute of the object + * or NULL is not available. + * + * @param[in] uac_flags UF_ACCOUNT_TYPE_MASKed userAccountControl field + * + * @param[in] mem_ctx The TALLOC_CTX to allocate _salt_principal. + * + * @param[out] _salt_principal The resulting principal as string. + * + * @retval 0 Success; otherwise - Kerberos error codes + * + * @see smb_krb5_salt_principal2data + */ +int smb_krb5_salt_principal_str(const char *realm, + const char *sAMAccountName, + const char *userPrincipalName, + uint32_t uac_flags, + TALLOC_CTX *mem_ctx, + char **_salt_principal_str) +{ + krb5_principal salt_principal = NULL; + char *salt_principal_malloc; + krb5_context krb5_ctx; + krb5_error_code krb5_ret + = smb_krb5_init_context_common(&krb5_ctx); + if (krb5_ret != 0) { + DBG_ERR("kerberos init context failed (%s)\n", + error_message(krb5_ret)); + return krb5_ret; + } + + krb5_ret = smb_krb5_salt_principal(krb5_ctx, + realm, + sAMAccountName, + userPrincipalName, + uac_flags, + &salt_principal); + + krb5_ret = krb5_unparse_name(krb5_ctx, salt_principal, + &salt_principal_malloc); + if (krb5_ret != 0) { + krb5_free_principal(krb5_ctx, salt_principal); + DBG_ERR("kerberos unparse of salt principal failed (%s)\n", + error_message(krb5_ret)); + return krb5_ret; + } + krb5_free_principal(krb5_ctx, salt_principal); + *_salt_principal_str + = talloc_strdup(mem_ctx, salt_principal_malloc); + krb5_free_unparsed_name(krb5_ctx, salt_principal_malloc); + + if (*_salt_principal_str == NULL) { + return ENOMEM; + } + return 0; +} + /** * @brief Converts the salt principal string into the salt data blob * diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h index 64ae0275dbd..8269847c735 100644 --- a/lib/krb5_wrap/krb5_samba.h +++ b/lib/krb5_wrap/krb5_samba.h @@ -350,12 +350,19 @@ krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx, int smb_krb5_get_pw_salt(krb5_context context, krb5_const_principal host_princ, krb5_data *psalt); -int smb_krb5_salt_principal(const char *realm, +int smb_krb5_salt_principal(krb5_context krb5_ctx, + const char *realm, const char *sAMAccountName, const char *userPrincipalName, uint32_t uac_flags, - TALLOC_CTX *mem_ctx, - char **_salt_principal); + krb5_principal *salt_princ); + +int smb_krb5_salt_principal_str(const char *realm, + const char *sAMAccountName, + const char *userPrincipalName, + uint32_t uac_flags, + TALLOC_CTX *mem_ctx, + char **_salt_principal); int smb_krb5_salt_principal2data(krb5_context context, const char *salt_principal, TALLOC_CTX *mem_ctx, diff --git a/selftest/knownfail.d/kdc-salt b/selftest/knownfail.d/kdc-salt index 1a4ecd44624..a671e4d93eb 100644 --- a/selftest/knownfail.d/kdc-salt +++ b/selftest/knownfail.d/kdc-salt @@ -1,12 +1 @@ -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_case_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_case_user -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_no_dollar_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_end_user -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_start_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_start_user -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_at_user -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_double_at_mac -^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_double_at_user ^samba.tests.krb5.salt_tests.samba.tests.krb5.salt_tests.SaltTests.test_salt_upn_at_realm_user diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index efba80f1474..f426d9da25e 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -1574,11 +1574,11 @@ NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r) if (info->salt_principal == NULL && r->out.domain_is_ad) { char *p = NULL; - ret = smb_krb5_salt_principal(info->domain_info.dns_domain.string, - info->account_name, - NULL /* userPrincipalName */, - UF_WORKSTATION_TRUST_ACCOUNT, - info, &p); + ret = smb_krb5_salt_principal_str(info->domain_info.dns_domain.string, + info->account_name, + NULL /* userPrincipalName */, + UF_WORKSTATION_TRUST_ACCOUNT, + info, &p); if (ret != 0) { status = krb5_to_nt_status(ret); DBG_ERR("smb_krb5_salt_principal() failed " diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index c321678e813..2111b5547d9 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -684,8 +684,8 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) { struct ldb_context *ldb; krb5_error_code krb5_ret; - char *salt_principal = NULL; - char *salt_data = NULL; + krb5_principal salt_principal = NULL; + krb5_data salt_data; krb5_data salt; krb5_keyblock key; krb5_data cleartext_data; @@ -696,11 +696,11 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) cleartext_data.length = io->n.cleartext_utf8->length; uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK; - krb5_ret = smb_krb5_salt_principal(io->ac->status->domain_data.realm, + krb5_ret = smb_krb5_salt_principal(io->smb_krb5_context->krb5_context, + io->ac->status->domain_data.realm, io->u.sAMAccountName, io->u.user_principal_name, uac_flags, - io->ac, &salt_principal); if (krb5_ret) { ldb_asprintf_errstring(ldb, @@ -714,8 +714,10 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) /* * create salt from salt_principal */ - krb5_ret = smb_krb5_salt_principal2data(io->smb_krb5_context->krb5_context, - salt_principal, io->ac, &salt_data); + krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context, + salt_principal, &salt_data); + + krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { ldb_asprintf_errstring(ldb, "setup_kerberos_keys: " @@ -724,12 +726,17 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } - io->g.salt = salt_data; /* now use the talloced copy of the salt */ - salt.data = discard_const(io->g.salt); + salt.data = talloc_strndup(io->ac, + (char *)salt_data.data, + salt_data.length); + io->g.salt = salt.data; salt.length = strlen(io->g.salt); + smb_krb5_free_data_contents(io->smb_krb5_context->krb5_context, + &salt_data); + /* * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of * the salt and the cleartext password -- 2.25.1 From e28fe6039bbeadfb6457a4325821aeb35718a8dd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 10:50:36 +1300 Subject: [PATCH 379/645] lib/krb5_wrap: Fix missing error check in new salt code CID 1492905: Control flow issues (DEADCODE) This was a regression in 5eeb441b771a1ffe1ba1c69b72e8795f525a58ed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Sat Oct 23 08:07:13 UTC 2021 on sn-devel-184 (cherry picked from commit 5094d986b7686f057195dcb10764295b88967019) Autobuild-User(v4-13-test): Stefan Metzmacher Autobuild-Date(v4-13-test): Wed Oct 27 23:29:34 UTC 2021 on sn-devel-184 --- lib/krb5_wrap/krb5_samba.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index 7655dab8ec6..b0ce48da669 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -594,9 +594,9 @@ int smb_krb5_salt_principal(krb5_context krb5_ctx, * No matter what realm (including none) in the UPN, * the realm is replaced with our upper-case realm */ - smb_krb5_principal_set_realm(krb5_ctx, - *salt_princ, - upper_realm); + krb5_ret = smb_krb5_principal_set_realm(krb5_ctx, + *salt_princ, + upper_realm); if (krb5_ret != 0) { krb5_free_principal(krb5_ctx, *salt_princ); TALLOC_FREE(frame); -- 2.25.1 From 74c657cb2042f100eb2733e123a75f2e134a4abb Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 5 May 2020 13:47:39 +1200 Subject: [PATCH 380/645] CVE-2020-25722 Fix clang 9 missing-field-initializer warnings Signed-off-by: Gary Lockyer Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 [abartlet@samba.org backported from commit 13a2f70a4dd6dd68e0dbd0379d35409c5f100f06 due to wscript changes] --- auth/credentials/pycredentials.c | 2 +- examples/libsmbclient/testbrowse.c | 4 +--- lib/crypto/py_crypto.c | 2 +- lib/ldb-samba/pyldb.c | 2 +- lib/ldb-samba/samba_extensions.c | 4 ++-- lib/ldb/pyldb.c | 16 ++++++++-------- lib/ldb/tools/cmdline.c | 2 +- lib/talloc/pytalloc.c | 2 +- lib/talloc/test_pytalloc.c | 2 +- lib/tdb/pytdb.c | 2 +- lib/tevent/pytevent.c | 16 ++++++++-------- libcli/nbt/pynbt.c | 2 +- libcli/security/pysecurity.c | 2 +- libgpo/pygpo.c | 8 ++++---- librpc/tools/ndrdump.c | 2 +- pidl/lib/Parse/Pidl/Samba4/Python.pm | 2 +- python/pyglue.c | 2 +- source3/libsmb/pylibsmb.c | 2 +- source3/param/pyparam.c | 2 +- source3/passdb/py_passdb.c | 4 ++-- source3/rpc_client/py_mdscli.c | 6 +++--- source3/rpcclient/cmd_spotlight.c | 2 +- source3/smbd/posix_acls.c | 2 +- source3/smbd/pysmbd.c | 2 +- source3/torture/cmd_vfs.c | 2 +- source3/utils/smbcontrol.c | 2 +- source4/auth/gensec/pygensec.c | 2 +- source4/auth/pyauth.c | 2 +- source4/client/cifsdd.c | 2 +- source4/dns_server/dlz_bind9.c | 2 +- source4/dns_server/pydns.c | 2 +- source4/dsdb/pydsdb.c | 2 +- source4/dsdb/samdb/ldb_modules/count_attrs.c | 2 +- source4/lib/policy/pypolicy.c | 2 +- source4/lib/registry/pyregistry.c | 6 +++--- source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 4 ++-- source4/lib/registry/tools/regtree.c | 2 +- source4/librpc/ndr/py_security.c | 8 ++++---- source4/librpc/ndr/py_xattr.c | 2 +- source4/ntvfs/posix/python/pyposix_eadb.c | 2 +- source4/ntvfs/posix/python/pyxattr_native.c | 2 +- source4/ntvfs/posix/python/pyxattr_tdb.c | 2 +- source4/param/pyparam.c | 6 +++--- source4/torture/gentest.c | 2 +- source4/torture/ldb/ldb.c | 15 +++++++++------ source4/torture/locktest.c | 2 +- source4/torture/masktest.c | 2 +- source4/torture/smbtorture.c | 2 +- source4/torture/vfs/fruit.c | 2 +- source4/utils/oLschema2ldif/main.c | 2 +- 52 files changed, 89 insertions(+), 88 deletions(-) diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index ad39fe13925..0234a9b44e5 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -1250,7 +1250,7 @@ static PyObject *py_ccache_name(PyObject *self, PyObject *unused) static PyMethodDef py_ccache_container_methods[] = { { "get_name", py_ccache_name, METH_NOARGS, "S.get_name() -> name\nObtain KRB5 credentials cache name." }, - { NULL } + {0} }; PyTypeObject PyCredentialCacheContainer = { diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c index 0629653ef8b..1609e2f4f91 100644 --- a/examples/libsmbclient/testbrowse.c +++ b/examples/libsmbclient/testbrowse.c @@ -65,9 +65,7 @@ int main(int argc, const char *argv[]) "contextauth", 'C', POPT_ARG_NONE, &context_auth, 0, "Use new authentication function with context", "integer" }, - { - NULL - } + {0} }; setbuf(stdout, NULL); diff --git a/lib/crypto/py_crypto.c b/lib/crypto/py_crypto.c index c85cd2c13d2..32b946eee8f 100644 --- a/lib/crypto/py_crypto.c +++ b/lib/crypto/py_crypto.c @@ -91,7 +91,7 @@ static const char py_crypto_arcfour_crypt_blob_doc[] = "arcfour_crypt_blob(data, static PyMethodDef py_crypto_methods[] = { { "arcfour_crypt_blob", (PyCFunction)py_crypto_arcfour_crypt_blob, METH_VARARGS, py_crypto_arcfour_crypt_blob_doc }, - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/lib/ldb-samba/pyldb.c b/lib/ldb-samba/pyldb.c index 48adc74b16a..bea489489ef 100644 --- a/lib/ldb-samba/pyldb.c +++ b/lib/ldb-samba/pyldb.c @@ -266,7 +266,7 @@ static PyMethodDef py_samba_ldb_methods[] = { { "samba_schema_attribute_add", (PyCFunction)py_ldb_samba_schema_attribute_add, METH_VARARGS, NULL }, - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/lib/ldb-samba/samba_extensions.c b/lib/ldb-samba/samba_extensions.c index 45b01e1b447..65a4079ec97 100644 --- a/lib/ldb-samba/samba_extensions.c +++ b/lib/ldb-samba/samba_extensions.c @@ -41,7 +41,7 @@ static unsigned calculate_popt_array_length(struct poptOption *opts) { unsigned i; - struct poptOption zero_opt = { NULL }; + struct poptOption zero_opt = { 0 }; for (i=0; memcmp(&zero_opt, &opts[i], sizeof(zero_opt)) != 0; i++) ; return i; } @@ -51,7 +51,7 @@ static struct poptOption cmdline_extensions[] = { POPT_COMMON_CREDENTIALS POPT_COMMON_CONNECTION POPT_COMMON_VERSION - { NULL } + {0} }; /* diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 0fa444cf985..6816c24ce96 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -735,7 +735,7 @@ static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args) { unsigned int num = 0; char *name = NULL, *value = NULL; - struct ldb_val val = { NULL, }; + struct ldb_val val = { 0 }; int err; Py_ssize_t size = 0; @@ -852,7 +852,7 @@ static PyMethodDef py_ldb_dn_methods[] = { { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS, "S.get_rdn_value() -> string\n" "get the RDN attribute value as a binary string" }, - { NULL } + {0} }; static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self) @@ -2417,7 +2417,7 @@ static PyMethodDef py_ldb_methods[] = { { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS, "S._register_test_extensions() -> None\n" "Register internal extensions used in testing" }, - { NULL }, + {0}, }; static PyObject *PyLdbModule_FromModule(struct ldb_module *mod) @@ -2744,7 +2744,7 @@ static PyMethodDef py_ldb_search_iterator_methods[] = { "S.result() -> ldb.Result (without msgs and referrals)\n" }, { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS, "S.abandon()\n" }, - { NULL } + {0} }; static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self) @@ -2939,7 +2939,7 @@ static PyMethodDef py_ldb_module_methods[] = { { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL }, { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL }, { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL }, - { NULL }, + {0}, }; static void py_ldb_module_dealloc(PyLdbModuleObject *self) @@ -3117,7 +3117,7 @@ static PyMethodDef py_ldb_msg_element_methods[] = { { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL }, { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL }, { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL }, - { NULL }, + {0}, }; static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self) @@ -3630,7 +3630,7 @@ static PyMethodDef py_ldb_msg_methods[] = { { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS, "S.add(element)\n\n" "Add an element to this message." }, - { NULL }, + {0}, }; static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self) @@ -4316,7 +4316,7 @@ static PyMethodDef py_ldb_global_methods[] = { { "binary_decode", py_binary_decode, METH_VARARGS, "S.binary_decode(string) -> string\n\n" "Perform a RFC2254 binary decode on a string" }, - { NULL } + {0} }; #define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server." diff --git a/lib/ldb/tools/cmdline.c b/lib/ldb/tools/cmdline.c index a2fe97ee6b2..b0f4c5c2141 100644 --- a/lib/ldb/tools/cmdline.c +++ b/lib/ldb/tools/cmdline.c @@ -59,7 +59,7 @@ static struct poptOption builtin_popt_options[] = { { "relax", 0, POPT_ARG_NONE, NULL, CMDLINE_RELAX, "pass relax control", NULL }, { "cross-ncs", 0, POPT_ARG_NONE, NULL, 'N', "search across NC boundaries", NULL }, { "extended-dn", 0, POPT_ARG_NONE, NULL, 'E', "show extended DNs", NULL }, - { NULL } + {0} }; void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f) diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c index 700e0f7f2af..4d3826153b9 100644 --- a/lib/talloc/pytalloc.c +++ b/lib/talloc/pytalloc.c @@ -70,7 +70,7 @@ static PyMethodDef talloc_methods[] = { "enable tracking of the NULL object"}, { "total_blocks", (PyCFunction)pytalloc_total_blocks, METH_VARARGS, "return talloc block count"}, - { NULL } + {0} }; /** diff --git a/lib/talloc/test_pytalloc.c b/lib/talloc/test_pytalloc.c index 6797b98c6b9..3b0484b2274 100644 --- a/lib/talloc/test_pytalloc.c +++ b/lib/talloc/test_pytalloc.c @@ -95,7 +95,7 @@ static PyMethodDef test_talloc_methods[] = { "call pytalloc_reference_ex"}, { "base_reference", (PyCFunction)testpytalloc_base_reference, METH_VARARGS, "call pytalloc_reference_ex"}, - { NULL } + {0} }; static PyTypeObject DObject_Type; diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c index 9fb1d84c0d8..e016bcbd213 100644 --- a/lib/tdb/pytdb.c +++ b/lib/tdb/pytdb.c @@ -543,7 +543,7 @@ static PyMethodDef tdb_object_methods[] = { "S.enable_seqnum() -> None" }, { "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS, "S.increment_seqnum_nonblock() -> None" }, - { NULL } + {0} }; static PyObject *obj_get_hash_size(PyTdbObject *self, void *closure) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 33a8c3bd64a..2643a9ae447 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -269,7 +269,7 @@ static PyMethodDef py_tevent_queue_methods[] = { "S.start()" }, { "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS, "S.add(ctx, req, trigger, baton)" }, - { NULL }, + {0}, }; static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args) @@ -394,7 +394,7 @@ struct PyGetSetDef py_tevent_timer_getset[] = { .get = (getter)py_tevent_timer_get_active, .doc = discard_const_p(char, "true if the timer is scheduled to run"), }, - {NULL}, + {0}, }; static PyTypeObject TeventTimer_Type = { @@ -576,7 +576,7 @@ static PyMethodDef py_tevent_context_methods[] = { METH_VARARGS, "S.add_timer_offset(offset_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, - { NULL }, + {0}, }; static PyObject *py_tevent_req_wakeup_recv(PyObject *self, @@ -620,7 +620,7 @@ static PyGetSetDef py_tevent_req_getsetters[] = { .get = (getter)py_tevent_req_is_in_progress, .doc = discard_const_p(char, "Whether the request is in progress"), }, - { NULL } + {0} }; static PyObject *py_tevent_req_post(PyObject *self, PyObject *args) @@ -688,7 +688,7 @@ static PyMethodDef py_tevent_req_methods[] = { METH_VARARGS, "set_endtime(ctx, endtime)" }, { "cancel", (PyCFunction)py_tevent_req_cancel, METH_NOARGS, "cancel()" }, - { NULL } + {0} }; static void py_tevent_req_dealloc(TeventReq_Object *self) @@ -718,7 +718,7 @@ static PyGetSetDef py_tevent_queue_getsetters[] = { .get = (getter)py_tevent_queue_get_length, .doc = discard_const_p(char, "The number of elements in the queue."), }, - { NULL }, + {0}, }; static void py_tevent_queue_dealloc(TeventQueue_Object *self) @@ -750,7 +750,7 @@ static PyGetSetDef py_tevent_context_getsetters[] = { py_tevent_context_signal_support), .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), }, - { NULL } + {0} }; static void py_tevent_context_dealloc(TeventContext_Object *self) @@ -861,7 +861,7 @@ static PyMethodDef tevent_methods[] = { METH_VARARGS, "set_default_backend(backend)" }, { "backend_list", (PyCFunction)py_backend_list, METH_NOARGS, "backend_list() -> list" }, - { NULL }, + {0}, }; #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") diff --git a/libcli/nbt/pynbt.c b/libcli/nbt/pynbt.c index a562f6dcb5e..4f49b284651 100644 --- a/libcli/nbt/pynbt.c +++ b/libcli/nbt/pynbt.c @@ -409,7 +409,7 @@ static PyMethodDef py_nbt_methods[] = { "S.name_status(name, dest, timeout=0, retries=0) -> (reply_from, name, status)\n" "Find the status of a name" }, - { NULL } + {0} }; PyTypeObject nbt_node_Type = { diff --git a/libcli/security/pysecurity.c b/libcli/security/pysecurity.c index fcef6007d54..b3e661a912f 100644 --- a/libcli/security/pysecurity.c +++ b/libcli/security/pysecurity.c @@ -73,7 +73,7 @@ static PyMethodDef py_security_methods[] = { py_se_access_check), METH_VARARGS|METH_KEYWORDS, "access_check(security_descriptor, token, access_desired) -> access_granted. Raises NT_STATUS on error, including on access check failure, returns access granted bitmask"}, - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index ddfb5c76ef9..3452bc77d61 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -67,7 +67,7 @@ static PyGetSetDef GPO_setters[] = { NULL, NULL, NULL}, {discard_const_p(char, "machine_extensions"), (getter)GPO_get_machine_extensions, NULL, NULL, NULL}, - {NULL} + {0} }; static PyObject *py_gpo_get_unix_path(PyObject *self, PyObject *args, @@ -120,7 +120,7 @@ static PyMethodDef GPO_methods[] = { py_gpo_get_unix_path), METH_VARARGS | METH_KEYWORDS, NULL }, - {NULL} + {0} }; static PyTypeObject GPOType = { @@ -493,7 +493,7 @@ static PyMethodDef ADS_methods[] = { METH_VARARGS | METH_KEYWORDS, NULL }, #endif - { NULL } + {0} }; static PyTypeObject ads_ADSType = { @@ -510,7 +510,7 @@ static PyMethodDef py_gpo_methods[] = { {"gpo_get_sysvol_gpt_version", (PyCFunction)py_gpo_get_sysvol_gpt_version, METH_VARARGS, NULL}, - {NULL} + {0} }; static struct PyModuleDef moduledef = { diff --git a/librpc/tools/ndrdump.c b/librpc/tools/ndrdump.c index 914c67e98e2..2872a85b621 100644 --- a/librpc/tools/ndrdump.c +++ b/librpc/tools/ndrdump.c @@ -316,7 +316,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...) "Try to print structures that fail to parse (used to develop parsers, segfaults are likely).", NULL }, POPT_COMMON_SAMBA POPT_COMMON_VERSION - { NULL } + {0} }; uint32_t highest_ofs; struct dcerpc_sec_verification_trailer *sec_vt = NULL; diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 84d4dade512..6c7bf7015c5 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -1419,7 +1419,7 @@ sub Interface($$$) my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d; $self->pidl("{ \"$prettyname\", $docstring, (py_dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },"); } - $self->pidl("{ NULL }"); + $self->pidl("{0}"); $self->deindent; $self->pidl("};"); $self->pidl(""); diff --git a/python/pyglue.c b/python/pyglue.c index 83b968bad8c..5328c620528 100644 --- a/python/pyglue.c +++ b/python/pyglue.c @@ -389,7 +389,7 @@ static PyMethodDef py_misc_methods[] = { METH_VARARGS, "generate_random_bytes(len) -> bytes\n" "Generate random bytes with specified length." }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index a882fe2f2a7..80017bfb607 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -1775,7 +1775,7 @@ static PyTypeObject py_cli_state_type = { }; static PyMethodDef py_libsmb_methods[] = { - { NULL }, + {0}, }; void initlibsmb_samba_internal(void); diff --git a/source3/param/pyparam.c b/source3/param/pyparam.c index 6f709afe96e..749cfe308f4 100644 --- a/source3/param/pyparam.c +++ b/source3/param/pyparam.c @@ -64,7 +64,7 @@ static PyObject *py_get_context(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyMethodDef pyparam_methods[] = { { "get_context", (PyCFunction)py_get_context, METH_NOARGS, "Returns LoadParm context." }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source3/passdb/py_passdb.c b/source3/passdb/py_passdb.c index c323adf2969..5cb1e2cd610 100644 --- a/source3/passdb/py_passdb.c +++ b/source3/passdb/py_passdb.c @@ -3749,7 +3749,7 @@ static PyMethodDef py_pdb_methods[] = { { "delete_secret", py_pdb_delete_secret, METH_VARARGS, "delete_secret(secret_name) -> None\n\n \ Delete secret information for secret_name." }, - { NULL }, + {0}, }; @@ -3965,7 +3965,7 @@ static PyMethodDef py_passdb_methods[] = { { "reload_static_pdb", py_reload_static_pdb, METH_NOARGS, "reload_static_pdb() -> None\n\n \ Re-initialise the static pdb used internally. Needed if 'passdb backend' is changed." }, - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/source3/rpc_client/py_mdscli.c b/source3/rpc_client/py_mdscli.c index 05dd0390cbd..290be3f86d9 100644 --- a/source3/rpc_client/py_mdscli.c +++ b/source3/rpc_client/py_mdscli.c @@ -243,7 +243,7 @@ static PyMethodDef search_methods[] = { .ml_flags = METH_VARARGS|METH_KEYWORDS, .ml_doc = "", }, - { NULL }, + {0}, }; static PyObject *search_new(PyTypeObject *type, @@ -448,7 +448,7 @@ static PyMethodDef conn_methods[] = { .ml_flags = METH_VARARGS|METH_KEYWORDS, .ml_doc = "mdscli.conn.disconnect(...) -> disconnect", }, - { NULL }, + {0}, }; static PyObject *conn_new(PyTypeObject *type, @@ -521,7 +521,7 @@ static PyTypeObject conn_type = { }; static PyMethodDef mdscli_methods[] = { - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/source3/rpcclient/cmd_spotlight.c b/source3/rpcclient/cmd_spotlight.c index 5bc5eb10888..661ada7efb8 100644 --- a/source3/rpcclient/cmd_spotlight.c +++ b/source3/rpcclient/cmd_spotlight.c @@ -456,5 +456,5 @@ struct cmd_set spotlight_commands[] = { .description = "Fetch attributes for a CNID", .usage = "", }, - { NULL } + {0} }; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 56c481fae79..cc4d19017f9 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4701,7 +4701,7 @@ int posix_sys_acl_blob_get_file(vfs_handle_struct *handle, TALLOC_CTX *frame = talloc_stackframe(); /* Initialise this to zero, in a portable way */ struct smb_acl_wrapper acl_wrapper = { - NULL + 0 }; struct smb_filename *smb_fname = cp_smb_filename_nostream(frame, smb_fname_in); diff --git a/source3/smbd/pysmbd.c b/source3/smbd/pysmbd.c index 58c96396e08..f624ce52630 100644 --- a/source3/smbd/pysmbd.c +++ b/source3/smbd/pysmbd.c @@ -1163,7 +1163,7 @@ static PyMethodDef py_smbd_methods[] = { PY_DISCARD_FUNC_SIG(PyCFunction, py_smbd_create_file), METH_VARARGS|METH_KEYWORDS, NULL }, - { NULL } + {0} }; void initsmbd(void); diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 81068fb84a0..d91802f82f3 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -2016,5 +2016,5 @@ struct cmd_set vfs_commands[] = { { "test_chain", cmd_test_chain, "test chain code", "test_chain" }, { "translate_name", cmd_translate_name, "VFS translate_name()", "translate_name unix_filename" }, - { NULL } + {0} }; diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index d779f0d14ea..6836b3ad7db 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -1689,7 +1689,7 @@ struct poptOption help_options[] = { NULL, NULL }, { "help", '?', 0, NULL, '?', "Show this help message", NULL }, { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL }, - { NULL } + {0} } ; /* Main program */ diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index 1a8d7b0489f..25ed3eee6ba 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -736,7 +736,7 @@ static PyMethodDef py_gensec_security_methods[] = { "S.sign_packet(data, whole_pdu) -> sig\nSign a DCERPC packet." }, { "check_packet", (PyCFunction)py_gensec_check_packet, METH_VARARGS, "S.check_packet(data, whole_pdu, sig)\nCheck a DCERPC packet." }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/auth/pyauth.c b/source4/auth/pyauth.c index 4203692025b..ed88a1751fe 100644 --- a/source4/auth/pyauth.c +++ b/source4/auth/pyauth.c @@ -434,7 +434,7 @@ static PyMethodDef py_auth_methods[] = { PY_DISCARD_FUNC_SIG(PyCFunction,py_copy_session_info), METH_VARARGS|METH_KEYWORDS, NULL }, - { NULL }, + {0}, }; static struct PyModuleDef moduledef = { diff --git a/source4/client/cifsdd.c b/source4/client/cifsdd.c index dadff84bda5..adc123b5e9c 100644 --- a/source4/client/cifsdd.c +++ b/source4/client/cifsdd.c @@ -622,7 +622,7 @@ int main(int argc, const char ** argv) POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; /* Block sizes. */ diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 9e4a3695866..a77dc4ef02a 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -544,7 +544,7 @@ static isc_result_t parse_options(struct dlz_bind9_data *state, struct poptOption long_options[] = { { "url", 'H', POPT_ARG_STRING, &options->url, 0, "database URL", "URL" }, { "debug", 'd', POPT_ARG_STRING, &options->debug, 0, "debug level", "DEBUG" }, - { NULL } + {0} }; pc = poptGetContext("dlz_bind9", argc, argv, long_options, diff --git a/source4/dns_server/pydns.c b/source4/dns_server/pydns.c index 9d4c1dd1727..1e6a1cb6105 100644 --- a/source4/dns_server/pydns.c +++ b/source4/dns_server/pydns.c @@ -336,7 +336,7 @@ static PyMethodDef py_dsdb_dns_methods[] = { METH_VARARGS, "Replace the DNS database entries for a LDB DN"}, { "extract", (PyCFunction)py_dsdb_dns_extract, METH_VARARGS, "Return the DNS database entry as a python structure from an Ldb.MessageElement of type dnsRecord"}, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index f173a355997..ac1563f2305 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -1479,7 +1479,7 @@ static PyMethodDef py_dsdb_methods[] = { "_dsdb_allocate_rid(samdb)" " -> RID" }, { "_dsdb_load_udv_v2", (PyCFunction)py_dsdb_load_udv_v2, METH_VARARGS, NULL }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/dsdb/samdb/ldb_modules/count_attrs.c b/source4/dsdb/samdb/ldb_modules/count_attrs.c index eb762cc25aa..aa9e2807e05 100644 --- a/source4/dsdb/samdb/ldb_modules/count_attrs.c +++ b/source4/dsdb/samdb/ldb_modules/count_attrs.c @@ -150,7 +150,7 @@ static int increment_req_vs_found(struct tdb_context *tdb, .dptr = (unsigned char *)k, .dsize = sizeof(k) }; - TDB_DATA data = {NULL}; + TDB_DATA data = {0}; ssize_t n_req = ac->n_attrs; if (ac->is_null) { n_req = NULL_REQ_PSEUDO_N; diff --git a/source4/lib/policy/pypolicy.c b/source4/lib/policy/pypolicy.c index 038fa0428c3..8d0b03ba4be 100644 --- a/source4/lib/policy/pypolicy.c +++ b/source4/lib/policy/pypolicy.c @@ -143,7 +143,7 @@ static PyMethodDef py_policy_methods[] = { "get_gplink_options(options) -> list" }, { "ads_to_dir_access_mask", (PyCFunction)py_ads_to_dir_access_mask, METH_VARARGS, "ads_to_dir_access_mask(access_mask) -> dir_mask" }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/lib/registry/pyregistry.c b/source4/lib/registry/pyregistry.c index 5b02a79787d..3a3d527a1a1 100644 --- a/source4/lib/registry/pyregistry.c +++ b/source4/lib/registry/pyregistry.c @@ -153,7 +153,7 @@ static PyMethodDef registry_methods[] = { "Apply the diff from the specified file" }, { "mount_hive", py_mount_hive, METH_VARARGS, "S.mount_hive(key, key_id, elements=None) -> None\n" "Mount the specified key at the specified path." }, - { NULL } + {0} }; PyTypeObject PyRegistry = { @@ -240,7 +240,7 @@ static PyMethodDef hive_key_methods[] = { "Delete a value" }, { "set_value", py_hive_key_set_value, METH_VARARGS, "S.set_value(name, type, data) -> None\n" "Set a value" }, - { NULL } + {0} }; static PyObject *hive_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { @@ -443,7 +443,7 @@ static PyMethodDef py_registry_methods[] = { METH_VARARGS|METH_KEYWORDS, "open_hive(location, session_info=None, credentials=None, loadparm_context=None) -> key" }, { "str_regtype", py_str_regtype, METH_VARARGS, "str_regtype(int) -> str" }, { "get_predef_name", py_get_predef_name, METH_VARARGS, "get_predef_name(hkey) -> str" }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index da813336b85..b5cf4dd2566 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -82,7 +82,7 @@ int main(int argc, const char **argv) POPT_COMMON_SAMBA POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; TALLOC_CTX *ctx; void *callback_data; diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 50195fe084c..4db7a5090e0 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -41,7 +41,7 @@ int main(int argc, const char **argv) {"file", 'F', POPT_ARG_STRING, &file, 0, "file path", NULL }, POPT_COMMON_SAMBA POPT_COMMON_CREDENTIALS - { NULL } + {0} }; pc = poptGetContext(argv[0], argc, argv, long_options,0); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 48251c33ea4..eebec4353cb 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -380,7 +380,7 @@ static struct { {"help", "?", "Help", cmd_help }, {"exit", "quit", "Exit", cmd_exit }, {"predef", "predefined", "Go to predefined key", cmd_predef }, - {NULL } + {0} }; static WERROR cmd_help(struct regshell_context *ctx, @@ -570,7 +570,7 @@ int main(int argc, const char **argv) POPT_COMMON_SAMBA POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; pc = poptGetContext(argv[0], argc, argv, long_options,0); diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index d4319f5f6bb..f147e2707f7 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -120,7 +120,7 @@ int main(int argc, const char **argv) POPT_COMMON_SAMBA POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; pc = poptGetContext(argv[0], argc, argv, long_options,0); diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index d957aa613b6..bfb378a35ec 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -150,7 +150,7 @@ static PyMethodDef py_dom_sid_extra_methods[] = { { "split", (PyCFunction)py_dom_sid_split, METH_NOARGS, "S.split() -> (domain_sid, rid)\n" "Split a domain sid" }, - { NULL } + {0} }; @@ -306,7 +306,7 @@ static PyMethodDef py_descriptor_extra_methods[] = { NULL }, { "as_sddl", (PyCFunction)py_descriptor_as_sddl, METH_VARARGS, NULL }, - { NULL } + {0} }; static PyObject *py_descriptor_richcmp( @@ -459,7 +459,7 @@ static PyMethodDef py_token_extra_methods[] = { NULL }, { "set_privilege", (PyCFunction)py_token_set_privilege, METH_VARARGS, NULL }, - { NULL } + {0} }; #define PY_TOKEN_PATCH py_token_patch @@ -516,7 +516,7 @@ static PyMethodDef py_mod_security_extra_methods[] = { { "random_sid", (PyCFunction)py_random_sid, METH_NOARGS, NULL }, { "privilege_id", (PyCFunction)py_privilege_id, METH_VARARGS, NULL }, { "privilege_name", (PyCFunction)py_privilege_name, METH_VARARGS, NULL }, - { NULL } + {0} }; static void py_mod_security_patch(PyObject *m) diff --git a/source4/librpc/ndr/py_xattr.c b/source4/librpc/ndr/py_xattr.c index 4052399bece..221b9771e0d 100644 --- a/source4/librpc/ndr/py_xattr.c +++ b/source4/librpc/ndr/py_xattr.c @@ -87,7 +87,7 @@ static PyObject *py_ntacl_print(PyObject *self, PyObject *args) static PyMethodDef py_ntacl_extra_methods[] = { { "dump", (PyCFunction)py_ntacl_print, METH_NOARGS, NULL }, - { NULL } + {0} }; static void py_xattr_NTACL_patch(PyTypeObject *type) diff --git a/source4/ntvfs/posix/python/pyposix_eadb.c b/source4/ntvfs/posix/python/pyposix_eadb.c index 14979b95a58..abf397f990c 100644 --- a/source4/ntvfs/posix/python/pyposix_eadb.c +++ b/source4/ntvfs/posix/python/pyposix_eadb.c @@ -116,7 +116,7 @@ static PyMethodDef py_posix_eadb_methods[] = { "Set the given attribute to the given value on the given file." }, { "is_xattr_supported", (PyCFunction)py_is_xattr_supported, METH_NOARGS, "Return true if xattr are supported on this system\n"}, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/ntvfs/posix/python/pyxattr_native.c b/source4/ntvfs/posix/python/pyxattr_native.c index c479be66a65..d242cd98a5d 100644 --- a/source4/ntvfs/posix/python/pyxattr_native.c +++ b/source4/ntvfs/posix/python/pyxattr_native.c @@ -105,7 +105,7 @@ static PyMethodDef py_xattr_methods[] = { "Set the given attribute to the given value on the given file." }, { "is_xattr_supported", (PyCFunction)py_is_xattr_supported, METH_NOARGS, "Return true if xattr are supported on this system\n"}, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/ntvfs/posix/python/pyxattr_tdb.c b/source4/ntvfs/posix/python/pyxattr_tdb.c index 133c7089d5f..425fd868ca0 100644 --- a/source4/ntvfs/posix/python/pyxattr_tdb.c +++ b/source4/ntvfs/posix/python/pyxattr_tdb.c @@ -152,7 +152,7 @@ static PyMethodDef py_xattr_methods[] = { "Set the given attribute to the given value on the given file." }, { "is_xattr_supported", (PyCFunction)py_is_xattr_supported, METH_NOARGS, "Return true if xattr are supported on this system\n"}, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/param/pyparam.c b/source4/param/pyparam.c index a251b024ebb..ef0ba2f5f62 100644 --- a/source4/param/pyparam.c +++ b/source4/param/pyparam.c @@ -446,7 +446,7 @@ static PyMethodDef py_lp_ctx_methods[] = { { "state_path", py_state_path, METH_VARARGS, "S.state_path(name) -> string\n" "Returns a path in the Samba state directory." }, - { NULL } + {0} }; static PyObject *py_lp_ctx_default_service(PyObject *self, void *closure) @@ -605,7 +605,7 @@ static PyObject *py_lp_service_dump(PyObject *self, PyObject *args) static PyMethodDef py_lp_service_methods[] = { { "dump", (PyCFunction)py_lp_service_dump, METH_VARARGS, "S.dump(default_service, show_defaults=False, file_name='', mode='w')" }, - { NULL } + {0} }; PyTypeObject PyLoadparmService = { @@ -650,7 +650,7 @@ static PyMethodDef pyparam_methods[] = { "Returns the compiled in BINDIR." }, { "sbin_dir", (PyCFunction)py_sbin_dir, METH_NOARGS, "Returns the compiled in SBINDIR." }, - { NULL } + {0} }; static struct PyModuleDef moduledef = { diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 76712b52397..5ad9901e623 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -3317,7 +3317,7 @@ int main(int argc, const char *argv[]) POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; TALLOC_CTX *mem_ctx = NULL; diff --git a/source4/torture/ldb/ldb.c b/source4/torture/ldb/ldb.c index cdf513a9fea..9c333e6b01f 100644 --- a/source4/torture/ldb/ldb.c +++ b/source4/torture/ldb/ldb.c @@ -1331,9 +1331,6 @@ static bool torture_ldb_unpack_data_corrupt(struct torture_context *torture) int i, j, current, expect_rcode, ret; const char *comment; - const char *comment_fmt = "Expected unpack rcode for index %d " - "(corrupt bytes index %d) " - "to be %d but got %d"; /* * List of corruptible byte ranges. First 12 bytes are corruptible, @@ -1358,9 +1355,15 @@ static bool torture_ldb_unpack_data_corrupt(struct torture_context *torture) ret = ldb_unpack_data(ldb, &bin_copy, msg); - comment = talloc_asprintf(bin_copy.data, comment_fmt, - current, i, - expect_rcode, ret); + comment = talloc_asprintf( + bin_copy.data, + "Expected unpack rcode for index %d " + "(corrupt bytes index %d) " + "to be %d but got %d", + current, + i, + expect_rcode, + ret); torture_assert_int_equal(torture, ret, expect_rcode, comment); diff --git a/source4/torture/locktest.c b/source4/torture/locktest.c index 546231fabec..97e0b6c0abd 100644 --- a/source4/torture/locktest.c +++ b/source4/torture/locktest.c @@ -578,7 +578,7 @@ int main(int argc, const char *argv[]) POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; TALLOC_CTX *mem_ctx = NULL; int ret = -1; diff --git a/source4/torture/masktest.c b/source4/torture/masktest.c index 5b9d1b2901f..35ec2e9d040 100644 --- a/source4/torture/masktest.c +++ b/source4/torture/masktest.c @@ -317,7 +317,7 @@ int main(int argc, const char *argv[]) POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; setlinebuf(stdout); diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c index 90b2b04cd88..1dbbe6c8301 100644 --- a/source4/torture/smbtorture.c +++ b/source4/torture/smbtorture.c @@ -426,7 +426,7 @@ int main(int argc, const char *argv[]) POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION - { NULL } + {0} }; setlinebuf(stdout); diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 94cbf277677..4984aaeb981 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -6897,7 +6897,7 @@ static bool test_empty_stream(struct torture_context *tctx, tcase_afpresource_rw, tcase_foo_ro, tcase_foo_rw, - {NULL} + {0} }; ret = torture_smb2_connection(tctx, &tree2); diff --git a/source4/utils/oLschema2ldif/main.c b/source4/utils/oLschema2ldif/main.c index 601b8a8f1f2..a3445f8ffe6 100644 --- a/source4/utils/oLschema2ldif/main.c +++ b/source4/utils/oLschema2ldif/main.c @@ -49,7 +49,7 @@ static struct poptOption popt_options[] = { { "output", 'O', POPT_ARG_STRING, &options.output, 0, "outputfile otherwise STDOUT", "outputfile"}, POPT_COMMON_VERSION - { NULL } + {0} }; -- 2.25.1 From 46a12ed3c3d18461d54a775b61da4ff979e40f2c Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 21 Apr 2020 15:37:40 +1200 Subject: [PATCH 381/645] lib ldb: Limit depth of ldb_parse_tree Limit the number of nested conditionals allowed by ldb_parse tree to 128, to avoid potential stack overflow issues. Credit Oss-Fuzz REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19508 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett Autobuild-User(master): Gary Lockyer Autobuild-Date(master): Sun May 10 23:21:08 UTC 2020 on sn-devel-184 (cherry picked from commit a699256f438527455aaff6c73c88ee87ac7083ef) --- lib/ldb/common/ldb_parse.c | 72 +++++++++++++++++++++++------ lib/ldb/tests/ldb_parse_test.c | 83 +++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 15 deletions(-) diff --git a/lib/ldb/common/ldb_parse.c b/lib/ldb/common/ldb_parse.c index 452c5830ed5..7e15206b168 100644 --- a/lib/ldb/common/ldb_parse.c +++ b/lib/ldb/common/ldb_parse.c @@ -43,6 +43,16 @@ #include "ldb_private.h" #include "system/locale.h" +/* + * Maximum depth of the filter parse tree, the value chosen is small enough to + * avoid triggering ASAN stack overflow checks. But large enough to be useful. + * + * On Windows clients the maximum number of levels of recursion allowed is 100. + * In the LDAP server, Windows restricts clients to 512 nested + * (eg) OR statements. + */ +#define LDB_MAX_PARSE_TREE_DEPTH 128 + static int ldb_parse_hex2char(const char *x) { if (isxdigit(x[0]) && isxdigit(x[1])) { @@ -231,7 +241,11 @@ static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *str return ret; } -static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s); +static struct ldb_parse_tree *ldb_parse_filter( + TALLOC_CTX *mem_ctx, + const char **s, + unsigned depth, + unsigned max_depth); /* @@ -498,7 +512,11 @@ static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char * ::= '|' ::= | */ -static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const char **s) +static struct ldb_parse_tree *ldb_parse_filterlist( + TALLOC_CTX *mem_ctx, + const char **s, + unsigned depth, + unsigned max_depth) { struct ldb_parse_tree *ret, *next; enum ldb_parse_op op; @@ -533,7 +551,8 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch return NULL; } - ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &p); + ret->u.list.elements[0] = + ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth); if (!ret->u.list.elements[0]) { talloc_free(ret); return NULL; @@ -547,7 +566,8 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch break; } - next = ldb_parse_filter(ret->u.list.elements, &p); + next = ldb_parse_filter( + ret->u.list.elements, &p, depth, max_depth); if (next == NULL) { /* an invalid filter element */ talloc_free(ret); @@ -576,7 +596,11 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch /* ::= '!' */ -static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s) +static struct ldb_parse_tree *ldb_parse_not( + TALLOC_CTX *mem_ctx, + const char **s, + unsigned depth, + unsigned max_depth) { struct ldb_parse_tree *ret; const char *p = *s; @@ -593,7 +617,7 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s) } ret->operation = LDB_OP_NOT; - ret->u.isnot.child = ldb_parse_filter(ret, &p); + ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth); if (!ret->u.isnot.child) { talloc_free(ret); return NULL; @@ -608,7 +632,11 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s) parse a filtercomp ::= | | | */ -static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const char **s) +static struct ldb_parse_tree *ldb_parse_filtercomp( + TALLOC_CTX *mem_ctx, + const char **s, + unsigned depth, + unsigned max_depth) { struct ldb_parse_tree *ret; const char *p = *s; @@ -617,15 +645,15 @@ static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const ch switch (*p) { case '&': - ret = ldb_parse_filterlist(mem_ctx, &p); + ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth); break; case '|': - ret = ldb_parse_filterlist(mem_ctx, &p); + ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth); break; case '!': - ret = ldb_parse_not(mem_ctx, &p); + ret = ldb_parse_not(mem_ctx, &p, depth, max_depth); break; case '(': @@ -641,21 +669,34 @@ static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const ch return ret; } - /* ::= '(' ')' */ -static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s) +static struct ldb_parse_tree *ldb_parse_filter( + TALLOC_CTX *mem_ctx, + const char **s, + unsigned depth, + unsigned max_depth) { struct ldb_parse_tree *ret; const char *p = *s; + /* + * Check the depth of the parse tree, and reject the input if + * max_depth exceeded. This avoids stack overflow + * issues. + */ + if (depth > max_depth) { + return NULL; + } + depth++; + if (*p != '(') { return NULL; } p++; - ret = ldb_parse_filtercomp(mem_ctx, &p); + ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth); if (*p != ')') { return NULL; @@ -679,6 +720,8 @@ static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char * */ struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) { + unsigned depth = 0; + while (s && isspace((unsigned char)*s)) s++; if (s == NULL || *s == 0) { @@ -686,7 +729,8 @@ struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) } if (*s == '(') { - return ldb_parse_filter(mem_ctx, &s); + return ldb_parse_filter( + mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH); } return ldb_parse_simple(mem_ctx, &s); diff --git a/lib/ldb/tests/ldb_parse_test.c b/lib/ldb/tests/ldb_parse_test.c index a739d7795d1..d7442b954ea 100644 --- a/lib/ldb/tests/ldb_parse_test.c +++ b/lib/ldb/tests/ldb_parse_test.c @@ -81,10 +81,91 @@ static void test_parse_filtertype(void **state) test_roundtrip(ctx, " ", "(|(objectClass=*)(distinguishedName=*))"); } +/* + * Test that a nested query with 128 levels of nesting is accepted + */ +static void test_nested_filter_eq_limit(void **state) +{ + struct test_ctx *ctx = + talloc_get_type_abort(*state, struct test_ctx); + + /* + * 128 nested clauses + */ + const char *nested_query = "" + "(|(!(|(&(|(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(&(|(|(|(|(|(|(!(|(!(|(|(|" + "(|(!(|(&(|(|(&(|(|(|(|(|(!(!(!(|" + "(|(!(|(&(|(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(&(|(|(|(!(|(|(&(|(|(|(|(|" + "(|(!(|(&(|(|(&(|(|(|(|(|(&(&(|(|" + "(|(!(|(&(|(|(|(|(|(|(!(|(|(|(|(|" + "(|(!(|(&(|(|(!(|(|(|(|(|(|(|(|(|" + "(a=b)" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))"; + + struct ldb_parse_tree *tree = ldb_parse_tree(ctx, nested_query); + + assert_non_null(tree); + /* + * Check that we get the same query back + */ + test_roundtrip(ctx, nested_query, nested_query); +} + +/* + * Test that a nested query with 129 levels of nesting is rejected. + */ +static void test_nested_filter_gt_limit(void **state) +{ + struct test_ctx *ctx = + talloc_get_type_abort(*state, struct test_ctx); + + /* + * 129 nested clauses + */ + const char *nested_query = "" + "(|(!(|(|(&(|(|(|(|(&(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(!(|(|(|(|(!(|(|(|" + "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(|(!(&(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|" + "(|(!(|(|(&(|(|(|(|(|(|(|(|(&(|(|" + "(|" + "(a=b)" + ")" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))" + "))))))))))))))))"; + + struct ldb_parse_tree *tree = ldb_parse_tree(ctx, nested_query); + + assert_null(tree); +} + int main(int argc, const char **argv) { const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown(test_parse_filtertype, setup, teardown), + cmocka_unit_test_setup_teardown( + test_parse_filtertype, setup, teardown), + cmocka_unit_test_setup_teardown( + test_nested_filter_eq_limit, setup, teardown), + cmocka_unit_test_setup_teardown( + test_nested_filter_gt_limit, setup, teardown), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); -- 2.25.1 From aceea78fc5501dbb33c9b7a4164babbd10344ad9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 21 Feb 2020 08:03:57 +0100 Subject: [PATCH 382/645] winbindd: Align integer types Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit bf07b16e30cb6be25b1e8df5c1f7cc004d078443) --- source3/winbindd/wb_sids2xids.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 7ab8dd133fd..e6698f94789 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -170,7 +170,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) struct lsa_TransNameArray *names = NULL; struct dcerpc_binding_handle *child_binding_handle = NULL; NTSTATUS status; - int i; + uint32_t i; status = wb_lookupsids_recv(subreq, state, &domains, &names); TALLOC_FREE(subreq); -- 2.25.1 From 48e674a8f3faa4b213553a64eca91824a8a074c8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Feb 2020 11:07:27 +1300 Subject: [PATCH 383/645] CVE-2020-25722 auth/credentials: Test connecting to LDAP with a "virtual user" style account This type of account is often used by e-mail hosting platforms that do not wish to create an AD domain for each DNS domain that they host mail for. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13598 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Andrew Bartlett Reviewed-by: Isaac Boukris (cherry picked from commit 8fbdff5c3d7bc68b4c89ac460914a5d18775244e) --- auth/credentials/tests/bind.py | 52 ++++++++++++++++++++++++- selftest/knownfail.d/ldap-virtual-users | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 selftest/knownfail.d/ldap-virtual-users diff --git a/auth/credentials/tests/bind.py b/auth/credentials/tests/bind.py index 2eaf0c0fd08..9e2b50b3352 100755 --- a/auth/credentials/tests/bind.py +++ b/auth/credentials/tests/bind.py @@ -14,7 +14,7 @@ from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options -from ldb import SCOPE_BASE, SCOPE_SUBTREE +from ldb import SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_INVALID_CREDENTIALS from samba import gensec import samba.tests @@ -48,6 +48,7 @@ creds = credopts.get_credentials(lp) creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) creds_machine = create_credential(lp, creds) +creds_virtual = create_credential(lp, creds) creds_user1 = create_credential(lp, creds) creds_user2 = create_credential(lp, creds) creds_user3 = create_credential(lp, creds) @@ -71,13 +72,62 @@ class BindTests(samba.tests.TestCase): self.schema_dn = self.info_dc["schemaNamingContext"][0] self.domain_dn = self.info_dc["defaultNamingContext"][0] self.config_dn = self.info_dc["configurationNamingContext"][0] + self.realm = self.info_dc["ldapServiceName"][0].split(b'@')[1].decode('utf-8') self.computer_dn = "CN=centos53,CN=Computers,%s" % self.domain_dn + self.virtual_user_dn = "CN=frednurk@%s,CN=Computers,%s" % (self.realm, self.domain_dn) self.password = "P@ssw0rd" self.username = "BindTestUser" def tearDown(self): + delete_force(self.ldb, self.virtual_user_dn) super(BindTests, self).tearDown() + def test_virtual_email_account_style_bind(self): + # create a user in the style often deployed for authentication + # of virtual email account at a hosting provider + # + # The userPrincipalName must not match the samAccountName for + # this test to detect when the LDAP DN is being double-parsed + # but must be in the user@realm style to allow the account to + # be created + self.ldb.add_ldif(""" +dn: """ + self.virtual_user_dn + """ +cn: frednurk@""" + self.realm + """ +displayName: Fred Nurk +sAMAccountName: frednurk@""" + self.realm + """ +userPrincipalName: frednurk@NOT.""" + self.realm + """ +countryCode: 0 +objectClass: computer +objectClass: organizationalPerson +objectClass: person +objectClass: top +objectClass: user +""") + self.addCleanup(delete_force, self.ldb, self.virtual_user_dn) + self.ldb.modify_ldif(""" +dn: """ + self.virtual_user_dn + """ +changetype: modify +replace: unicodePwd +unicodePwd:: """ + base64.b64encode(u"\"P@ssw0rd\"".encode('utf-16-le')).decode('utf8') + """ +""") + + self.ldb.enable_account('distinguishedName=%s' % self.virtual_user_dn) + + # do a simple bind and search with the machine account + creds_virtual.set_bind_dn(self.virtual_user_dn) + creds_virtual.set_password(self.password) + print("BindTest with: " + creds_virtual.get_bind_dn()) + try: + ldb_virtual = samba.tests.connect_samdb(host, credentials=creds_virtual, + lp=lp, ldap_only=True) + except LdbError as e: + (num, msg) = e.args + if num != ERR_INVALID_CREDENTIALS: + raise + self.fail(msg) + + res = ldb_virtual.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) + def test_computer_account_bind(self): # create a computer acocount for the test delete_force(self.ldb, self.computer_dn) diff --git a/selftest/knownfail.d/ldap-virtual-users b/selftest/knownfail.d/ldap-virtual-users new file mode 100644 index 00000000000..318a2b587b7 --- /dev/null +++ b/selftest/knownfail.d/ldap-virtual-users @@ -0,0 +1 @@ +^samba4.ldap.bind\(fl2008r2dc\).__main__.BindTests.test_virtual_email_account_style_bind \ No newline at end of file -- 2.25.1 From d53b55de591e020774d6ce7423b3c7365a46e3a7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Feb 2020 11:52:33 +1300 Subject: [PATCH 384/645] CVE-2020-25722 s4-auth: Allow simple bind login of a user with an @ in the samAccountName LDAP Simple BIND authentications have already been mapped to a DOMAIN\username pair and should not be mapped twice. This appears to be a regression in 09e24ce40f89ac2f03d0c5fefa8b59f0d113fa6b included in Samba 4.7. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13598 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Andrew Bartlett Reviewed-by: Isaac Boukris Autobuild-User(master): Isaac Boukris Autobuild-Date(master): Fri Feb 14 17:13:33 UTC 2020 on sn-devel-184 (cherry picked from commit f231a072d5c09a61e75091c294f722622dcd45da) --- selftest/knownfail.d/ldap-virtual-users | 1 - source4/auth/ntlm/auth_sam.c | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) delete mode 100644 selftest/knownfail.d/ldap-virtual-users diff --git a/selftest/knownfail.d/ldap-virtual-users b/selftest/knownfail.d/ldap-virtual-users deleted file mode 100644 index 318a2b587b7..00000000000 --- a/selftest/knownfail.d/ldap-virtual-users +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.bind\(fl2008r2dc\).__main__.BindTests.test_virtual_email_account_style_bind \ No newline at end of file diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index fb88cb87f66..70eddc12c53 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -644,7 +644,27 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx return NT_STATUS_NO_SUCH_DOMAIN; } - p = strchr_m(account_name, '@'); + /* + * If we have not already mapped this user, then now is a good + * time to do so, before we look it up. We used to do this + * earlier, but in a multi-forest environment we want to do + * this mapping at the final domain. + * + * However, on the flip side we may have already mapped the + * user if this was an LDAP simple bind, in which case we + * really, really want to get back to exactly the same account + * we got the DN for. + */ + if (user_info->mapped_state == false) { + p = strchr_m(account_name, '@'); + } else { + /* + * This is slightly nicer than double-indenting the + * block below + */ + p = NULL; + } + if (p != NULL) { const char *nt4_domain = NULL; const char *nt4_account = NULL; -- 2.25.1 From f0a76e3d2e112db4bd238085079c768af7ee4b1b Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 7 Feb 2020 11:02:38 +1300 Subject: [PATCH 385/645] CVE-2020-25722 pytests: heed assertEquals deprecation warning en-masse TestCase.assertEquals() is an alias for TestCase.assertEqual() and has been deprecated since Python 2.7. When we run our tests with in python developer mode (`PYTHONDEVMODE=1 make test`) we get 580 DeprecationWarnings about this. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Douglas Bagnall Reviewed-by: Noel Power [abartlet@samba.org backported from commit c247afbda00013bf4821e5a2d4f3166bf31814f0 as 9873932520a10a9be0d5c5ac10a630051ed62d40 conflicts with a b"" -> b"" change for 'in'] --- auth/credentials/tests/bind.py | 6 +- buildtools/wafsamba/tests/test_abi.py | 20 +- buildtools/wafsamba/tests/test_bundled.py | 2 +- buildtools/wafsamba/tests/test_utils.py | 28 +- lib/ldb-samba/tests/match_rules.py | 38 +- python/samba/tests/__init__.py | 2 +- python/samba/tests/audit_log_dsdb.py | 222 +-- python/samba/tests/audit_log_pass_change.py | 94 +- python/samba/tests/auth_log.py | 350 ++-- python/samba/tests/auth_log_ncalrpc.py | 22 +- python/samba/tests/auth_log_netlogon.py | 24 +- .../tests/auth_log_netlogon_bad_creds.py | 10 +- python/samba/tests/auth_log_pass_change.py | 6 +- python/samba/tests/auth_log_samlogon.py | 10 +- python/samba/tests/auth_log_winbind.py | 166 +- python/samba/tests/blackbox/mdfind.py | 2 +- .../samba/tests/blackbox/traffic_learner.py | 8 +- .../samba/tests/blackbox/traffic_summary.py | 2 +- python/samba/tests/common.py | 24 +- python/samba/tests/core.py | 16 +- python/samba/tests/dcerpc/bare.py | 12 +- python/samba/tests/dcerpc/dnsserver.py | 36 +- python/samba/tests/dcerpc/integer.py | 22 +- python/samba/tests/dcerpc/mdssvc.py | 2 +- python/samba/tests/dcerpc/misc.py | 18 +- python/samba/tests/dcerpc/raw_protocol.py | 1504 ++++++++--------- python/samba/tests/dcerpc/raw_testcase.py | 134 +- python/samba/tests/dcerpc/registry.py | 4 +- python/samba/tests/dcerpc/rpc_talloc.py | 2 +- python/samba/tests/dcerpc/rpcecho.py | 20 +- python/samba/tests/dcerpc/sam.py | 108 +- python/samba/tests/dcerpc/unix.py | 4 +- python/samba/tests/dns.py | 110 +- python/samba/tests/dns_base.py | 12 +- python/samba/tests/dns_forwarder.py | 4 +- python/samba/tests/dns_tkey.py | 8 +- python/samba/tests/dns_wildcard.py | 48 +- python/samba/tests/dsdb.py | 10 +- python/samba/tests/dsdb_schema_attributes.py | 52 +- python/samba/tests/encrypted_secrets.py | 2 +- python/samba/tests/get_opt.py | 14 +- python/samba/tests/gpo.py | 22 +- python/samba/tests/group_audit.py | 70 +- python/samba/tests/hostconfig.py | 10 +- python/samba/tests/join.py | 12 +- python/samba/tests/kcc/graph.py | 4 +- python/samba/tests/kcc/kcc_utils.py | 4 +- python/samba/tests/netcmd.py | 10 +- python/samba/tests/ntacls.py | 4 +- python/samba/tests/ntacls_backup.py | 8 +- python/samba/tests/ntlm_auth.py | 24 +- python/samba/tests/param.py | 14 +- python/samba/tests/password_hash.py | 14 +- python/samba/tests/password_hash_fl2003.py | 76 +- python/samba/tests/password_hash_fl2008.py | 92 +- python/samba/tests/password_hash_gpgme.py | 104 +- python/samba/tests/password_hash_ldap.py | 2 +- python/samba/tests/policy.py | 4 +- python/samba/tests/posixacl.py | 466 ++--- python/samba/tests/prefork_restart.py | 22 +- python/samba/tests/provision.py | 24 +- python/samba/tests/registry.py | 4 +- python/samba/tests/s3idmapdb.py | 12 +- python/samba/tests/s3param.py | 8 +- python/samba/tests/s3passdb.py | 100 +- python/samba/tests/s3registry.py | 6 +- python/samba/tests/s3windb.py | 2 +- python/samba/tests/samba3sam.py | 666 ++++---- python/samba/tests/samba_tool/computer.py | 18 +- python/samba/tests/samba_tool/contact.py | 20 +- .../samba_tool/drs_clone_dc_data_lmdb_size.py | 4 +- python/samba/tests/samba_tool/dsacl.py | 22 +- python/samba/tests/samba_tool/forest.py | 4 +- python/samba/tests/samba_tool/fsmo.py | 2 +- python/samba/tests/samba_tool/group.py | 22 +- .../samba/tests/samba_tool/join_lmdb_size.py | 8 +- python/samba/tests/samba_tool/ntacl.py | 60 +- python/samba/tests/samba_tool/ou.py | 22 +- .../tests/samba_tool/passwordsettings.py | 60 +- .../tests/samba_tool/promote_dc_lmdb_size.py | 16 +- .../tests/samba_tool/provision_lmdb_size.py | 8 +- python/samba/tests/samba_tool/schema.py | 12 +- python/samba/tests/samba_tool/sites.py | 2 +- python/samba/tests/samba_tool/timecmd.py | 4 +- python/samba/tests/samba_tool/user.py | 50 +- .../tests/samba_tool/user_virtualCryptSHA.py | 28 +- .../samba/tests/samba_tool/visualize_drs.py | 2 +- python/samba/tests/samdb_api.py | 24 +- python/samba/tests/security.py | 38 +- python/samba/tests/smb.py | 10 +- python/samba/tests/strings.py | 4 +- python/samba/tests/upgrade.py | 4 +- python/samba/tests/upgradeprovision.py | 30 +- python/samba/tests/upgradeprovisionneeddc.py | 8 +- python/samba/tests/xattr.py | 6 +- source4/dsdb/tests/python/acl.py | 178 +- source4/dsdb/tests/python/deletetest.py | 50 +- source4/dsdb/tests/python/dirsync.py | 4 +- source4/dsdb/tests/python/dsdb_schema_info.py | 2 +- source4/dsdb/tests/python/ldap.py | 670 ++++---- source4/dsdb/tests/python/ldap_schema.py | 118 +- source4/dsdb/tests/python/ldap_syntaxes.py | 62 +- source4/dsdb/tests/python/notification.py | 24 +- source4/dsdb/tests/python/password_lockout.py | 44 +- .../tests/python/password_lockout_base.py | 50 +- .../dsdb/tests/python/password_settings.py | 16 +- source4/dsdb/tests/python/passwords.py | 98 +- source4/dsdb/tests/python/rodc_rwdc.py | 24 +- source4/dsdb/tests/python/sam.py | 376 ++--- source4/dsdb/tests/python/sec_descriptor.py | 32 +- source4/dsdb/tests/python/sort.py | 8 +- source4/dsdb/tests/python/token_group.py | 18 +- .../tests/python/tombstone_reanimation.py | 20 +- .../dsdb/tests/python/urgent_replication.py | 32 +- source4/dsdb/tests/python/vlv.py | 14 +- source4/torture/drs/python/cracknames.py | 28 +- source4/torture/drs/python/delete_object.py | 26 +- source4/torture/drs/python/drs_base.py | 14 +- source4/torture/drs/python/fsmo.py | 2 +- source4/torture/drs/python/getnc_exop.py | 2 +- source4/torture/drs/python/getncchanges.py | 2 +- source4/torture/drs/python/repl_move.py | 138 +- source4/torture/drs/python/repl_rodc.py | 26 +- source4/torture/drs/python/repl_schema.py | 4 +- source4/torture/drs/python/repl_secdesc.py | 18 +- source4/torture/drs/python/replica_sync.py | 8 +- .../torture/drs/python/replica_sync_rodc.py | 4 +- source4/torture/drs/python/ridalloc_exop.py | 6 +- .../drs/python/samba_tool_drs_no_dns.py | 24 +- 129 files changed, 3796 insertions(+), 3796 deletions(-) diff --git a/auth/credentials/tests/bind.py b/auth/credentials/tests/bind.py index 9e2b50b3352..8bee6f96c62 100755 --- a/auth/credentials/tests/bind.py +++ b/auth/credentials/tests/bind.py @@ -66,7 +66,7 @@ class BindTests(samba.tests.TestCase): if self.info_dc is None: res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) BindTests.info_dc = res[0] # cache some of RootDSE props self.schema_dn = self.info_dc["schemaNamingContext"][0] @@ -170,7 +170,7 @@ unicodePwd:: """ + base64.b64encode(u"\"P@ssw0rd\"".encode('utf-16-le')).decode( ldb_res = self.ldb.search(base=self.domain_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % self.username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_dn = ldb_res[0]["dn"] self.addCleanup(delete_force, self.ldb, user_dn) @@ -204,7 +204,7 @@ unicodePwd:: """ + base64.b64encode(u"\"P@ssw0rd\"".encode('utf-16-le')).decode( ldb_res = self.ldb.search(base=self.domain_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % self.username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_dn = ldb_res[0]["dn"] self.addCleanup(delete_force, self.ldb, user_dn) diff --git a/buildtools/wafsamba/tests/test_abi.py b/buildtools/wafsamba/tests/test_abi.py index d6bdb041f72..8521c49d8e8 100644 --- a/buildtools/wafsamba/tests/test_abi.py +++ b/buildtools/wafsamba/tests/test_abi.py @@ -27,30 +27,30 @@ from samba.compat import StringIO class NormaliseSignatureTests(TestCase): def test_function_simple(self): - self.assertEquals("int (const struct GUID *, const struct GUID *)", + self.assertEqual("int (const struct GUID *, const struct GUID *)", normalise_signature("$2 = {int (const struct GUID *, const struct GUID *)} 0xe871 ")) def test_maps_Bool(self): # Some types have different internal names - self.assertEquals("bool (const struct GUID *)", + self.assertEqual("bool (const struct GUID *)", normalise_signature("$1 = {_Bool (const struct GUID *)} 0xe75b ")) def test_function_keep(self): - self.assertEquals( + self.assertEqual( "enum ndr_err_code (struct ndr_push *, int, const union winreg_Data *)", normalise_signature("enum ndr_err_code (struct ndr_push *, int, const union winreg_Data *)")) def test_struct_constant(self): - self.assertEquals( + self.assertEqual( 'uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\\000", node = "\\000\\000\\000\\000\\000"}, if_version = 0', normalise_signature('$239 = {uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\\000", node = "\\000\\000\\000\\000\\000"}, if_version = 0}')) def test_incomplete_sequence(self): # Newer versions of gdb insert these incomplete sequence elements - self.assertEquals( + self.assertEqual( 'uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2', normalise_signature('$244 = {uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237", , node = "\\b\\000+\\020H`"}, if_version = 2}')) - self.assertEquals( + self.assertEqual( 'uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2', normalise_signature('$244 = {uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\\237\\350", node = "\\b\\000+\\020H`"}, if_version = 2}')) @@ -62,7 +62,7 @@ class WriteVscriptTests(TestCase): abi_write_vscript(f, "MYLIB", "1.0", [], { "old": "1.0", "new": "1.0"}, ["*"]) - self.assertEquals(f.getvalue(), """\ + self.assertEqual(f.getvalue(), """\ 1.0 { \tglobal: \t\t*; @@ -79,7 +79,7 @@ class WriteVscriptTests(TestCase): abi_write_vscript(f, "MYLIB", "1.0", ["0.1"], { "old": "0.1", "new": "1.0"}, ["*"]) - self.assertEquals(f.getvalue(), """\ + self.assertEqual(f.getvalue(), """\ MYLIB_0.1 { \tglobal: \t\told; @@ -101,7 +101,7 @@ MYLIB_0.1 { "exc_old": "0.1", "old": "0.1", "new": "1.0"}, ["!exc_*"]) - self.assertEquals(f.getvalue(), """\ + self.assertEqual(f.getvalue(), """\ 1.0 { \tglobal: \t\t*; @@ -120,7 +120,7 @@ MYLIB_0.1 { "exc_bar": "1.0", "other": "1.0" }, ["pub_*", "!exc_*"]) - self.assertEquals(f.getvalue(), """\ + self.assertEqual(f.getvalue(), """\ 1.0 { \tglobal: \t\tpub_*; diff --git a/buildtools/wafsamba/tests/test_bundled.py b/buildtools/wafsamba/tests/test_bundled.py index c5f0db63cba..a8e982190d1 100644 --- a/buildtools/wafsamba/tests/test_bundled.py +++ b/buildtools/wafsamba/tests/test_bundled.py @@ -24,4 +24,4 @@ from wafsamba.samba_bundled import ( class TuplizeVersionTests(TestCase): def test_simple(self): - self.assertEquals((1, 2, 10), tuplize_version("1.2.10")) + self.assertEqual((1, 2, 10), tuplize_version("1.2.10")) diff --git a/buildtools/wafsamba/tests/test_utils.py b/buildtools/wafsamba/tests/test_utils.py index a9578e25ae6..77fc55c0e52 100644 --- a/buildtools/wafsamba/tests/test_utils.py +++ b/buildtools/wafsamba/tests/test_utils.py @@ -26,33 +26,33 @@ from wafsamba.samba_utils import ( class ToListTests(TestCase): def test_none(self): - self.assertEquals([], TO_LIST(None)) + self.assertEqual([], TO_LIST(None)) def test_already_list(self): - self.assertEquals(["foo", "bar", 1], TO_LIST(["foo", "bar", 1])) + self.assertEqual(["foo", "bar", 1], TO_LIST(["foo", "bar", 1])) def test_default_delimiter(self): - self.assertEquals(["foo", "bar"], TO_LIST("foo bar")) - self.assertEquals(["foo", "bar"], TO_LIST(" foo bar ")) - self.assertEquals(["foo ", "bar"], TO_LIST(" \"foo \" bar ")) + self.assertEqual(["foo", "bar"], TO_LIST("foo bar")) + self.assertEqual(["foo", "bar"], TO_LIST(" foo bar ")) + self.assertEqual(["foo ", "bar"], TO_LIST(" \"foo \" bar ")) def test_delimiter(self): - self.assertEquals(["foo", "bar"], TO_LIST("foo,bar", ",")) - self.assertEquals([" foo", "bar "], TO_LIST(" foo,bar ", ",")) - self.assertEquals([" \" foo\"", " bar "], TO_LIST(" \" foo\", bar ", ",")) + self.assertEqual(["foo", "bar"], TO_LIST("foo,bar", ",")) + self.assertEqual([" foo", "bar "], TO_LIST(" foo,bar ", ",")) + self.assertEqual([" \" foo\"", " bar "], TO_LIST(" \" foo\", bar ", ",")) class UniqueListTests(TestCase): def test_unique_list(self): - self.assertEquals(["foo", "bar"], unique_list(["foo", "bar", "foo"])) + self.assertEqual(["foo", "bar"], unique_list(["foo", "bar", "foo"])) class SubstVarsErrorTests(TestCase): def test_valid(self): - self.assertEquals("", subst_vars_error("", {})) - self.assertEquals("FOO bar", subst_vars_error("${F} bar", {"F": "FOO"})) + self.assertEqual("", subst_vars_error("", {})) + self.assertEqual("FOO bar", subst_vars_error("${F} bar", {"F": "FOO"})) def test_invalid(self): self.assertRaises(KeyError, subst_vars_error, "${F}", {}) @@ -63,14 +63,14 @@ class DictConcatTests(TestCase): def test_empty(self): ret = {} dict_concat(ret, {}) - self.assertEquals({}, ret) + self.assertEqual({}, ret) def test_same(self): ret = {"foo": "bar"} dict_concat(ret, {"foo": "bla"}) - self.assertEquals({"foo": "bar"}, ret) + self.assertEqual({"foo": "bar"}, ret) def test_simple(self): ret = {"foo": "bar"} dict_concat(ret, {"blie": "bla"}) - self.assertEquals({"foo": "bar", "blie": "bla"}, ret) + self.assertEqual({"foo": "bar", "blie": "bla"}, ret) diff --git a/lib/ldb-samba/tests/match_rules.py b/lib/ldb-samba/tests/match_rules.py index 0ad375653f6..abf485c9eab 100755 --- a/lib/ldb-samba/tests/match_rules.py +++ b/lib/ldb-samba/tests/match_rules.py @@ -1132,7 +1132,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf=cn=g1,%s" % self.ou_groups) - self.assertEquals(len(res1), 2) + self.assertEqual(len(res1), 2) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=g2,%s" % self.ou_groups in dn_list) self.assertTrue("CN=u2,%s" % self.ou_users in dn_list) @@ -1140,7 +1140,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf:1.2.840.113556.1.4.1941:=cn=g1,%s" % self.ou_groups) - self.assertEquals(len(res1), 6) + self.assertEqual(len(res1), 6) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u2,%s" % self.ou_users in dn_list) self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) @@ -1152,18 +1152,18 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member=cn=g1,%s" % self.ou_groups) - self.assertEquals(len(res1), 0) + self.assertEqual(len(res1), 0) res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member:1.2.840.113556.1.4.1941:=cn=g1,%s" % self.ou_groups) - self.assertEquals(len(res1), 0) + self.assertEqual(len(res1), 0) def test_g2_members(self): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf=cn=g2,%s" % self.ou_groups) - self.assertEquals(len(res1), 2) + self.assertEqual(len(res1), 2) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=g3,%s" % self.ou_groups in dn_list) self.assertTrue("CN=u2,%s" % self.ou_users in dn_list) @@ -1171,7 +1171,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf:1.2.840.113556.1.4.1941:=cn=g2,%s" % self.ou_groups) - self.assertEquals(len(res1), 5) + self.assertEqual(len(res1), 5) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u2,%s" % self.ou_users in dn_list) self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) @@ -1182,20 +1182,20 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member=cn=g2,%s" % self.ou_groups) - self.assertEquals(len(res1), 1) - self.assertEquals(str(res1[0].dn), "CN=g1,%s" % self.ou_groups) + self.assertEqual(len(res1), 1) + self.assertEqual(str(res1[0].dn), "CN=g1,%s" % self.ou_groups) res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member:1.2.840.113556.1.4.1941:=cn=g2,%s" % self.ou_groups) - self.assertEquals(len(res1), 1) - self.assertEquals(str(res1[0].dn), "CN=g1,%s" % self.ou_groups) + self.assertEqual(len(res1), 1) + self.assertEqual(str(res1[0].dn), "CN=g1,%s" % self.ou_groups) def test_g3_members(self): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf=cn=g3,%s" % self.ou_groups) - self.assertEquals(len(res1), 2) + self.assertEqual(len(res1), 2) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) self.assertTrue("CN=c3,%s" % self.ou_computers in dn_list) @@ -1203,7 +1203,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf:1.2.840.113556.1.4.1941:=cn=g3,%s" % self.ou_groups) - self.assertEquals(len(res1), 3) + self.assertEqual(len(res1), 3) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) self.assertTrue("CN=c1,%s" % self.ou_computers in dn_list) @@ -1212,13 +1212,13 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member=cn=g3,%s" % self.ou_groups) - self.assertEquals(len(res1), 1) - self.assertEquals(str(res1[0].dn), "CN=g2,%s" % self.ou_groups) + self.assertEqual(len(res1), 1) + self.assertEqual(str(res1[0].dn), "CN=g2,%s" % self.ou_groups) res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member:1.2.840.113556.1.4.1941:=cn=g3,%s" % self.ou_groups) - self.assertEquals(len(res1), 2) + self.assertEqual(len(res1), 2) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=g1,%s" % self.ou_groups in dn_list) self.assertTrue("CN=g2,%s" % self.ou_groups in dn_list) @@ -1227,7 +1227,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf=cn=g4,%s" % self.ou_groups) - self.assertEquals(len(res1), 3) + self.assertEqual(len(res1), 3) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) self.assertTrue("CN=u4,%s" % self.ou_users in dn_list) @@ -1236,7 +1236,7 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="memberOf:1.2.840.113556.1.4.1941:=cn=g4,%s" % self.ou_groups) - self.assertEquals(len(res1), 4) + self.assertEqual(len(res1), 4) dn_list = [str(res.dn) for res in res1] self.assertTrue("CN=u3,%s" % self.ou_users in dn_list) self.assertTrue("CN=u4,%s" % self.ou_users in dn_list) @@ -1246,12 +1246,12 @@ class MatchRuleConditionTests(samba.tests.TestCase): res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member=cn=g4,%s" % self.ou_groups) - self.assertEquals(len(res1), 0) + self.assertEqual(len(res1), 0) res1 = self.ldb.search(self.ou, scope=SCOPE_SUBTREE, expression="member:1.2.840.113556.1.4.1941:=cn=g4,%s" % self.ou_groups) - self.assertEquals(len(res1), 0) + self.assertEqual(len(res1), 0) def test_u1_members(self): res1 = self.ldb.search(self.ou, diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index d7abffe4060..d895802c34f 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -326,7 +326,7 @@ class TestCaseInTempDir(TestCase): def _remove_tempdir(self): # Note asserting here is treated as an error rather than a test failure - self.assertEquals([], os.listdir(self.tempdir)) + self.assertEqual([], os.listdir(self.tempdir)) os.rmdir(self.tempdir) self.tempdir = None diff --git a/python/samba/tests/audit_log_dsdb.py b/python/samba/tests/audit_log_dsdb.py index 29861332518..5de25502087 100644 --- a/python/samba/tests/audit_log_dsdb.py +++ b/python/samba/tests/audit_log_dsdb.py @@ -137,18 +137,18 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Modify", audit["operation"]) + self.assertEqual("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code # as to which will set the description as it is DCE/RPC over SMB @@ -156,11 +156,11 @@ class AuditLogDsdbTests(AuditLogTestBase): self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["clearTextPassword"]["actions"] - self.assertEquals(1, len(actions)) + self.assertEqual(1, len(actions)) self.assertTrue(actions[0]["redacted"]) - self.assertEquals("replace", actions[0]["action"]) + self.assertEqual("replace", actions[0]["action"]) def test_net_set_password(self): @@ -179,17 +179,17 @@ class AuditLogDsdbTests(AuditLogTestBase): domain_name=domain) messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Modify", audit["operation"]) + self.assertEqual("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code # as to which will set the description as it is DCE/RPC over SMB @@ -197,11 +197,11 @@ class AuditLogDsdbTests(AuditLogTestBase): self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["clearTextPassword"]["actions"] - self.assertEquals(1, len(actions)) + self.assertEqual(1, len(actions)) self.assertTrue(actions[0]["redacted"]) - self.assertEquals("replace", actions[0]["action"]) + self.assertEqual("replace", actions[0]["action"]) def test_ldap_change_password(self): @@ -220,30 +220,30 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Modify", audit["operation"]) + self.assertEqual("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") attributes = audit["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["userPassword"]["actions"] - self.assertEquals(2, len(actions)) + self.assertEqual(2, len(actions)) self.assertTrue(actions[0]["redacted"]) - self.assertEquals("delete", actions[0]["action"]) + self.assertEqual("delete", actions[0]["action"]) self.assertTrue(actions[1]["redacted"]) - self.assertEquals("add", actions[1]["action"]) + self.assertEqual("add", actions[1]["action"]) def test_ldap_replace_password(self): @@ -259,29 +259,29 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Modify", audit["operation"]) + self.assertEqual("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["userPassword"]["actions"] - self.assertEquals(1, len(actions)) + self.assertEqual(1, len(actions)) self.assertTrue(actions[0]["redacted"]) - self.assertEquals("replace", actions[0]["action"]) + self.assertEqual("replace", actions[0]["action"]) def test_ldap_add_user(self): @@ -290,41 +290,41 @@ class AuditLogDsdbTests(AuditLogTestBase): dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn messages = self.waitForMessages(2, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") audit = messages[1]["dsdbChange"] - self.assertEquals("Add", audit["operation"]) + self.assertEqual("Add", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["sessionId"])) self.assertTrue(self.is_guid(audit["transactionId"])) attributes = audit["attributes"] - self.assertEquals(3, len(attributes)) + self.assertEqual(3, len(attributes)) actions = attributes["objectclass"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) - self.assertEquals(1, len(actions[0]["values"])) - self.assertEquals("user", actions[0]["values"][0]["value"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) + self.assertEqual(1, len(actions[0]["values"])) + self.assertEqual("user", actions[0]["values"][0]["value"]) actions = attributes["sAMAccountName"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) - self.assertEquals(1, len(actions[0]["values"])) - self.assertEquals(USER_NAME, actions[0]["values"][0]["value"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) + self.assertEqual(1, len(actions[0]["values"])) + self.assertEqual(USER_NAME, actions[0]["values"][0]["value"]) actions = attributes["userPassword"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) self.assertTrue(actions[0]["redacted"]) def test_samdb_delete_user(self): @@ -336,28 +336,28 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Delete", audit["operation"]) + self.assertEqual("Delete", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) - self.assertEquals(0, audit["statusCode"]) - self.assertEquals("Success", audit["status"]) + self.assertEqual(0, audit["statusCode"]) + self.assertEqual("Success", audit["status"]) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") transactionId = audit["transactionId"] message = self.waitForTransaction(transactionId) audit = message["dsdbTransaction"] - self.assertEquals("commit", audit["action"]) + self.assertEqual("commit", audit["action"]) self.assertTrue(self.is_guid(audit["transactionId"])) self.assertTrue(audit["duration"] > 0) @@ -376,28 +376,28 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Delete", audit["operation"]) + self.assertEqual("Delete", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) - self.assertEquals(ERR_NO_SUCH_OBJECT, audit["statusCode"]) - self.assertEquals("No such object", audit["status"]) + self.assertEqual(ERR_NO_SUCH_OBJECT, audit["statusCode"]) + self.assertEqual("No such object", audit["status"]) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") transactionId = audit["transactionId"] message = self.waitForTransaction(transactionId) audit = message["dsdbTransaction"] - self.assertEquals("rollback", audit["action"]) + self.assertEqual("rollback", audit["action"]) self.assertTrue(self.is_guid(audit["transactionId"])) self.assertTrue(audit["duration"] > 0) @@ -424,42 +424,42 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Add", audit["operation"]) + self.assertEqual("Add", audit["operation"]) self.assertTrue(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code # as to which will set the description as it is DCE/RPC over SMB attributes = audit["attributes"] - self.assertEquals(2, len(attributes)) + self.assertEqual(2, len(attributes)) object_class = attributes["objectClass"] - self.assertEquals(1, len(object_class["actions"])) + self.assertEqual(1, len(object_class["actions"])) action = object_class["actions"][0] - self.assertEquals("add", action["action"]) + self.assertEqual("add", action["action"]) values = action["values"] - self.assertEquals(1, len(values)) - self.assertEquals("secret", values[0]["value"]) + self.assertEqual(1, len(values)) + self.assertEqual("secret", values[0]["value"]) cn = attributes["cn"] - self.assertEquals(1, len(cn["actions"])) + self.assertEqual(1, len(cn["actions"])) action = cn["actions"][0] - self.assertEquals("add", action["action"]) + self.assertEqual("add", action["action"]) values = action["values"] - self.assertEquals(1, len(values)) - self.assertEquals("Test Secret", values[0]["value"]) + self.assertEqual(1, len(values)) + self.assertEqual("Test Secret", values[0]["value"]) # # Now delete the secret. @@ -472,20 +472,20 @@ class AuditLogDsdbTests(AuditLogTestBase): lsa_conn.DeleteObject(h) messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") dn = "cn=Test Secret,CN=System," + self.base_dn audit = messages[0]["dsdbChange"] - self.assertEquals("Delete", audit["operation"]) + self.assertEqual("Delete", audit["operation"]) self.assertTrue(audit["performedAsSystem"]) self.assertTrue(dn.lower(), audit["dn"].lower()) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) # We skip the check for self.get_service_description() as this # is subject to a race between smbd and the s4 rpc_server code @@ -507,30 +507,30 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["dsdbChange"] - self.assertEquals("Modify", audit["operation"]) + self.assertEqual("Modify", audit["operation"]) self.assertFalse(audit["performedAsSystem"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") attributes = audit["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["carLicense"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) values = actions[0]["values"] - self.assertEquals(1, len(values)) - self.assertEquals("license-01", values[0]["value"]) + self.assertEqual(1, len(values)) + self.assertEqual("license-01", values[0]["value"]) # # Add an another value to the attribute @@ -544,17 +544,17 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") attributes = messages[0]["dsdbChange"]["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["carLicense"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) values = actions[0]["values"] - self.assertEquals(1, len(values)) - self.assertEquals("license-02", values[0]["value"]) + self.assertEqual(1, len(values)) + self.assertEqual("license-02", values[0]["value"]) # # Add an another two values to the attribute @@ -569,18 +569,18 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") attributes = messages[0]["dsdbChange"]["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["carLicense"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("add", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("add", actions[0]["action"]) values = actions[0]["values"] - self.assertEquals(2, len(values)) - self.assertEquals("license-03", values[0]["value"]) - self.assertEquals("license-04", values[1]["value"]) + self.assertEqual(2, len(values)) + self.assertEqual("license-03", values[0]["value"]) + self.assertEqual("license-04", values[1]["value"]) # # delete two values to the attribute @@ -595,18 +595,18 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") attributes = messages[0]["dsdbChange"]["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["carLicense"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("delete", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("delete", actions[0]["action"]) values = actions[0]["values"] - self.assertEquals(2, len(values)) - self.assertEquals("license-03", values[0]["value"]) - self.assertEquals("license-04", values[1]["value"]) + self.assertEqual(2, len(values)) + self.assertEqual("license-03", values[0]["value"]) + self.assertEqual("license-04", values[1]["value"]) # # replace two values to the attribute @@ -621,15 +621,15 @@ class AuditLogDsdbTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") attributes = messages[0]["dsdbChange"]["attributes"] - self.assertEquals(1, len(attributes)) + self.assertEqual(1, len(attributes)) actions = attributes["carLicense"]["actions"] - self.assertEquals(1, len(actions)) - self.assertEquals("replace", actions[0]["action"]) + self.assertEqual(1, len(actions)) + self.assertEqual("replace", actions[0]["action"]) values = actions[0]["values"] - self.assertEquals(2, len(values)) - self.assertEquals("license-05", values[0]["value"]) - self.assertEquals("license-06", values[1]["value"]) + self.assertEqual(2, len(values)) + self.assertEqual("license-05", values[0]["value"]) + self.assertEqual("license-06", values[1]["value"]) diff --git a/python/samba/tests/audit_log_pass_change.py b/python/samba/tests/audit_log_pass_change.py index 4e25c872d2d..04bb850fa4f 100644 --- a/python/samba/tests/audit_log_pass_change.py +++ b/python/samba/tests/audit_log_pass_change.py @@ -119,19 +119,19 @@ class AuditLogPassChangeTests(AuditLogTestBase): messages = self.waitForMessages(1, net, dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_CHANGE, audit["eventId"]) - self.assertEquals("Change", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_CHANGE, audit["eventId"]) + self.assertEqual("Change", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "DCE/RPC") + self.assertEqual(service_description, "DCE/RPC") self.assertTrue(self.is_guid(audit["transactionId"])) def test_net_set_password_user_without_permission(self): @@ -147,23 +147,23 @@ class AuditLogPassChangeTests(AuditLogTestBase): dn = "CN=" + SECOND_USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) - self.assertEquals("Reset", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) + self.assertEqual("Reset", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["transactionId"])) - self.assertEquals(0, audit["statusCode"]) - self.assertEquals("Success", audit["status"]) + self.assertEqual(0, audit["statusCode"]) + self.assertEqual("Success", audit["status"]) self.discardMessages() creds = self.insta_creds( @@ -188,23 +188,23 @@ class AuditLogPassChangeTests(AuditLogTestBase): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, net, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) - self.assertEquals("Reset", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) + self.assertEqual("Reset", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "DCE/RPC") + self.assertEqual(service_description, "DCE/RPC") self.assertTrue(self.is_guid(audit["transactionId"])) - self.assertEquals(ERR_INSUFFICIENT_ACCESS_RIGHTS, audit["statusCode"]) - self.assertEquals("insufficient access rights", audit["status"]) + self.assertEqual(ERR_INSUFFICIENT_ACCESS_RIGHTS, audit["statusCode"]) + self.assertEqual("insufficient access rights", audit["status"]) def test_net_set_password(self): @@ -225,22 +225,22 @@ class AuditLogPassChangeTests(AuditLogTestBase): dn = "CN=" + USER_NAME + ",CN=Users," + self.base_dn messages = self.waitForMessages(1, net, dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) - self.assertEquals("Reset", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) + self.assertEqual("Reset", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "DCE/RPC") + self.assertEqual(service_description, "DCE/RPC") session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) self.assertTrue(self.is_guid(audit["transactionId"])) def test_ldap_change_password(self): @@ -259,21 +259,21 @@ class AuditLogPassChangeTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_CHANGE, audit["eventId"]) - self.assertEquals("Change", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_CHANGE, audit["eventId"]) + self.assertEqual("Change", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["transactionId"])) def test_ldap_replace_password(self): @@ -290,21 +290,21 @@ class AuditLogPassChangeTests(AuditLogTestBase): messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) - self.assertEquals("Reset", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) + self.assertEqual("Reset", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["transactionId"])) def test_ldap_add_user(self): @@ -314,7 +314,7 @@ class AuditLogPassChangeTests(AuditLogTestBase): dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn messages = self.waitForMessages(1, dn=dn) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -322,14 +322,14 @@ class AuditLogPassChangeTests(AuditLogTestBase): # The first message should be the reset from the Setup code. # audit = messages[0]["passwordChange"] - self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"]) - self.assertEquals("Reset", audit["action"]) - self.assertEquals(dn, audit["dn"]) + self.assertEqual(EVT_ID_PASSWORD_RESET, audit["eventId"]) + self.assertEqual("Reset", audit["action"]) + self.assertEqual(dn, audit["dn"]) self.assertRegexpMatches(audit["remoteAddress"], self.remoteAddress) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") self.assertTrue(self.is_guid(audit["sessionId"])) self.assertTrue(self.is_guid(audit["transactionId"])) diff --git a/python/samba/tests/auth_log.py b/python/samba/tests/auth_log.py index 06fb841a62b..3c56bc48e7f 100644 --- a/python/samba/tests/auth_log.py +++ b/python/samba/tests/auth_log.py @@ -97,9 +97,9 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): # Handle explicit smb2, smb1 or auto negotiation if "smb2" in binding_list: - self.assertEquals(serviceDescription, "SMB2") + self.assertEqual(serviceDescription, "SMB2") elif "smb1" in binding_list: - self.assertEquals(serviceDescription, "SMB") + self.assertEqual(serviceDescription, "SMB") else: self.assertIn(serviceDescription, ["SMB", "SMB2"]) @@ -107,30 +107,30 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): binding, protection): expected_messages = len(authTypes) - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals( + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) self._assert_ncacn_np_serviceDescription( binding, msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[1], + self.assertEqual(authTypes[1], msg["Authentication"]["authDescription"]) # Check the second message it should be an Authorization msg = messages[1] - self.assertEquals("Authorization", msg["type"]) + self.assertEqual("Authorization", msg["type"]) self._assert_ncacn_np_serviceDescription( binding, msg["Authorization"]["serviceDescription"]) - self.assertEquals(authTypes[2], msg["Authorization"]["authType"]) - self.assertEquals("SMB", msg["Authorization"]["transportProtection"]) + self.assertEqual(authTypes[2], msg["Authorization"]["authType"]) + self.assertEqual("SMB", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Check the third message it should be an Authentication @@ -140,17 +140,17 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): return (desc == "DCE/RPC" or desc == service) msg = messages[2] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) self.assertTrue( checkServiceDescription( msg["Authentication"]["serviceDescription"])) - self.assertEquals(authTypes[3], + self.assertEqual(authTypes[3], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def rpc_ncacn_np_krb5_check( @@ -162,7 +162,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): protection): expected_messages = len(authTypes) - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") @@ -170,39 +170,39 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): # This is almost certainly Authentication over UDP, and is probably # returning message too big, msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[1], + self.assertEqual(authTypes[1], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the second message it should be an Authentication # This this the TCP Authentication in response to the message too big # response to the UDP Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[2], + self.assertEqual(authTypes[2], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the third message it should be an Authorization msg = messages[2] - self.assertEquals("Authorization", msg["type"]) + self.assertEqual("Authorization", msg["type"]) self._assert_ncacn_np_serviceDescription( binding, msg["Authorization"]["serviceDescription"]) - self.assertEquals(authTypes[3], msg["Authorization"]["authType"]) - self.assertEquals("SMB", msg["Authorization"]["transportProtection"]) + self.assertEqual(authTypes[3], msg["Authorization"]["authType"]) + self.assertEqual("SMB", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) def test_rpc_ncacn_np_ntlm_dns_sign(self): @@ -321,73 +321,73 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): binding, protection): expected_messages = len(authTypes) - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals(authTypes[1], msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual(authTypes[1], msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("DCE/RPC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[2], + self.assertEqual(authTypes[2], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def rpc_ncacn_ip_tcp_krb5_check(self, messages, authTypes, service, binding, protection): expected_messages = len(authTypes) - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals(authTypes[1], msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual(authTypes[1], msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[2], + self.assertEqual(authTypes[2], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the third message it should be an Authentication msg = messages[2] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[2], + self.assertEqual(authTypes[2], msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_rpc_ncacn_ip_tcp_ntlm_dns_sign(self): @@ -479,36 +479,36 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=self.get_credentials()) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(3, + self.assertEqual(3, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals("ENC-TS Pre-authentication", + self.assertEqual("ENC-TS Pre-authentication", msg["Authentication"]["authDescription"]) self.assertTrue(msg["Authentication"]["duration"] > 0) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals("ENC-TS Pre-authentication", + self.assertEqual("ENC-TS Pre-authentication", msg["Authentication"]["authDescription"]) self.assertTrue(msg["Authentication"]["duration"] > 0) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_ldap_ntlm(self): @@ -524,20 +524,20 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=self.get_credentials()) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("LDAP", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("LDAP", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMSSP", msg["Authentication"]["authDescription"]) + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) self.assertTrue(msg["Authentication"]["duration"] > 0) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_ldap_simple_bind(self): @@ -556,21 +556,21 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=creds) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("LDAP", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("LDAP", msg["Authentication"]["serviceDescription"]) - self.assertEquals("simple bind", + self.assertEqual("simple bind", msg["Authentication"]["authDescription"]) - self.assertEquals( + self.assertEqual( EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals( + self.assertEqual( EVT_LOGON_NETWORK_CLEAR_TEXT, msg["Authentication"]["logonType"]) def test_ldap_simple_bind_bad_password(self): @@ -598,10 +598,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=creds) except LdbError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -628,10 +628,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=creds) except LdbError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -658,10 +658,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=creds) except LdbError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -683,7 +683,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): credentials=creds) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(0, + self.assertEqual(0, len(messages), "Did not receive the expected number of messages") @@ -709,7 +709,7 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): pass messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -724,33 +724,33 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(3, + self.assertEqual(3, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals("ENC-TS Pre-authentication", + self.assertEqual("ENC-TS Pre-authentication", msg["Authentication"]["authDescription"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("Kerberos KDC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Kerberos KDC", msg["Authentication"]["serviceDescription"]) - self.assertEquals("ENC-TS Pre-authentication", + self.assertEqual("ENC-TS Pre-authentication", msg["Authentication"]["authDescription"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_smb_bad_password(self): @@ -772,10 +772,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -802,10 +802,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -824,42 +824,42 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): call(["bin/smbclient", path, auth, "-mNT1", "-c quit"]) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(3, + self.assertEqual(3, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals("SMB", + self.assertEqual("SMB", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMSSP", + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) - self.assertEquals("No-Password", + self.assertEqual("No-Password", msg["Authentication"]["passwordType"]) - self.assertEquals(EVT_ID_UNSUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_UNSUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("SMB", + self.assertEqual("SMB", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMSSP", + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) - self.assertEquals("No-Password", + self.assertEqual("No-Password", msg["Authentication"]["passwordType"]) - self.assertEquals("ANONYMOUS LOGON", + self.assertEqual("ANONYMOUS LOGON", msg["Authentication"]["becameAccount"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_smb2_anonymous(self): @@ -877,42 +877,42 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): call(["bin/smbclient", path, auth, "-mSMB3", "-c quit"]) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(3, + self.assertEqual(3, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals("SMB2", + self.assertEqual("SMB2", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMSSP", + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) - self.assertEquals("No-Password", + self.assertEqual("No-Password", msg["Authentication"]["passwordType"]) - self.assertEquals(EVT_ID_UNSUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_UNSUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("SMB2", + self.assertEqual("SMB2", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMSSP", + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) - self.assertEquals("No-Password", + self.assertEqual("No-Password", msg["Authentication"]["passwordType"]) - self.assertEquals("ANONYMOUS LOGON", + self.assertEqual("ANONYMOUS LOGON", msg["Authentication"]["becameAccount"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_smb_no_krb_spnego(self): @@ -927,22 +927,22 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) self.assertIn(msg["Authentication"]["serviceDescription"], ["SMB", "SMB2"]) - self.assertEquals("NTLMSSP", + self.assertEqual("NTLMSSP", msg["Authentication"]["authDescription"]) - self.assertEquals("NTLMv2", + self.assertEqual("NTLMv2", msg["Authentication"]["passwordType"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_smb_no_krb_spnego_bad_password(self): @@ -967,10 +967,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -996,10 +996,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): self.smb_connection(creds) except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -1018,22 +1018,22 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): use_spnego="no") messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("SMB", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("SMB", msg["Authentication"]["serviceDescription"]) - self.assertEquals("bare-NTLM", + self.assertEqual("bare-NTLM", msg["Authentication"]["authDescription"]) - self.assertEquals("NTLMv1", + self.assertEqual("NTLMv1", msg["Authentication"]["passwordType"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_smb_no_krb_no_spnego_no_ntlmv2_bad_password(self): @@ -1061,10 +1061,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): use_spnego="no") except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -1093,10 +1093,10 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): use_spnego="no") except NTSTATUSError: thrown = True - self.assertEquals(thrown, True) + self.assertEqual(thrown, True) messages = self.waitForMessages(isLastExpectedMessage) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") @@ -1427,11 +1427,11 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): # Check the second to last message it should be an Authorization msg = messages[-2] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals("schannel", msg["Authorization"]["authType"]) - self.assertEquals("SEAL", msg["Authorization"]["transportProtection"]) + self.assertEqual("schannel", msg["Authorization"]["authType"]) + self.assertEqual("SEAL", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Signed logons get promoted to sealed, this test ensures that @@ -1470,9 +1470,9 @@ class AuthLogTests(samba.tests.auth_log_base.AuthLogTestBase): # Check the second to last message it should be an Authorization msg = messages[-2] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals("schannel", msg["Authorization"]["authType"]) - self.assertEquals("SEAL", msg["Authorization"]["transportProtection"]) + self.assertEqual("schannel", msg["Authorization"]["authType"]) + self.assertEqual("SEAL", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) diff --git a/python/samba/tests/auth_log_ncalrpc.py b/python/samba/tests/auth_log_ncalrpc.py index 1281d28040e..511e575d9bd 100644 --- a/python/samba/tests/auth_log_ncalrpc.py +++ b/python/samba/tests/auth_log_ncalrpc.py @@ -58,30 +58,30 @@ class AuthLogTestsNcalrpc(samba.tests.auth_log_base.AuthLogTestBase): def rpc_ncacn_np_ntlm_check(self, messages, authTypes, protection): expected_messages = len(authTypes) - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals(authTypes[1], msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual(authTypes[1], msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Check the second message it should be an Authentication msg = messages[1] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual("DCE/RPC", msg["Authentication"]["serviceDescription"]) - self.assertEquals(authTypes[2], + self.assertEqual(authTypes[2], msg["Authentication"]["authDescription"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_ncalrpc_ntlm_dns_sign(self): diff --git a/python/samba/tests/auth_log_netlogon.py b/python/samba/tests/auth_log_netlogon.py index 36920eeef34..04bca03cc06 100644 --- a/python/samba/tests/auth_log_netlogon.py +++ b/python/samba/tests/auth_log_netlogon.py @@ -102,33 +102,33 @@ class AuthLogTestsNetLogon(samba.tests.auth_log_base.AuthLogTestBase): def netlogon_check(self, messages): expected_messages = 5 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals("ncalrpc", msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual("ncalrpc", msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) # Check the fourth message it should be a NETLOGON Authentication msg = messages[3] - self.assertEquals("Authentication", msg["type"]) - self.assertEquals("NETLOGON", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual("NETLOGON", msg["Authentication"]["serviceDescription"]) - self.assertEquals("ServerAuthenticate", + self.assertEqual("ServerAuthenticate", msg["Authentication"]["authDescription"]) - self.assertEquals("NT_STATUS_OK", + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals("HMAC-SHA256", + self.assertEqual("HMAC-SHA256", msg["Authentication"]["passwordType"]) - self.assertEquals(EVT_ID_SUCCESSFUL_LOGON, + self.assertEqual(EVT_ID_SUCCESSFUL_LOGON, msg["Authentication"]["eventId"]) - self.assertEquals(EVT_LOGON_NETWORK, + self.assertEqual(EVT_LOGON_NETWORK, msg["Authentication"]["logonType"]) def test_netlogon(self): diff --git a/python/samba/tests/auth_log_netlogon_bad_creds.py b/python/samba/tests/auth_log_netlogon_bad_creds.py index bd8b497cd88..a89c0312d1a 100644 --- a/python/samba/tests/auth_log_netlogon_bad_creds.py +++ b/python/samba/tests/auth_log_netlogon_bad_creds.py @@ -106,17 +106,17 @@ class AuthLogTestsNetLogonBadCreds(samba.tests.auth_log_base.AuthLogTestBase): def netlogon_check(self, messages): expected_messages = 4 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals("ncalrpc", msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual("ncalrpc", msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) def test_netlogon_bad_machine_name(self): diff --git a/python/samba/tests/auth_log_pass_change.py b/python/samba/tests/auth_log_pass_change.py index 0300fbc06d1..ee646722b20 100644 --- a/python/samba/tests/auth_log_pass_change.py +++ b/python/samba/tests/auth_log_pass_change.py @@ -130,7 +130,7 @@ class AuthLogPassChangeTests(samba.tests.auth_log_base.AuthLogTestBase): username=USER_NAME) except Exception: exception_thrown = True - self.assertEquals(True, exception_thrown, + self.assertEqual(True, exception_thrown, "Expected exception not thrown") self.assertTrue(self.waitForMessages(isLastExpectedMessage), "Did not receive the expected message") @@ -162,7 +162,7 @@ class AuthLogPassChangeTests(samba.tests.auth_log_base.AuthLogTestBase): username="badUser") except Exception: exception_thrown = True - self.assertEquals(True, exception_thrown, + self.assertEqual(True, exception_thrown, "Expected exception not thrown") self.assertTrue(self.waitForMessages(isLastExpectedMessage), @@ -195,7 +195,7 @@ class AuthLogPassChangeTests(samba.tests.auth_log_base.AuthLogTestBase): username=USER_NAME) except Exception: exception_thrown = True - self.assertEquals(True, exception_thrown, + self.assertEqual(True, exception_thrown, "Expected exception not thrown") self.assertTrue(self.waitForMessages(isLastExpectedMessage), diff --git a/python/samba/tests/auth_log_samlogon.py b/python/samba/tests/auth_log_samlogon.py index 4959543937e..5999b9842ea 100644 --- a/python/samba/tests/auth_log_samlogon.py +++ b/python/samba/tests/auth_log_samlogon.py @@ -159,17 +159,17 @@ class AuthLogTestsSamLogon(samba.tests.auth_log_base.AuthLogTestBase): messages = self.remove_netlogon_messages(messages) expected_messages = 5 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authorization msg = messages[0] - self.assertEquals("Authorization", msg["type"]) - self.assertEquals("DCE/RPC", + self.assertEqual("Authorization", msg["type"]) + self.assertEqual("DCE/RPC", msg["Authorization"]["serviceDescription"]) - self.assertEquals("ncalrpc", msg["Authorization"]["authType"]) - self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + self.assertEqual("ncalrpc", msg["Authorization"]["authType"]) + self.assertEqual("NONE", msg["Authorization"]["transportProtection"]) self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"])) def test_ncalrpc_samlogon(self): diff --git a/python/samba/tests/auth_log_winbind.py b/python/samba/tests/auth_log_winbind.py index 4c68187aef8..dcb12fdb4c0 100644 --- a/python/samba/tests/auth_log_winbind.py +++ b/python/samba/tests/auth_log_winbind.py @@ -190,11 +190,11 @@ class AuthLogTestsWinbind(AuthLogTestBase, BlackboxTestCase): # # Validate that message contains the expected data # - self.assertEquals("Authentication", msg["type"]) - self.assertEquals(logon_id, msg["Authentication"]["logonId"]) - self.assertEquals("SamLogon", + self.assertEqual("Authentication", msg["type"]) + self.assertEqual(logon_id, msg["Authentication"]["logonId"]) + self.assertEqual("SamLogon", msg["Authentication"]["serviceDescription"]) - self.assertEquals(description, + self.assertEqual(description, msg["Authentication"]["authDescription"]) def test_ntlm_auth(self): @@ -218,30 +218,30 @@ class AuthLogTestsWinbind(AuthLogTestBase, BlackboxTestCase): messages = self.waitForMessages(isLastExpectedMessage) messages = self.filter_messages(messages) expected_messages = 1 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # Check the first message it should be an Authentication msg = messages[0] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue( msg["Authentication"]["authDescription"].startswith( "PAM_AUTH, ntlm_auth,")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) - self.assertEquals("Plaintext", msg["Authentication"]["passwordType"]) + self.assertEqual("Plaintext", msg["Authentication"]["passwordType"]) # Logon type should be NetworkCleartext - self.assertEquals(8, msg["Authentication"]["logonType"]) + self.assertEqual(8, msg["Authentication"]["logonType"]) # Event code should be Successful logon - self.assertEquals(4624, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals(self.domain, msg["Authentication"]["clientDomain"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual(4624, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual(self.domain, msg["Authentication"]["clientDomain"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals(self.credentials.get_domain(), + self.assertEqual(self.credentials.get_domain(), msg["Authentication"]["clientDomain"]) self.assertTrue(msg["Authentication"]["workstation"] is None) @@ -275,76 +275,76 @@ class AuthLogTestsWinbind(AuthLogTestBase, BlackboxTestCase): messages = self.waitForMessages(isLastExpectedMessage) messages = self.filter_messages(messages) expected_messages = 3 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # The 1st message should be an Authentication against the local # password database msg = messages[0] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "PASSDB, wbinfo,")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) # Logon type should be Interactive - self.assertEquals(2, msg["Authentication"]["logonType"]) + self.assertEqual(2, msg["Authentication"]["logonType"]) # Event code should be Unsuccessful logon - self.assertEquals(4625, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals('', msg["Authentication"]["clientDomain"]) + self.assertEqual(4625, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual('', msg["Authentication"]["clientDomain"]) # This is what the existing winbind implementation returns. - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals("NTLMv2", msg["Authentication"]["passwordType"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual("NTLMv2", msg["Authentication"]["passwordType"]) + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals("", msg["Authentication"]["clientDomain"]) + self.assertEqual("", msg["Authentication"]["clientDomain"]) logon_id = msg["Authentication"]["logonId"] # The 2nd message should be a PAM_AUTH with the same logon id as the # 1st message msg = messages[1] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "PAM_AUTH")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) - self.assertEquals(logon_id, msg["Authentication"]["logonId"]) + self.assertEqual(logon_id, msg["Authentication"]["logonId"]) # Logon type should be NetworkCleartext - self.assertEquals(8, msg["Authentication"]["logonType"]) + self.assertEqual(8, msg["Authentication"]["logonType"]) # Event code should be Unsuccessful logon - self.assertEquals(4625, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals('', msg["Authentication"]["clientDomain"]) + self.assertEqual(4625, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual('', msg["Authentication"]["clientDomain"]) # This is what the existing winbind implementation returns. - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals("", msg["Authentication"]["clientDomain"]) + self.assertEqual("", msg["Authentication"]["clientDomain"]) # The 3rd message should be an NTLM_AUTH msg = messages[2] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "NTLM_AUTH, wbinfo,")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) # Logon type should be Network - self.assertEquals(3, msg["Authentication"]["logonType"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual(3, msg["Authentication"]["logonType"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) # Event code should be successful logon - self.assertEquals(4624, msg["Authentication"]["eventId"]) - self.assertEquals("NTLMv2", msg["Authentication"]["passwordType"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual(4624, msg["Authentication"]["eventId"]) + self.assertEqual("NTLMv2", msg["Authentication"]["passwordType"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals(self.credentials.get_domain(), + self.assertEqual(self.credentials.get_domain(), msg["Authentication"]["clientDomain"]) logon_id = msg["Authentication"]["logonId"] @@ -377,78 +377,78 @@ class AuthLogTestsWinbind(AuthLogTestBase, BlackboxTestCase): messages = self.waitForMessages(isLastExpectedMessage) messages = self.filter_messages(messages) expected_messages = 3 - self.assertEquals(expected_messages, + self.assertEqual(expected_messages, len(messages), "Did not receive the expected number of messages") # The 1st message should be an Authentication against the local # password database msg = messages[0] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "PASSDB, wbinfo,")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) # Logon type should be Interactive - self.assertEquals(2, msg["Authentication"]["logonType"]) + self.assertEqual(2, msg["Authentication"]["logonType"]) # Event code should be Unsuccessful logon - self.assertEquals(4625, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals('', msg["Authentication"]["clientDomain"]) + self.assertEqual(4625, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual('', msg["Authentication"]["clientDomain"]) # This is what the existing winbind implementation returns. - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals("NTLMv2", msg["Authentication"]["passwordType"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual("NTLMv2", msg["Authentication"]["passwordType"]) + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals("", msg["Authentication"]["clientDomain"]) + self.assertEqual("", msg["Authentication"]["clientDomain"]) logon_id = msg["Authentication"]["logonId"] # The 2nd message should be a PAM_AUTH with the same logon id as the # 1st message msg = messages[1] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "PAM_AUTH")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) - self.assertEquals(logon_id, msg["Authentication"]["logonId"]) - self.assertEquals("Plaintext", msg["Authentication"]["passwordType"]) + self.assertEqual(logon_id, msg["Authentication"]["logonId"]) + self.assertEqual("Plaintext", msg["Authentication"]["passwordType"]) # Logon type should be NetworkCleartext - self.assertEquals(8, msg["Authentication"]["logonType"]) + self.assertEqual(8, msg["Authentication"]["logonType"]) # Event code should be Unsuccessful logon - self.assertEquals(4625, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals('', msg["Authentication"]["clientDomain"]) + self.assertEqual(4625, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual('', msg["Authentication"]["clientDomain"]) # This is what the existing winbind implementation returns. - self.assertEquals("NT_STATUS_NO_SUCH_USER", + self.assertEqual("NT_STATUS_NO_SUCH_USER", msg["Authentication"]["status"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals("", msg["Authentication"]["clientDomain"]) + self.assertEqual("", msg["Authentication"]["clientDomain"]) # The 3rd message should be an NTLM_AUTH msg = messages[2] - self.assertEquals("Authentication", msg["type"]) + self.assertEqual("Authentication", msg["type"]) self.assertTrue(msg["Authentication"]["authDescription"].startswith( "NTLM_AUTH, wbinfo,")) - self.assertEquals("winbind", + self.assertEqual("winbind", msg["Authentication"]["serviceDescription"]) - self.assertEquals("NTLMv1", + self.assertEqual("NTLMv1", msg["Authentication"]["passwordType"]) # Logon type should be Network - self.assertEquals(3, msg["Authentication"]["logonType"]) - self.assertEquals("NT_STATUS_OK", msg["Authentication"]["status"]) + self.assertEqual(3, msg["Authentication"]["logonType"]) + self.assertEqual("NT_STATUS_OK", msg["Authentication"]["status"]) # Event code should be successful logon - self.assertEquals(4624, msg["Authentication"]["eventId"]) - self.assertEquals("unix:", msg["Authentication"]["remoteAddress"]) - self.assertEquals("unix:", msg["Authentication"]["localAddress"]) - self.assertEquals(self.credentials.get_username(), + self.assertEqual(4624, msg["Authentication"]["eventId"]) + self.assertEqual("unix:", msg["Authentication"]["remoteAddress"]) + self.assertEqual("unix:", msg["Authentication"]["localAddress"]) + self.assertEqual(self.credentials.get_username(), msg["Authentication"]["clientAccount"]) - self.assertEquals(self.credentials.get_domain(), + self.assertEqual(self.credentials.get_domain(), msg["Authentication"]["clientDomain"]) logon_id = msg["Authentication"]["logonId"] diff --git a/python/samba/tests/blackbox/mdfind.py b/python/samba/tests/blackbox/mdfind.py index 44de51cf767..e00af054007 100644 --- a/python/samba/tests/blackbox/mdfind.py +++ b/python/samba/tests/blackbox/mdfind.py @@ -127,4 +127,4 @@ class MdfindBlackboxTests(BlackboxTestCase): actual = output.decode('utf-8').splitlines() expected = ["%s/%s" % (self.sharepath, file) for file in testfiles] - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) diff --git a/python/samba/tests/blackbox/traffic_learner.py b/python/samba/tests/blackbox/traffic_learner.py index bf2bb722d2e..ac941cea81c 100644 --- a/python/samba/tests/blackbox/traffic_learner.py +++ b/python/samba/tests/blackbox/traffic_learner.py @@ -57,13 +57,13 @@ class TrafficLearnerTests(BlackboxTestCase): actual_ngrams = {k: sorted(v) for k, v in actual.ngrams.items()} expected_ngrams = {k: sorted(v) for k, v in expected.ngrams.items()} - self.assertEquals(expected_ngrams, actual_ngrams) + self.assertEqual(expected_ngrams, actual_ngrams) actual_details = {k: sorted(v) for k, v in actual.query_details.items()} expected_details = {k: sorted(v) for k, v in expected.query_details.items()} - self.assertEquals(expected_details, actual_details) - self.assertEquals(expected.cumulative_duration, actual.cumulative_duration) - self.assertEquals(expected.packet_rate, actual.packet_rate) + self.assertEqual(expected_details, actual_details) + self.assertEqual(expected.cumulative_duration, actual.cumulative_duration) + self.assertEqual(expected.packet_rate, actual.packet_rate) with open(expected_fn) as f1, open(output) as f2: expected_json = json.load(f1) diff --git a/python/samba/tests/blackbox/traffic_summary.py b/python/samba/tests/blackbox/traffic_summary.py index c0be4c082e6..b895083fdb5 100644 --- a/python/samba/tests/blackbox/traffic_summary.py +++ b/python/samba/tests/blackbox/traffic_summary.py @@ -50,4 +50,4 @@ class TrafficSummaryTests(BlackboxTestCase): self.check_run(command) expected = open(EXPECTED_FN).readlines() actual = open(output).readlines() - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) diff --git a/python/samba/tests/common.py b/python/samba/tests/common.py index 2b7d22fd629..b7248b0826e 100644 --- a/python/samba/tests/common.py +++ b/python/samba/tests/common.py @@ -27,18 +27,18 @@ from samba.samdb import SamDB, dsdb_Dn class CommonTests(samba.tests.TestCaseInTempDir): def test_normalise_int32(self): - self.assertEquals('17', normalise_int32(17)) - self.assertEquals('17', normalise_int32('17')) - self.assertEquals('-123', normalise_int32('-123')) - self.assertEquals('-1294967296', normalise_int32('3000000000')) + self.assertEqual('17', normalise_int32(17)) + self.assertEqual('17', normalise_int32('17')) + self.assertEqual('-123', normalise_int32('-123')) + self.assertEqual('-1294967296', normalise_int32('3000000000')) def test_dsdb_Dn_binary(self): url = self.tempdir + "/test_dsdb_Dn_binary.ldb" sam = samba.Ldb(url=url) dn1 = dsdb_Dn(sam, "DC=foo,DC=bar") dn2 = dsdb_Dn(sam, "B:8:0000000D:;DC=samba,DC=example,DC=com") - self.assertEquals(dn2.binary, "0000000D") - self.assertEquals(13, dn2.get_binary_integer()) + self.assertEqual(dn2.binary, "0000000D") + self.assertEqual(13, dn2.get_binary_integer()) os.unlink(url) def test_dsdb_Dn_sorted(self): @@ -53,14 +53,14 @@ class CommonTests(samba.tests.TestCaseInTempDir): dn6 = dsdb_Dn(sam, ";OU=dn6,DC=samba,DC=example,DC=com") unsorted_links14 = [dn1, dn2, dn3, dn4] sorted_vals14 = [str(dn) for dn in sorted(unsorted_links14)] - self.assertEquals(sorted_vals14[0], str(dn3)) - self.assertEquals(sorted_vals14[1], str(dn2)) - self.assertEquals(sorted_vals14[2], str(dn1)) - self.assertEquals(sorted_vals14[3], str(dn4)) + self.assertEqual(sorted_vals14[0], str(dn3)) + self.assertEqual(sorted_vals14[1], str(dn2)) + self.assertEqual(sorted_vals14[2], str(dn1)) + self.assertEqual(sorted_vals14[3], str(dn4)) unsorted_links56 = [dn5, dn6] sorted_vals56 = [str(dn) for dn in sorted(unsorted_links56)] - self.assertEquals(sorted_vals56[0], str(dn6)) - self.assertEquals(sorted_vals56[1], str(dn5)) + self.assertEqual(sorted_vals56[0], str(dn6)) + self.assertEqual(sorted_vals56[1], str(dn5)) finally: del sam os.unlink(url) diff --git a/python/samba/tests/core.py b/python/samba/tests/core.py index 2614e9c9962..e3b44d18696 100644 --- a/python/samba/tests/core.py +++ b/python/samba/tests/core.py @@ -27,22 +27,22 @@ from samba.tests import TestCase, TestCaseInTempDir class SubstituteVarTestCase(TestCase): def test_empty(self): - self.assertEquals("", samba.substitute_var("", {})) + self.assertEqual("", samba.substitute_var("", {})) def test_nothing(self): - self.assertEquals("foo bar", + self.assertEqual("foo bar", samba.substitute_var("foo bar", {"bar": "bla"})) def test_replace(self): - self.assertEquals("foo bla", + self.assertEqual("foo bla", samba.substitute_var("foo ${bar}", {"bar": "bla"})) def test_broken(self): - self.assertEquals("foo ${bdkjfhsdkfh sdkfh ", + self.assertEqual("foo ${bdkjfhsdkfh sdkfh ", samba.substitute_var("foo ${bdkjfhsdkfh sdkfh ", {"bar": "bla"})) def test_unknown_var(self): - self.assertEquals("foo ${bla} gsff", + self.assertEqual("foo ${bla} gsff", samba.substitute_var("foo ${bla} gsff", {"bar": "bla"})) def test_check_all_substituted(self): @@ -58,7 +58,7 @@ class ArcfourTestCase(TestCase): plain = b'abcdefghi' crypt_expected = b'\xda\x91Z\xb0l\xd7\xb9\xcf\x99' crypt_calculated = arcfour_encrypt(key, plain) - self.assertEquals(crypt_expected, crypt_calculated) + self.assertEqual(crypt_expected, crypt_calculated) class StringToByteArrayTestCase(TestCase): @@ -66,7 +66,7 @@ class StringToByteArrayTestCase(TestCase): def test_byte_array(self): expected = [218, 145, 90, 176, 108, 215, 185, 207, 153] calculated = string_to_byte_array('\xda\x91Z\xb0l\xd7\xb9\xcf\x99') - self.assertEquals(expected, calculated) + self.assertEqual(expected, calculated) class LdbExtensionTests(TestCaseInTempDir): @@ -76,7 +76,7 @@ class LdbExtensionTests(TestCaseInTempDir): l = samba.Ldb(path) try: l.add({"dn": "foo=dc", "bar": "bla"}) - self.assertEquals(b"bla", + self.assertEqual(b"bla", l.searchone(basedn=ldb.Dn(l, "foo=dc"), attribute="bar")) finally: del l diff --git a/python/samba/tests/dcerpc/bare.py b/python/samba/tests/dcerpc/bare.py index bb25546ddc7..622965277e7 100644 --- a/python/samba/tests/dcerpc/bare.py +++ b/python/samba/tests/dcerpc/bare.py @@ -31,7 +31,7 @@ class BareTestCase(samba.tests.TestCase): x = ClientConnection("ncalrpc:localhost[DEFAULT]", ("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=samba.tests.env_loadparm()) - self.assertEquals(b"\x01\x00\x00\x00", x.request(0, chr(0) * 4)) + self.assertEqual(b"\x01\x00\x00\x00", x.request(0, chr(0) * 4)) def test_two_contexts(self): x = ClientConnection("ncalrpc:localhost[DEFAULT]", @@ -40,15 +40,15 @@ class BareTestCase(samba.tests.TestCase): y = ClientConnection("ncalrpc:localhost", ("60a15ec5-4de8-11d7-a637-005056a20182", 1), basis_connection=x, lp_ctx=samba.tests.env_loadparm()) - self.assertEquals(24, len(x.request(0, chr(0) * 8))) - self.assertEquals(b"\x01\x00\x00\x00", y.request(0, chr(0) * 4)) + self.assertEqual(24, len(x.request(0, chr(0) * 8))) + self.assertEqual(b"\x01\x00\x00\x00", y.request(0, chr(0) * 4)) def test_bare_tcp(self): # Connect to the echo pipe x = ClientConnection("ncacn_ip_tcp:%s" % os.environ["SERVER"], ("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=samba.tests.env_loadparm()) - self.assertEquals(b"\x01\x00\x00\x00", x.request(0, chr(0) * 4)) + self.assertEqual(b"\x01\x00\x00\x00", x.request(0, chr(0) * 4)) def test_two_contexts_tcp(self): x = ClientConnection("ncacn_ip_tcp:%s" % os.environ["SERVER"], @@ -57,5 +57,5 @@ class BareTestCase(samba.tests.TestCase): y = ClientConnection("ncacn_ip_tcp:%s" % os.environ["SERVER"], ("60a15ec5-4de8-11d7-a637-005056a20182", 1), basis_connection=x, lp_ctx=samba.tests.env_loadparm()) - self.assertEquals(24, len(x.request(0, chr(0) * 8))) - self.assertEquals(b"\x01\x00\x00\x00", y.request(0, chr(0) * 4)) + self.assertEqual(24, len(x.request(0, chr(0) * 8))) + self.assertEqual(b"\x01\x00\x00\x00", y.request(0, chr(0) * 4)) diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py index c6a150c876f..540ba009850 100644 --- a/python/samba/tests/dcerpc/dnsserver.py +++ b/python/samba/tests/dcerpc/dnsserver.py @@ -840,21 +840,21 @@ class DnsserverTests(RpcInterfaceTestCase): self.server, None, 'ServerInfo') - self.assertEquals(dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K, typeid) + self.assertEqual(dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K, typeid) typeid, result = self.conn.DnssrvQuery2(dnsserver.DNS_CLIENT_VERSION_DOTNET, 0, self.server, None, 'ServerInfo') - self.assertEquals(dnsserver.DNSSRV_TYPEID_SERVER_INFO_DOTNET, typeid) + self.assertEqual(dnsserver.DNSSRV_TYPEID_SERVER_INFO_DOTNET, typeid) typeid, result = self.conn.DnssrvQuery2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, self.server, None, 'ServerInfo') - self.assertEquals(dnsserver.DNSSRV_TYPEID_SERVER_INFO, typeid) + self.assertEqual(dnsserver.DNSSRV_TYPEID_SERVER_INFO, typeid) # This test is to confirm that we do not support multizone operations, @@ -936,7 +936,7 @@ class DnsserverTests(RpcInterfaceTestCase): 'EnumZones', dnsserver.DNSSRV_TYPEID_DWORD, request_filter) - self.assertEquals(1, zones.dwZoneCount) + self.assertEqual(1, zones.dwZoneCount) # Delete zone self.conn.DnssrvOperation2(client_version, @@ -955,7 +955,7 @@ class DnsserverTests(RpcInterfaceTestCase): 'EnumZones', dnsserver.DNSSRV_TYPEID_DWORD, request_filter) - self.assertEquals(0, zones.dwZoneCount) + self.assertEqual(0, zones.dwZoneCount) def test_complexoperation2(self): client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN @@ -969,8 +969,8 @@ class DnsserverTests(RpcInterfaceTestCase): 'EnumZones', dnsserver.DNSSRV_TYPEID_DWORD, request_filter) - self.assertEquals(dnsserver.DNSSRV_TYPEID_ZONE_LIST, typeid) - self.assertEquals(3, zones.dwZoneCount) + self.assertEqual(dnsserver.DNSSRV_TYPEID_ZONE_LIST, typeid) + self.assertEqual(3, zones.dwZoneCount) request_filter = (dnsserver.DNS_ZONE_REQUEST_REVERSE | dnsserver.DNS_ZONE_REQUEST_PRIMARY) @@ -981,8 +981,8 @@ class DnsserverTests(RpcInterfaceTestCase): 'EnumZones', dnsserver.DNSSRV_TYPEID_DWORD, request_filter) - self.assertEquals(dnsserver.DNSSRV_TYPEID_ZONE_LIST, typeid) - self.assertEquals(0, zones.dwZoneCount) + self.assertEqual(dnsserver.DNSSRV_TYPEID_ZONE_LIST, typeid) + self.assertEqual(0, zones.dwZoneCount) def test_enumrecords2(self): client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN @@ -999,7 +999,7 @@ class DnsserverTests(RpcInterfaceTestCase): select_flags, None, None) - self.assertEquals(14, roothints.count) # 1 NS + 13 A records (a-m) + self.assertEqual(14, roothints.count) # 1 NS + 13 A records (a-m) def test_updaterecords2(self): client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN @@ -1031,10 +1031,10 @@ class DnsserverTests(RpcInterfaceTestCase): select_flags, None, None) - self.assertEquals(1, result.count) - self.assertEquals(1, result.rec[0].wRecordCount) - self.assertEquals(dnsp.DNS_TYPE_A, result.rec[0].records[0].wType) - self.assertEquals('1.2.3.4', result.rec[0].records[0].data) + self.assertEqual(1, result.count) + self.assertEqual(1, result.rec[0].wRecordCount) + self.assertEqual(dnsp.DNS_TYPE_A, result.rec[0].records[0].wType) + self.assertEqual('1.2.3.4', result.rec[0].records[0].data) # Update record add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() @@ -1059,10 +1059,10 @@ class DnsserverTests(RpcInterfaceTestCase): select_flags, None, None) - self.assertEquals(1, result.count) - self.assertEquals(1, result.rec[0].wRecordCount) - self.assertEquals(dnsp.DNS_TYPE_A, result.rec[0].records[0].wType) - self.assertEquals('5.6.7.8', result.rec[0].records[0].data) + self.assertEqual(1, result.count) + self.assertEqual(1, result.rec[0].wRecordCount) + self.assertEqual(dnsp.DNS_TYPE_A, result.rec[0].records[0].wType) + self.assertEqual('5.6.7.8', result.rec[0].records[0].data) # Delete record del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF() diff --git a/python/samba/tests/dcerpc/integer.py b/python/samba/tests/dcerpc/integer.py index 2825c670843..69a6a09a381 100644 --- a/python/samba/tests/dcerpc/integer.py +++ b/python/samba/tests/dcerpc/integer.py @@ -26,12 +26,12 @@ class IntegerTests(samba.tests.TestCase): def test_uint32_into_hyper(self): s = server_id.server_id() s.unique_id = server_id.NONCLUSTER_VNN - self.assertEquals(s.unique_id, 0xFFFFFFFF) + self.assertEqual(s.unique_id, 0xFFFFFFFF) def test_int_into_hyper(self): s = server_id.server_id() s.unique_id = 1 - self.assertEquals(s.unique_id, 1) + self.assertEqual(s.unique_id, 1) def test_negative_int_into_hyper(self): s = server_id.server_id() @@ -57,7 +57,7 @@ class IntegerTests(samba.tests.TestCase): def test_int_into_int32(self): s = srvsvc.NetRemoteTODInfo() s.timezone = 5 - self.assertEquals(s.timezone, 5) + self.assertEqual(s.timezone, 5) def test_uint32_into_int32(self): s = srvsvc.NetRemoteTODInfo() @@ -75,7 +75,7 @@ class IntegerTests(samba.tests.TestCase): # s.timezone = 5L # but that is a syntax error in py3. s.timezone = (5 << 65) >> 65 - self.assertEquals(s.timezone, 5) + self.assertEqual(s.timezone, 5) def test_larger_long_int_into_int32(self): s = srvsvc.NetRemoteTODInfo() @@ -87,7 +87,7 @@ class IntegerTests(samba.tests.TestCase): def test_larger_int_into_int32(self): s = srvsvc.NetRemoteTODInfo() s.timezone = 2147483647 - self.assertEquals(s.timezone, 2147483647) + self.assertEqual(s.timezone, 2147483647) def test_float_into_int32(self): s = srvsvc.NetRemoteTODInfo() @@ -106,7 +106,7 @@ class IntegerTests(samba.tests.TestCase): def test_negative_int_into_int32(self): s = srvsvc.NetRemoteTODInfo() s.timezone = -2147483648 - self.assertEquals(s.timezone, -2147483648) + self.assertEqual(s.timezone, -2147483648) def test_negative_into_uint32(self): s = server_id.server_id() @@ -139,7 +139,7 @@ class IntegerTests(samba.tests.TestCase): def test_enum_into_uint16(self): g = misc.GUID() g.time_mid = misc.SEC_CHAN_DOMAIN - self.assertEquals(g.time_mid, misc.SEC_CHAN_DOMAIN) + self.assertEqual(g.time_mid, misc.SEC_CHAN_DOMAIN) def test_bitmap_into_uint16(self): g = misc.GUID() @@ -170,22 +170,22 @@ class IntegerTests(samba.tests.TestCase): def test_int_into_int64(self): s = samr.DomInfo1() s.max_password_age = 5 - self.assertEquals(s.max_password_age, 5) + self.assertEqual(s.max_password_age, 5) def test_negative_int_into_int64(self): s = samr.DomInfo1() s.max_password_age = -5 - self.assertEquals(s.max_password_age, -5) + self.assertEqual(s.max_password_age, -5) def test_larger_int_into_int64(self): s = samr.DomInfo1() s.max_password_age = server_id.NONCLUSTER_VNN - self.assertEquals(s.max_password_age, 0xFFFFFFFF) + self.assertEqual(s.max_password_age, 0xFFFFFFFF) def test_larger_negative_int_into_int64(self): s = samr.DomInfo1() s.max_password_age = -2147483649 - self.assertEquals(s.max_password_age, -2147483649) + self.assertEqual(s.max_password_age, -2147483649) def test_int_list_over_list(self): g = misc.GUID() diff --git a/python/samba/tests/dcerpc/mdssvc.py b/python/samba/tests/dcerpc/mdssvc.py index 480587c1d95..68243aa4354 100644 --- a/python/samba/tests/dcerpc/mdssvc.py +++ b/python/samba/tests/dcerpc/mdssvc.py @@ -118,7 +118,7 @@ class MdssvcTests(RpcInterfaceTestCase): time.sleep(1) results = search.get_results(self.pipe) - self.assertEquals(results, expect) + self.assertEqual(results, expect) search.close(self.pipe) self.conn.disconnect(self.pipe) diff --git a/python/samba/tests/dcerpc/misc.py b/python/samba/tests/dcerpc/misc.py index d2ba1843a0e..009d8d02768 100644 --- a/python/samba/tests/dcerpc/misc.py +++ b/python/samba/tests/dcerpc/misc.py @@ -36,11 +36,11 @@ class GUIDTests(samba.tests.TestCase): def test_str(self): guid = misc.GUID(text1) - self.assertEquals(text1, str(guid)) + self.assertEqual(text1, str(guid)) def test_repr(self): guid = misc.GUID(text1) - self.assertEquals("GUID('%s')" % text1, repr(guid)) + self.assertEqual("GUID('%s')" % text1, repr(guid)) def test_compare_different(self): guid1 = misc.GUID(text1) @@ -53,8 +53,8 @@ class GUIDTests(samba.tests.TestCase): guid1 = misc.GUID(text1) guid2 = misc.GUID(text1) self.assertTrue(guid1 == guid2) - self.assertEquals(guid1, guid2) - self.assertEquals(0, cmp(guid1, guid2)) + self.assertEqual(guid1, guid2) + self.assertEqual(0, cmp(guid1, guid2)) def test_valid_formats(self): fmts = [ @@ -70,7 +70,7 @@ class GUIDTests(samba.tests.TestCase): ] for fmt in fmts: guid = misc.GUID(fmt) - self.assertEquals(text3, str(guid)) + self.assertEqual(text3, str(guid)) def test_invalid_formats(self): fmts = [ @@ -95,13 +95,13 @@ class PolicyHandleTests(samba.tests.TestCase): def test_init(self): x = misc.policy_handle(text1, 1) - self.assertEquals(1, x.handle_type) - self.assertEquals(text1, str(x.uuid)) + self.assertEqual(1, x.handle_type) + self.assertEqual(text1, str(x.uuid)) def test_repr(self): x = misc.policy_handle(text1, 42) - self.assertEquals("policy_handle(%d, '%s')" % (42, text1), repr(x)) + self.assertEqual("policy_handle(%d, '%s')" % (42, text1), repr(x)) def test_str(self): x = misc.policy_handle(text1, 42) - self.assertEquals("%d, %s" % (42, text1), str(x)) + self.assertEqual("%d, %s" % (42, text1), str(x)) diff --git a/python/samba/tests/dcerpc/raw_protocol.py b/python/samba/tests/dcerpc/raw_protocol.py index 0bce5c82e42..f810cad3d2f 100755 --- a/python/samba/tests/dcerpc/raw_protocol.py +++ b/python/samba/tests/dcerpc/raw_protocol.py @@ -64,19 +64,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, pfc_flags=rep_pfc_flags, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # And now try a request req = self.generate_request(call_id=1, @@ -88,8 +88,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) def _test_no_auth_request_alter_pfc_flags(self, req_pfc_flags, rep_pfc_flags): @@ -107,19 +107,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # And now try a alter context req = self.generate_alter(call_id=0, pfc_flags=req_pfc_flags, ctx_list=[ctx1]) @@ -127,19 +127,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, pfc_flags=rep_pfc_flags, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) - self.assertEquals(rep.u.secondary_address, "") + self.assertEqual(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address, "") self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # And now try a request req = self.generate_request(call_id=1, @@ -151,8 +151,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) def test_no_auth_request(self): @@ -359,11 +359,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) def test_invalid_auth_noctx(self): @@ -373,11 +373,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) def test_no_auth_valid_valid_request(self): @@ -395,19 +395,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # Send a bind again tsf2_list = [ndr32] @@ -422,11 +422,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) # wait for a disconnect @@ -441,11 +441,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) # wait for a disconnect @@ -468,19 +468,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # Send a alter req = self.generate_alter(call_id=1, ctx_list=[]) @@ -491,12 +491,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, 0) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, 0) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -520,19 +520,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # Send a alter req = self.generate_alter(call_id=1, ctx_list=[ctx1]) @@ -540,18 +540,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=2, context_id=ctx1.context_id, @@ -564,12 +564,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, ctx1.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_OP_RNG_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, ctx1.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_OP_RNG_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) def test_no_auth_presentation_ctx_invalid1(self): ndr32 = base.transfer_syntax_ndr() @@ -588,19 +588,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # Send a alter req = self.generate_alter(call_id=1, ctx_list=[ctx1]) @@ -608,18 +608,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=2, context_id=12345, @@ -632,12 +632,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, 0) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_UNKNOWN_IF) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, 0) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_UNKNOWN_IF) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # Send a alter again to prove the connection is still alive req = self.generate_alter(call_id=3, ctx_list=[ctx1]) @@ -645,18 +645,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_presentation_ctx_invalid2(self): ndr32 = base.transfer_syntax_ndr() @@ -675,11 +675,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) # wait for a disconnect @@ -704,19 +704,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) tsf1b_list = [] ctx1b = dcerpc.ctx_list() @@ -734,12 +734,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, 0) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, 0) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -764,19 +764,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # With a known but wrong syntax we get a protocol error # see test_no_auth_presentation_ctx_valid2 @@ -796,12 +796,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, 0) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, 0) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -825,19 +825,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # With a unknown but wrong syntaxes we get NO protocol error # see test_no_auth_presentation_ctx_invalid4 @@ -854,18 +854,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=2, context_id=ctx1a.context_id, @@ -878,12 +878,12 @@ class TestDCERPC_BIND(RawDCERPCTest): dcerpc.DCERPC_PFC_FLAG_DID_NOT_EXECUTE, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, ctx1a.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_OP_RNG_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, ctx1a.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_OP_RNG_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) def test_no_auth_presentation_ctx_no_ndr64(self): ndr32 = base.transfer_syntax_ndr() @@ -901,19 +901,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) tsf0_list = [ndr32] ctx0 = dcerpc.ctx_list() @@ -927,18 +927,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx0.context_id, @@ -949,8 +949,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) tsf1_list = [zero_syntax, ndr32] @@ -965,18 +965,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx1.context_id, @@ -987,8 +987,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) tsf2_list = [ndr32, ndr32] @@ -1003,18 +1003,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx2.context_id, @@ -1025,8 +1025,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) tsf3_list = [ndr32] @@ -1048,23 +1048,23 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 2) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 2) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.ctx_list[1].result, + self.assertEqual(rep.u.ctx_list[1].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[1].reason, + self.assertEqual(rep.u.ctx_list[1].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[1].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx3.context_id, @@ -1075,8 +1075,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_alter(call_id=43, ctx_list=[ctx4, ctx3]) @@ -1084,23 +1084,23 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 2) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 2) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.ctx_list[1].result, + self.assertEqual(rep.u.ctx_list[1].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[1].reason, + self.assertEqual(rep.u.ctx_list[1].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[1].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx4.context_id, @@ -1111,8 +1111,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_request(call_id=1, @@ -1124,8 +1124,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_alter(call_id=44, ctx_list=[ctx4, ctx4]) @@ -1133,23 +1133,23 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 2) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 2) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.ctx_list[1].result, + self.assertEqual(rep.u.ctx_list[1].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[1].reason, + self.assertEqual(rep.u.ctx_list[1].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[1].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx4.context_id, @@ -1160,8 +1160,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_request(call_id=1, @@ -1173,8 +1173,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) tsf5mgmt_list = [ndr32] @@ -1196,23 +1196,23 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 2) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 2) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.ctx_list[1].result, + self.assertEqual(rep.u.ctx_list[1].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[1].reason, + self.assertEqual(rep.u.ctx_list[1].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[1].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx5mgmt.context_id, @@ -1223,8 +1223,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_alter(call_id=55, ctx_list=[ctx5mgmt, ctx5epm]) @@ -1232,23 +1232,23 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 2) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 2) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.ctx_list[1].result, + self.assertEqual(rep.u.ctx_list[1].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[1].reason, + self.assertEqual(rep.u.ctx_list[1].reason, dcerpc.DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[1].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) req = self.generate_request(call_id=1, context_id=ctx5mgmt.context_id, @@ -1259,8 +1259,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) def test_no_auth_bind_time_none_simple(self): @@ -1281,18 +1281,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) - self.assertEquals(rep.u.ctx_list[0].reason, features) + self.assertEqual(rep.u.ctx_list[0].reason, features) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_bind_time_none_ignore_additional(self): features1 = 0 @@ -1317,18 +1317,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) - self.assertEquals(rep.u.ctx_list[0].reason, features1) + self.assertEqual(rep.u.ctx_list[0].reason, features1) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_bind_time_only_first(self): features1 = dcerpc.DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN @@ -1351,19 +1351,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_bind_time_twice(self): features1 = dcerpc.DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN @@ -1393,11 +1393,11 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, + self.assertEqual(rep.u.reject_reason, dcerpc.DCERPC_BIND_NAK_REASON_NOT_SPECIFIED) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) # wait for a disconnect @@ -1423,18 +1423,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) - self.assertEquals(rep.u.ctx_list[0].reason, features) + self.assertEqual(rep.u.ctx_list[0].reason, features) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_bind_time_keep_on_orphan_ignore_additional(self): features1 = dcerpc.DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN @@ -1458,18 +1458,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) - self.assertEquals(rep.u.ctx_list[0].reason, features1) + self.assertEqual(rep.u.ctx_list[0].reason, features1) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def test_no_auth_bind_time_sec_ctx_ignore_additional(self): features1 = dcerpc.DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING @@ -1493,18 +1493,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) - self.assertEquals(rep.u.ctx_list[0].reason, features1) + self.assertEqual(rep.u.ctx_list[0].reason, features1) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, zero_syntax) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) def _test_auth_type_level_bind_nak(self, auth_type, auth_level, creds=None, reason=dcerpc.DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE): @@ -1549,10 +1549,10 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_NAK, req.call_id, auth_length=0) - self.assertEquals(rep.u.reject_reason, reason) - self.assertEquals(rep.u.num_versions, 1) - self.assertEquals(rep.u.versions[0].rpc_vers, req.rpc_vers) - self.assertEquals(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) + self.assertEqual(rep.u.reject_reason, reason) + self.assertEqual(rep.u.num_versions, 1) + self.assertEqual(rep.u.versions[0].rpc_vers, req.rpc_vers) + self.assertEqual(rep.u.versions[0].rpc_vers_minor, req.rpc_vers_minor) self.assertPadding(rep.u._pad, 3) # wait for a disconnect @@ -1616,19 +1616,19 @@ class TestDCERPC_BIND(RawDCERPCTest): self.send_pdu(req) rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(len(rep.u.auth_info), 0) + self.assertEqual(len(rep.u.auth_info), 0) # And now try a request without auth_info req = self.generate_request(call_id=2, @@ -1640,8 +1640,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) auth_info = self.generate_auth(auth_type=auth_type, @@ -1660,12 +1660,12 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_FAULT_ACCESS_DENIED) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -1707,19 +1707,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, rep_both) - self.assertEquals(rep.u.max_recv_frag, rep_both) + self.assertEqual(rep.u.max_xmit_frag, rep_both) + self.assertEqual(rep.u.max_recv_frag, rep_both) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) assoc_group_id = rep.u.assoc_group_id if alter_xmit is None: @@ -1738,18 +1738,18 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_ALTER_RESP, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, rep_both) - self.assertEquals(rep.u.max_recv_frag, rep_both) - self.assertEquals(rep.u.assoc_group_id, rep.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 0) + self.assertEqual(rep.u.max_xmit_frag, rep_both) + self.assertEqual(rep.u.max_recv_frag, rep_both) + self.assertEqual(rep.u.assoc_group_id, rep.u.assoc_group_id) + self.assertEqual(rep.u.secondary_address_size, 0) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) chunk_size = rep_both - dcerpc.DCERPC_REQUEST_LENGTH req = self.generate_request(call_id=2, @@ -1762,8 +1762,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) chunk_size = 5840 - dcerpc.DCERPC_REQUEST_LENGTH @@ -1777,8 +1777,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) chunk_size += 1 @@ -1793,12 +1793,12 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, 0) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, 0) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, dcerpc.DCERPC_NCA_S_PROTO_ERROR) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -1865,19 +1865,19 @@ class TestDCERPC_BIND(RawDCERPCTest): rep = self.recv_pdu() self.verify_pdu(rep, dcerpc.DCERPC_PKT_BIND_ACK, req.call_id, auth_length=0) - self.assertEquals(rep.u.max_xmit_frag, req.u.max_xmit_frag) - self.assertEquals(rep.u.max_recv_frag, req.u.max_recv_frag) + self.assertEqual(rep.u.max_xmit_frag, req.u.max_xmit_frag) + self.assertEqual(rep.u.max_recv_frag, req.u.max_recv_frag) self.assertNotEquals(rep.u.assoc_group_id, req.u.assoc_group_id) - self.assertEquals(rep.u.secondary_address_size, 4) - self.assertEquals(rep.u.secondary_address, "%d" % self.tcp_port) + self.assertEqual(rep.u.secondary_address_size, 4) + self.assertEqual(rep.u.secondary_address, "%d" % self.tcp_port) self.assertPadding(rep.u._pad1, 2) - self.assertEquals(rep.u.num_results, 1) - self.assertEquals(rep.u.ctx_list[0].result, + self.assertEqual(rep.u.num_results, 1) + self.assertEqual(rep.u.ctx_list[0].result, dcerpc.DCERPC_BIND_ACK_RESULT_ACCEPTANCE) - self.assertEquals(rep.u.ctx_list[0].reason, + self.assertEqual(rep.u.ctx_list[0].reason, dcerpc.DCERPC_BIND_ACK_REASON_NOT_SPECIFIED) self.assertNDRSyntaxEquals(rep.u.ctx_list[0].syntax, ndr32) - self.assertEquals(rep.u.auth_info, b'\0' * 0) + self.assertEqual(rep.u.auth_info, b'\0' * 0) # And now try a request without auth_info req = self.generate_request(call_id=2, @@ -1890,8 +1890,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_request(call_id=3, @@ -1904,8 +1904,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) req = self.generate_request(call_id=4, @@ -1918,8 +1918,8 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) def _get_netlogon_ctx(self): @@ -1996,12 +1996,12 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, fault_first) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, fault_first) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -2016,12 +2016,12 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, fault_last) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, fault_last) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -2038,12 +2038,12 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_FAULT, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) - self.assertEquals(rep.u.flags, 0) - self.assertEquals(rep.u.status, fault_last) - self.assertEquals(rep.u.reserved, 0) - self.assertEquals(len(rep.u.error_and_verifier), 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) + self.assertEqual(rep.u.flags, 0) + self.assertEqual(rep.u.status, fault_last) + self.assertEqual(rep.u.reserved, 0) + self.assertEqual(len(rep.u.error_and_verifier), 0) # wait for a disconnect rep = self.recv_pdu() @@ -2054,13 +2054,13 @@ class TestDCERPC_BIND(RawDCERPCTest): self.verify_pdu(rep, dcerpc.DCERPC_PKT_RESPONSE, req.call_id, auth_length=0) self.assertNotEquals(rep.u.alloc_hint, 0) - self.assertEquals(rep.u.context_id, req.u.context_id) - self.assertEquals(rep.u.cancel_count, 0) + self.assertEqual(rep.u.context_id, req.u.context_id) + self.assertEqual(rep.u.cancel_count, 0) self.assertGreaterEqual(len(rep.u.stub_and_verifier), rep.u.alloc_hint) - self.assertEquals(len(rep.u.stub_and_verifier), 12) + self.assertEqual(len(rep.u.stub_and_verifier), 12) status = struct.unpack_from("= dcerpc.DCERPC_AUTH_LEVEL_PRIVACY: # TODO: not yet supported here @@ -925,13 +925,13 @@ class RawDCERPCTest(TestCase): elif auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_PACKET: req_sig = auth_context["gensec"].sign_packet(req_data, req_whole) elif auth_context["auth_level"] >= dcerpc.DCERPC_AUTH_LEVEL_CONNECT: - self.assertEquals(auth_context["auth_type"], + self.assertEqual(auth_context["auth_type"], dcerpc.DCERPC_AUTH_TYPE_NTLMSSP) req_sig = b"\x01" +b"\x00" *15 else: return req - self.assertEquals(len(req_sig), req.auth_length) - self.assertEquals(len(req_sig), sig_size) + self.assertEqual(len(req_sig), req.auth_length) + self.assertEqual(len(req_sig), sig_size) stub_sig_ofs = len(req.u.stub_and_verifier) - sig_size stub = req.u.stub_and_verifier[0:stub_sig_ofs] + req_sig @@ -1147,7 +1147,7 @@ class RawDCERPCTest(TestCase): return def assertPadding(self, pad, length): - self.assertEquals(len(pad), length) + self.assertEqual(len(pad), length) # # sometimes windows sends random bytes # @@ -1157,7 +1157,7 @@ class RawDCERPCTest(TestCase): if self.ignore_random_pad: return zero_pad = b'\0' * length - self.assertEquals(pad, zero_pad) + self.assertEqual(pad, zero_pad) def assertEqualsStrLower(self, s1, s2): - self.assertEquals(str(s1).lower(), str(s2).lower()) + self.assertEqual(str(s1).lower(), str(s2).lower()) diff --git a/python/samba/tests/dcerpc/registry.py b/python/samba/tests/dcerpc/registry.py index 279eeb1cc82..04838ff6f1b 100644 --- a/python/samba/tests/dcerpc/registry.py +++ b/python/samba/tests/dcerpc/registry.py @@ -40,12 +40,12 @@ class WinregTests(RpcInterfaceTestCase): def test_getversion(self): handle = self.get_hklm() version = self.conn.GetVersion(handle) - self.assertEquals(int, version.__class__) + self.assertEqual(int, version.__class__) self.conn.CloseKey(handle) def test_getkeyinfo(self): handle = self.conn.OpenHKLM(None, winreg.KEY_QUERY_VALUE | winreg.KEY_ENUMERATE_SUB_KEYS) x = self.conn.QueryInfoKey(handle, winreg.String()) - self.assertEquals(9, len(x)) # should return a 9-tuple + self.assertEqual(9, len(x)) # should return a 9-tuple self.conn.CloseKey(handle) diff --git a/python/samba/tests/dcerpc/rpc_talloc.py b/python/samba/tests/dcerpc/rpc_talloc.py index 191e70c9702..4d50f382d45 100644 --- a/python/samba/tests/dcerpc/rpc_talloc.py +++ b/python/samba/tests/dcerpc/rpc_talloc.py @@ -45,7 +45,7 @@ class TallocTests(samba.tests.TestCase): nblocks = talloc.total_blocks(object) if object is None: nblocks -= self.initial_blocks - self.assertEquals(nblocks, num_expected) + self.assertEqual(nblocks, num_expected) def get_rodc_partial_attribute_set(self): '''get a list of attributes for RODC replication''' diff --git a/python/samba/tests/dcerpc/rpcecho.py b/python/samba/tests/dcerpc/rpcecho.py index 0711ae41546..0ae86c56350 100644 --- a/python/samba/tests/dcerpc/rpcecho.py +++ b/python/samba/tests/dcerpc/rpcecho.py @@ -30,33 +30,33 @@ class RpcEchoTests(RpcInterfaceTestCase): def test_two_contexts(self): self.conn2 = echo.rpcecho("ncalrpc:", self.get_loadparm(), basis_connection=self.conn) - self.assertEquals(3, self.conn2.AddOne(2)) + self.assertEqual(3, self.conn2.AddOne(2)) def test_abstract_syntax(self): - self.assertEquals(("60a15ec5-4de8-11d7-a637-005056a20182", 1), + self.assertEqual(("60a15ec5-4de8-11d7-a637-005056a20182", 1), self.conn.abstract_syntax) def test_addone(self): - self.assertEquals(2, self.conn.AddOne(1)) + self.assertEqual(2, self.conn.AddOne(1)) def test_echodata(self): - self.assertEquals([1, 2, 3], self.conn.EchoData([1, 2, 3])) + self.assertEqual([1, 2, 3], self.conn.EchoData([1, 2, 3])) def test_call(self): - self.assertEquals(u"foobar", self.conn.TestCall(u"foobar")) + self.assertEqual(u"foobar", self.conn.TestCall(u"foobar")) def test_surrounding(self): surrounding_struct = echo.Surrounding() surrounding_struct.x = 4 surrounding_struct.surrounding = [1, 2, 3, 4] y = self.conn.TestSurrounding(surrounding_struct) - self.assertEquals(8 * [0], y.surrounding) + self.assertEqual(8 * [0], y.surrounding) def test_manual_request(self): - self.assertEquals(b"\x01\x00\x00\x00", self.conn.request(0, chr(0) * 4)) + self.assertEqual(b"\x01\x00\x00\x00", self.conn.request(0, chr(0) * 4)) def test_server_name(self): - self.assertEquals(None, self.conn.server_name) + self.assertEqual(None, self.conn.server_name) class NdrEchoTests(TestCase): @@ -64,8 +64,8 @@ class NdrEchoTests(TestCase): def test_info1_push(self): x = echo.info1() x.v = 42 - self.assertEquals(b"\x2a", ndr_pack(x)) + self.assertEqual(b"\x2a", ndr_pack(x)) def test_info1_pull(self): x = ndr_unpack(echo.info1, b"\x42") - self.assertEquals(x.v, 66) + self.assertEqual(x.v, 66) diff --git a/python/samba/tests/dcerpc/sam.py b/python/samba/tests/dcerpc/sam.py index c24d308dd0d..32b9faec881 100644 --- a/python/samba/tests/dcerpc/sam.py +++ b/python/samba/tests/dcerpc/sam.py @@ -197,8 +197,8 @@ class SamrTests(RpcInterfaceTestCase): (ts, rs, actual) = self.conn.QueryDisplayInfo( self.domain_handle, level, 0, 1024, 4294967295) - self.assertEquals(len(expected), ts) - self.assertEquals(len(expected), rs) + self.assertEqual(len(expected), ts) + self.assertEqual(len(expected), rs) check_results(expected, actual.entries) # @@ -206,8 +206,8 @@ class SamrTests(RpcInterfaceTestCase): # results returned from the first query, should return the same results (ts1, rs1, actual1) = self.conn.QueryDisplayInfo( self.domain_handle, level, 0, rs, 4294967295) - self.assertEquals(ts, ts1) - self.assertEquals(rs, rs1) + self.assertEqual(ts, ts1) + self.assertEqual(rs, rs1) check_results(expected, actual1.entries) # @@ -216,8 +216,8 @@ class SamrTests(RpcInterfaceTestCase): self.assertTrue(ts > 2) (ts2, rs2, actual2) = self.conn.QueryDisplayInfo( self.domain_handle, level, (ts - 2), 2, 4294967295) - self.assertEquals(ts, ts2) - self.assertEquals(2, rs2) + self.assertEqual(ts, ts2) + self.assertEqual(2, rs2) check_results(list(expected)[-2:], actual2.entries) # @@ -226,8 +226,8 @@ class SamrTests(RpcInterfaceTestCase): self.assertTrue(ts > 2) (ts2, rs2, actual2) = self.conn.QueryDisplayInfo( self.domain_handle, level, 0, 2, 4294967295) - self.assertEquals(ts, ts2) - self.assertEquals(2, rs2) + self.assertEqual(ts, ts2) + self.assertEqual(2, rs2) check_results(list(expected)[:2], actual2.entries) # @@ -237,8 +237,8 @@ class SamrTests(RpcInterfaceTestCase): self.assertTrue(ts > 3) (ts2, rs2, actual2) = self.conn.QueryDisplayInfo( self.domain_handle, level, 1, 2, 4294967295) - self.assertEquals(ts, ts2) - self.assertEquals(2, rs2) + self.assertEqual(ts, ts2) + self.assertEqual(2, rs2) check_results(list(expected)[1:2], actual2.entries) # @@ -254,8 +254,8 @@ class SamrTests(RpcInterfaceTestCase): # should not be present (ts3, rs3, actual3) = self.conn.QueryDisplayInfo( self.domain_handle, level, 1, 1024, 4294967295) - self.assertEquals(ts, ts3) - self.assertEquals(len(expected) - 1, rs3) + self.assertEqual(ts, ts3) + self.assertEqual(len(expected) - 1, rs3) check_results(list(expected)[1:], actual3.entries) # @@ -265,8 +265,8 @@ class SamrTests(RpcInterfaceTestCase): new = self.samdb.search(expression=select, attrs=attributes) (ts4, rs4, actual4) = self.conn.QueryDisplayInfo( self.domain_handle, level, 0, 1024, 4294967295) - self.assertEquals(len(expected) + len(dns), ts4) - self.assertEquals(len(expected) + len(dns), rs4) + self.assertEqual(len(expected) + len(dns), ts4) + self.assertEqual(len(expected) + len(dns), rs4) check_results(new, actual4.entries) # Delete the added DN's and query all but the first entry. @@ -275,7 +275,7 @@ class SamrTests(RpcInterfaceTestCase): self.delete_dns(dns) (ts5, rs5, actual5) = self.conn.QueryDisplayInfo( self.domain_handle, level, 1, 1024, 4294967295) - self.assertEquals(len(expected) + len(dns), ts5) + self.assertEqual(len(expected) + len(dns), ts5) # The deleted results will be filtered from the result set so should # be missing from the returned results. # Note: depending on the GUID order, the first result in the cache may @@ -295,8 +295,8 @@ class SamrTests(RpcInterfaceTestCase): # Should return no data. (ts6, rs6, actual6) = self.conn.QueryDisplayInfo( self.domain_handle, level, ts5, 1, 4294967295) - self.assertEquals(ts5, ts6) - self.assertEquals(0, rs6) + self.assertEqual(ts5, ts6) + self.assertEqual(0, rs6) self.conn.Close(self.handle) @@ -310,7 +310,7 @@ class SamrTests(RpcInterfaceTestCase): # in the same order for (e, a) in zip(expected, actual): self.assertTrue(isinstance(a, samr.DispEntryGeneral)) - self.assertEquals(str(e["sAMAccountName"]), + self.assertEqual(str(e["sAMAccountName"]), str(a.account_name)) # The displayName and description are optional. @@ -321,12 +321,12 @@ class SamrTests(RpcInterfaceTestCase): if a.full_name.length == 0: self.assertFalse("displayName" in e) else: - self.assertEquals(str(e["displayName"]), str(a.full_name)) + self.assertEqual(str(e["displayName"]), str(a.full_name)) if a.description.length == 0: self.assertFalse("description" in e) else: - self.assertEquals(str(e["description"]), + self.assertEqual(str(e["description"]), str(a.description)) # Create four user accounts # to ensure that we have the minimum needed for the tests. @@ -350,7 +350,7 @@ class SamrTests(RpcInterfaceTestCase): # in the same order for (e, a) in zip(expected, actual): self.assertTrue(isinstance(a, samr.DispEntryFull)) - self.assertEquals(str(e["sAMAccountName"]), + self.assertEqual(str(e["sAMAccountName"]), str(a.account_name)) # The description is optional. @@ -361,7 +361,7 @@ class SamrTests(RpcInterfaceTestCase): if a.description.length == 0: self.assertFalse("description" in e) else: - self.assertEquals(str(e["description"]), + self.assertEqual(str(e["description"]), str(a.description)) # Create four computer accounts @@ -386,7 +386,7 @@ class SamrTests(RpcInterfaceTestCase): # in the same order for (e, a) in zip(expected, actual): self.assertTrue(isinstance(a, samr.DispEntryFullGroup)) - self.assertEquals(str(e["sAMAccountName"]), + self.assertEqual(str(e["sAMAccountName"]), str(a.account_name)) # The description is optional. @@ -397,7 +397,7 @@ class SamrTests(RpcInterfaceTestCase): if a.description.length == 0: self.assertFalse("description" in e) else: - self.assertEquals(str(e["description"]), + self.assertEqual(str(e["description"]), str(a.description)) # Create four groups @@ -425,7 +425,7 @@ class SamrTests(RpcInterfaceTestCase): self.assertTrue(isinstance(a, samr.DispEntryAscii)) self.assertTrue( isinstance(a.account_name, lsa.AsciiStringLarge)) - self.assertEquals( + self.assertEqual( str(e["sAMAccountName"]), str(a.account_name.string)) # Create four user accounts @@ -452,7 +452,7 @@ class SamrTests(RpcInterfaceTestCase): self.assertTrue(isinstance(a, samr.DispEntryAscii)) self.assertTrue( isinstance(a.account_name, lsa.AsciiStringLarge)) - self.assertEquals( + self.assertEqual( str(e["sAMAccountName"]), str(a.account_name.string)) # Create four groups @@ -472,7 +472,7 @@ class SamrTests(RpcInterfaceTestCase): def check_results(expected, actual): for (e, a) in zip(expected, actual): self.assertTrue(isinstance(a, samr.SamEntry)) - self.assertEquals( + self.assertEqual( str(e["sAMAccountName"]), str(a.name.string)) # Create four groups @@ -501,7 +501,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(len(expected) + 10) (resume_handle, actual, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, 0, max_size) - self.assertEquals(len(expected), num_entries) + self.assertEqual(len(expected), num_entries) check_results(expected, actual.entries) # @@ -511,7 +511,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(4) (resume_handle, actual, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, 0, max_size) - self.assertEquals(4, num_entries) + self.assertEqual(4, num_entries) check_results(expected[:4], actual.entries) # @@ -523,8 +523,8 @@ class SamrTests(RpcInterfaceTestCase): (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, rh, max_size) - self.assertEquals(0, num_entries) - self.assertEquals(0, resume_handle) + self.assertEqual(0, num_entries) + self.assertEqual(0, resume_handle) # # Enumerate through the domain groups one element at a time. @@ -534,7 +534,7 @@ class SamrTests(RpcInterfaceTestCase): (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, 0, max_size) while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) actual.append(a.entries[0]) (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, resume_handle, max_size) @@ -552,14 +552,14 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, max_size) extra_dns = self.create_groups([1000, 1002, 1003, 1004]) while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) actual.append(a.entries[0]) (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, resume_handle, max_size) if num_entries: actual.append(a.entries[0]) - self.assertEquals(len(expected), len(actual)) + self.assertEqual(len(expected), len(actual)) check_results(expected, actual) # @@ -568,7 +568,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(len(expected) + len(extra_dns) + 10) (resume_handle, actual, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, 0, max_size) - self.assertEquals(len(expected) + len(extra_dns), num_entries) + self.assertEqual(len(expected) + len(extra_dns), num_entries) # # Get a new expected result set by querying the database directly @@ -594,14 +594,14 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, max_size) self.delete_dns(extra_dns) while resume_handle and num_entries: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) actual.append(a.entries[0]) (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, resume_handle, max_size) if num_entries: actual.append(a.entries[0]) - self.assertEquals(len(expected), len(actual)) + self.assertEqual(len(expected), len(actual)) check_results(expected, actual) self.delete_dns(dns) @@ -610,7 +610,7 @@ class SamrTests(RpcInterfaceTestCase): def check_results(expected, actual): for (e, a) in zip(expected, actual): self.assertTrue(isinstance(a, samr.SamEntry)) - self.assertEquals( + self.assertEqual( str(e["sAMAccountName"]), str(a.name.string)) # Create four users @@ -637,7 +637,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(len(expected) + 10) (resume_handle, actual, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, 0, 0, max_size) - self.assertEquals(len(expected), num_entries) + self.assertEqual(len(expected), num_entries) check_results(expected, actual.entries) # @@ -646,7 +646,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(4) (resume_handle, actual, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, 0, 0, max_size) - self.assertEquals(4, num_entries) + self.assertEqual(4, num_entries) check_results(expected[:4], actual.entries) # @@ -658,8 +658,8 @@ class SamrTests(RpcInterfaceTestCase): (resume_handle, a, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, rh, 0, max_size) - self.assertEquals(0, num_entries) - self.assertEquals(0, resume_handle) + self.assertEqual(0, num_entries) + self.assertEqual(0, resume_handle) # # Enumerate through the domain users one element at a time. @@ -670,14 +670,14 @@ class SamrTests(RpcInterfaceTestCase): (resume_handle, a, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, 0, 0, max_size) while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) actual.append(a.entries[0]) (resume_handle, a, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, resume_handle, 0, max_size) if num_entries: actual.append(a.entries[0]) - self.assertEquals(len(expected), len(actual)) + self.assertEqual(len(expected), len(actual)) check_results(expected, actual) # @@ -692,14 +692,14 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, 0, max_size) extra_dns = self.create_users([1000, 1002, 1003, 1004]) while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) actual.append(a.entries[0]) (resume_handle, a, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, resume_handle, 0, max_size) if num_entries: actual.append(a.entries[0]) - self.assertEquals(len(expected), len(actual)) + self.assertEqual(len(expected), len(actual)) check_results(expected, actual) # @@ -709,7 +709,7 @@ class SamrTests(RpcInterfaceTestCase): max_size = calc_max_size(len(expected) + len(extra_dns) + 10) (resume_handle, actual, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, 0, 0, max_size) - self.assertEquals(len(expected) + len(extra_dns), num_entries) + self.assertEqual(len(expected) + len(extra_dns), num_entries) # # Get a new expected result set by querying the database directly @@ -723,7 +723,7 @@ class SamrTests(RpcInterfaceTestCase): # # Now check that we read the new entries. # - self.assertEquals(len(expected01), num_entries) + self.assertEqual(len(expected01), num_entries) check_results(expected01, actual.entries) self.delete_dns(dns + extra_dns) @@ -739,12 +739,12 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, 0, max_size) count = num_entries while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) (resume_handle, a, num_entries) = self.conn.EnumDomainUsers( self.domain_handle, resume_handle, 0, max_size) count += num_entries - self.assertEquals(count, info.num_users) + self.assertEqual(count, info.num_users) def test_DomGeneralInformation_num_groups(self): info = self.conn.QueryDomainInfo( @@ -757,12 +757,12 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, max_size) count = num_entries while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) (resume_handle, a, num_entries) = self.conn.EnumDomainGroups( self.domain_handle, resume_handle, max_size) count += num_entries - self.assertEquals(count, info.num_groups) + self.assertEqual(count, info.num_groups) def test_DomGeneralInformation_num_aliases(self): info = self.conn.QueryDomainInfo( @@ -775,9 +775,9 @@ class SamrTests(RpcInterfaceTestCase): self.domain_handle, 0, max_size) count = num_entries while resume_handle: - self.assertEquals(1, num_entries) + self.assertEqual(1, num_entries) (resume_handle, a, num_entries) = self.conn.EnumDomainAliases( self.domain_handle, resume_handle, max_size) count += num_entries - self.assertEquals(count, info.num_aliases) + self.assertEqual(count, info.num_aliases) diff --git a/python/samba/tests/dcerpc/unix.py b/python/samba/tests/dcerpc/unix.py index 77a5c221eab..0b56babdd14 100644 --- a/python/samba/tests/dcerpc/unix.py +++ b/python/samba/tests/dcerpc/unix.py @@ -30,8 +30,8 @@ class UnixinfoTests(RpcInterfaceTestCase): def test_getpwuid_int(self): infos = self.conn.GetPWUid(range(512)) - self.assertEquals(512, len(infos)) - self.assertEquals("/bin/false", infos[0].shell) + self.assertEqual(512, len(infos)) + self.assertEqual("/bin/false", infos[0].shell) self.assertTrue(isinstance(infos[0].homedir, text_type)) def test_gidtosid(self): diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py index d06cf0b0b19..093cae14078 100644 --- a/python/samba/tests/dns.py +++ b/python/samba/tests/dns.py @@ -94,8 +94,8 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rdata, + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rdata, self.server_ip) def test_one_SOA_query(self): @@ -113,8 +113,8 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals( + self.assertEqual(response.ancount, 1) + self.assertEqual( response.answers[0].rdata.mname.upper(), ("%s.%s" % (self.server, self.get_dns_domain())).upper()) @@ -133,8 +133,8 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_tcp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rdata, + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rdata, self.server_ip) def test_one_mx_query(self): @@ -152,7 +152,7 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) p = self.make_name_packet(dns.DNS_OPCODE_QUERY) questions = [] @@ -167,7 +167,7 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) def test_two_queries(self): "create a query packet containing two query records" @@ -215,11 +215,11 @@ class TestSimpleQueries(DNSTest): self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, num_answers) - self.assertEquals(response.answers[0].rdata, + self.assertEqual(response.ancount, num_answers) + self.assertEqual(response.answers[0].rdata, self.server_ip) if dc_ipv6 is not None: - self.assertEquals(response.answers[1].rdata, dc_ipv6) + self.assertEqual(response.answers[1].rdata, dc_ipv6) def test_qclass_none_query(self): "create a QCLASS_NONE query" @@ -260,7 +260,7 @@ class TestSimpleQueries(DNSTest): self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) # We don't get SOA records for single hosts - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) # But we do respond with an authority section self.assertEqual(response.nscount, 1) @@ -279,7 +279,7 @@ class TestSimpleQueries(DNSTest): self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) # We don't get SOA records for single hosts - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) # But we do respond with an authority section self.assertEqual(response.nscount, 1) @@ -297,8 +297,8 @@ class TestSimpleQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rdata.minimum, 3600) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rdata.minimum, 3600) class TestDNSUpdates(DNSTest): @@ -754,12 +754,12 @@ class TestComplexQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 2) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[0].rdata, "%s.%s" % + self.assertEqual(response.ancount, 2) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[0].rdata, "%s.%s" % (self.server, self.get_dns_domain())) - self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[1].rdata, + self.assertEqual(response.answers[1].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[1].rdata, self.server_ip) finally: @@ -810,18 +810,18 @@ class TestComplexQueries(DNSTest): self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 3) + self.assertEqual(response.ancount, 3) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[0].name, name1) - self.assertEquals(response.answers[0].rdata, name2) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[0].name, name1) + self.assertEqual(response.answers[0].rdata, name2) - self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[1].name, name2) - self.assertEquals(response.answers[1].rdata, name0) + self.assertEqual(response.answers[1].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[1].name, name2) + self.assertEqual(response.answers[1].rdata, name0) - self.assertEquals(response.answers[2].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[2].rdata, + self.assertEqual(response.answers[2].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[2].rdata, self.server_ip) def test_invalid_empty_cname(self): @@ -855,15 +855,15 @@ class TestComplexQueries(DNSTest): # CNAME should return all intermediate results! # Only the A records exists, not the TXT. - self.assertEquals(response.ancount, 2) + self.assertEqual(response.ancount, 2) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[0].name, name1) - self.assertEquals(response.answers[0].rdata, name2) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[0].name, name1) + self.assertEqual(response.answers[0].rdata, name2) - self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[1].name, name2) - self.assertEquals(response.answers[1].rdata, name0) + self.assertEqual(response.answers[1].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[1].name, name2) + self.assertEqual(response.answers[1].rdata, name0) def test_cname_loop(self): cname1 = "cnamelooptestrec." + self.get_dns_domain() @@ -886,7 +886,7 @@ class TestComplexQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) max_recursion_depth = 20 - self.assertEquals(len(response.answers), max_recursion_depth) + self.assertEqual(len(response.answers), max_recursion_depth) # Make sure cname limit doesn't count other records. This is a generic # test called in tests below @@ -1025,8 +1025,8 @@ class TestInvalidQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rdata, + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rdata, self.server_ip) def test_one_a_reply(self): @@ -1054,7 +1054,7 @@ class TestInvalidQueries(DNSTest): tcp_packet += send_packet s.send(tcp_packet, 0) recv_packet = s.recv(0xffff + 2, 0) - self.assertEquals(0, len(recv_packet)) + self.assertEqual(0, len(recv_packet)) except socket.timeout: # Windows chooses not to respond to incorrectly formatted queries. # Although this appears to be non-deterministic even for the same @@ -1447,29 +1447,29 @@ class TestZones(DNSTest): expr = "(dnsProperty:1.3.6.1.4.1.7165.4.5.3:=1)" res = samdb.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # No value for tombstone time try: expr = "(dnsRecord:1.3.6.1.4.1.7165.4.5.3:=)" res = samdb.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.fail("Exception: ldb.ldbError not generated") except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # Tombstone time = - try: expr = "(dnsRecord:1.3.6.1.4.1.7165.4.5.3:=-)" res = samdb.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.fail("Exception: ldb.ldbError not generated") except ldb.LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # Tombstone time longer than 64 characters try: @@ -1477,22 +1477,22 @@ class TestZones(DNSTest): expr = expr.format("1" * 65) res = samdb.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.fail("Exception: ldb.ldbError not generated") except ldb.LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # Non numeric Tombstone time try: expr = "(dnsRecord:1.3.6.1.4.1.7165.4.5.3:=expired)" res = samdb.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.fail("Exception: ldb.ldbError not generated") except ldb.LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # Non system session try: @@ -1503,11 +1503,11 @@ class TestZones(DNSTest): expr = "(dnsRecord:1.3.6.1.4.1.7165.4.5.3:=2)" res = db.search(base=self.zone_dn, scope=ldb.SCOPE_SUBTREE, expression=expr, attrs=["*"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.fail("Exception: ldb.ldbError not generated") except ldb.LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) def test_basic_scavenging(self): lp = self.get_loadparm() @@ -1685,22 +1685,22 @@ class TestZones(DNSTest): # Windows returns OK while BIND logically seems to return NXDOMAIN self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) self.create_zone(zone) (response, response_packet) =\ self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_SOA) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_SOA) self.delete_zone(zone) (response, response_packet) =\ self.dns_transaction_udp(p, host=server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 0) + self.assertEqual(response.ancount, 0) def set_dnsProperty_zero_length(self, dnsproperty_id): records = self.samdb.search(base=self.zone_dn, scope=ldb.SCOPE_BASE, diff --git a/python/samba/tests/dns_base.py b/python/samba/tests/dns_base.py index ddd8b4efd1a..c90e48d1fc0 100644 --- a/python/samba/tests/dns_base.py +++ b/python/samba/tests/dns_base.py @@ -63,19 +63,19 @@ class DNSTest(TestCaseInTempDir): def assert_rcode_equals(self, rcode, expected): "Helper function to check return code" - self.assertEquals(rcode, expected, "Expected RCODE %s, got %s" % + self.assertEqual(rcode, expected, "Expected RCODE %s, got %s" % (self.errstr(expected), self.errstr(rcode))) def assert_dns_rcode_equals(self, packet, rcode): "Helper function to check return code" p_errcode = packet.operation & dns.DNS_RCODE - self.assertEquals(p_errcode, rcode, "Expected RCODE %s, got %s" % + self.assertEqual(p_errcode, rcode, "Expected RCODE %s, got %s" % (self.errstr(rcode), self.errstr(p_errcode))) def assert_dns_opcode_equals(self, packet, opcode): "Helper function to check opcode" p_opcode = packet.operation & dns.DNS_OPCODE - self.assertEquals(p_opcode, opcode, "Expected OPCODE %s, got %s" % + self.assertEqual(p_opcode, opcode, "Expected OPCODE %s, got %s" % (opcode, p_opcode)) def make_name_packet(self, opcode, qid=None): @@ -164,7 +164,7 @@ class DNSTest(TestCaseInTempDir): # unpacking and packing again should produce same bytestream my_packet = ndr.ndr_pack(response) - self.assertEquals(my_packet, recv_packet[2:]) + self.assertEqual(my_packet, recv_packet[2:]) return (response, recv_packet[2:]) def make_txt_update(self, prefix, txt_array, domain=None): @@ -203,8 +203,8 @@ class DNSTest(TestCaseInTempDir): (response, response_packet) =\ self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rdata.txt.str, txt_array) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rdata.txt.str, txt_array) class DNSTKeyTest(DNSTest): diff --git a/python/samba/tests/dns_forwarder.py b/python/samba/tests/dns_forwarder.py index 65616898172..0af885913a8 100644 --- a/python/samba/tests/dns_forwarder.py +++ b/python/samba/tests/dns_forwarder.py @@ -82,13 +82,13 @@ class DNSTest(TestCase): def assert_dns_rcode_equals(self, packet, rcode): "Helper function to check return code" p_errcode = packet.operation & dns.DNS_RCODE - self.assertEquals(p_errcode, rcode, "Expected RCODE %s, got %s" % + self.assertEqual(p_errcode, rcode, "Expected RCODE %s, got %s" % (self.errcodes[rcode], self.errcodes[p_errcode])) def assert_dns_opcode_equals(self, packet, opcode): "Helper function to check opcode" p_opcode = packet.operation & dns.DNS_OPCODE - self.assertEquals(p_opcode, opcode, "Expected OPCODE %s, got %s" % + self.assertEqual(p_opcode, opcode, "Expected OPCODE %s, got %s" % (opcode, p_opcode)) def make_name_packet(self, opcode, qid=None): diff --git a/python/samba/tests/dns_tkey.py b/python/samba/tests/dns_tkey.py index 8dd1b551670..07316271d56 100644 --- a/python/samba/tests/dns_tkey.py +++ b/python/samba/tests/dns_tkey.py @@ -80,8 +80,8 @@ class TestDNSUpdates(DNSTKeyTest): (response, response_p) = self.dns_transaction_udp(p, self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH) tsig_record = response.additional[0].rdata - self.assertEquals(tsig_record.error, dns.DNS_RCODE_BADKEY) - self.assertEquals(tsig_record.mac_size, 0) + self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADKEY) + self.assertEqual(tsig_record.mac_size, 0) rcode = self.search_record(self.newrecname) self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN) @@ -96,8 +96,8 @@ class TestDNSUpdates(DNSTKeyTest): (response, response_p) = self.dns_transaction_udp(p, self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH) tsig_record = response.additional[0].rdata - self.assertEquals(tsig_record.error, dns.DNS_RCODE_BADSIG) - self.assertEquals(tsig_record.mac_size, 0) + self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADSIG) + self.assertEqual(tsig_record.mac_size, 0) rcode = self.search_record(self.newrecname) self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN) diff --git a/python/samba/tests/dns_wildcard.py b/python/samba/tests/dns_wildcard.py index 01e06b8e262..38232a4df07 100644 --- a/python/samba/tests/dns_wildcard.py +++ b/python/samba/tests/dns_wildcard.py @@ -168,9 +168,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, WILDCARD_IP) def test_one_a_query_match_wildcard_2_labels(self): """ Query an A record, should match the wild card entry @@ -192,9 +192,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, WILDCARD_IP) def test_one_a_query_wildcard_entry(self): "Query the wildcard entry" @@ -214,9 +214,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, WILDCARD_IP) def test_one_a_query_exact_match(self): """Query an entry that matches the wild card but has an exact match as @@ -237,9 +237,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, EXACT_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, EXACT_IP) def test_one_a_query_match_wildcard_l2(self): "Query an A record, should match the level 2 wildcard entry" @@ -259,9 +259,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, LEVEL2_WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, LEVEL2_WILDCARD_IP) def test_one_a_query_match_wildcard_l2_2_labels(self): """Query an A record, should match the level 2 wild card entry @@ -283,9 +283,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, LEVEL2_WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, LEVEL2_WILDCARD_IP) def test_one_a_query_exact_match_l2(self): """Query an entry that matches the wild card but has an exact match as @@ -306,9 +306,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, LEVEL2_EXACT_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, LEVEL2_EXACT_IP) def test_one_a_query_wildcard_entry_l2(self): "Query the level 2 wildcard entry" @@ -328,9 +328,9 @@ class TestWildCardQueries(DNSTest): self.dns_transaction_udp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_A) - self.assertEquals(response.answers[0].rdata, LEVEL2_WILDCARD_IP) + self.assertEqual(response.ancount, 1) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.answers[0].rdata, LEVEL2_WILDCARD_IP) TestProgram(module=__name__, opts=subunitopts) diff --git a/python/samba/tests/dsdb.py b/python/samba/tests/dsdb.py index 2432c3cd509..33cfcc12271 100644 --- a/python/samba/tests/dsdb.py +++ b/python/samba/tests/dsdb.py @@ -59,7 +59,7 @@ class DsdbTests(TestCase): def test_get_oid_from_attrid(self): oid = self.samdb.get_oid_from_attid(591614) - self.assertEquals(oid, "1.2.840.113556.1.4.1790") + self.assertEqual(oid, "1.2.840.113556.1.4.1790") def test_error_replpropertymetadata(self): res = self.samdb.search(scope=ldb.SCOPE_SUBTREE, @@ -144,16 +144,16 @@ class DsdbTests(TestCase): self.samdb.modify(msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"]) def test_ok_get_attribute_from_attid(self): - self.assertEquals(self.samdb.get_attribute_from_attid(13), "description") + self.assertEqual(self.samdb.get_attribute_from_attid(13), "description") def test_ko_get_attribute_from_attid(self): - self.assertEquals(self.samdb.get_attribute_from_attid(11979), None) + self.assertEqual(self.samdb.get_attribute_from_attid(11979), None) def test_get_attribute_replmetadata_version(self): res = self.samdb.search(scope=ldb.SCOPE_SUBTREE, base=self.account_dn, attrs=["dn"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn = str(res[0].dn) self.assertEqual(self.samdb.get_attribute_replmetadata_version(dn, "unicodePwd"), 2) @@ -161,7 +161,7 @@ class DsdbTests(TestCase): res = self.samdb.search(scope=ldb.SCOPE_SUBTREE, base=self.account_dn, attrs=["dn"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn = str(res[0].dn) version = self.samdb.get_attribute_replmetadata_version(dn, "description") self.samdb.set_attribute_replmetadata_version(dn, "description", version + 2) diff --git a/python/samba/tests/dsdb_schema_attributes.py b/python/samba/tests/dsdb_schema_attributes.py index 5928511cd44..bb4603d4703 100644 --- a/python/samba/tests/dsdb_schema_attributes.py +++ b/python/samba/tests/dsdb_schema_attributes.py @@ -41,7 +41,7 @@ class SchemaAttributesTestCase(samba.tests.TestCase): # fetch rootDSE res = self.samdb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.schema_dn = res[0]["schemaNamingContext"][0] self.base_dn = res[0]["defaultNamingContext"][0] self.forest_level = int(res[0]["forestFunctionality"][0]) @@ -100,8 +100,8 @@ systemOnly: FALSE attr_res = self.samdb.search(base="@ATTRIBUTES", scope=ldb.SCOPE_BASE) self.assertIn(attr_ldap_name, attr_res[0]) - self.assertEquals(len(attr_res[0][attr_ldap_name]), 1) - self.assertEquals(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") + self.assertEqual(len(attr_res[0][attr_ldap_name]), 1) + self.assertEqual(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") # Check @INDEXLIST @@ -123,8 +123,8 @@ systemOnly: FALSE attr_res = self.samdb.search(base="@ATTRIBUTES", scope=ldb.SCOPE_BASE) self.assertIn(attr_ldap_name, attr_res[0]) - self.assertEquals(len(attr_res[0][attr_ldap_name]), 1) - self.assertEquals(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") + self.assertEqual(len(attr_res[0][attr_ldap_name]), 1) + self.assertEqual(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") # Check @INDEXLIST @@ -156,12 +156,12 @@ systemOnly: FALSE attr_res = self.samdb.search(base="@ATTRIBUTES", scope=ldb.SCOPE_BASE) self.assertIn(attr_ldap_name, attr_res[0]) - self.assertEquals(len(attr_res[0][attr_ldap_name]), 1) - self.assertEquals(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") + self.assertEqual(len(attr_res[0][attr_ldap_name]), 1) + self.assertEqual(str(attr_res[0][attr_ldap_name][0]), "CASE_INSENSITIVE") self.assertIn(attr_ldap_name2, attr_res[0]) - self.assertEquals(len(attr_res[0][attr_ldap_name2]), 1) - self.assertEquals(str(attr_res[0][attr_ldap_name2][0]), "CASE_INSENSITIVE") + self.assertEqual(len(attr_res[0][attr_ldap_name2]), 1) + self.assertEqual(str(attr_res[0][attr_ldap_name2][0]), "CASE_INSENSITIVE") # Check @INDEXLIST @@ -180,12 +180,12 @@ systemOnly: FALSE res = self.samdb.search(base="@ATTRIBUTES", scope=ldb.SCOPE_BASE, attrs=["@TEST_EXTRA"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), "@ATTRIBUTES") - self.assertEquals(len(res[0]), 1) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), "@ATTRIBUTES") + self.assertEqual(len(res[0]), 1) self.assertTrue("@TEST_EXTRA" in res[0]) - self.assertEquals(len(res[0]["@TEST_EXTRA"]), 1) - self.assertEquals(str(res[0]["@TEST_EXTRA"][0]), "HIDDEN") + self.assertEqual(len(res[0]["@TEST_EXTRA"]), 1) + self.assertEqual(str(res[0]["@TEST_EXTRA"][0]), "HIDDEN") samdb2 = samba.tests.connect_samdb(self.lp.samdb_url()) @@ -199,9 +199,9 @@ systemOnly: FALSE res = self.samdb.search(base="@ATTRIBUTES", scope=ldb.SCOPE_BASE, attrs=["@TEST_EXTRA"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), "@ATTRIBUTES") - self.assertEquals(len(res[0]), 0) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), "@ATTRIBUTES") + self.assertEqual(len(res[0]), 0) self.assertFalse("@TEST_EXTRA" in res[0]) def test_modify_at_indexlist(self): @@ -214,12 +214,12 @@ systemOnly: FALSE res = self.samdb.search(base="@INDEXLIST", scope=ldb.SCOPE_BASE, attrs=["@TEST_EXTRA"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), "@INDEXLIST") - self.assertEquals(len(res[0]), 1) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), "@INDEXLIST") + self.assertEqual(len(res[0]), 1) self.assertTrue("@TEST_EXTRA" in res[0]) - self.assertEquals(len(res[0]["@TEST_EXTRA"]), 1) - self.assertEquals(str(res[0]["@TEST_EXTRA"][0]), "1") + self.assertEqual(len(res[0]["@TEST_EXTRA"]), 1) + self.assertEqual(str(res[0]["@TEST_EXTRA"][0]), "1") samdb2 = samba.tests.connect_samdb(self.lp.samdb_url()) @@ -233,9 +233,9 @@ systemOnly: FALSE res = self.samdb.search(base="@INDEXLIST", scope=ldb.SCOPE_BASE, attrs=["@TEST_EXTRA"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), "@INDEXLIST") - self.assertEquals(len(res[0]), 0) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), "@INDEXLIST") + self.assertEqual(len(res[0]), 0) self.assertFalse("@TEST_EXTRA" in res[0]) def test_modify_fail_of_at_indexlist(self): @@ -249,4 +249,4 @@ systemOnly: FALSE self.fail("modify of @INDEXLIST with a failed constraint should fail") except LdbError as err: enum = err.args[0] - self.assertEquals(enum, ldb.ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(enum, ldb.ERR_NO_SUCH_ATTRIBUTE) diff --git a/python/samba/tests/encrypted_secrets.py b/python/samba/tests/encrypted_secrets.py index db0822797f7..96da7048a77 100644 --- a/python/samba/tests/encrypted_secrets.py +++ b/python/samba/tests/encrypted_secrets.py @@ -68,7 +68,7 @@ class EncryptedSecretsTests(TestCase): # Now verify that the header contains the correct magic value. encrypted = ndr_unpack(drsblobs.EncryptedSecret, blob) magic = 0xca5caded - self.assertEquals(magic, encrypted.header.magic) + self.assertEqual(magic, encrypted.header.magic) def test_required_features(self): """Test that databases are provisioned with encryptedSecrets as a diff --git a/python/samba/tests/get_opt.py b/python/samba/tests/get_opt.py index e51c7068aba..2aad954830b 100644 --- a/python/samba/tests/get_opt.py +++ b/python/samba/tests/get_opt.py @@ -32,23 +32,23 @@ import samba.tests class KerberosOptionTests(samba.tests.TestCase): def test_parse_true(self): - self.assertEquals( + self.assertEqual( MUST_USE_KERBEROS, parse_kerberos_arg("yes", "--kerberos")) - self.assertEquals( + self.assertEqual( MUST_USE_KERBEROS, parse_kerberos_arg("true", "--kerberos")) - self.assertEquals( + self.assertEqual( MUST_USE_KERBEROS, parse_kerberos_arg("1", "--kerberos")) def test_parse_false(self): - self.assertEquals( + self.assertEqual( DONT_USE_KERBEROS, parse_kerberos_arg("no", "--kerberos")) - self.assertEquals( + self.assertEqual( DONT_USE_KERBEROS, parse_kerberos_arg("false", "--kerberos")) - self.assertEquals( + self.assertEqual( DONT_USE_KERBEROS, parse_kerberos_arg("0", "--kerberos")) def test_parse_auto(self): - self.assertEquals( + self.assertEqual( AUTO_USE_KERBEROS, parse_kerberos_arg("auto", "--kerberos")) def test_parse_invalid(self): diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py index bf92aea77b6..dce00bd8f86 100644 --- a/python/samba/tests/gpo.py +++ b/python/samba/tests/gpo.py @@ -102,11 +102,11 @@ class GPOTests(tests.TestCase): file_sys_paths = [None, '%s\\%s' % (poldir, guid)] ds_paths = [None, 'CN=%s,%s' % (guid, dspath)] for i in range(0, len(gpos)): - self.assertEquals(gpos[i].name, names[i], + self.assertEqual(gpos[i].name, names[i], 'The gpo name did not match expected name %s' % gpos[i].name) - self.assertEquals(gpos[i].file_sys_path, file_sys_paths[i], + self.assertEqual(gpos[i].file_sys_path, file_sys_paths[i], 'file_sys_path did not match expected %s' % gpos[i].file_sys_path) - self.assertEquals(gpos[i].ds_path, ds_paths[i], + self.assertEqual(gpos[i].ds_path, ds_paths[i], 'ds_path did not match expected %s' % gpos[i].ds_path) def test_gpo_ads_does_not_segfault(self): @@ -124,12 +124,12 @@ class GPOTests(tests.TestCase): with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt: gpt.write(gpt_data % 42) - self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42, + self.assertEqual(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42, 'gpo_get_sysvol_gpt_version() did not return the expected version') with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt: gpt.write(gpt_data % old_vers) - self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers, + self.assertEqual(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers, 'gpo_get_sysvol_gpt_version() did not return the expected version') def test_check_refresh_gpo_list(self): @@ -162,7 +162,7 @@ class GPOTests(tests.TestCase): after = realm + '/Policies/' \ '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI' result = check_safe_path(before) - self.assertEquals(result, after, 'check_safe_path() didn\'t' + self.assertEqual(result, after, 'check_safe_path() didn\'t' ' correctly convert \\ to /') def test_gpt_ext_register(self): @@ -177,7 +177,7 @@ class GPOTests(tests.TestCase): gp_exts = list_gp_extensions(self.lp.configfile) self.assertTrue(ext_guid in gp_exts.keys(), 'Failed to list gp exts') - self.assertEquals(gp_exts[ext_guid]['DllName'], ext_path, + self.assertEqual(gp_exts[ext_guid]['DllName'], ext_path, 'Failed to list gp exts') unregister_gp_extension(ext_guid) @@ -197,7 +197,7 @@ class GPOTests(tests.TestCase): lp, parser = parse_gpext_conf(self.lp.configfile) self.assertTrue('test_section' in parser.sections(), 'test_section not found in gpext.conf') - self.assertEquals(parser.get('test_section', 'test_var'), ext_guid, + self.assertEqual(parser.get('test_section', 'test_var'), ext_guid, 'Failed to find test variable in gpext.conf') parser.remove_section('test_section') atomic_write_conf(lp, parser) @@ -217,12 +217,12 @@ class GPOTests(tests.TestCase): self.assertTrue(ret, 'Could not create the target %s' % gpttmpl) ret = gpupdate_force(self.lp) - self.assertEquals(ret, 0, 'gpupdate force failed') + self.assertEqual(ret, 0, 'gpupdate force failed') gp_db = store.get_gplog(self.dc_account) applied_guids = gp_db.get_applied_guids() - self.assertEquals(len(applied_guids), 2, 'The guids were not found') + self.assertEqual(len(applied_guids), 2, 'The guids were not found') self.assertIn(guids[0], applied_guids, '%s not in applied guids' % guids[0]) self.assertIn(guids[1], applied_guids, @@ -260,7 +260,7 @@ class GPOTests(tests.TestCase): unstage_file(gpttmpl) ret = gpupdate_unapply(self.lp) - self.assertEquals(ret, 0, 'gpupdate unapply failed') + self.assertEqual(ret, 0, 'gpupdate unapply failed') def test_process_group_policy(self): local_path = self.lp.cache_path('gpo_cache') diff --git a/python/samba/tests/group_audit.py b/python/samba/tests/group_audit.py index 7163c5016a3..8af61340584 100644 --- a/python/samba/tests/group_audit.py +++ b/python/samba/tests/group_audit.py @@ -105,7 +105,7 @@ class GroupAuditTests(AuditLogTestBase): # messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -119,9 +119,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") # Check the Add message for the new users primary group audit = messages[1]["groupChange"] @@ -135,8 +135,8 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) - self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + self.assertEqual(session_id, audit["sessionId"]) + self.assertEqual(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # # Add the user to a group @@ -146,7 +146,7 @@ class GroupAuditTests(AuditLogTestBase): self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -160,9 +160,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") # # Add the user to another group @@ -172,7 +172,7 @@ class GroupAuditTests(AuditLogTestBase): messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -186,9 +186,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") # # Remove the user from a group @@ -200,7 +200,7 @@ class GroupAuditTests(AuditLogTestBase): add_members_operation=False) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -214,9 +214,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") # # Re-add the user to a group @@ -226,7 +226,7 @@ class GroupAuditTests(AuditLogTestBase): messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -240,9 +240,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") def test_change_primary_group(self): @@ -251,7 +251,7 @@ class GroupAuditTests(AuditLogTestBase): # messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) - self.assertEquals(2, + self.assertEqual(2, len(messages), "Did not receive the expected number of messages") @@ -267,9 +267,9 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") # Check the Add message for the new users primary group audit = messages[1]["groupChange"] @@ -283,8 +283,8 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) - self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + self.assertEqual(session_id, audit["sessionId"]) + self.assertEqual(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # @@ -296,7 +296,7 @@ class GroupAuditTests(AuditLogTestBase): self.ldb.add_remove_group_members(GROUP_NAME_01, [USER_NAME]) messages = self.waitForMessages(1) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEqual(1, len(messages), "Did not receive the expected number of messages") audit = messages[0]["groupChange"] @@ -310,10 +310,10 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") - self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + self.assertEqual(service_description, "LDAP") + self.assertEqual(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) # @@ -344,7 +344,7 @@ class GroupAuditTests(AuditLogTestBase): # messages = self.waitForMessages(3) print("Received %d messages" % len(messages)) - self.assertEquals(3, + self.assertEqual(3, len(messages), "Did not receive the expected number of messages") @@ -358,10 +358,10 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") - self.assertEquals(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP, + self.assertEqual(service_description, "LDAP") + self.assertEqual(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[1]["groupChange"] @@ -375,10 +375,10 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") - self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + self.assertEqual(service_description, "LDAP") + self.assertEqual(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, audit["eventId"]) audit = messages[2]["groupChange"] @@ -392,6 +392,6 @@ class GroupAuditTests(AuditLogTestBase): self.remoteAddress) self.assertTrue(self.is_guid(audit["sessionId"])) session_id = self.get_session() - self.assertEquals(session_id, audit["sessionId"]) + self.assertEqual(session_id, audit["sessionId"]) service_description = self.get_service_description() - self.assertEquals(service_description, "LDAP") + self.assertEqual(service_description, "LDAP") diff --git a/python/samba/tests/hostconfig.py b/python/samba/tests/hostconfig.py index 94f511ccf3f..0f03388d6ad 100644 --- a/python/samba/tests/hostconfig.py +++ b/python/samba/tests/hostconfig.py @@ -52,18 +52,18 @@ class ShareTests(TestCase): def test_len_no_global(self): shares = self._get_shares({}) - self.assertEquals(0, len(shares)) + self.assertEqual(0, len(shares)) def test_iter(self): - self.assertEquals([], list(self._get_shares({}))) - self.assertEquals([], list(self._get_shares({"global": {}}))) - self.assertEquals( + self.assertEqual([], list(self._get_shares({}))) + self.assertEqual([], list(self._get_shares({"global": {}}))) + self.assertEqual( ["bla"], list(self._get_shares({"global": {}, "bla": {}}))) def test_len(self): shares = self._get_shares({"global": {}}) - self.assertEquals(0, len(shares)) + self.assertEqual(0, len(shares)) def test_getitem_nonexistent(self): shares = self._get_shares({"global": {}}) diff --git a/python/samba/tests/join.py b/python/samba/tests/join.py index e0ad34e1e74..db9d8a892b7 100644 --- a/python/samba/tests/join.py +++ b/python/samba/tests/join.py @@ -99,7 +99,7 @@ class JoinTestCase(DNSTKeyTest): (response, response_packet) = self.dns_transaction_tcp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, len(IPs)) + self.assertEqual(response.ancount, len(IPs)) questions = [] name = "%s._msdcs.%s" % (self.join_ctx.ntds_guid, self.join_ctx.dnsforest) @@ -111,10 +111,10 @@ class JoinTestCase(DNSTKeyTest): self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1 + len(IPs)) - self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) - self.assertEquals(response.answers[0].rdata, self.join_ctx.dnshostname) - self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_A) + self.assertEqual(response.ancount, 1 + len(IPs)) + self.assertEqual(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME) + self.assertEqual(response.answers[0].rdata, self.join_ctx.dnshostname) + self.assertEqual(response.answers[1].rr_type, dns.DNS_QTYPE_A) def test_join_records_can_update(self): dc_creds = Credentials() @@ -174,4 +174,4 @@ class JoinTestCase(DNSTKeyTest): (response, response_packet) = self.dns_transaction_tcp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) - self.assertEquals(response.ancount, 1) + self.assertEqual(response.ancount, 1) diff --git a/python/samba/tests/kcc/graph.py b/python/samba/tests/kcc/graph.py index ed02b0d4ed8..b581158218c 100644 --- a/python/samba/tests/kcc/graph.py +++ b/python/samba/tests/kcc/graph.py @@ -52,7 +52,7 @@ class GraphFunctionTests(samba.tests.TestCase): ([0x03, 0x33] * 42, 42 * 6), (list(range(7)) * 12, 12 * 9), (list(range(4)) * 21, 21 * 4)): - self.assertEquals(total_schedule(schedule), total) + self.assertEqual(total_schedule(schedule), total) def test_convert_schedule_to_repltimes(self): for ntdsconn_times, repltimes in ( @@ -63,5 +63,5 @@ class GraphFunctionTests(samba.tests.TestCase): (list(range(7)) * 24, [0x01, 0x23, 0x45, 0x60, 0x12, 0x34, 0x56] * 12)): schedule = ntdsconn_schedule(ntdsconn_times) - self.assertEquals(convert_schedule_to_repltimes(schedule), + self.assertEqual(convert_schedule_to_repltimes(schedule), repltimes) diff --git a/python/samba/tests/kcc/kcc_utils.py b/python/samba/tests/kcc/kcc_utils.py index bad32b9ed6e..1597240efcd 100644 --- a/python/samba/tests/kcc/kcc_utils.py +++ b/python/samba/tests/kcc/kcc_utils.py @@ -33,8 +33,8 @@ class ScheduleTests(samba.tests.TestCase): def test_new_connection_schedule(self): schedule = new_connection_schedule() self.assertIsInstance(schedule, drsblobs.schedule) - self.assertEquals(schedule.size, 188) - self.assertEquals(len(schedule.dataArray[0].slots), 168) + self.assertEqual(schedule.size, 188) + self.assertEqual(len(schedule.dataArray[0].slots), 168) # OK, this is pathetic, but the rest of it looks really hard, with the diff --git a/python/samba/tests/netcmd.py b/python/samba/tests/netcmd.py index 8efd47c18ff..cdc4e3b0c22 100644 --- a/python/samba/tests/netcmd.py +++ b/python/samba/tests/netcmd.py @@ -33,7 +33,7 @@ class NetCmdTestCase(samba.tests.TestCase): except Exception as e: cmd.show_command_error(e) retval = 1 - self.assertEquals(retcode, retval) + self.assertEqual(retcode, retval) return cmd.outf.getvalue(), cmd.errf.getvalue() def iter_all_subcommands(self): @@ -51,8 +51,8 @@ class TestParmTests(NetCmdTestCase): def test_no_client_ip(self): out, err = self.run_netcmd(cmd_testparm, ["--client-name=foo"], retcode=-1) - self.assertEquals("", out) - self.assertEquals( + self.assertEqual("", out) + self.assertEqual( "ERROR: Both a DNS name and an IP address are " "required for the host access check\n", err) @@ -62,12 +62,12 @@ class CommandTests(NetCmdTestCase): def test_description(self): class cmd_foo(Command): """Mydescription""" - self.assertEquals("Mydescription", cmd_foo().short_description) + self.assertEqual("Mydescription", cmd_foo().short_description) def test_name(self): class cmd_foo(Command): pass - self.assertEquals("foo", cmd_foo().name) + self.assertEqual("foo", cmd_foo().name) def test_synopsis_everywhere(self): missing = [] diff --git a/python/samba/tests/ntacls.py b/python/samba/tests/ntacls.py index 44c8e535218..600135d88c0 100644 --- a/python/samba/tests/ntacls.py +++ b/python/samba/tests/ntacls.py @@ -56,7 +56,7 @@ class NtaclsTests(TestCaseInTempDir): setntacl(lp, self.tempf, NTACL_SDDL, DOMAIN_SID, self.session_info) facl = getntacl(lp, self.tempf, self.session_info) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(anysid), NTACL_SDDL) + self.assertEqual(facl.as_sddl(anysid), NTACL_SDDL) os.unlink(os.path.join(self.tempdir, "eadbtest.tdb")) def test_setntacl_getntacl_param(self): @@ -67,7 +67,7 @@ class NtaclsTests(TestCaseInTempDir): facl = getntacl(lp, self.tempf, self.session_info, "tdb", os.path.join( self.tempdir, "eadbtest.tdb")) domsid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(domsid), NTACL_SDDL) + self.assertEqual(facl.as_sddl(domsid), NTACL_SDDL) os.unlink(os.path.join(self.tempdir, "eadbtest.tdb")) def test_setntacl_invalidbackend(self): diff --git a/python/samba/tests/ntacls_backup.py b/python/samba/tests/ntacls_backup.py index 6ac73d4a1b8..265208805b7 100644 --- a/python/samba/tests/ntacls_backup.py +++ b/python/samba/tests/ntacls_backup.py @@ -117,7 +117,7 @@ class NtaclsBackupRestoreTests(SmbdBaseTests): # This works in conjunction with the TEST_UMASK in smbd_base # to ensure that permissions are not related to the umask # but instead the smb.conf settings - self.assertEquals(mode & 0o777, 0o755) + self.assertEqual(mode & 0o777, 0o755) self.assertTrue(os.path.isdir(dirpath)) def test_smbd_create_file(self): @@ -134,7 +134,7 @@ class NtaclsBackupRestoreTests(SmbdBaseTests): # This works in conjunction with the TEST_UMASK in smbd_base # to ensure that permissions are not related to the umask # but instead the smb.conf settings - self.assertEquals(mode & 0o777, 0o644) + self.assertEqual(mode & 0o777, 0o644) # As well as checking that unlink works, this removes the # fake xattrs from the dev/inode based DB @@ -157,8 +157,8 @@ class NtaclsBackupRestoreTests(SmbdBaseTests): sd2 = self.ntacls_helper.getntacl( file_path, system_session_unix(), as_sddl=True, direct_db_access=True) - self.assertEquals(sd0, sd1) - self.assertEquals(sd1, sd2) + self.assertEqual(sd0, sd1) + self.assertEqual(sd1, sd2) def test_backup_online(self): """ diff --git a/python/samba/tests/ntlm_auth.py b/python/samba/tests/ntlm_auth.py index 4b6fbee8b58..f6ae708ad24 100644 --- a/python/samba/tests/ntlm_auth.py +++ b/python/samba/tests/ntlm_auth.py @@ -228,11 +228,11 @@ class NTLMAuthHelpersTests(NTLMAuthTestCase): lines = out.split(b"\n") self.assertEqual(len(lines), 4) - self.assertEquals(lines[0], b"Authenticated: Yes") - self.assertEquals( + self.assertEqual(lines[0], b"Authenticated: Yes") + self.assertEqual( lines[1], b"User-Session-Key: 3F373EA8E4AF954F14FAA506F8EEBDC4") - self.assertEquals(lines[2], b".") - self.assertEquals(lines[3], b"") + self.assertEqual(lines[2], b".") + self.assertEqual(lines[3], b"") # Break the password with a leading A on the challenge ntlm_cmds[0] = "LANMAN-Challenge: A123456789abcdef" @@ -247,7 +247,7 @@ class NTLMAuthHelpersTests(NTLMAuthTestCase): lines = out.split(b"\n") self.assertEqual(len(lines), 5) - self.assertEquals(lines[0], b"Authenticated: No") + self.assertEqual(lines[0], b"Authenticated: No") def test_ntlm_server_1_with_plaintext_winbind(self): """ ntlm_auth ntlm-server-1 with plaintext password against winbind """ @@ -270,9 +270,9 @@ class NTLMAuthHelpersTests(NTLMAuthTestCase): lines = out.split(b"\n") self.assertEqual(len(lines), 3) - self.assertEquals(lines[0], b"Authenticated: Yes") - self.assertEquals(lines[1], b".") - self.assertEquals(lines[2], b"") + self.assertEqual(lines[0], b"Authenticated: Yes") + self.assertEqual(lines[1], b".") + self.assertEqual(lines[2], b"") # Check membership failure @@ -287,9 +287,9 @@ class NTLMAuthHelpersTests(NTLMAuthTestCase): lines = out.split(b"\n") self.assertEqual(len(lines), 3) - self.assertEquals(lines[0], b"Authenticated: No") - self.assertEquals(lines[1], b".") - self.assertEquals(lines[2], b"") + self.assertEqual(lines[0], b"Authenticated: No") + self.assertEqual(lines[1], b".") + self.assertEqual(lines[2], b"") def test_ntlm_server_1_with_incorrect_password_winbind(self): """ ntlm_auth ntlm-server-1 with incorrect fixed password against @@ -313,7 +313,7 @@ class NTLMAuthHelpersTests(NTLMAuthTestCase): lines = out.split(b"\n") self.assertEqual(len(lines), 5) - self.assertEquals(lines[0], b"Authenticated: No") + self.assertEqual(lines[0], b"Authenticated: No") def test_diagnostics(self): """ ntlm_auth diagnostics """ diff --git a/python/samba/tests/param.py b/python/samba/tests/param.py index 43a3452396b..0a7f86adad7 100644 --- a/python/samba/tests/param.py +++ b/python/samba/tests/param.py @@ -39,12 +39,12 @@ class LoadParmTestCase(samba.tests.TestCaseInTempDir): def test_length(self): file = param.LoadParm() - self.assertEquals(0, len(file)) + self.assertEqual(0, len(file)) def test_set_workgroup(self): file = param.LoadParm() file.set("workgroup", "bla") - self.assertEquals("BLA", file.get("workgroup")) + self.assertEqual("BLA", file.get("workgroup")) def test_is_mydomain(self): file = param.LoadParm() @@ -70,16 +70,16 @@ class LoadParmTestCase(samba.tests.TestCaseInTempDir): def test_log_level(self): samba_lp = param.LoadParm() samba_lp.set("log level", "5 auth:4") - self.assertEquals(5, samba_lp.log_level()) + self.assertEqual(5, samba_lp.log_level()) def test_dump(self): samba_lp = param.LoadParm() # Just test successfull method execution (outputs to stdout) - self.assertEquals(None, samba_lp.dump()) + self.assertEqual(None, samba_lp.dump()) def test_dump_to_file(self): samba_lp = param.LoadParm() - self.assertEquals(None, samba_lp.dump(False, self.tempf)) + self.assertEqual(None, samba_lp.dump(False, self.tempf)) content = open(self.tempf, 'r').read() self.assertIn('[global]', content) self.assertIn('interfaces', content) @@ -88,12 +88,12 @@ class LoadParmTestCase(samba.tests.TestCaseInTempDir): samba_lp = param.LoadParm() samba_lp.load_default() # Just test successfull method execution - self.assertEquals(None, samba_lp.dump_a_parameter('interfaces')) + self.assertEqual(None, samba_lp.dump_a_parameter('interfaces')) def test_dump_a_parameter_to_file(self): samba_lp = param.LoadParm() samba_lp.load_default() - self.assertEquals(None, + self.assertEqual(None, samba_lp.dump_a_parameter('interfaces', 'global', self.tempf)) diff --git a/python/samba/tests/password_hash.py b/python/samba/tests/password_hash.py index 9892c3238a3..ec50b2b3f2e 100644 --- a/python/samba/tests/password_hash.py +++ b/python/samba/tests/password_hash.py @@ -165,13 +165,13 @@ class PassWordHashTests(TestCase): error = "Digest expected[%s], actual[%s], " \ "user[%s], realm[%s], pass[%s]" % \ (expected, actual, user, realm, password) - self.assertEquals(expected, actual, error) + self.assertEqual(expected, actual, error) # Check all of the 29 expected WDigest values # def check_wdigests(self, digests): - self.assertEquals(29, digests.num_hashes) + self.assertEqual(29, digests.num_hashes) # Using the n-1 pattern in the array indexes to make it easier # to check the tests against the spec and the samba-tool user tests. @@ -306,15 +306,15 @@ class PassWordHashTests(TestCase): def checkUserPassword(self, up, expected): # Check we've received the correct number of hashes - self.assertEquals(len(expected), up.num_hashes) + self.assertEqual(len(expected), up.num_hashes) i = 0 for (tag, alg, rounds) in expected: - self.assertEquals(tag, up.hashes[i].scheme) + self.assertEqual(tag, up.hashes[i].scheme) data = up.hashes[i].value.decode('utf8').split("$") # Check we got the expected crypt algorithm - self.assertEquals(alg, data[1]) + self.assertEqual(alg, data[1]) if rounds is None: cmd = "$%s$%s" % (alg, data[2]) @@ -323,7 +323,7 @@ class PassWordHashTests(TestCase): # Calculate the expected hash value expected = crypt.crypt(USER_PASS, cmd) - self.assertEquals(expected, up.hashes[i].value.decode('utf8')) + self.assertEqual(expected, up.hashes[i].value.decode('utf8')) i += 1 # Check that the correct nt_hash was stored for userPassword @@ -333,4 +333,4 @@ class PassWordHashTests(TestCase): creds.set_password(password) expected = creds.get_nt_hash() actual = bytearray(nt_hash) - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) diff --git a/python/samba/tests/password_hash_fl2003.py b/python/samba/tests/password_hash_fl2003.py index ab99b3b1823..c412a0676e6 100644 --- a/python/samba/tests/password_hash_fl2003.py +++ b/python/samba/tests/password_hash_fl2003.py @@ -49,19 +49,19 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(3, size) + self.assertEqual(3, size) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(2, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(2, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", package.name) # Check that the WDigest values are correct. # @@ -78,23 +78,23 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(4, size) + self.assertEqual(4, size) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(2, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(3, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(3, pos) + self.assertEqual("Packages", package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(4, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:userPassword", up_package.name) # Check that the WDigest values are correct. # @@ -119,23 +119,23 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(4, size) + self.assertEqual(4, size) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(2, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(3, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(3, pos) + self.assertEqual("Packages", package.name) (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") - self.assertEquals(4, pos) - self.assertEquals("Primary:CLEARTEXT", ct_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:CLEARTEXT", ct_package.name) # Check that the WDigest values are correct. # @@ -146,7 +146,7 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check the clear text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + self.assertEqual(USER_PASS.encode('utf-16-le'), ct.cleartext) def test_userPassword_cleartext_sha512(self): self.add_user(clear_text=True, @@ -158,27 +158,27 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(5, size) + self.assertEqual(5, size) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(2, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") - self.assertEquals(3, pos) - self.assertEquals("Primary:CLEARTEXT", ct_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:CLEARTEXT", ct_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(4, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(4, pos) + self.assertEqual("Packages", package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(5, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(5, pos) + self.assertEqual("Primary:userPassword", up_package.name) # Check that the WDigest values are correct. # @@ -189,7 +189,7 @@ class PassWordHashFl2003Tests(PassWordHashTests): # Check the clear text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + self.assertEqual(USER_PASS.encode('utf-16-le'), ct.cleartext) # Check that the userPassword hashes are computed correctly # diff --git a/python/samba/tests/password_hash_fl2008.py b/python/samba/tests/password_hash_fl2008.py index 685c73edaf2..a43ac3f815b 100644 --- a/python/samba/tests/password_hash_fl2008.py +++ b/python/samba/tests/password_hash_fl2008.py @@ -48,22 +48,22 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(4, size) + self.assertEqual(4, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(3, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(3, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:WDigest") - self.assertEquals(4, pos) - self.assertEquals("Primary:WDigest", package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:WDigest", package.name) # Check that the WDigest values are correct. # @@ -80,27 +80,27 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(5, size) + self.assertEqual(5, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wp_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wp_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wp_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(4, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(4, pos) + self.assertEqual("Packages", package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(5, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(5, pos) + self.assertEqual("Primary:userPassword", up_package.name) # Check that the WDigest values are correct. # @@ -123,26 +123,26 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(5, size) + self.assertEqual(5, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(4, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(4, pos) + self.assertEqual("Packages", package.name) (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") - self.assertEquals(5, pos) - self.assertEquals("Primary:CLEARTEXT", ct_package.name) + self.assertEqual(5, pos) + self.assertEqual("Primary:CLEARTEXT", ct_package.name) # Check that the WDigest values are correct. # @@ -153,7 +153,7 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check the clear text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + self.assertEqual(USER_PASS.encode('utf-16-le'), ct.cleartext) def test_userPassword_cleartext_sha256(self): self.add_user(clear_text=True, @@ -165,31 +165,31 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(6, size) + self.assertEqual(6, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") - self.assertEquals(4, pos) - self.assertEquals("Primary:CLEARTEXT", ct_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:CLEARTEXT", ct_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(5, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(5, pos) + self.assertEqual("Packages", package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(6, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(6, pos) + self.assertEqual("Primary:userPassword", up_package.name) # Check that the WDigest values are correct. # @@ -200,7 +200,7 @@ class PassWordHashFl2008Tests(PassWordHashTests): # Check the clear text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + self.assertEqual(USER_PASS.encode('utf-16-le'), ct.cleartext) # Check that the userPassword hashes are computed correctly # diff --git a/python/samba/tests/password_hash_gpgme.py b/python/samba/tests/password_hash_gpgme.py index 42cd71d3e08..16247bc3451 100644 --- a/python/samba/tests/password_hash_gpgme.py +++ b/python/samba/tests/password_hash_gpgme.py @@ -54,26 +54,26 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(5, size) + self.assertEqual(5, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(4, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(4, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:SambaGPG") - self.assertEquals(5, pos) - self.assertEquals("Primary:SambaGPG", package.name) + self.assertEqual(5, pos) + self.assertEqual("Primary:SambaGPG", package.name) # Check that the WDigest values are correct. # @@ -92,30 +92,30 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(6, size) + self.assertEqual(6, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wd_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wd_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wd_package.name) (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") - self.assertEquals(4, pos) - self.assertEquals("Primary:CLEARTEXT", ct_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:CLEARTEXT", ct_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(5, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(5, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:SambaGPG") - self.assertEquals(6, pos) - self.assertEquals("Primary:SambaGPG", package.name) + self.assertEqual(6, pos) + self.assertEqual("Primary:SambaGPG", package.name) # Check that the WDigest values are correct. # @@ -126,7 +126,7 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check the clear text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + self.assertEqual(USER_PASS.encode('utf-16-le'), ct.cleartext) def assert_cleartext(self, expect_cleartext, password=None): """Checks cleartext is (or isn't) returned as expected""" @@ -138,7 +138,7 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check the clear-text value is correct. ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, binascii.a2b_hex(ct_package.data)) - self.assertEquals(password.encode('utf-16-le'), ct.cleartext) + self.assertEqual(password.encode('utf-16-le'), ct.cleartext) else: ct_package = get_package(sc, "Primary:CLEARTEXT") self.assertTrue(ct_package is None, @@ -199,31 +199,31 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(6, size) + self.assertEqual(6, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wp_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wp_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wp_package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(4, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:userPassword", up_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(5, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(5, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:SambaGPG") - self.assertEquals(6, pos) - self.assertEquals("Primary:SambaGPG", package.name) + self.assertEqual(6, pos) + self.assertEqual("Primary:SambaGPG", package.name) # Check that the WDigest values are correct. # @@ -252,31 +252,31 @@ class PassWordHashGpgmeTests(PassWordHashTests): # Check that we got all the expected supplemental credentials # And they are in the expected order. size = len(sc.sub.packages) - self.assertEquals(6, size) + self.assertEqual(6, size) (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys") - self.assertEquals(1, pos) - self.assertEquals("Primary:Kerberos-Newer-Keys", package.name) + self.assertEqual(1, pos) + self.assertEqual("Primary:Kerberos-Newer-Keys", package.name) (pos, package) = get_package(sc, "Primary:Kerberos") - self.assertEquals(2, pos) - self.assertEquals("Primary:Kerberos", package.name) + self.assertEqual(2, pos) + self.assertEqual("Primary:Kerberos", package.name) (pos, wp_package) = get_package(sc, "Primary:WDigest") - self.assertEquals(3, pos) - self.assertEquals("Primary:WDigest", wp_package.name) + self.assertEqual(3, pos) + self.assertEqual("Primary:WDigest", wp_package.name) (pos, up_package) = get_package(sc, "Primary:userPassword") - self.assertEquals(4, pos) - self.assertEquals("Primary:userPassword", up_package.name) + self.assertEqual(4, pos) + self.assertEqual("Primary:userPassword", up_package.name) (pos, package) = get_package(sc, "Packages") - self.assertEquals(5, pos) - self.assertEquals("Packages", package.name) + self.assertEqual(5, pos) + self.assertEqual("Packages", package.name) (pos, package) = get_package(sc, "Primary:SambaGPG") - self.assertEquals(6, pos) - self.assertEquals("Primary:SambaGPG", package.name) + self.assertEqual(6, pos) + self.assertEqual("Primary:SambaGPG", package.name) # Check that the WDigest values are correct. # diff --git a/python/samba/tests/password_hash_ldap.py b/python/samba/tests/password_hash_ldap.py index 5bb407e0906..4d6904b455b 100644 --- a/python/samba/tests/password_hash_ldap.py +++ b/python/samba/tests/password_hash_ldap.py @@ -125,7 +125,7 @@ class PassWordHashLDAPTests(PassWordHashTests): sc = self.get_supplemental_creds_drs() (pos, package) = get_package(sc, "Primary:WDigest") - self.assertEquals("Primary:WDigest", package.name) + self.assertEqual("Primary:WDigest", package.name) # Check that the WDigest values are correct. # diff --git a/python/samba/tests/policy.py b/python/samba/tests/policy.py index 538efcd95b0..4029150c752 100644 --- a/python/samba/tests/policy.py +++ b/python/samba/tests/policy.py @@ -26,9 +26,9 @@ from samba import policy class PolicyTests(TestCase): def test_get_gpo_flags(self): - self.assertEquals(["GPO_FLAG_USER_DISABLE"], + self.assertEqual(["GPO_FLAG_USER_DISABLE"], policy.get_gpo_flags(policy.GPO_FLAG_USER_DISABLE)) def test_get_gplink_options(self): - self.assertEquals(["GPLINK_OPT_DISABLE"], + self.assertEqual(["GPLINK_OPT_DISABLE"], policy.get_gplink_options(policy.GPLINK_OPT_DISABLE)) diff --git a/python/samba/tests/posixacl.py b/python/samba/tests/posixacl.py index f2734f54120..9f60b297c9b 100644 --- a/python/samba/tests/posixacl.py +++ b/python/samba/tests/posixacl.py @@ -78,7 +78,7 @@ class PosixAclMappingTests(SmbdBaseTests): self.get_session_info(), use_ntvfs=True) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=True) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(anysid), acl) + self.assertEqual(facl.as_sddl(anysid), acl) def test_setntacl_smbd_setposixacl_getntacl(self): acl = ACL @@ -105,7 +105,7 @@ class PosixAclMappingTests(SmbdBaseTests): # however, as this is direct DB access, we do not notice it facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=True) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(acl, facl.as_sddl(anysid)) + self.assertEqual(acl, facl.as_sddl(anysid)) def test_setntacl_invalidate_getntacl_smbd(self): acl = ACL @@ -120,7 +120,7 @@ class PosixAclMappingTests(SmbdBaseTests): # the hash would break, and we return an ACL based only on the mode, except we set the ACL using the 'ntvfs' mode that doesn't include a hash facl = getntacl(self.lp, self.tempf, self.get_session_info()) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(acl, facl.as_sddl(anysid)) + self.assertEqual(acl, facl.as_sddl(anysid)) def test_setntacl_smbd_invalidate_getntacl_smbd(self): acl = ACL @@ -137,7 +137,7 @@ class PosixAclMappingTests(SmbdBaseTests): # the hash will break, and we return an ACL based only on the mode facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid)) + self.assertEqual(simple_acl_from_posix, facl.as_sddl(anysid)) def test_setntacl_getntacl_smbd(self): acl = ACL @@ -145,7 +145,7 @@ class PosixAclMappingTests(SmbdBaseTests): self.get_session_info(), use_ntvfs=True) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(anysid), acl) + self.assertEqual(facl.as_sddl(anysid), acl) def test_setntacl_smbd_getntacl_smbd(self): acl = ACL @@ -153,7 +153,7 @@ class PosixAclMappingTests(SmbdBaseTests): self.get_session_info(), use_ntvfs=False) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(anysid), acl) + self.assertEqual(facl.as_sddl(anysid), acl) def test_setntacl_smbd_setposixacl_getntacl_smbd(self): acl = ACL @@ -164,7 +164,7 @@ class PosixAclMappingTests(SmbdBaseTests): smbd.set_simple_acl(self.tempf, 0o640, self.get_session_info()) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid)) + self.assertEqual(simple_acl_from_posix, facl.as_sddl(anysid)) def test_setntacl_smbd_setposixacl_group_getntacl_smbd(self): acl = ACL @@ -180,7 +180,7 @@ class PosixAclMappingTests(SmbdBaseTests): # This should re-calculate an ACL based on the posix details facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid)) + self.assertEqual(simple_acl_from_posix, facl.as_sddl(anysid)) def test_setntacl_smbd_getntacl_smbd_gpo(self): acl = "O:DAG:DUD:P(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;EA)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" @@ -188,7 +188,7 @@ class PosixAclMappingTests(SmbdBaseTests): self.get_session_info(), use_ntvfs=False) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) domsid = security.dom_sid(DOM_SID) - self.assertEquals(facl.as_sddl(domsid), acl) + self.assertEqual(facl.as_sddl(domsid), acl) def test_setntacl_getposixacl(self): acl = ACL @@ -196,7 +196,7 @@ class PosixAclMappingTests(SmbdBaseTests): self.get_session_info(), use_ntvfs=False) facl = getntacl(self.lp, self.tempf, self.get_session_info()) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(facl.as_sddl(anysid), acl) + self.assertEqual(facl.as_sddl(anysid), acl) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS, self.get_session_info()) def test_setposixacl_getntacl(self): @@ -212,7 +212,7 @@ class PosixAclMappingTests(SmbdBaseTests): facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) acl = "O:%sG:%sD:(A;;0x001f019f;;;%s)(A;;0x00120089;;;%s)(A;;;;;WD)" % (user_SID, group_SID, user_SID, group_SID) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(acl, facl.as_sddl(anysid)) + self.assertEqual(acl, facl.as_sddl(anysid)) def test_setposixacl_dir_getntacl_smbd(self): s4_passdb = passdb.PDB(self.lp.get("passdb backend")) @@ -220,17 +220,17 @@ class PosixAclMappingTests(SmbdBaseTests): BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_id, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) SO_sid = security.dom_sid(security.SID_BUILTIN_SERVER_OPERATORS) (SO_id, SO_type) = s4_passdb.sid_to_id(SO_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) smbd.chown(self.tempdir, BA_id, SO_id, self.get_session_info()) smbd.set_simple_acl(self.tempdir, 0o750, self.get_session_info()) facl = getntacl(self.lp, self.tempdir, self.get_session_info(), direct_db_access=False) acl = "O:BAG:SOD:(A;;0x001f01ff;;;BA)(A;;0x001200a9;;;SO)(A;;;;;WD)(A;OICIIO;0x001f01ff;;;CO)(A;OICIIO;0x001200a9;;;CG)(A;OICIIO;0x001200a9;;;WD)" anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(acl, facl.as_sddl(anysid)) + self.assertEqual(acl, facl.as_sddl(anysid)) def test_setposixacl_group_getntacl_smbd(self): BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) @@ -238,73 +238,73 @@ class PosixAclMappingTests(SmbdBaseTests): (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) group_SID = s4_passdb.gid_to_sid(os.stat(self.tempf).st_gid) user_SID = s4_passdb.uid_to_sid(os.stat(self.tempf).st_uid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) smbd.set_simple_acl(self.tempf, 0o640, self.get_session_info(), BA_gid) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) domsid = passdb.get_global_sam_sid() acl = "O:%sG:%sD:(A;;0x001f019f;;;%s)(A;;0x00120089;;;BA)(A;;0x00120089;;;%s)(A;;;;;WD)" % (user_SID, group_SID, user_SID, group_SID) anysid = security.dom_sid(security.SID_NT_SELF) - self.assertEquals(acl, facl.as_sddl(anysid)) + self.assertEqual(acl, facl.as_sddl(anysid)) def test_setposixacl_getposixacl(self): smbd.set_simple_acl(self.tempf, 0o640, self.get_session_info()) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS, self.get_session_info()) - self.assertEquals(posix_acl.count, 4, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 4, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) - self.assertEquals(posix_acl.acl[0].a_perm, 6) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[0].a_perm, 6) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[1].a_perm, 4) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[1].a_perm, 4) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[3].a_perm, 7) def test_setposixacl_dir_getposixacl(self): smbd.set_simple_acl(self.tempdir, 0o750, self.get_session_info()) posix_acl = smbd.get_sys_acl(self.tempdir, smb_acl.SMB_ACL_TYPE_ACCESS, self.get_session_info()) - self.assertEquals(posix_acl.count, 4, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 4, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) - self.assertEquals(posix_acl.acl[0].a_perm, 7) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[0].a_perm, 7) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[1].a_perm, 5) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[1].a_perm, 5) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[3].a_perm, 7) def test_setposixacl_group_getposixacl(self): BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) smbd.set_simple_acl(self.tempf, 0o670, self.get_session_info(), BA_gid) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS, self.get_session_info()) - self.assertEquals(posix_acl.count, 5, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 5, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) - self.assertEquals(posix_acl.acl[0].a_perm, 6) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[0].a_perm, 6) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[1].a_perm, 7) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[1].a_perm, 7) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[3].a_perm, 7) - self.assertEquals(posix_acl.acl[3].info.gid, BA_gid) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].info.gid, BA_gid) - self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[4].a_perm, 7) + self.assertEqual(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[4].a_perm, 7) def test_setntacl_sysvol_check_getposixacl(self): acl = provision.SYSVOL_ACL @@ -313,7 +313,7 @@ class PosixAclMappingTests(SmbdBaseTests): setntacl(self.lp, self.tempf, acl, str(domsid), session_info, use_ntvfs=False) facl = getntacl(self.lp, self.tempf, session_info) - self.assertEquals(facl.as_sddl(domsid), acl) + self.assertEqual(facl.as_sddl(domsid), acl) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS, session_info) nwrap_module_so_path = os.getenv('NSS_WRAPPER_MODULE_SO_PATH') @@ -335,71 +335,71 @@ class PosixAclMappingTests(SmbdBaseTests): # configuration. When other environments have a broad range of # groups mapped via passdb, we can relax some of these checks (LA_uid, LA_type) = s4_passdb.sid_to_id(LA_sid) - self.assertEquals(LA_type, idmap.ID_TYPE_UID) + self.assertEqual(LA_type, idmap.ID_TYPE_UID) (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) (SO_gid, SO_type) = s4_passdb.sid_to_id(SO_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (SY_gid, SY_type) = s4_passdb.sid_to_id(SY_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (AU_gid, AU_type) = s4_passdb.sid_to_id(AU_sid) - self.assertEquals(AU_type, idmap.ID_TYPE_BOTH) + self.assertEqual(AU_type, idmap.ID_TYPE_BOTH) - self.assertEquals(posix_acl.count, 13, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 13, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[0].a_perm, 7) - self.assertEquals(posix_acl.acl[0].info.gid, BA_gid) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[0].a_perm, 7) + self.assertEqual(posix_acl.acl[0].info.gid, BA_gid) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) if nwrap_winbind_active or is_user_session: - self.assertEquals(posix_acl.acl[1].a_perm, 7) + self.assertEqual(posix_acl.acl[1].a_perm, 7) else: - self.assertEquals(posix_acl.acl[1].a_perm, 6) - self.assertEquals(posix_acl.acl[1].info.uid, LA_uid) + self.assertEqual(posix_acl.acl[1].a_perm, 6) + self.assertEqual(posix_acl.acl[1].info.uid, LA_uid) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) if nwrap_winbind_active or is_user_session: - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_perm, 7) else: - self.assertEquals(posix_acl.acl[3].a_perm, 6) + self.assertEqual(posix_acl.acl[3].a_perm, 6) - self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[4].a_perm, 7) - self.assertEquals(posix_acl.acl[4].info.uid, BA_gid) + self.assertEqual(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[4].a_perm, 7) + self.assertEqual(posix_acl.acl[4].info.uid, BA_gid) - self.assertEquals(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[5].a_perm, 7) + self.assertEqual(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[5].a_perm, 7) - self.assertEquals(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[6].a_perm, 5) - self.assertEquals(posix_acl.acl[6].info.uid, SO_gid) + self.assertEqual(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[6].a_perm, 5) + self.assertEqual(posix_acl.acl[6].info.uid, SO_gid) - self.assertEquals(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[7].a_perm, 5) - self.assertEquals(posix_acl.acl[7].info.gid, SO_gid) + self.assertEqual(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[7].a_perm, 5) + self.assertEqual(posix_acl.acl[7].info.gid, SO_gid) - self.assertEquals(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[8].a_perm, 7) - self.assertEquals(posix_acl.acl[8].info.uid, SY_gid) + self.assertEqual(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[8].a_perm, 7) + self.assertEqual(posix_acl.acl[8].info.uid, SY_gid) - self.assertEquals(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[9].a_perm, 7) - self.assertEquals(posix_acl.acl[9].info.gid, SY_gid) + self.assertEqual(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[9].a_perm, 7) + self.assertEqual(posix_acl.acl[9].info.gid, SY_gid) - self.assertEquals(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[10].a_perm, 5) - self.assertEquals(posix_acl.acl[10].info.uid, AU_gid) + self.assertEqual(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[10].a_perm, 5) + self.assertEqual(posix_acl.acl[10].info.uid, AU_gid) - self.assertEquals(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[11].a_perm, 5) - self.assertEquals(posix_acl.acl[11].info.gid, AU_gid) + self.assertEqual(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[11].a_perm, 5) + self.assertEqual(posix_acl.acl[11].info.gid, AU_gid) - self.assertEquals(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[12].a_perm, 7) + self.assertEqual(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[12].a_perm, 7) # check that it matches: # user::rwx @@ -457,7 +457,7 @@ class PosixAclMappingTests(SmbdBaseTests): setntacl(self.lp, self.tempdir, acl, str(domsid), session_info, use_ntvfs=False) facl = getntacl(self.lp, self.tempdir, session_info) - self.assertEquals(facl.as_sddl(domsid), acl) + self.assertEqual(facl.as_sddl(domsid), acl) posix_acl = smbd.get_sys_acl(self.tempdir, smb_acl.SMB_ACL_TYPE_ACCESS, session_info) LA_sid = security.dom_sid(str(domsid) + "-" + str(security.DOMAIN_RID_ADMINISTRATOR)) @@ -472,65 +472,65 @@ class PosixAclMappingTests(SmbdBaseTests): # configuration. When other environments have a broad range of # groups mapped via passdb, we can relax some of these checks (LA_uid, LA_type) = s4_passdb.sid_to_id(LA_sid) - self.assertEquals(LA_type, idmap.ID_TYPE_UID) + self.assertEqual(LA_type, idmap.ID_TYPE_UID) (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) (SO_gid, SO_type) = s4_passdb.sid_to_id(SO_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (SY_gid, SY_type) = s4_passdb.sid_to_id(SY_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (AU_gid, AU_type) = s4_passdb.sid_to_id(AU_sid) - self.assertEquals(AU_type, idmap.ID_TYPE_BOTH) + self.assertEqual(AU_type, idmap.ID_TYPE_BOTH) - self.assertEquals(posix_acl.count, 13, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 13, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[0].a_perm, 7) - self.assertEquals(posix_acl.acl[0].info.gid, BA_gid) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[0].a_perm, 7) + self.assertEqual(posix_acl.acl[0].info.gid, BA_gid) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[1].a_perm, 7) - self.assertEquals(posix_acl.acl[1].info.uid, LA_uid) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[1].a_perm, 7) + self.assertEqual(posix_acl.acl[1].info.uid, LA_uid) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[3].a_perm, 7) - self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[4].a_perm, 7) - self.assertEquals(posix_acl.acl[4].info.uid, BA_gid) + self.assertEqual(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[4].a_perm, 7) + self.assertEqual(posix_acl.acl[4].info.uid, BA_gid) - self.assertEquals(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[5].a_perm, 7) + self.assertEqual(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[5].a_perm, 7) - self.assertEquals(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[6].a_perm, 5) - self.assertEquals(posix_acl.acl[6].info.uid, SO_gid) + self.assertEqual(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[6].a_perm, 5) + self.assertEqual(posix_acl.acl[6].info.uid, SO_gid) - self.assertEquals(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[7].a_perm, 5) - self.assertEquals(posix_acl.acl[7].info.gid, SO_gid) + self.assertEqual(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[7].a_perm, 5) + self.assertEqual(posix_acl.acl[7].info.gid, SO_gid) - self.assertEquals(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[8].a_perm, 7) - self.assertEquals(posix_acl.acl[8].info.uid, SY_gid) + self.assertEqual(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[8].a_perm, 7) + self.assertEqual(posix_acl.acl[8].info.uid, SY_gid) - self.assertEquals(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[9].a_perm, 7) - self.assertEquals(posix_acl.acl[9].info.gid, SY_gid) + self.assertEqual(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[9].a_perm, 7) + self.assertEqual(posix_acl.acl[9].info.gid, SY_gid) - self.assertEquals(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[10].a_perm, 5) - self.assertEquals(posix_acl.acl[10].info.uid, AU_gid) + self.assertEqual(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[10].a_perm, 5) + self.assertEqual(posix_acl.acl[10].info.uid, AU_gid) - self.assertEquals(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[11].a_perm, 5) - self.assertEquals(posix_acl.acl[11].info.gid, AU_gid) + self.assertEqual(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[11].a_perm, 5) + self.assertEqual(posix_acl.acl[11].info.gid, AU_gid) - self.assertEquals(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[12].a_perm, 7) + self.assertEqual(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[12].a_perm, 7) # check that it matches: # user::rwx @@ -550,7 +550,7 @@ class PosixAclMappingTests(SmbdBaseTests): setntacl(self.lp, self.tempdir, acl, str(domsid), session_info, use_ntvfs=False) facl = getntacl(self.lp, self.tempdir, session_info) - self.assertEquals(facl.as_sddl(domsid), acl) + self.assertEqual(facl.as_sddl(domsid), acl) posix_acl = smbd.get_sys_acl(self.tempdir, smb_acl.SMB_ACL_TYPE_ACCESS, session_info) LA_sid = security.dom_sid(str(domsid) + "-" + str(security.DOMAIN_RID_ADMINISTRATOR)) @@ -566,75 +566,75 @@ class PosixAclMappingTests(SmbdBaseTests): # configuration. When other environments have a broad range of # groups mapped via passdb, we can relax some of these checks (LA_uid, LA_type) = s4_passdb.sid_to_id(LA_sid) - self.assertEquals(LA_type, idmap.ID_TYPE_UID) + self.assertEqual(LA_type, idmap.ID_TYPE_UID) (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) (SO_gid, SO_type) = s4_passdb.sid_to_id(SO_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (SY_gid, SY_type) = s4_passdb.sid_to_id(SY_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (AU_gid, AU_type) = s4_passdb.sid_to_id(AU_sid) - self.assertEquals(AU_type, idmap.ID_TYPE_BOTH) + self.assertEqual(AU_type, idmap.ID_TYPE_BOTH) (PA_gid, PA_type) = s4_passdb.sid_to_id(PA_sid) - self.assertEquals(PA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(PA_type, idmap.ID_TYPE_BOTH) - self.assertEquals(posix_acl.count, 15, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 15, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[0].a_perm, 7) - self.assertEquals(posix_acl.acl[0].info.gid, BA_gid) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[0].a_perm, 7) + self.assertEqual(posix_acl.acl[0].info.gid, BA_gid) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[1].a_perm, 7) - self.assertEquals(posix_acl.acl[1].info.uid, LA_uid) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[1].a_perm, 7) + self.assertEqual(posix_acl.acl[1].info.uid, LA_uid) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[3].a_perm, 7) - self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[4].a_perm, 7) - self.assertEquals(posix_acl.acl[4].info.uid, BA_gid) + self.assertEqual(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[4].a_perm, 7) + self.assertEqual(posix_acl.acl[4].info.uid, BA_gid) - self.assertEquals(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[5].a_perm, 7) + self.assertEqual(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[5].a_perm, 7) - self.assertEquals(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[6].a_perm, 5) - self.assertEquals(posix_acl.acl[6].info.uid, SO_gid) + self.assertEqual(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[6].a_perm, 5) + self.assertEqual(posix_acl.acl[6].info.uid, SO_gid) - self.assertEquals(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[7].a_perm, 5) - self.assertEquals(posix_acl.acl[7].info.gid, SO_gid) + self.assertEqual(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[7].a_perm, 5) + self.assertEqual(posix_acl.acl[7].info.gid, SO_gid) - self.assertEquals(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[8].a_perm, 7) - self.assertEquals(posix_acl.acl[8].info.uid, SY_gid) + self.assertEqual(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[8].a_perm, 7) + self.assertEqual(posix_acl.acl[8].info.uid, SY_gid) - self.assertEquals(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[9].a_perm, 7) - self.assertEquals(posix_acl.acl[9].info.gid, SY_gid) + self.assertEqual(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[9].a_perm, 7) + self.assertEqual(posix_acl.acl[9].info.gid, SY_gid) - self.assertEquals(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[10].a_perm, 5) - self.assertEquals(posix_acl.acl[10].info.uid, AU_gid) + self.assertEqual(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[10].a_perm, 5) + self.assertEqual(posix_acl.acl[10].info.uid, AU_gid) - self.assertEquals(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[11].a_perm, 5) - self.assertEquals(posix_acl.acl[11].info.gid, AU_gid) + self.assertEqual(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[11].a_perm, 5) + self.assertEqual(posix_acl.acl[11].info.gid, AU_gid) - self.assertEquals(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[12].a_perm, 7) - self.assertEquals(posix_acl.acl[12].info.uid, PA_gid) + self.assertEqual(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[12].a_perm, 7) + self.assertEqual(posix_acl.acl[12].info.uid, PA_gid) - self.assertEquals(posix_acl.acl[13].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[13].a_perm, 7) - self.assertEquals(posix_acl.acl[13].info.gid, PA_gid) + self.assertEqual(posix_acl.acl[13].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[13].a_perm, 7) + self.assertEqual(posix_acl.acl[13].info.gid, PA_gid) - self.assertEquals(posix_acl.acl[14].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[14].a_perm, 7) + self.assertEqual(posix_acl.acl[14].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[14].a_perm, 7) # check that it matches: # user::rwx @@ -656,7 +656,7 @@ class PosixAclMappingTests(SmbdBaseTests): setntacl(self.lp, self.tempf, acl, str(domsid), session_info, use_ntvfs=False) facl = getntacl(self.lp, self.tempf, session_info) - self.assertEquals(facl.as_sddl(domsid), acl) + self.assertEqual(facl.as_sddl(domsid), acl) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS, session_info) nwrap_module_so_path = os.getenv('NSS_WRAPPER_MODULE_SO_PATH') @@ -679,81 +679,81 @@ class PosixAclMappingTests(SmbdBaseTests): # configuration. When other environments have a broad range of # groups mapped via passdb, we can relax some of these checks (LA_uid, LA_type) = s4_passdb.sid_to_id(LA_sid) - self.assertEquals(LA_type, idmap.ID_TYPE_UID) + self.assertEqual(LA_type, idmap.ID_TYPE_UID) (BA_gid, BA_type) = s4_passdb.sid_to_id(BA_sid) - self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(BA_type, idmap.ID_TYPE_BOTH) (SO_gid, SO_type) = s4_passdb.sid_to_id(SO_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (SY_gid, SY_type) = s4_passdb.sid_to_id(SY_sid) - self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) + self.assertEqual(SO_type, idmap.ID_TYPE_BOTH) (AU_gid, AU_type) = s4_passdb.sid_to_id(AU_sid) - self.assertEquals(AU_type, idmap.ID_TYPE_BOTH) + self.assertEqual(AU_type, idmap.ID_TYPE_BOTH) (PA_gid, PA_type) = s4_passdb.sid_to_id(PA_sid) - self.assertEquals(PA_type, idmap.ID_TYPE_BOTH) + self.assertEqual(PA_type, idmap.ID_TYPE_BOTH) - self.assertEquals(posix_acl.count, 15, self.print_posix_acl(posix_acl)) + self.assertEqual(posix_acl.count, 15, self.print_posix_acl(posix_acl)) - self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[0].a_perm, 7) - self.assertEquals(posix_acl.acl[0].info.gid, BA_gid) + self.assertEqual(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[0].a_perm, 7) + self.assertEqual(posix_acl.acl[0].info.gid, BA_gid) - self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_USER) if nwrap_winbind_active or is_user_session: - self.assertEquals(posix_acl.acl[1].a_perm, 7) + self.assertEqual(posix_acl.acl[1].a_perm, 7) else: - self.assertEquals(posix_acl.acl[1].a_perm, 6) - self.assertEquals(posix_acl.acl[1].info.uid, LA_uid) + self.assertEqual(posix_acl.acl[1].a_perm, 6) + self.assertEqual(posix_acl.acl[1].info.uid, LA_uid) - self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) - self.assertEquals(posix_acl.acl[2].a_perm, 0) + self.assertEqual(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) + self.assertEqual(posix_acl.acl[2].a_perm, 0) - self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) + self.assertEqual(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_USER_OBJ) if nwrap_winbind_active or is_user_session: - self.assertEquals(posix_acl.acl[3].a_perm, 7) + self.assertEqual(posix_acl.acl[3].a_perm, 7) else: - self.assertEquals(posix_acl.acl[3].a_perm, 6) + self.assertEqual(posix_acl.acl[3].a_perm, 6) - self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[4].a_perm, 7) - self.assertEquals(posix_acl.acl[4].info.uid, BA_gid) + self.assertEqual(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[4].a_perm, 7) + self.assertEqual(posix_acl.acl[4].info.uid, BA_gid) - self.assertEquals(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) - self.assertEquals(posix_acl.acl[5].a_perm, 7) + self.assertEqual(posix_acl.acl[5].a_type, smb_acl.SMB_ACL_GROUP_OBJ) + self.assertEqual(posix_acl.acl[5].a_perm, 7) - self.assertEquals(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[6].a_perm, 5) - self.assertEquals(posix_acl.acl[6].info.uid, SO_gid) + self.assertEqual(posix_acl.acl[6].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[6].a_perm, 5) + self.assertEqual(posix_acl.acl[6].info.uid, SO_gid) - self.assertEquals(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[7].a_perm, 5) - self.assertEquals(posix_acl.acl[7].info.gid, SO_gid) + self.assertEqual(posix_acl.acl[7].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[7].a_perm, 5) + self.assertEqual(posix_acl.acl[7].info.gid, SO_gid) - self.assertEquals(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[8].a_perm, 7) - self.assertEquals(posix_acl.acl[8].info.uid, SY_gid) + self.assertEqual(posix_acl.acl[8].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[8].a_perm, 7) + self.assertEqual(posix_acl.acl[8].info.uid, SY_gid) - self.assertEquals(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[9].a_perm, 7) - self.assertEquals(posix_acl.acl[9].info.gid, SY_gid) + self.assertEqual(posix_acl.acl[9].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[9].a_perm, 7) + self.assertEqual(posix_acl.acl[9].info.gid, SY_gid) - self.assertEquals(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[10].a_perm, 5) - self.assertEquals(posix_acl.acl[10].info.uid, AU_gid) + self.assertEqual(posix_acl.acl[10].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[10].a_perm, 5) + self.assertEqual(posix_acl.acl[10].info.uid, AU_gid) - self.assertEquals(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[11].a_perm, 5) - self.assertEquals(posix_acl.acl[11].info.gid, AU_gid) + self.assertEqual(posix_acl.acl[11].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[11].a_perm, 5) + self.assertEqual(posix_acl.acl[11].info.gid, AU_gid) - self.assertEquals(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_USER) - self.assertEquals(posix_acl.acl[12].a_perm, 7) - self.assertEquals(posix_acl.acl[12].info.uid, PA_gid) + self.assertEqual(posix_acl.acl[12].a_type, smb_acl.SMB_ACL_USER) + self.assertEqual(posix_acl.acl[12].a_perm, 7) + self.assertEqual(posix_acl.acl[12].info.uid, PA_gid) - self.assertEquals(posix_acl.acl[13].a_type, smb_acl.SMB_ACL_GROUP) - self.assertEquals(posix_acl.acl[13].a_perm, 7) - self.assertEquals(posix_acl.acl[13].info.gid, PA_gid) + self.assertEqual(posix_acl.acl[13].a_type, smb_acl.SMB_ACL_GROUP) + self.assertEqual(posix_acl.acl[13].a_perm, 7) + self.assertEqual(posix_acl.acl[13].info.gid, PA_gid) - self.assertEquals(posix_acl.acl[14].a_type, smb_acl.SMB_ACL_MASK) - self.assertEquals(posix_acl.acl[14].a_perm, 7) + self.assertEqual(posix_acl.acl[14].a_type, smb_acl.SMB_ACL_MASK) + self.assertEqual(posix_acl.acl[14].a_perm, 7) # check that it matches: # user::rwx diff --git a/python/samba/tests/prefork_restart.py b/python/samba/tests/prefork_restart.py index 9ab97d062b4..8557ae0d8d7 100644 --- a/python/samba/tests/prefork_restart.py +++ b/python/samba/tests/prefork_restart.py @@ -122,7 +122,7 @@ class PreforkProcessRestartTests(TestCase): def rpc_echo(self): conn = echo.rpcecho("ncalrpc:", self.get_loadparm()) - self.assertEquals([1, 2, 3], conn.EchoData([1, 2, 3])) + self.assertEqual([1, 2, 3], conn.EchoData([1, 2, 3])) def netlogon(self): server = os.environ["SERVER"] @@ -227,15 +227,15 @@ class PreforkProcessRestartTests(TestCase): self.assertIsNotNone(new_pid) # check that the pid has not changed - self.assertEquals(pid, new_pid) + self.assertEqual(pid, new_pid) # check that the worker processes have restarted new_workers = self.get_worker_pids("ldap", NUM_WORKERS) # process 0 should have a new pid the others should be unchanged self.assertNotEquals(workers[0], new_workers[0]) - self.assertEquals(workers[1], new_workers[1]) - self.assertEquals(workers[2], new_workers[2]) - self.assertEquals(workers[3], new_workers[3]) + self.assertEqual(workers[1], new_workers[1]) + self.assertEqual(workers[2], new_workers[2]) + self.assertEqual(workers[3], new_workers[3]) # check that the previous server entries have been removed. self.check_for_duplicate_processes() @@ -270,7 +270,7 @@ class PreforkProcessRestartTests(TestCase): self.assertIsNotNone(new_pid) # check that the pid has not changed - self.assertEquals(pid, new_pid) + self.assertEqual(pid, new_pid) # check that the worker processes have restarted new_workers = self.get_worker_pids("ldap", NUM_WORKERS) @@ -344,15 +344,15 @@ class PreforkProcessRestartTests(TestCase): self.assertIsNotNone(new_pid) # check that the pid has not changed - self.assertEquals(pid, new_pid) + self.assertEqual(pid, new_pid) # check that the worker processes have restarted new_workers = self.get_worker_pids("rpc", NUM_WORKERS) # process 0 should have a new pid the others should be unchanged self.assertNotEquals(workers[0], new_workers[0]) - self.assertEquals(workers[1], new_workers[1]) - self.assertEquals(workers[2], new_workers[2]) - self.assertEquals(workers[3], new_workers[3]) + self.assertEqual(workers[1], new_workers[1]) + self.assertEqual(workers[2], new_workers[2]) + self.assertEqual(workers[3], new_workers[3]) # check that the previous server entries have been removed. self.check_for_duplicate_processes() @@ -387,7 +387,7 @@ class PreforkProcessRestartTests(TestCase): self.assertIsNotNone(new_pid) # check that the pid has not changed - self.assertEquals(pid, new_pid) + self.assertEqual(pid, new_pid) # check that the worker processes have restarted new_workers = self.get_worker_pids("rpc", NUM_WORKERS) diff --git a/python/samba/tests/provision.py b/python/samba/tests/provision.py index f51098629d8..43ad373b2ca 100644 --- a/python/samba/tests/provision.py +++ b/python/samba/tests/provision.py @@ -66,7 +66,7 @@ class ProvisionTestCase(samba.tests.TestCaseInTempDir): paths.dns_keytab = "no.dns.keytab" ldb = setup_secretsdb(paths, None, None, lp=env_loadparm()) try: - self.assertEquals("LSA Secrets", + self.assertEqual("LSA Secrets", ldb.searchone(basedn="CN=LSA Secrets", attribute="CN").decode('utf8')) finally: del ldb @@ -84,14 +84,14 @@ class FindNssTests(TestCase): self.assertRaises(KeyError, findnss, x, []) def test_first(self): - self.assertEquals("bla", findnss(lambda x: "bla", ["bla"])) + self.assertEqual("bla", findnss(lambda x: "bla", ["bla"])) def test_skip_first(self): def x(y): if y != "bla": raise KeyError return "ha" - self.assertEquals("ha", findnss(x, ["bloe", "bla"])) + self.assertEqual("ha", findnss(x, ["bloe", "bla"])) class Disabled(object): @@ -124,22 +124,22 @@ class Disabled(object): class SanitizeServerRoleTests(TestCase): def test_same(self): - self.assertEquals("standalone server", + self.assertEqual("standalone server", sanitize_server_role("standalone server")) - self.assertEquals("member server", + self.assertEqual("member server", sanitize_server_role("member server")) def test_invalid(self): self.assertRaises(ValueError, sanitize_server_role, "foo") def test_valid(self): - self.assertEquals( + self.assertEqual( "standalone server", sanitize_server_role("ROLE_STANDALONE")) - self.assertEquals( + self.assertEqual( "standalone server", sanitize_server_role("standalone")) - self.assertEquals( + self.assertEqual( "active directory domain controller", sanitize_server_role("domain controller")) @@ -174,7 +174,7 @@ class ProvisionResultTests(TestCase): def test_basic_report_logger(self): result = self.base_result() entries = self.report_logger(result) - self.assertEquals(entries, [ + self.assertEqual(entries, [ ('INFO', 'Once the above files are installed, your Samba AD server ' 'will be ready to use'), ('INFO', 'Server Role: domain controller'), @@ -188,14 +188,14 @@ class ProvisionResultTests(TestCase): result.adminpass_generated = True result.adminpass = "geheim" entries = self.report_logger(result) - self.assertEquals(entries[1], + self.assertEqual(entries[1], ("INFO", 'Admin password: geheim')) class DetermineNetbiosNameTests(TestCase): def test_limits_to_15(self): - self.assertEquals("A" * 15, determine_netbios_name("a" * 30)) + self.assertEqual("A" * 15, determine_netbios_name("a" * 30)) def test_strips_invalid(self): - self.assertEquals("BLABLA", determine_netbios_name("bla/bla")) + self.assertEqual("BLABLA", determine_netbios_name("bla/bla")) diff --git a/python/samba/tests/registry.py b/python/samba/tests/registry.py index f6af5f7bd15..51b280a6348 100644 --- a/python/samba/tests/registry.py +++ b/python/samba/tests/registry.py @@ -27,11 +27,11 @@ from subprocess import Popen, PIPE class HelperTests(samba.tests.TestCase): def test_predef_to_name(self): - self.assertEquals("HKEY_LOCAL_MACHINE", + self.assertEqual("HKEY_LOCAL_MACHINE", registry.get_predef_name(0x80000002)) def test_str_regtype(self): - self.assertEquals("REG_DWORD", registry.str_regtype(4)) + self.assertEqual("REG_DWORD", registry.str_regtype(4)) class HiveTests(samba.tests.TestCaseInTempDir): diff --git a/python/samba/tests/s3idmapdb.py b/python/samba/tests/s3idmapdb.py index e3e23469493..b8d936f056f 100644 --- a/python/samba/tests/s3idmapdb.py +++ b/python/samba/tests/s3idmapdb.py @@ -35,22 +35,22 @@ class IdmapDbTestCase(TestCase): "winbindd_idmap")) def test_user_hwm(self): - self.assertEquals(10000, self.idmapdb.get_user_hwm()) + self.assertEqual(10000, self.idmapdb.get_user_hwm()) def test_group_hwm(self): - self.assertEquals(10002, self.idmapdb.get_group_hwm()) + self.assertEqual(10002, self.idmapdb.get_group_hwm()) def test_uids(self): - self.assertEquals(1, len(list(self.idmapdb.uids()))) + self.assertEqual(1, len(list(self.idmapdb.uids()))) def test_gids(self): - self.assertEquals(3, len(list(self.idmapdb.gids()))) + self.assertEqual(3, len(list(self.idmapdb.gids()))) def test_get_user_sid(self): - self.assertEquals(b"S-1-5-21-58189338-3053988021-627566699-501", self.idmapdb.get_user_sid(65534)) + self.assertEqual(b"S-1-5-21-58189338-3053988021-627566699-501", self.idmapdb.get_user_sid(65534)) def test_get_group_sid(self): - self.assertEquals(b"S-1-5-21-2447931902-1787058256-3961074038-3007", self.idmapdb.get_group_sid(10001)) + self.assertEqual(b"S-1-5-21-2447931902-1787058256-3961074038-3007", self.idmapdb.get_group_sid(10001)) def tearDown(self): self.idmapdb.close() diff --git a/python/samba/tests/s3param.py b/python/samba/tests/s3param.py index bdbdbced5e0..232e79bbd5f 100644 --- a/python/samba/tests/s3param.py +++ b/python/samba/tests/s3param.py @@ -44,7 +44,7 @@ class ParamTestCase(TestCaseInTempDir): super(ParamTestCase, self).tearDown() def test_param(self): - self.assertEquals("BEDWYR", self.lp.get("netbios name")) - self.assertEquals("SAMBA", self.lp.get("workgroup")) - self.assertEquals("USER", self.lp.get("security")) - self.assertEquals("/mnt/cd1", self.lp.get("path", "cd1")) + self.assertEqual("BEDWYR", self.lp.get("netbios name")) + self.assertEqual("SAMBA", self.lp.get("workgroup")) + self.assertEqual("USER", self.lp.get("security")) + self.assertEqual("/mnt/cd1", self.lp.get("path", "cd1")) diff --git a/python/samba/tests/s3passdb.py b/python/samba/tests/s3passdb.py index 7b0f34ebca0..734ca96110a 100644 --- a/python/samba/tests/s3passdb.py +++ b/python/samba/tests/s3passdb.py @@ -54,70 +54,70 @@ class PassdbTestCase(TestCaseInTempDir): def test_policy(self): policy = self.pdb.get_account_policy() - self.assertEquals(0, policy['bad lockout attempt']) - self.assertEquals(-1, policy['disconnect time']) - self.assertEquals(0, policy['lockout duration']) - self.assertEquals(999999999, policy['maximum password age']) - self.assertEquals(0, policy['minimum password age']) - self.assertEquals(5, policy['min password length']) - self.assertEquals(0, policy['password history']) - self.assertEquals(0, policy['refuse machine password change']) - self.assertEquals(0, policy['reset count minutes']) - self.assertEquals(0, policy['user must logon to change password']) + self.assertEqual(0, policy['bad lockout attempt']) + self.assertEqual(-1, policy['disconnect time']) + self.assertEqual(0, policy['lockout duration']) + self.assertEqual(999999999, policy['maximum password age']) + self.assertEqual(0, policy['minimum password age']) + self.assertEqual(5, policy['min password length']) + self.assertEqual(0, policy['password history']) + self.assertEqual(0, policy['refuse machine password change']) + self.assertEqual(0, policy['reset count minutes']) + self.assertEqual(0, policy['user must logon to change password']) def test_get_sid(self): domain_sid = passdb.get_global_sam_sid() - self.assertEquals(dom_sid("S-1-5-21-2470180966-3899876309-2637894779"), domain_sid) + self.assertEqual(dom_sid("S-1-5-21-2470180966-3899876309-2637894779"), domain_sid) def test_usernames(self): userlist = self.pdb.search_users(0) - self.assertEquals(3, len(userlist)) + self.assertEqual(3, len(userlist)) def test_getuser(self): user = self.pdb.getsampwnam("root") - self.assertEquals(16, user.acct_ctrl) - self.assertEquals("", user.acct_desc) - self.assertEquals(0, user.bad_password_count) - self.assertEquals(0, user.bad_password_time) - self.assertEquals(0, user.code_page) - self.assertEquals(0, user.country_code) - self.assertEquals("", user.dir_drive) - self.assertEquals("BEDWYR", user.domain) - self.assertEquals("root", user.full_name) - self.assertEquals(dom_sid('S-1-5-21-2470180966-3899876309-2637894779-513'), user.group_sid) - self.assertEquals("\\\\BEDWYR\\root", user.home_dir) - self.assertEquals([-1 for i in range(21)], user.hours) - self.assertEquals(21, user.hours_len) - self.assertEquals(9223372036854775807, user.kickoff_time) - self.assertEquals(None, user.lanman_passwd) - self.assertEquals(9223372036854775807, user.logoff_time) - self.assertEquals(0, user.logon_count) - self.assertEquals(168, user.logon_divs) - self.assertEquals("", user.logon_script) - self.assertEquals(0, user.logon_time) - self.assertEquals("", user.munged_dial) - self.assertEquals(b'\x87\x8d\x80\x14`l\xda)gzD\xef\xa15?\xc7', user.nt_passwd) - self.assertEquals("", user.nt_username) - self.assertEquals(1125418267, user.pass_can_change_time) - self.assertEquals(1125418267, user.pass_last_set_time) - self.assertEquals(2125418266, user.pass_must_change_time) - self.assertEquals(None, user.plaintext_passwd) - self.assertEquals("\\\\BEDWYR\\root\\profile", user.profile_path) - self.assertEquals(None, user.pw_history) - self.assertEquals(dom_sid("S-1-5-21-2470180966-3899876309-2637894779-1000"), user.user_sid) - self.assertEquals("root", user.username) - self.assertEquals("", user.workstations) + self.assertEqual(16, user.acct_ctrl) + self.assertEqual("", user.acct_desc) + self.assertEqual(0, user.bad_password_count) + self.assertEqual(0, user.bad_password_time) + self.assertEqual(0, user.code_page) + self.assertEqual(0, user.country_code) + self.assertEqual("", user.dir_drive) + self.assertEqual("BEDWYR", user.domain) + self.assertEqual("root", user.full_name) + self.assertEqual(dom_sid('S-1-5-21-2470180966-3899876309-2637894779-513'), user.group_sid) + self.assertEqual("\\\\BEDWYR\\root", user.home_dir) + self.assertEqual([-1 for i in range(21)], user.hours) + self.assertEqual(21, user.hours_len) + self.assertEqual(9223372036854775807, user.kickoff_time) + self.assertEqual(None, user.lanman_passwd) + self.assertEqual(9223372036854775807, user.logoff_time) + self.assertEqual(0, user.logon_count) + self.assertEqual(168, user.logon_divs) + self.assertEqual("", user.logon_script) + self.assertEqual(0, user.logon_time) + self.assertEqual("", user.munged_dial) + self.assertEqual(b'\x87\x8d\x80\x14`l\xda)gzD\xef\xa15?\xc7', user.nt_passwd) + self.assertEqual("", user.nt_username) + self.assertEqual(1125418267, user.pass_can_change_time) + self.assertEqual(1125418267, user.pass_last_set_time) + self.assertEqual(2125418266, user.pass_must_change_time) + self.assertEqual(None, user.plaintext_passwd) + self.assertEqual("\\\\BEDWYR\\root\\profile", user.profile_path) + self.assertEqual(None, user.pw_history) + self.assertEqual(dom_sid("S-1-5-21-2470180966-3899876309-2637894779-1000"), user.user_sid) + self.assertEqual("root", user.username) + self.assertEqual("", user.workstations) def test_group_length(self): grouplist = self.pdb.enum_group_mapping() - self.assertEquals(13, len(grouplist)) + self.assertEqual(13, len(grouplist)) def test_get_group(self): group = self.pdb.getgrsid(dom_sid("S-1-5-32-544")) - self.assertEquals("Administrators", group.nt_name) - self.assertEquals(-1, group.gid) - self.assertEquals(5, group.sid_name_use) + self.assertEqual("Administrators", group.nt_name) + self.assertEqual(-1, group.gid) + self.assertEqual(5, group.sid_name_use) def test_groupsids(self): grouplist = self.pdb.enum_group_mapping() @@ -134,5 +134,5 @@ class PassdbTestCase(TestCaseInTempDir): def test_alias_length(self): aliaslist = self.pdb.search_aliases() - self.assertEquals(1, len(aliaslist)) - self.assertEquals("Jelmers NT Group", aliaslist[0]['account_name']) + self.assertEqual(1, len(aliaslist)) + self.assertEqual("Jelmers NT Group", aliaslist[0]['account_name']) diff --git a/python/samba/tests/s3registry.py b/python/samba/tests/s3registry.py index e049e9de927..5e9004e4e1d 100644 --- a/python/samba/tests/s3registry.py +++ b/python/samba/tests/s3registry.py @@ -39,15 +39,15 @@ class RegistryTestCase(TestCase): super(RegistryTestCase, self).tearDown() def test_length(self): - self.assertEquals(28, len(self.registry)) + self.assertEqual(28, len(self.registry)) def test_keys(self): self.assertTrue(b"HKLM" in self.registry.keys()) def test_subkeys(self): - self.assertEquals([b"SOFTWARE", b"SYSTEM"], self.registry.subkeys(b"HKLM")) + self.assertEqual([b"SOFTWARE", b"SYSTEM"], self.registry.subkeys(b"HKLM")) def test_values(self): - self.assertEquals({b'DisplayName': (1, b'E\x00v\x00e\x00n\x00t\x00 \x00L\x00o\x00g\x00\x00\x00'), + self.assertEqual({b'DisplayName': (1, b'E\x00v\x00e\x00n\x00t\x00 \x00L\x00o\x00g\x00\x00\x00'), b'ErrorControl': (4, b'\x01\x00\x00\x00')}, self.registry.values(b"HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/EVENTLOG")) diff --git a/python/samba/tests/s3windb.py b/python/samba/tests/s3windb.py index 1ad9b3487ca..b92105c46b4 100644 --- a/python/samba/tests/s3windb.py +++ b/python/samba/tests/s3windb.py @@ -35,7 +35,7 @@ class WinsDatabaseTestCase(TestCase): self.winsdb = WinsDatabase(os.path.join(DATADIR, "wins.dat")) def test_length(self): - self.assertEquals(22, len(self.winsdb)) + self.assertEqual(22, len(self.winsdb)) def test_first_entry(self): self.assertEqual((1124185120, ["192.168.1.5"], 0x64), self.winsdb["ADMINISTRATOR#03"]) diff --git a/python/samba/tests/samba3sam.py b/python/samba/tests/samba3sam.py index 591cfebbdde..17bb4a7b7bc 100644 --- a/python/samba/tests/samba3sam.py +++ b/python/samba/tests/samba3sam.py @@ -133,7 +133,7 @@ class MapBaseTestCase(TestCaseInTempDir): sid_obj1 = samba.ndr.ndr_unpack(samba.dcerpc.security.dom_sid, ndr_sid[0]) sid_obj2 = samba.dcerpc.security.dom_sid(text) - self.assertEquals(sid_obj1, sid_obj2) + self.assertEqual(sid_obj1, sid_obj2) class Samba3SamTestCase(MapBaseTestCase): @@ -153,36 +153,36 @@ class Samba3SamTestCase(MapBaseTestCase): def test_search_non_mapped(self): """Looking up by non-mapped attribute""" msg = self.ldb.search(expression="(cn=Administrator)") - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0]["cn"]), "Administrator") + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0]["cn"]), "Administrator") def test_search_mapped(self): """Looking up by mapped attribute""" msg = self.ldb.search(expression="(name=Backup Operators)") - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0]["name"]), "Backup Operators") + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0]["name"]), "Backup Operators") def test_old_name_of_renamed(self): """Looking up by old name of renamed attribute""" msg = self.ldb.search(expression="(displayName=Backup Operators)") - self.assertEquals(len(msg), 0) + self.assertEqual(len(msg), 0) def test_mapped_containing_sid(self): """Looking up mapped entry containing SID""" msg = self.ldb.search(expression="(cn=Replicator)") - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0].dn), + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0].dn), "cn=Replicator,ou=Groups,dc=vernstok,dc=nl") self.assertTrue("objectSid" in msg[0]) self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052", msg[0]["objectSid"]) oc = set(msg[0]["objectClass"]) - self.assertEquals(oc, set([b"group"])) + self.assertEqual(oc, set([b"group"])) def test_search_by_objclass(self): """Looking up by objectClass""" msg = self.ldb.search(expression="(|(objectClass=user)(cn=Administrator))") - self.assertEquals(set([str(m.dn) for m in msg]), + self.assertEqual(set([str(m.dn) for m in msg]), set(["unixName=Administrator,ou=Users,dc=vernstok,dc=nl", "unixName=nobody,ou=Users,dc=vernstok,dc=nl"])) @@ -205,10 +205,10 @@ class Samba3SamTestCase(MapBaseTestCase): msg = self.ldb.search(expression="(cn=Foo)", base="cn=Foo", scope=SCOPE_BASE, attrs=['foo', 'blah', 'cn', 'showInAdvancedViewOnly']) - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0]["showInAdvancedViewOnly"]), "TRUE") - self.assertEquals(str(msg[0]["foo"]), "bar") - self.assertEquals(str(msg[0]["blah"]), "Blie") + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0]["showInAdvancedViewOnly"]), "TRUE") + self.assertEqual(str(msg[0]["foo"]), "bar") + self.assertEqual(str(msg[0]["blah"]), "Blie") # Adding record that will be mapped self.ldb.add({"dn": "cn=Niemand,cn=Users,dc=vernstok,dc=nl", @@ -220,33 +220,33 @@ class Samba3SamTestCase(MapBaseTestCase): # Checking for existence of record (remote) msg = self.ldb.search(expression="(unixName=bin)", attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd']) - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0]["cn"]), "Niemand") - self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim") + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0]["cn"]), "Niemand") + self.assertEqual(str(msg[0]["sambaUnicodePwd"]), "geheim") # Checking for existence of record (local && remote) msg = self.ldb.search(expression="(&(unixName=bin)(sambaUnicodePwd=geheim))", attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd']) - self.assertEquals(len(msg), 1) # TODO: should check with more records - self.assertEquals(str(msg[0]["cn"]), "Niemand") - self.assertEquals(str(msg[0]["unixName"]), "bin") - self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim") + self.assertEqual(len(msg), 1) # TODO: should check with more records + self.assertEqual(str(msg[0]["cn"]), "Niemand") + self.assertEqual(str(msg[0]["unixName"]), "bin") + self.assertEqual(str(msg[0]["sambaUnicodePwd"]), "geheim") # Checking for existence of record (local || remote) msg = self.ldb.search(expression="(|(unixName=bin)(sambaUnicodePwd=geheim))", attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd']) # print "got %d replies" % len(msg) - self.assertEquals(len(msg), 1) # TODO: should check with more records - self.assertEquals(str(msg[0]["cn"]), "Niemand") - self.assertEquals(str(msg[0]["unixName"]), "bin") - self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim") + self.assertEqual(len(msg), 1) # TODO: should check with more records + self.assertEqual(str(msg[0]["cn"]), "Niemand") + self.assertEqual(str(msg[0]["unixName"]), "bin") + self.assertEqual(str(msg[0]["sambaUnicodePwd"]), "geheim") # Checking for data in destination database msg = self.samba3.db.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) - self.assertEquals(str(msg[0]["sambaSID"]), + self.assertEqual(str(msg[0]["sambaSID"]), "S-1-5-21-4231626423-2410014848-2360679739-2001") - self.assertEquals(str(msg[0]["displayName"]), "Niemand") + self.assertEqual(str(msg[0]["displayName"]), "Niemand") # Adding attribute... self.ldb.modify_ldif(""" @@ -259,8 +259,8 @@ description: Blah # Checking whether changes are still there... msg = self.ldb.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) - self.assertEquals(str(msg[0]["cn"]), "Niemand") - self.assertEquals(str(msg[0]["description"]), "Blah") + self.assertEqual(str(msg[0]["cn"]), "Niemand") + self.assertEqual(str(msg[0]["description"]), "Blah") # Modifying attribute... self.ldb.modify_ldif(""" @@ -273,7 +273,7 @@ description: Blie # Checking whether changes are still there... msg = self.ldb.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) - self.assertEquals(str(msg[0]["description"]), "Blie") + self.assertEqual(str(msg[0]["description"]), "Blie") # Deleting attribute... self.ldb.modify_ldif(""" @@ -293,8 +293,8 @@ delete: description # Checking whether DN has changed... msg = self.ldb.search(expression="(cn=Niemand2)") - self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0].dn), + self.assertEqual(len(msg), 1) + self.assertEqual(str(msg[0].dn), "cn=Niemand2,cn=Users,dc=vernstok,dc=nl") # Deleting record... @@ -302,7 +302,7 @@ delete: description # Checking whether record is gone... msg = self.ldb.search(expression="(cn=Niemand2)") - self.assertEquals(len(msg), 0) + self.assertEqual(len(msg), 0) class MapTestCase(MapBaseTestCase): @@ -409,77 +409,77 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052 dn = self.samba4.dn("cn=A") res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") # Search remote record by remote DN dn = self.samba3.dn("cn=A") res = self.samba3.db.search(dn, scope=SCOPE_BASE, attrs=["dnsHostName", "lastLogon", "sambaLogonTime"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("dnsHostName" not in res[0]) self.assertTrue("lastLogon" not in res[0]) - self.assertEquals(str(res[0]["sambaLogonTime"]), "x") + self.assertEqual(str(res[0]["sambaLogonTime"]), "x") # Search split record by local DN dn = self.samba4.dn("cn=X") res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["dnsHostName"]), "x") - self.assertEquals(str(res[0]["lastLogon"]), "x") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["dnsHostName"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") # Search split record by remote DN dn = self.samba3.dn("cn=X") res = self.samba3.db.search(dn, scope=SCOPE_BASE, attrs=["dnsHostName", "lastLogon", "sambaLogonTime"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("dnsHostName" not in res[0]) self.assertTrue("lastLogon" not in res[0]) - self.assertEquals(str(res[0]["sambaLogonTime"]), "x") + self.assertEqual(str(res[0]["sambaLogonTime"]), "x") # Testing search by attribute # Search by ignored attribute res = self.ldb.search(expression="(revision=x)", scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[0]["dnsHostName"]), "x") - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[1]["dnsHostName"]), "y") - self.assertEquals(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[0]["dnsHostName"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[1]["dnsHostName"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") # Search by kept attribute res = self.ldb.search(expression="(description=y)", scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "z") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[1]["dnsHostName"]), "z") - self.assertEquals(str(res[1]["lastLogon"]), "z") + self.assertEqual(str(res[0]["lastLogon"]), "z") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[1]["dnsHostName"]), "z") + self.assertEqual(str(res[1]["lastLogon"]), "z") # Search by renamed attribute res = self.ldb.search(expression="(badPwdCount=x)", scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") # Search by converted attribute # TODO: @@ -487,17 +487,17 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052 # errors, letting the search fail with no results. # res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-1052)", scope=SCOPE_DEFAULT, attrs) res = self.ldb.search(expression="(objectSid=*)", base=None, scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon", "objectSid"]) - self.assertEquals(len(res), 4) + self.assertEqual(len(res), 4) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[1]["dnsHostName"]), "x") - self.assertEquals(str(res[1]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[1]["dnsHostName"]), "x") + self.assertEqual(str(res[1]["lastLogon"]), "x") self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052", res[1]["objectSid"]) self.assertTrue("objectSid" in res[1]) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052", res[0]["objectSid"]) self.assertTrue("objectSid" in res[0]) @@ -507,11 +507,11 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052 # a `convert_operator' by enumerating the remote db. res = self.ldb.search(expression="(primaryGroupID=512)", attrs=["dnsHostName", "lastLogon", "primaryGroupID"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[0]["primaryGroupID"]), "512") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[0]["primaryGroupID"]), "512") # Note that Xs "objectSid" seems to be fine in the previous search for # "objectSid"... @@ -527,284 +527,284 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052 # Search by remote name of renamed attribute */ res = self.ldb.search(expression="(sambaBadPasswordCount=*)", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Search by objectClass attrs = ["dnsHostName", "lastLogon", "objectClass"] res = self.ldb.search(expression="(objectClass=user)", attrs=attrs) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[0]["objectClass"][0]), "user") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[1]["dnsHostName"]), "x") - self.assertEquals(str(res[1]["lastLogon"]), "x") - self.assertEquals(str(res[1]["objectClass"][0]), "user") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[0]["objectClass"][0]), "user") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[1]["dnsHostName"]), "x") + self.assertEqual(str(res[1]["lastLogon"]), "x") + self.assertEqual(str(res[1]["objectClass"][0]), "user") # Prove that the objectClass is actually used for the search res = self.ldb.search(expression="(|(objectClass=user)(badPwdCount=x))", attrs=attrs) - self.assertEquals(len(res), 3) + self.assertEqual(len(res), 3) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[0]["objectClass"][0]), "user") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[0]["objectClass"][0]), "user") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(set(res[1]["objectClass"]), set([b"top"])) - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[2]["dnsHostName"]), "x") - self.assertEquals(str(res[2]["lastLogon"]), "x") - self.assertEquals(str(res[2]["objectClass"][0]), "user") + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(set(res[1]["objectClass"]), set([b"top"])) + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[2]["dnsHostName"]), "x") + self.assertEqual(str(res[2]["lastLogon"]), "x") + self.assertEqual(str(res[2]["objectClass"][0]), "user") # Testing search by parse tree # Search by conjunction of local attributes res = self.ldb.search(expression="(&(codePage=x)(revision=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[0]["dnsHostName"]), "x") - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[1]["dnsHostName"]), "y") - self.assertEquals(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[0]["dnsHostName"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[1]["dnsHostName"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") # Search by conjunction of remote attributes res = self.ldb.search(expression="(&(lastLogon=x)(description=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[1]["dnsHostName"]), "x") - self.assertEquals(str(res[1]["lastLogon"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[1]["dnsHostName"]), "x") + self.assertEqual(str(res[1]["lastLogon"]), "x") # Search by conjunction of local and remote attribute res = self.ldb.search(expression="(&(codePage=x)(description=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[0]["dnsHostName"]), "x") - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[1]["dnsHostName"]), "y") - self.assertEquals(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[0]["dnsHostName"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[1]["dnsHostName"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") # Search by conjunction of local and remote attribute w/o match attrs = ["dnsHostName", "lastLogon"] res = self.ldb.search(expression="(&(codePage=x)(nextRid=x))", attrs=attrs) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) res = self.ldb.search(expression="(&(revision=x)(lastLogon=z))", attrs=attrs) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Search by disjunction of local attributes res = self.ldb.search(expression="(|(revision=x)(dnsHostName=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[0]["dnsHostName"]), "x") - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[1]["dnsHostName"]), "y") - self.assertEquals(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[0]["dnsHostName"]), "x") + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[1]["dnsHostName"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") # Search by disjunction of remote attributes res = self.ldb.search(expression="(|(badPwdCount=x)(lastLogon=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 3) + self.assertEqual(len(res), 3) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertFalse("dnsHostName" in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertFalse("dnsHostName" in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[2]["dnsHostName"]), "x") - self.assertEquals(str(res[2]["lastLogon"]), "x") + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[2]["dnsHostName"]), "x") + self.assertEqual(str(res[2]["lastLogon"]), "x") # Search by disjunction of local and remote attribute res = self.ldb.search(expression="(|(revision=x)(lastLogon=y))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 3) + self.assertEqual(len(res), 3) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=B")) self.assertFalse("dnsHostName" in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "y") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[1]["dnsHostName"]), "x") - self.assertEquals(str(res[1]["lastLogon"]), "x") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[2]["dnsHostName"]), "y") - self.assertEquals(str(res[2]["lastLogon"]), "y") + self.assertEqual(str(res[0]["lastLogon"]), "y") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[1]["dnsHostName"]), "x") + self.assertEqual(str(res[1]["lastLogon"]), "x") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[2]["dnsHostName"]), "y") + self.assertEqual(str(res[2]["lastLogon"]), "y") # Search by disjunction of local and remote attribute w/o match res = self.ldb.search(expression="(|(codePage=y)(nextRid=z))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Search by negated local attribute res = self.ldb.search(expression="(!(revision=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[2]) - self.assertEquals(str(res[2]["lastLogon"]), "z") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[3]["dnsHostName"]), "z") - self.assertEquals(str(res[3]["lastLogon"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[3]["dnsHostName"]), "z") + self.assertEqual(str(res[3]["lastLogon"]), "z") # Search by negated remote attribute res = self.ldb.search(expression="(!(description=x))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 4) + self.assertEqual(len(res), 4) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "z") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[1]["dnsHostName"]), "z") - self.assertEquals(str(res[1]["lastLogon"]), "z") + self.assertEqual(str(res[0]["lastLogon"]), "z") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[1]["dnsHostName"]), "z") + self.assertEqual(str(res[1]["lastLogon"]), "z") # Search by negated conjunction of local attributes res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[2]) - self.assertEquals(str(res[2]["lastLogon"]), "z") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[3]["dnsHostName"]), "z") - self.assertEquals(str(res[3]["lastLogon"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[3]["dnsHostName"]), "z") + self.assertEqual(str(res[3]["lastLogon"]), "z") # Search by negated conjunction of remote attributes res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "y") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[0]["lastLogon"]), "y") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "z") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[2]["dnsHostName"]), "y") - self.assertEquals(str(res[2]["lastLogon"]), "y") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[3]["dnsHostName"]), "z") - self.assertEquals(str(res[3]["lastLogon"]), "z") + self.assertEqual(str(res[1]["lastLogon"]), "z") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[2]["dnsHostName"]), "y") + self.assertEqual(str(res[2]["lastLogon"]), "y") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[3]["dnsHostName"]), "z") + self.assertEqual(str(res[3]["lastLogon"]), "z") # Search by negated conjunction of local and remote attribute res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[2]) - self.assertEquals(str(res[2]["lastLogon"]), "z") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[3]["dnsHostName"]), "z") - self.assertEquals(str(res[3]["lastLogon"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[3]["dnsHostName"]), "z") + self.assertEqual(str(res[3]["lastLogon"]), "z") # Search by negated disjunction of local attributes res = self.ldb.search(expression="(!(|(revision=x)(dnsHostName=x)))", attrs=["dnsHostName", "lastLogon"]) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[2]) - self.assertEquals(str(res[2]["lastLogon"]), "z") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[3]["dnsHostName"]), "z") - self.assertEquals(str(res[3]["lastLogon"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[3]["dnsHostName"]), "z") + self.assertEqual(str(res[3]["lastLogon"]), "z") # Search by negated disjunction of remote attributes res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 5) + self.assertEqual(len(res), 5) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "z") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y")) - self.assertEquals(str(res[1]["dnsHostName"]), "y") - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[2]["dnsHostName"]), "z") - self.assertEquals(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[0]["lastLogon"]), "z") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=Y")) + self.assertEqual(str(res[1]["dnsHostName"]), "y") + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[2]["dnsHostName"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") # Search by negated disjunction of local and remote attribute res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 5) + self.assertEqual(len(res), 5) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "z") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[2]["dnsHostName"]), "z") - self.assertEquals(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[1]["lastLogon"]), "z") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[2]["dnsHostName"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") # Search by complex parse tree res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=["dnsHostName", "lastLogon"]) - self.assertEquals(len(res), 7) + self.assertEqual(len(res), 7) res = sorted(res, key=attrgetter('dn')) - self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) + self.assertEqual(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue("dnsHostName" not in res[0]) - self.assertEquals(str(res[0]["lastLogon"]), "x") - self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) + self.assertEqual(str(res[0]["lastLogon"]), "x") + self.assertEqual(str(res[1].dn), self.samba4.dn("cn=B")) self.assertTrue("dnsHostName" not in res[1]) - self.assertEquals(str(res[1]["lastLogon"]), "y") - self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C")) + self.assertEqual(str(res[1]["lastLogon"]), "y") + self.assertEqual(str(res[2].dn), self.samba4.dn("cn=C")) self.assertTrue("dnsHostName" not in res[2]) - self.assertEquals(str(res[2]["lastLogon"]), "z") - self.assertEquals(str(res[3].dn), self.samba4.dn("cn=X")) - self.assertEquals(str(res[3]["dnsHostName"]), "x") - self.assertEquals(str(res[3]["lastLogon"]), "x") - self.assertEquals(str(res[4].dn), self.samba4.dn("cn=Z")) - self.assertEquals(str(res[4]["dnsHostName"]), "z") - self.assertEquals(str(res[4]["lastLogon"]), "z") + self.assertEqual(str(res[2]["lastLogon"]), "z") + self.assertEqual(str(res[3].dn), self.samba4.dn("cn=X")) + self.assertEqual(str(res[3]["dnsHostName"]), "x") + self.assertEqual(str(res[3]["lastLogon"]), "x") + self.assertEqual(str(res[4].dn), self.samba4.dn("cn=Z")) + self.assertEqual(str(res[4]["dnsHostName"]), "z") + self.assertEqual(str(res[4]["lastLogon"]), "z") # Clean up dns = [self.samba4.dn("cn=%s" % n) for n in ["A", "B", "C", "X", "Y", "Z"]] @@ -823,19 +823,19 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052 # Check it's there attrs = ["foo", "revision", "description"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["foo"]), "bar") - self.assertEquals(str(res[0]["revision"]), "1") - self.assertEquals(str(res[0]["description"]), "test") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["foo"]), "bar") + self.assertEqual(str(res[0]["revision"]), "1") + self.assertEqual(str(res[0]["description"]), "test") # Check it's not in the local db res = self.samba4.db.search(expression="(cn=test)", scope=SCOPE_DEFAULT, attrs=attrs) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Check it's not in the remote db res = self.samba3.db.search(expression="(cn=test)", scope=SCOPE_DEFAULT, attrs=attrs) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Modify local record ldif = """ @@ -848,28 +848,28 @@ description: foo self.ldb.modify_ldif(ldif) # Check in local db res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["foo"]), "baz") - self.assertEquals(str(res[0]["revision"]), "1") - self.assertEquals(str(res[0]["description"]), "foo") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["foo"]), "baz") + self.assertEqual(str(res[0]["revision"]), "1") + self.assertEqual(str(res[0]["description"]), "foo") # Rename local record dn2 = "cn=toast,dc=idealx,dc=org" self.ldb.rename(dn, dn2) # Check in local db res = self.ldb.search(dn2, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["foo"]), "baz") - self.assertEquals(str(res[0]["revision"]), "1") - self.assertEquals(str(res[0]["description"]), "foo") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["foo"]), "baz") + self.assertEqual(str(res[0]["revision"]), "1") + self.assertEqual(str(res[0]["description"]), "foo") # Delete local record self.ldb.delete(dn2) # Check it's gone res = self.ldb.search(dn2, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) def test_map_modify_remote_remote(self): """Modification of remote data of remote records""" @@ -884,22 +884,22 @@ description: foo # Check it's there res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "foo") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "foo") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "3") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") # Check in mapped db attrs = ["description", "badPwdCount", "nextRid"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs, expression="") - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "foo") - self.assertEquals(str(res[0]["badPwdCount"]), "3") - self.assertEquals(str(res[0]["nextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "foo") + self.assertEqual(str(res[0]["badPwdCount"]), "3") + self.assertEqual(str(res[0]["nextRid"]), "1001") # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Modify remote data of remote record ldif = """ @@ -913,19 +913,19 @@ badPwdCount: 4 # Check in mapped db res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["description", "badPwdCount", "nextRid"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["badPwdCount"]), "4") - self.assertEquals(str(res[0]["nextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["badPwdCount"]), "4") + self.assertEqual(str(res[0]["nextRid"]), "1001") # Check in remote db res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "4") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") # Rename remote record dn2 = self.samba4.dn("cn=toast") @@ -934,29 +934,29 @@ badPwdCount: 4 dn = dn2 res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=["description", "badPwdCount", "nextRid"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["badPwdCount"]), "4") - self.assertEquals(str(res[0]["nextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["badPwdCount"]), "4") + self.assertEqual(str(res[0]["nextRid"]), "1001") # Check in remote db dn2 = self.samba3.dn("cn=toast") res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "4") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") # Delete remote record self.ldb.delete(dn) # Check in mapped db that it's removed res = self.ldb.search(dn, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Check in remote db res = self.samba3.db.search(dn2, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) def test_map_modify_remote_local(self): """Modification of local data of remote records""" @@ -982,22 +982,22 @@ description: test # Check in mapped db attrs = ["revision", "description"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["revision"]), "1") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["revision"]), "1") # Check in remote db res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "test") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "test") self.assertTrue("revision" not in res[0]) # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("description" not in res[0]) - self.assertEquals(str(res[0]["revision"]), "1") + self.assertEqual(str(res[0]["revision"]), "1") # Delete (newly) split record self.ldb.delete(dn) @@ -1017,29 +1017,29 @@ description: test # Check it's there attrs = ["description", "badPwdCount", "nextRid", "revision"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "foo") - self.assertEquals(str(res[0]["badPwdCount"]), "3") - self.assertEquals(str(res[0]["nextRid"]), "1001") - self.assertEquals(str(res[0]["revision"]), "1") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "foo") + self.assertEqual(str(res[0]["badPwdCount"]), "3") + self.assertEqual(str(res[0]["nextRid"]), "1001") + self.assertEqual(str(res[0]["revision"]), "1") # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("description" not in res[0]) self.assertTrue("badPwdCount" not in res[0]) self.assertTrue("nextRid" not in res[0]) - self.assertEquals(str(res[0]["revision"]), "1") + self.assertEqual(str(res[0]["revision"]), "1") # Check in remote db attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", "revision"] res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "foo") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "foo") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "3") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") self.assertTrue("revision" not in res[0]) # Modify of split record @@ -1056,29 +1056,29 @@ revision: 2 # Check in mapped db attrs = ["description", "badPwdCount", "nextRid", "revision"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["badPwdCount"]), "4") - self.assertEquals(str(res[0]["nextRid"]), "1001") - self.assertEquals(str(res[0]["revision"]), "2") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["badPwdCount"]), "4") + self.assertEqual(str(res[0]["nextRid"]), "1001") + self.assertEqual(str(res[0]["revision"]), "2") # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("description" not in res[0]) self.assertTrue("badPwdCount" not in res[0]) self.assertTrue("nextRid" not in res[0]) - self.assertEquals(str(res[0]["revision"]), "2") + self.assertEqual(str(res[0]["revision"]), "2") # Check in remote db attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", "revision"] res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "4") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") self.assertTrue("revision" not in res[0]) # Rename split record @@ -1088,40 +1088,40 @@ revision: 2 dn = dn2 attrs = ["description", "badPwdCount", "nextRid", "revision"] res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["badPwdCount"]), "4") - self.assertEquals(str(res[0]["nextRid"]), "1001") - self.assertEquals(str(res[0]["revision"]), "2") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["badPwdCount"]), "4") + self.assertEqual(str(res[0]["nextRid"]), "1001") + self.assertEqual(str(res[0]["revision"]), "2") # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn) self.assertTrue("description" not in res[0]) self.assertTrue("badPwdCount" not in res[0]) self.assertTrue("nextRid" not in res[0]) - self.assertEquals(str(res[0]["revision"]), "2") + self.assertEqual(str(res[0]["revision"]), "2") # Check in remote db dn2 = self.samba3.dn("cn=toast") res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=["description", "sambaBadPasswordCount", "sambaNextRid", "revision"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0].dn), dn2) - self.assertEquals(str(res[0]["description"]), "test") - self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4") - self.assertEquals(str(res[0]["sambaNextRid"]), "1001") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0].dn), dn2) + self.assertEqual(str(res[0]["description"]), "test") + self.assertEqual(str(res[0]["sambaBadPasswordCount"]), "4") + self.assertEqual(str(res[0]["sambaNextRid"]), "1001") self.assertTrue("revision" not in res[0]) # Delete split record self.ldb.delete(dn) # Check in mapped db res = self.ldb.search(dn, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Check in local db res = self.samba4.db.search(dn, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Check in remote db res = self.samba3.db.search(dn2, scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) diff --git a/python/samba/tests/samba_tool/computer.py b/python/samba/tests/samba_tool/computer.py index 9912fd408a4..3110a3b04e8 100644 --- a/python/samba/tests/samba_tool/computer.py +++ b/python/samba/tests/samba_tool/computer.py @@ -78,10 +78,10 @@ class ComputerCmdTestCase(SambaToolCmdTest): expectedsamaccountname = computer["name"] if not computer["name"].endswith('$'): expectedsamaccountname = "%s$" % computer["name"] - self.assertEquals("%s" % found.get("name"), expectedname) - self.assertEquals("%s" % found.get("sAMAccountName"), + self.assertEqual("%s" % found.get("name"), expectedname) + self.assertEqual("%s" % found.get("sAMAccountName"), expectedsamaccountname) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("description"), computer["description"]) def tearDown(self): @@ -155,7 +155,7 @@ class ComputerCmdTestCase(SambaToolCmdTest): "--description=%s" % computer["description"]) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn("Computer '%s' created successfully" % computer["name"], out) @@ -165,10 +165,10 @@ class ComputerCmdTestCase(SambaToolCmdTest): expectedsamaccountname = computer["name"] if not computer["name"].endswith('$'): expectedsamaccountname = "%s$" % computer["name"] - self.assertEquals("%s" % found.get("name"), expectedname) - self.assertEquals("%s" % found.get("sAMAccountName"), + self.assertEqual("%s" % found.get("name"), expectedname) + self.assertEqual("%s" % found.get("sAMAccountName"), expectedsamaccountname) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("description"), computer["description"]) def test_list(self): @@ -243,7 +243,7 @@ class ComputerCmdTestCase(SambaToolCmdTest): self.assertCmdSuccess(result, out, err, "Failed to move computer '%s'" % computer["name"]) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn('Moved computer "%s"' % computer["name"], out) found = self._find_computer(computer["name"]) @@ -255,7 +255,7 @@ class ComputerCmdTestCase(SambaToolCmdTest): "CN=%s,OU=%s,%s" % (computername, parentou["name"], self.samdb.domain_dn())) - self.assertEquals(found.get("dn"), newexpecteddn, + self.assertEqual(found.get("dn"), newexpecteddn, "Moved computer '%s' does not exist" % computer["name"]) diff --git a/python/samba/tests/samba_tool/contact.py b/python/samba/tests/samba_tool/contact.py index f02e3603e5d..8b34e20b249 100644 --- a/python/samba/tests/samba_tool/contact.py +++ b/python/samba/tests/samba_tool/contact.py @@ -78,8 +78,8 @@ class ContactCmdTestCase(SambaToolCmdTest): self.assertIsNotNone(found) contactname = contact["expectedname"] - self.assertEquals("%s" % found.get("name"), contactname) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("name"), contactname) + self.assertEqual("%s" % found.get("description"), contact["description"]) def tearDown(self): @@ -122,15 +122,15 @@ class ContactCmdTestCase(SambaToolCmdTest): (result, out, err) = self._create_contact(contact, ou="OU=testOU") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn("Contact '%s' created successfully" % contact["expectedname"], out) found = self._find_contact(contact["expectedname"]) contactname = contact["expectedname"] - self.assertEquals("%s" % found.get("name"), contactname) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("name"), contactname) + self.assertEqual("%s" % found.get("description"), contact["description"]) # try to delete all the contacts we just created, by DN @@ -160,15 +160,15 @@ class ContactCmdTestCase(SambaToolCmdTest): (result, out, err) = self._create_contact(contact) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn("Contact '%s' created successfully" % contact["expectedname"], out) found = self._find_contact(contact["expectedname"]) contactname = contact["expectedname"] - self.assertEquals("%s" % found.get("name"), contactname) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("name"), contactname) + self.assertEqual("%s" % found.get("description"), contact["description"]) def test_list(self): @@ -237,7 +237,7 @@ class ContactCmdTestCase(SambaToolCmdTest): self.assertCmdSuccess(result, out, err, "Failed to move contact '%s'" % contact["expectedname"]) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn('Moved contact "%s"' % contact["expectedname"], out) found = self._find_contact(contact["expectedname"]) @@ -250,7 +250,7 @@ class ContactCmdTestCase(SambaToolCmdTest): (contactname, parentou["name"], self.samdb.domain_dn())) - self.assertEquals(found.get("dn"), newexpecteddn, + self.assertEqual(found.get("dn"), newexpecteddn, "Moved contact '%s' does not exist" % contact["expectedname"]) diff --git a/python/samba/tests/samba_tool/drs_clone_dc_data_lmdb_size.py b/python/samba/tests/samba_tool/drs_clone_dc_data_lmdb_size.py index ae78784a04d..71521b6a07f 100644 --- a/python/samba/tests/samba_tool/drs_clone_dc_data_lmdb_size.py +++ b/python/samba/tests/samba_tool/drs_clone_dc_data_lmdb_size.py @@ -83,12 +83,12 @@ class DrsCloneDcDataLmdbSizeTestCase(SambaToolCmdTest): # 8Gb is used def test_default(self): (result, out, err) = self.clone() - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) def test_64Mb(self): (result, out, err) = self.clone("64Mb") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(64 * 1024 * 1024) def test_no_unit_suffix(self): diff --git a/python/samba/tests/samba_tool/dsacl.py b/python/samba/tests/samba_tool/dsacl.py index 4a2ee56009c..66c662f7a3b 100644 --- a/python/samba/tests/samba_tool/dsacl.py +++ b/python/samba/tests/samba_tool/dsacl.py @@ -43,7 +43,7 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): """Tests if a sddl string can be added 'the normal way'""" (result, out, err) = self.runsubcmd("dsacl", "set","--objectdn=%s" % self.dn, "--sddl=%s" % self.sddl) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") #extract only the two sddl strings from samba-tool output acl_list=re.findall('.*descriptor for.*:\n(.*?)\n',out) self.assertNotEqual(acl_list[0], acl_list[1], "new and old SDDL string differ") @@ -54,7 +54,7 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("dsacl", "get", "--objectdn=%s" % self.dn) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") #extract only the two sddl strings from samba-tool output acl_list_get=re.findall('^descriptor for.*:\n(.*?)\n', out) @@ -62,7 +62,7 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): "--objectdn=%s" % self.dn, "--sddl=%s" % self.sddl) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") #extract only the two sddl strings from samba-tool output acl_list_old=re.findall('old descriptor for.*:\n(.*?)\n', out) self.assertEqual(acl_list_old, acl_list_get, @@ -73,7 +73,7 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("dsacl", "get", "--objectdn=%s" % self.dn) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") #extract only the two sddl strings from samba-tool output acl_list_get2=re.findall('^descriptor for.*:\n(.*?)\n', out) self.assertEqual(acl_list, acl_list_get2, @@ -83,7 +83,7 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): """Tests if we can add multiple, different sddl strings at the same time""" (result, out, err) = self.runsubcmd("dsacl", "set","--objectdn=%s" % self.dn, "--sddl=%s" % self.sddl_multi) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") #extract only the two sddl strings from samba-tool output acl_list=re.findall('.*descriptor for.*:\n(.*?)\n',out) for ace in re.findall('\(.*?\)',self.sddl_multi): @@ -92,33 +92,33 @@ class DSaclSetSddlTestCase(SambaToolCmdTest): def test_duplicatesddl(self): """Tests if an already existing sddl string can be added causing duplicate entry""" acl_list = self._double_sddl_check(self.sddl,self.sddl) - self.assertEquals(acl_list[0],acl_list[1]) + self.assertEqual(acl_list[0],acl_list[1]) def test_casesensitivesddl(self): """Tests if an already existing sddl string can be added in different cases causing duplicate entry""" acl_list = self._double_sddl_check(self.sddl_lc,self.sddl_uc) - self.assertEquals(acl_list[0],acl_list[1]) + self.assertEqual(acl_list[0],acl_list[1]) def test_sidsddl(self): """Tests if an already existing sddl string can be added with SID instead of SDDL SIDString causing duplicate entry""" acl_list = self._double_sddl_check(self.sddl,self.sddl_sid) - self.assertEquals(acl_list[0],acl_list[1]) + self.assertEqual(acl_list[0],acl_list[1]) def test_twosddl(self): """Tests if an already existing sddl string can be added by using it twice/in combination with non existing sddl string causing duplicate entry""" acl_list = self._double_sddl_check(self.sddl,self.sddl + self.sddl) - self.assertEquals(acl_list[0],acl_list[1]) + self.assertEqual(acl_list[0],acl_list[1]) def _double_sddl_check(self,sddl1,sddl2): """Adds two sddl strings and checks if there was an ace change after the second adding""" (result, out, err) = self.runsubcmd("dsacl", "set","--objectdn=%s" % self.dn, "--sddl=%s" % sddl1) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") acl_list = re.findall('.*descriptor for.*:\n(.*?)\n',out) self.assertMatch(acl_list[1], sddl1, "new SDDL string should be contained within second sddl output - is not") #add sddl2 (result, out, err) = self.runsubcmd("dsacl", "set","--objectdn=%s" % self.dn, "--sddl=%s" % sddl2) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") acl_list = re.findall('.*descriptor for.*:\n(.*?)\n',out) return acl_list diff --git a/python/samba/tests/samba_tool/forest.py b/python/samba/tests/samba_tool/forest.py index 8817636bd63..f5cb3c03126 100644 --- a/python/samba/tests/samba_tool/forest.py +++ b/python/samba/tests/samba_tool/forest.py @@ -50,7 +50,7 @@ class ForestCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("dsheuristics: ", out) def test_modify_dsheuristics(self): @@ -63,5 +63,5 @@ class ForestCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("set dsheuristics: 0000002", out) diff --git a/python/samba/tests/samba_tool/fsmo.py b/python/samba/tests/samba_tool/fsmo.py index 674cc0e32dc..29fe7bfe08a 100644 --- a/python/samba/tests/samba_tool/fsmo.py +++ b/python/samba/tests/samba_tool/fsmo.py @@ -28,7 +28,7 @@ class FsmoCmdTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("fsmo", "show") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # Check that the output is sensible samdb = self.getSamDB("-H", "ldap://%s" % os.environ["SERVER"], diff --git a/python/samba/tests/samba_tool/group.py b/python/samba/tests/samba_tool/group.py index cd9d9d9ed28..e283e6c97c4 100644 --- a/python/samba/tests/samba_tool/group.py +++ b/python/samba/tests/samba_tool/group.py @@ -56,7 +56,7 @@ class GroupCmdTestCase(SambaToolCmdTest): (result, out, err) = group["createGroupFn"](group) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") if 'unix' in group["name"]: self.assertIn("Modified Group '%s' successfully" @@ -70,8 +70,8 @@ class GroupCmdTestCase(SambaToolCmdTest): self.assertIsNotNone(found) - self.assertEquals("%s" % found.get("name"), group["name"]) - self.assertEquals("%s" % found.get("description"), group["description"]) + self.assertEqual("%s" % found.get("name"), group["name"]) + self.assertEqual("%s" % found.get("description"), group["description"]) def tearDown(self): super(GroupCmdTestCase, self).tearDown() @@ -106,12 +106,12 @@ class GroupCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn("Added group %s" % group["name"], out) found = self._find_group(group["name"]) - self.assertEquals("%s" % found.get("samaccountname"), + self.assertEqual("%s" % found.get("samaccountname"), "%s" % group["name"]) def test_list(self): @@ -266,7 +266,7 @@ class GroupCmdTestCase(SambaToolCmdTest): full_ou_dn = str(self.samdb.normalize_dn_in_domain("OU=movetest")) (result, out, err) = self.runsubcmd("ou", "create", full_ou_dn) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn('Created ou "%s"' % full_ou_dn, out) for group in self.groups: @@ -301,7 +301,7 @@ class GroupCmdTestCase(SambaToolCmdTest): "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("dn: CN=Domain Users,CN=Users,DC=addom,DC=samba,DC=example,DC=com", out) def _randomGroup(self, base={}): @@ -350,15 +350,15 @@ class GroupCmdTestCase(SambaToolCmdTest): its template """ found = self._find_group(group["name"]) - self.assertEquals("%s" % found.get("name"), group["name"]) - self.assertEquals("%s" % found.get("description"), group["description"]) + self.assertEqual("%s" % found.get("name"), group["name"]) + self.assertEqual("%s" % found.get("description"), group["description"]) def _check_posix_group(self, group): """ check if a posix_group from SamDB has the same attributes as its template """ found = self._find_group(group["name"]) - self.assertEquals("%s" % found.get("gidNumber"), "%s" % + self.assertEqual("%s" % found.get("gidNumber"), "%s" % group["gidNumber"]) self._check_group(group) @@ -367,7 +367,7 @@ class GroupCmdTestCase(SambaToolCmdTest): template """ found = self._find_group(group["name"]) - self.assertEquals("%s" % found.get("gidNumber"), "%s" % + self.assertEqual("%s" % found.get("gidNumber"), "%s" % group["gidNumber"]) self._check_group(group) diff --git a/python/samba/tests/samba_tool/join_lmdb_size.py b/python/samba/tests/samba_tool/join_lmdb_size.py index 2b68f2a48d8..e410d5fba23 100644 --- a/python/samba/tests/samba_tool/join_lmdb_size.py +++ b/python/samba/tests/samba_tool/join_lmdb_size.py @@ -92,7 +92,7 @@ class JoinLmdbSizeTestCase(SambaToolCmdTest): # 8Gb is used def test_join_as_dc_default(self): (result, out, err) = self.join(role="DC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) self.assertFalse(self.is_rodc()) @@ -100,7 +100,7 @@ class JoinLmdbSizeTestCase(SambaToolCmdTest): # Join as an DC with the lmdb backend size set to 1Gb def test_join_as_dc(self): (result, out, err) = self.join("1Gb", "DC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(1 * 1024 * 1024 * 1024) self.assertFalse(self.is_rodc()) @@ -108,7 +108,7 @@ class JoinLmdbSizeTestCase(SambaToolCmdTest): # Join as an RODC with the lmdb backend size set to 128Mb def test_join_as_rodc(self): (result, out, err) = self.join("128Mb", "RODC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(128 * 1024 * 1024) self.assertTrue(self.is_rodc()) @@ -116,7 +116,7 @@ class JoinLmdbSizeTestCase(SambaToolCmdTest): # Join as an RODC with --backend-store-size def test_join_as_rodc_default(self): (result, out, err) = self.join(role="RODC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) self.assertTrue(self.is_rodc()) diff --git a/python/samba/tests/samba_tool/ntacl.py b/python/samba/tests/samba_tool/ntacl.py index ee166764b6a..c9a14ec0ec8 100644 --- a/python/samba/tests/samba_tool/ntacl.py +++ b/python/samba/tests/samba_tool/ntacl.py @@ -32,7 +32,7 @@ class NtACLCmdSysvolTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("ntacl", "sysvolreset", "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been changed, only the stored NT ACL", err) def test_s3fs(self): @@ -40,34 +40,34 @@ class NtACLCmdSysvolTestCase(SambaToolCmdTest): "--use-s3fs") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") def test_ntvfs_check(self): (result, out, err) = self.runsubcmd("ntacl", "sysvolreset", "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been changed, only the stored NT ACL", err) # Now check they were set correctly (result, out, err) = self.runsubcmd("ntacl", "sysvolcheck") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") def test_s3fs_check(self): (result, out, err) = self.runsubcmd("ntacl", "sysvolreset", "--use-s3fs") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") # Now check they were set correctly (result, out, err) = self.runsubcmd("ntacl", "sysvolcheck") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") class NtACLCmdGetSetTestCase(SambaToolCmdTest): @@ -83,7 +83,7 @@ class NtACLCmdGetSetTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("ntacl", "set", self.acl, tempf, "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been changed, only the stored NT ACL", err) def test_s3fs(self): @@ -95,8 +95,8 @@ class NtACLCmdGetSetTestCase(SambaToolCmdTest): "--use-s3fs") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") def test_ntvfs_check(self): path = os.environ['SELFTEST_PREFIX'] @@ -106,15 +106,15 @@ class NtACLCmdGetSetTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("ntacl", "set", self.acl, tempf, "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been changed, only the stored NT ACL", err) # Now check they were set correctly (result, out, err) = self.runsubcmd("ntacl", "get", tempf, "--use-ntvfs", "--as-sddl") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(self.acl + "\n", out, "Output should be the ACL") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(self.acl + "\n", out, "Output should be the ACL") def test_s3fs_check(self): path = os.environ['SELFTEST_PREFIX'] @@ -124,15 +124,15 @@ class NtACLCmdGetSetTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd("ntacl", "set", self.acl, tempf, "--use-s3fs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # Now check they were set correctly (result, out, err) = self.runsubcmd("ntacl", "get", tempf, "--use-s3fs", "--as-sddl") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(self.acl + "\n", out, "Output should be the ACL") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(self.acl + "\n", out, "Output should be the ACL") class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): """Tests for samba-tool ntacl changedomsid subcommand""" @@ -156,7 +156,7 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): tempf, "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been " "changed, only the stored NT ACL", err) @@ -167,7 +167,7 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): tempf, "--use-ntvfs") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEqual(out, "", "Shouldn't be any output messages") self.assertIn("Please note that POSIX permissions have NOT been " "changed, only the stored NT ACL.", err) @@ -178,8 +178,8 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): "--use-ntvfs", "--as-sddl") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(self.new_acl + "\n", out, "Output should be the ACL") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(self.new_acl + "\n", out, "Output should be the ACL") def test_s3fs_check(self): path = os.environ['SELFTEST_PREFIX'] @@ -196,8 +196,8 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): "--use-s3fs", "--service=sysvol") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") (result, out, err) = self.runsubcmd("ntacl", "changedomsid", @@ -207,8 +207,8 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): "--use-s3fs", "--service=sysvol") self.assertCmdSuccess(result, out, err) - self.assertEquals(out, "", "Shouldn't be any output messages") - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(out, "", "Shouldn't be any output messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # Now check they were set correctly (result, out, err) = self.runsubcmd("ntacl", @@ -218,5 +218,5 @@ class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): "--as-sddl", "--service=sysvol") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") - self.assertEquals(self.new_acl + "\n", out, "Output should be the ACL") + self.assertEqual(err, "", "Shouldn't be any error messages") + self.assertEqual(self.new_acl + "\n", out, "Output should be the ACL") diff --git a/python/samba/tests/samba_tool/ou.py b/python/samba/tests/samba_tool/ou.py index 9a6ccfe226a..54fad3c0161 100644 --- a/python/samba/tests/samba_tool/ou.py +++ b/python/samba/tests/samba_tool/ou.py @@ -44,7 +44,7 @@ class OUCmdTestCase(SambaToolCmdTest): (result, out, err) = self._create_ou(ou) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"]) self.assertIn('Created ou "%s"' % full_ou_dn, out) @@ -52,8 +52,8 @@ class OUCmdTestCase(SambaToolCmdTest): self.assertIsNotNone(found) - self.assertEquals("%s" % found.get("name"), ou["name"]) - self.assertEquals("%s" % found.get("description"), + self.assertEqual("%s" % found.get("name"), ou["name"]) + self.assertEqual("%s" % found.get("description"), ou["description"]) def tearDown(self): @@ -91,13 +91,13 @@ class OUCmdTestCase(SambaToolCmdTest): "--description=%s" % ou["description"]) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"]) self.assertIn('Created ou "%s"' % full_ou_dn, out) found = self._find_ou(ou["name"]) - self.assertEquals("%s" % found.get("ou"), + self.assertEqual("%s" % found.get("ou"), "%s" % ou["name"]) # try to delete all the ous we just created (with full dn) @@ -118,13 +118,13 @@ class OUCmdTestCase(SambaToolCmdTest): "--description=%s" % ou["description"]) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"]) self.assertIn('Created ou "%s"' % full_ou_dn, out) found = self._find_ou(ou["name"]) - self.assertEquals("%s" % found.get("ou"), + self.assertEqual("%s" % found.get("ou"), "%s" % ou["name"]) def test_list(self): @@ -199,7 +199,7 @@ class OUCmdTestCase(SambaToolCmdTest): "OU=%s" % parentou["name"]) self.assertCmdSuccess(result, out, err, "Failed to move ou '%s'" % ou["name"]) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"]) self.assertIn('Moved ou "%s"' % full_ou_dn, out) @@ -211,7 +211,7 @@ class OUCmdTestCase(SambaToolCmdTest): "OU=%s,OU=%s,%s" % (ou["name"], parentou["name"], self.samdb.domain_dn())) - self.assertEquals(found.get("dn"), newexpecteddn, + self.assertEqual(found.get("dn"), newexpecteddn, "Moved ou '%s' does not exist" % ou["name"]) @@ -232,7 +232,7 @@ class OUCmdTestCase(SambaToolCmdTest): "--full-dn") self.assertCmdSuccess(result, out, err, "Failed to list ou's objects") - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") objlist = self.samdb.search(base=self.samdb.domain_dn(), scope=ldb.SCOPE_ONELEVEL, @@ -248,7 +248,7 @@ class OUCmdTestCase(SambaToolCmdTest): "--full-dn") self.assertCmdSuccess(result, out, err, "Failed to list ous") - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") filter = "(objectClass=organizationalUnit)" objlist = self.samdb.search(base=self.samdb.domain_dn(), diff --git a/python/samba/tests/samba_tool/passwordsettings.py b/python/samba/tests/samba_tool/passwordsettings.py index 43264b64608..4d83d346717 100644 --- a/python/samba/tests/samba_tool/passwordsettings.py +++ b/python/samba/tests/samba_tool/passwordsettings.py @@ -56,7 +56,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): 'msDS-LockoutObservationWindow', 'msDS-LockoutThreshold', 'msDS-LockoutDuration'] res = self.ldb.search(dn, scope=ldb.SCOPE_BASE, attrs=pso_attrs) - self.assertEquals(len(res), 1, "PSO lookup failed") + self.assertEqual(len(res), 1, "PSO lookup failed") # convert types in the PSO-settings to what the search returns, i.e. # boolean --> string, seconds --> timestamps in -100 nanosecond units @@ -68,23 +68,23 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): max_age = -int(pso.password_age_max * (1e7)) # check the PSO's settings match the search results - self.assertEquals(str(res[0]['msDS-PasswordComplexityEnabled'][0]), + self.assertEqual(str(res[0]['msDS-PasswordComplexityEnabled'][0]), complexity_str) plaintext_res = res[0]['msDS-PasswordReversibleEncryptionEnabled'][0] - self.assertEquals(str(plaintext_res), plaintext_str) - self.assertEquals(int(res[0]['msDS-PasswordHistoryLength'][0]), + self.assertEqual(str(plaintext_res), plaintext_str) + self.assertEqual(int(res[0]['msDS-PasswordHistoryLength'][0]), pso.history_len) - self.assertEquals(int(res[0]['msDS-MinimumPasswordLength'][0]), + self.assertEqual(int(res[0]['msDS-MinimumPasswordLength'][0]), pso.password_len) - self.assertEquals(int(res[0]['msDS-MinimumPasswordAge'][0]), min_age) - self.assertEquals(int(res[0]['msDS-MaximumPasswordAge'][0]), max_age) - self.assertEquals(int(res[0]['msDS-LockoutObservationWindow'][0]), + self.assertEqual(int(res[0]['msDS-MinimumPasswordAge'][0]), min_age) + self.assertEqual(int(res[0]['msDS-MaximumPasswordAge'][0]), max_age) + self.assertEqual(int(res[0]['msDS-LockoutObservationWindow'][0]), lockout_window) - self.assertEquals(int(res[0]['msDS-LockoutDuration'][0]), + self.assertEqual(int(res[0]['msDS-LockoutDuration'][0]), lockout_duration) - self.assertEquals(int(res[0]['msDS-LockoutThreshold'][0]), + self.assertEqual(int(res[0]['msDS-LockoutThreshold'][0]), pso.lockout_attempts) - self.assertEquals(int(res[0]['msDS-PasswordSettingsPrecedence'][0]), + self.assertEqual(int(res[0]['msDS-PasswordSettingsPrecedence'][0]), pso.precedence) # check we can also display the PSO via the show command @@ -121,7 +121,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): self.obj_cleanup.append("CN=%s,%s" % (pso_name, self.pso_container)) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successfully created", out) self.check_pso(pso_name, expected_pso) @@ -163,7 +163,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): self.user_auth) self.obj_cleanup.append("CN=%s,%s" % (pso_name, self.pso_container)) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successfully created", out) self.check_pso(pso_name, expected_pso) @@ -195,7 +195,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): # sanity-check the cmd was successful self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successfully created", out) self.check_pso(pso_name, pso_settings) @@ -219,7 +219,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "-H", self.server, self.user_auth) self.assertCmdSuccess(res, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("Successfully updated", out) # check the PSO's settings now reflect the new values @@ -237,7 +237,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("Deleted PSO", out) dn = "CN=%s,%s" % (pso_name, self.pso_container) self.obj_cleanup.remove(dn) @@ -248,7 +248,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): self.fail("PSO shouldn't exist") except ldb.LdbError as e: (enum, estr) = e.args - self.assertEquals(enum, ldb.ERR_NO_SUCH_OBJECT) + self.assertEqual(enum, ldb.ERR_NO_SUCH_OBJECT) # run the same cmd again - it should fail because PSO no longer exists (result, out, err) = self.runsublevelcmd("domain", ("passwordsettings", @@ -267,7 +267,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): user.name, "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") if pso is None: self.assertIn("No PSO applies to user", out) else: @@ -275,9 +275,9 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): # then check the DB tells us the same thing if pso is None: - self.assertEquals(user.get_resultant_PSO(), None) + self.assertEqual(user.get_resultant_PSO(), None) else: - self.assertEquals(user.get_resultant_PSO(), pso.dn) + self.assertEqual(user.get_resultant_PSO(), pso.dn) def test_pso_apply_to_user(self): """Checks we can apply/unapply a PSO to a user""" @@ -307,7 +307,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): group_name, "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.check_pso_applied(user, pso=test_pso) # we should fail if we try to apply the same PSO/group twice though @@ -324,7 +324,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): user.name, "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.check_pso_applied(user, pso=test_pso) # check samba-tool can successfully unlink a group from a PSO @@ -333,7 +333,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): group_name, "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # PSO still applies directly to the user, even though group was removed self.check_pso_applied(user, pso=test_pso) @@ -343,7 +343,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): user.name, "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.check_pso_applied(user, pso=None) def test_pso_unpriv(self): @@ -418,7 +418,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "show"), "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # check an arbitrary setting is displayed correctly min_pwd_len = self.ldb.get_minPwdLength() @@ -433,16 +433,16 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successful", out) - self.assertEquals(new_len, self.ldb.get_minPwdLength()) + self.assertEqual(new_len, self.ldb.get_minPwdLength()) # check the updated value is now displayed (result, out, err) = self.runsublevelcmd("domain", ("passwordsettings", "show"), "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("Minimum password length: %u" % new_len, out) def test_domain_passwordsettings_pwdage(self): @@ -457,7 +457,7 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successful", out) self.assertNotEquals(max_pwd_age, self.ldb.get_maxPwdAge()) @@ -479,6 +479,6 @@ class PwdSettingsCmdTestCase(SambaToolCmdTest): "-H", self.server, self.user_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("successful", out) self.assertNotEquals(min_pwd_age, self.ldb.get_minPwdAge()) diff --git a/python/samba/tests/samba_tool/promote_dc_lmdb_size.py b/python/samba/tests/samba_tool/promote_dc_lmdb_size.py index 5e682ca506f..8e679a5c95f 100644 --- a/python/samba/tests/samba_tool/promote_dc_lmdb_size.py +++ b/python/samba/tests/samba_tool/promote_dc_lmdb_size.py @@ -105,9 +105,9 @@ class PromoteDcLmdbSizeTestCase(SambaToolCmdTest): # 8Gb is used def test_promote_dc_default(self): (result, out, err) = self.join_member() - self.assertEquals(0, result) + self.assertEqual(0, result) (result, out, err) = self.promote(role="DC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) self.assertFalse(self.is_rodc()) @@ -116,9 +116,9 @@ class PromoteDcLmdbSizeTestCase(SambaToolCmdTest): # 8Gb is used def test_promote_rodc_default(self): (result, out, err) = self.join_member() - self.assertEquals(0, result) + self.assertEqual(0, result) (result, out, err) = self.promote(role="RODC") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) self.assertTrue(self.is_rodc()) @@ -126,9 +126,9 @@ class PromoteDcLmdbSizeTestCase(SambaToolCmdTest): # Promote to a DC with a backend size of 96Mb def test_promote_dc_96Mb(self): (result, out, err) = self.join_member() - self.assertEquals(0, result) + self.assertEqual(0, result) (result, out, err) = self.promote(role="DC", size="96Mb") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(96 * 1024 * 1024) self.assertFalse(self.is_rodc()) @@ -136,9 +136,9 @@ class PromoteDcLmdbSizeTestCase(SambaToolCmdTest): # Promote to an RODC with a backend size of 256Mb def test_promote_rodc_256Mb(self): (result, out, err) = self.join_member() - self.assertEquals(0, result) + self.assertEqual(0, result) (result, out, err) = self.promote(role="RODC", size="256Mb") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(256 * 1024 * 1024) self.assertTrue(self.is_rodc()) diff --git a/python/samba/tests/samba_tool/provision_lmdb_size.py b/python/samba/tests/samba_tool/provision_lmdb_size.py index c48cb67eac5..970486622df 100644 --- a/python/samba/tests/samba_tool/provision_lmdb_size.py +++ b/python/samba/tests/samba_tool/provision_lmdb_size.py @@ -84,24 +84,24 @@ class ProvisionLmdbSizeTestCase(SambaToolCmdTest): # 8Gb is used def test_default(self): (result, out, err) = self.provision() - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(8 * 1024 * 1024 * 1024) def test_64Mb(self): (result, out, err) = self.provision("64Mb") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(64 * 1024 * 1024) def test_1Gb(self): (result, out, err) = self.provision("1Gb") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(1 * 1024 * 1024 * 1024) # 128Mb specified in bytes. # def test_134217728b(self): (result, out, err) = self.provision("134217728b") - self.assertEquals(0, result) + self.assertEqual(0, result) self.check_lmdb_environment_sizes(134217728) def test_no_unit_suffix(self): diff --git a/python/samba/tests/samba_tool/schema.py b/python/samba/tests/samba_tool/schema.py index 7a80b33cd26..6f899ef4b68 100644 --- a/python/samba/tests/samba_tool/schema.py +++ b/python/samba/tests/samba_tool/schema.py @@ -41,7 +41,7 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("dn: CN=uid,CN=Schema,CN=Configuration,", out) def test_modify_attribute_searchflags(self): @@ -61,7 +61,7 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("modified cn=uid,CN=Schema,CN=Configuration,", out) (result, out, err) = self.runsublevelcmd("schema", ("attribute", @@ -72,7 +72,7 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("modified cn=uid,CN=Schema,CN=Configuration,", out) (result, out, err) = self.runsublevelcmd("schema", ("attribute", @@ -83,7 +83,7 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("modified cn=uid,CN=Schema,CN=Configuration,", out) def test_show_oc_attribute(self): @@ -95,7 +95,7 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("--- MAY contain ---", out) self.assertIn("--- MUST contain ---", out) @@ -108,5 +108,5 @@ class SchemaCmdTestCase(SambaToolCmdTest): os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("dn: CN=Person,CN=Schema,CN=Configuration,", out) diff --git a/python/samba/tests/samba_tool/sites.py b/python/samba/tests/samba_tool/sites.py index 89197f7764a..1009cf28b98 100644 --- a/python/samba/tests/samba_tool/sites.py +++ b/python/samba/tests/samba_tool/sites.py @@ -51,7 +51,7 @@ class SitesCmdTestCase(BaseSitesCmdTestCase): ret = self.samdb.search(base=dnsites, scope=ldb.SCOPE_ONELEVEL, expression='(cn=%s)' % sitename) - self.assertEquals(len(ret), 1) + self.assertEqual(len(ret), 1) # now delete it self.samdb.delete(dnsite, ["tree_delete:0"]) diff --git a/python/samba/tests/samba_tool/timecmd.py b/python/samba/tests/samba_tool/timecmd.py index 1db51dc73e9..8e286f67f37 100644 --- a/python/samba/tests/samba_tool/timecmd.py +++ b/python/samba/tests/samba_tool/timecmd.py @@ -39,6 +39,6 @@ class TimeCmdTestCase(SambaToolCmdTest): def test_timefail(self): """Run time against a non-existent server, and make sure it fails""" (result, out, err) = self.runcmd("time", "notaserver") - self.assertEquals(result, -1, "check for result code") + self.assertEqual(result, -1, "check for result code") self.assertNotEqual(err.strip().find("NT_STATUS_OBJECT_NAME_NOT_FOUND"), -1, "ensure right error string") - self.assertEquals(out, "", "ensure no output returned") + self.assertEqual(out, "", "ensure no output returned") diff --git a/python/samba/tests/samba_tool/user.py b/python/samba/tests/samba_tool/user.py index 65930ed89de..2ca32a26ed7 100644 --- a/python/samba/tests/samba_tool/user.py +++ b/python/samba/tests/samba_tool/user.py @@ -60,7 +60,7 @@ class UserCmdTestCase(SambaToolCmdTest): (result, out, err) = user["createUserFn"](user) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") if 'unix' in user["name"]: self.assertIn("Modified User '%s' successfully" % user["name"], out) @@ -112,13 +112,13 @@ class UserCmdTestCase(SambaToolCmdTest): "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("User '%s' created successfully" % user["name"], out) found = self._find_user(user["name"]) - self.assertEquals("%s" % found.get("cn"), "%(name)s" % user) - self.assertEquals("%s" % found.get("name"), "%(name)s" % user) + self.assertEqual("%s" % found.get("cn"), "%(name)s" % user) + self.assertEqual("%s" % found.get("name"), "%(name)s" % user) def _verify_supplementalCredentials(self, ldif, min_packages=3, @@ -212,7 +212,7 @@ class UserCmdTestCase(SambaToolCmdTest): "-H", "ldap://%s" % os.environ["DC_SERVER"], "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err, "Ensure setpassword runs") - self.assertEquals(err, "", "setpassword with url") + self.assertEqual(err, "", "setpassword with url") self.assertMatch(out, "Changed password OK", "setpassword with url") attributes = "sAMAccountName,unicodePwd,supplementalCredentials,virtualClearTextUTF8,virtualClearTextUTF16,virtualSSHA,virtualSambaGPG" @@ -260,7 +260,7 @@ class UserCmdTestCase(SambaToolCmdTest): user["name"], "--newpassword=%s" % newpasswd) self.assertCmdSuccess(result, out, err, "Ensure setpassword runs") - self.assertEquals(err, "", "setpassword without url") + self.assertEqual(err, "", "setpassword without url") self.assertMatch(out, "Changed password OK", "setpassword without url") (result, out, err) = self.runsubcmd("user", "syncpasswords", "--no-wait") @@ -317,7 +317,7 @@ class UserCmdTestCase(SambaToolCmdTest): "-H", "ldap://%s" % os.environ["DC_SERVER"], "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err, "Ensure setpassword runs") - self.assertEquals(err, "", "setpassword with forced change") + self.assertEqual(err, "", "setpassword with forced change") self.assertMatch(out, "Changed password OK", "setpassword with forced change") def test_setexpiry(self): @@ -451,7 +451,7 @@ sAMAccountName: %s full_ou_dn = str(self.samdb.normalize_dn_in_domain("OU=movetest")) (result, out, err) = self.runsubcmd("ou", "create", full_ou_dn) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "There shouldn't be any error message") + self.assertEqual(err, "", "There shouldn't be any error message") self.assertIn('Created ou "%s"' % full_ou_dn, out) for user in self.users: @@ -524,7 +524,7 @@ sAMAccountName: %s "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("User '%s' created successfully" % user["name"], out) self._check_posix_user(user) @@ -553,7 +553,7 @@ sAMAccountName: %s "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"])) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") self.assertIn("User '%s' created successfully" % user["name"], out) self._check_posix_user(user) @@ -616,21 +616,21 @@ sAMAccountName: %s """ check if a user from SamDB has the same attributes as its template """ found = self._find_user(user["name"]) - self.assertEquals("%s" % found.get("name"), "%(given-name)s %(surname)s" % user) - self.assertEquals("%s" % found.get("title"), user["job-title"]) - self.assertEquals("%s" % found.get("company"), user["company"]) - self.assertEquals("%s" % found.get("description"), user["description"]) - self.assertEquals("%s" % found.get("department"), user["department"]) + self.assertEqual("%s" % found.get("name"), "%(given-name)s %(surname)s" % user) + self.assertEqual("%s" % found.get("title"), user["job-title"]) + self.assertEqual("%s" % found.get("company"), user["company"]) + self.assertEqual("%s" % found.get("description"), user["description"]) + self.assertEqual("%s" % found.get("department"), user["department"]) def _check_posix_user(self, user): """ check if a posix_user from SamDB has the same attributes as its template """ found = self._find_user(user["name"]) - self.assertEquals("%s" % found.get("loginShell"), user["loginShell"]) - self.assertEquals("%s" % found.get("gecos"), user["gecos"]) - self.assertEquals("%s" % found.get("uidNumber"), "%s" % user["uidNumber"]) - self.assertEquals("%s" % found.get("gidNumber"), "%s" % user["gidNumber"]) - self.assertEquals("%s" % found.get("uid"), user["uid"]) + self.assertEqual("%s" % found.get("loginShell"), user["loginShell"]) + self.assertEqual("%s" % found.get("gecos"), user["gecos"]) + self.assertEqual("%s" % found.get("uidNumber"), "%s" % user["uidNumber"]) + self.assertEqual("%s" % found.get("gidNumber"), "%s" % user["gidNumber"]) + self.assertEqual("%s" % found.get("uid"), user["uid"]) self._check_user(user) def _check_unix_user(self, user): @@ -638,13 +638,13 @@ sAMAccountName: %s template """ found = self._find_user(user["name"]) - self.assertEquals("%s" % found.get("loginShell"), user["loginShell"]) - self.assertEquals("%s" % found.get("gecos"), user["gecos"]) - self.assertEquals("%s" % found.get("uidNumber"), "%s" % + self.assertEqual("%s" % found.get("loginShell"), user["loginShell"]) + self.assertEqual("%s" % found.get("gecos"), user["gecos"]) + self.assertEqual("%s" % found.get("uidNumber"), "%s" % user["uidNumber"]) - self.assertEquals("%s" % found.get("gidNumber"), "%s" % + self.assertEqual("%s" % found.get("gidNumber"), "%s" % user["gidNumber"]) - self.assertEquals("%s" % found.get("uid"), user["uid"]) + self.assertEqual("%s" % found.get("uid"), user["uid"]) self._check_user(user) def _create_user(self, user): diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA.py b/python/samba/tests/samba_tool/user_virtualCryptSHA.py index f488bc7799d..3db6ffddacd 100644 --- a/python/samba/tests/samba_tool/user_virtualCryptSHA.py +++ b/python/samba/tests/samba_tool/user_virtualCryptSHA.py @@ -329,8 +329,8 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): sha512 = _get_attribute(out, "virtualCryptSHA512") out = self._get_password("virtualCryptSHA256,virtualCryptSHA512") - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # gpg decryption not enabled. # both virtual attributes specified, rounds specified @@ -352,8 +352,8 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): sha512 = _get_attribute(out, "virtualCryptSHA512") out = self._get_password("virtualCryptSHA256,virtualCryptSHA512") - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # gpg decryption not enabled. # both virtual attributes specified, rounds specified @@ -379,8 +379,8 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): out = self._get_password("virtualCryptSHA256;rounds=2561," + "virtualCryptSHA512;rounds=5129") - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # Number of rounds should match that specified self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=2561")) @@ -411,15 +411,15 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): out = self._get_password("virtualCryptSHA256;rounds=4000," + "virtualCryptSHA512;rounds=5000") - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # As the number of rounds did not match, should have returned the # first hash of the coresponding scheme out = self._get_password("virtualCryptSHA256," + "virtualCryptSHA512") - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # gpg decryption enabled. # both virtual attributes specified, no rounds option @@ -440,8 +440,8 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): sha512 = _get_attribute(out, "virtualCryptSHA512") out = self._get_password("virtualCryptSHA256,virtualCryptSHA512", True) - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # gpg decryption enabled. # both virtual attributes specified, rounds specified @@ -499,8 +499,8 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest): out = self._get_password("virtualCryptSHA256;rounds=2561," + "virtualCryptSHA512;rounds=5129", True) - self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256")) - self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512")) + self.assertEqual(sha256, _get_attribute(out, "virtualCryptSHA256")) + self.assertEqual(sha512, _get_attribute(out, "virtualCryptSHA512")) # The returned hashes should specify the correct number of rounds self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=2561")) diff --git a/python/samba/tests/samba_tool/visualize_drs.py b/python/samba/tests/samba_tool/visualize_drs.py index 9b1588bd1ef..3eda02783f6 100644 --- a/python/samba/tests/samba_tool/visualize_drs.py +++ b/python/samba/tests/samba_tool/visualize_drs.py @@ -223,7 +223,7 @@ class SambaToolVisualizeDrsTest(SambaToolCmdTest): self.assertCmdSuccess(result, out, err) lines = out.splitlines() - self.assertEquals(len(lines), 1) + self.assertEqual(len(lines), 1) line = lines[0] self.assertTrue(line.startswith('DOMAIN')) diff --git a/python/samba/tests/samdb_api.py b/python/samba/tests/samdb_api.py index cf32151d259..a7260180187 100644 --- a/python/samba/tests/samdb_api.py +++ b/python/samba/tests/samdb_api.py @@ -32,12 +32,12 @@ class SamDBApiTestCase(TestCaseInTempDir): try: os.remove(self.tempdir + "/test.db") except OSError as e: - self.assertEquals(e.errno, errno.ENOENT) + self.assertEqual(e.errno, errno.ENOENT) try: os.remove(self.tempdir + "/existing.db") except OSError as e: - self.assertEquals(e.errno, errno.ENOENT) + self.assertEqual(e.errno, errno.ENOENT) super(SamDBApiTestCase, self).tearDown() @@ -58,11 +58,11 @@ class SamDBApiTestCase(TestCaseInTempDir): self.fail("Exception not thrown ") except LdbError as e: (err, _) = e.args - self.assertEquals(err, ERR_OPERATIONS_ERROR) + self.assertEqual(err, ERR_OPERATIONS_ERROR) existing = open(existing_name, "r") contents = existing.readline() - self.assertEquals("This is not a tdb file!!!!!!\n", contents) + self.assertEqual("This is not a tdb file!!!!!!\n", contents) # Attempt to open and existing non tdb file as a tdb file. # Don't create new db is cleared @@ -80,7 +80,7 @@ class SamDBApiTestCase(TestCaseInTempDir): existing = open(existing_name, "rb") contents = existing.readline() - self.assertEquals(b"TDB file\n", contents) + self.assertEqual(b"TDB file\n", contents) # # Attempt to open an existing tdb file as a tdb file. @@ -99,11 +99,11 @@ class SamDBApiTestCase(TestCaseInTempDir): }) cn = initial.searchone("cn", dn) - self.assertEquals(b"test_dont_create_db_existing_tdb_file", cn) + self.assertEqual(b"test_dont_create_db_existing_tdb_file", cn) second = SamDB(url="tdb://" + existing_name) cn = second.searchone("cn", dn) - self.assertEquals(b"test_dont_create_db_existing_tdb_file", cn) + self.assertEqual(b"test_dont_create_db_existing_tdb_file", cn) # # Attempt to open an existing tdb file as a tdb file. @@ -122,11 +122,11 @@ class SamDBApiTestCase(TestCaseInTempDir): }) cn = initial.searchone("cn", dn) - self.assertEquals(b"test_dont_create_db_existing_tdb_file", cn) + self.assertEqual(b"test_dont_create_db_existing_tdb_file", cn) second = SamDB(url="tdb://" + existing_name, flags=0) cn = second.searchone("cn", dn) - self.assertEquals(b"test_dont_create_db_existing_tdb_file", cn) + self.assertEqual(b"test_dont_create_db_existing_tdb_file", cn) # Open a non existent TDB file. # Don't create new db is set, the default @@ -139,13 +139,13 @@ class SamDBApiTestCase(TestCaseInTempDir): self.fail("Exception not thrown ") except LdbError as e1: (err, _) = e1.args - self.assertEquals(err, ERR_OPERATIONS_ERROR) + self.assertEqual(err, ERR_OPERATIONS_ERROR) try: file = open(self.tempdir + "/test.db", "r") self.fail("New database file created") except IOError as e: - self.assertEquals(e.errno, errno.ENOENT) + self.assertEqual(e.errno, errno.ENOENT) # Open a SamDB with the don't create new DB flag cleared. # The underlying database file does not exist. @@ -157,4 +157,4 @@ class SamDBApiTestCase(TestCaseInTempDir): SamDB(url="tdb://" + self.tempdir + "/test.db", flags=0) existing = open(self.tempdir + "/test.db", mode="rb") contents = existing.readline() - self.assertEquals(b"TDB file\n", contents) + self.assertEqual(b"TDB file\n", contents) diff --git a/python/samba/tests/security.py b/python/samba/tests/security.py index 1b1c1557eee..1dacf78499a 100644 --- a/python/samba/tests/security.py +++ b/python/samba/tests/security.py @@ -59,11 +59,11 @@ class SecurityDescriptorTests(samba.tests.TestCase): def test_from_sddl(self): desc = security.descriptor.from_sddl("O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)", security.dom_sid("S-2-0-0")) - self.assertEquals(desc.group_sid, security.dom_sid('S-2-0-0-512')) - self.assertEquals(desc.owner_sid, security.dom_sid('S-1-5-32-548')) - self.assertEquals(desc.revision, 1) - self.assertEquals(desc.sacl, None) - self.assertEquals(desc.type, 0x8004) + self.assertEqual(desc.group_sid, security.dom_sid('S-2-0-0-512')) + self.assertEqual(desc.owner_sid, security.dom_sid('S-1-5-32-548')) + self.assertEqual(desc.revision, 1) + self.assertEqual(desc.sacl, None) + self.assertEqual(desc.type, 0x8004) def test_from_sddl_invalidsddl(self): self.assertRaises(TypeError, security.descriptor.from_sddl, "foo", security.dom_sid("S-2-0-0")) @@ -81,10 +81,10 @@ class SecurityDescriptorTests(samba.tests.TestCase): dom = security.dom_sid("S-2-0-0") desc1 = security.descriptor.from_sddl(text, dom) desc2 = security.descriptor.from_sddl(desc1.as_sddl(dom), dom) - self.assertEquals(desc1.group_sid, desc2.group_sid) - self.assertEquals(desc1.owner_sid, desc2.owner_sid) - self.assertEquals(desc1.sacl, desc2.sacl) - self.assertEquals(desc1.type, desc2.type) + self.assertEqual(desc1.group_sid, desc2.group_sid) + self.assertEqual(desc1.owner_sid, desc2.owner_sid) + self.assertEqual(desc1.sacl, desc2.sacl) + self.assertEqual(desc1.type, desc2.type) def test_as_sddl_invalid(self): text = "O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" @@ -97,10 +97,10 @@ class SecurityDescriptorTests(samba.tests.TestCase): text = "O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" desc1 = security.descriptor.from_sddl(text, dom) desc2 = security.descriptor.from_sddl(desc1.as_sddl(), dom) - self.assertEquals(desc1.group_sid, desc2.group_sid) - self.assertEquals(desc1.owner_sid, desc2.owner_sid) - self.assertEquals(desc1.sacl, desc2.sacl) - self.assertEquals(desc1.type, desc2.type) + self.assertEqual(desc1.group_sid, desc2.group_sid) + self.assertEqual(desc1.owner_sid, desc2.owner_sid) + self.assertEqual(desc1.sacl, desc2.sacl) + self.assertEqual(desc1.type, desc2.type) def test_domsid_nodomsid_as_sddl(self): dom = security.dom_sid("S-2-0-0") @@ -110,20 +110,20 @@ class SecurityDescriptorTests(samba.tests.TestCase): def test_split(self): dom = security.dom_sid("S-2-0-7") - self.assertEquals((security.dom_sid("S-2-0"), 7), dom.split()) + self.assertEqual((security.dom_sid("S-2-0"), 7), dom.split()) class DomSidTests(samba.tests.TestCase): def test_parse_sid(self): sid = security.dom_sid("S-1-5-21") - self.assertEquals("S-1-5-21", str(sid)) + self.assertEqual("S-1-5-21", str(sid)) def test_sid_equal(self): sid1 = security.dom_sid("S-1-5-21") sid2 = security.dom_sid("S-1-5-21") - self.assertEquals(sid1, sid1) - self.assertEquals(sid1, sid2) + self.assertEqual(sid1, sid1) + self.assertEqual(sid1, sid2) def test_random(self): sid = security.random_sid() @@ -137,11 +137,11 @@ class DomSidTests(samba.tests.TestCase): class PrivilegeTests(samba.tests.TestCase): def test_privilege_name(self): - self.assertEquals("SeShutdownPrivilege", + self.assertEqual("SeShutdownPrivilege", security.privilege_name(security.SEC_PRIV_SHUTDOWN)) def test_privilege_id(self): - self.assertEquals(security.SEC_PRIV_SHUTDOWN, + self.assertEqual(security.SEC_PRIV_SHUTDOWN, security.privilege_id("SeShutdownPrivilege")) diff --git a/python/samba/tests/smb.py b/python/samba/tests/smb.py index 5a52885c2f4..e43b030adcc 100644 --- a/python/samba/tests/smb.py +++ b/python/samba/tests/smb.py @@ -194,14 +194,14 @@ class SMBTests(samba.tests.TestCase): self.smb_conn.savefile(test_file, test_contents.encode('utf8')) contents = self.smb_conn.loadfile(test_file) - self.assertEquals(contents.decode('utf8'), test_contents, + self.assertEqual(contents.decode('utf8'), test_contents, msg='contents of test file did not match what was written') # check we can overwrite the file with new contents new_contents = 'wxyz' * 128 self.smb_conn.savefile(test_file, new_contents.encode('utf8')) contents = self.smb_conn.loadfile(test_file) - self.assertEquals(contents.decode('utf8'), new_contents, + self.assertEqual(contents.decode('utf8'), new_contents, msg='contents of test file did not match what was written') # with python2 this will save/load str type (with embedded nulls) @@ -210,7 +210,7 @@ class SMBTests(samba.tests.TestCase): self.smb_conn.savefile(test_file, test_literal_bytes_embed_nulls) contents = self.smb_conn.loadfile(test_file) - self.assertEquals(contents, test_literal_bytes_embed_nulls, + self.assertEqual(contents, test_literal_bytes_embed_nulls, msg='contents of test file did not match what was written') # python3 only this will save/load unicode @@ -219,7 +219,7 @@ class SMBTests(samba.tests.TestCase): self.smb_conn.savefile(test_file, utf_contents.encode('utf8')) contents = self.smb_conn.loadfile(test_file) - self.assertEquals(contents.decode('utf8'), utf_contents, + self.assertEqual(contents.decode('utf8'), utf_contents, msg='contents of test file did not match what was written') # with python2 this will save/load str type @@ -228,7 +228,7 @@ class SMBTests(samba.tests.TestCase): self.smb_conn.savefile(test_file, binary_contents) contents = self.smb_conn.loadfile(test_file) - self.assertEquals(contents, binary_contents, + self.assertEqual(contents, binary_contents, msg='contents of test file did not match what was written') def make_sysvol_path(self, dirpath, filename): diff --git a/python/samba/tests/strings.py b/python/samba/tests/strings.py index 657d99496fc..e812df8a97e 100644 --- a/python/samba/tests/strings.py +++ b/python/samba/tests/strings.py @@ -60,7 +60,7 @@ class strcasecmp_m_Tests(samba.tests.TestCase): (KATAKANA_LETTER_A, 'a', 1), ] for a, b, expect in cases: - self.assertEquals(signum(strcasecmp_m(a, b)), expect) + self.assertEqual(signum(strcasecmp_m(a, b)), expect) class strstr_m_Tests(samba.tests.TestCase): @@ -96,4 +96,4 @@ class strstr_m_Tests(samba.tests.TestCase): (KATAKANA_LETTER_A * 3, 'a', None), ] for a, b, expect in cases: - self.assertEquals(strstr_m(a, b), expect) + self.assertEqual(strstr_m(a, b), expect) diff --git a/python/samba/tests/upgrade.py b/python/samba/tests/upgrade.py index 9e539a98ff5..0cca2d0dc6c 100644 --- a/python/samba/tests/upgrade.py +++ b/python/samba/tests/upgrade.py @@ -29,12 +29,12 @@ class WinsUpgradeTests(LdbTestCase): } import_wins(self.ldb, winsdb) - self.assertEquals( + self.assertEqual( ['name=FOO,type=0x20'], [str(m.dn) for m in self.ldb.search(expression="(objectClass=winsRecord)")]) def test_version(self): import_wins(self.ldb, {}) - self.assertEquals("VERSION", + self.assertEqual("VERSION", str(self.ldb.search(expression="(objectClass=winsMaxVersion)")[0]["cn"])) diff --git a/python/samba/tests/upgradeprovision.py b/python/samba/tests/upgradeprovision.py index ab091676fca..5f77a777fc9 100644 --- a/python/samba/tests/upgradeprovision.py +++ b/python/samba/tests/upgradeprovision.py @@ -54,11 +54,11 @@ class UpgradeProvisionTestCase(TestCaseInTempDir): # higher level comes after lower even if lexicographicaly closer # ie dc=tata,dc=toto (2 levels), comes after dc=toto # even if dc=toto is lexicographicaly after dc=tata, dc=toto - self.assertEquals(dn_sort("dc=tata,dc=toto", "dc=toto"), 1) - self.assertEquals(dn_sort("dc=zata", "dc=tata"), 1) - self.assertEquals(dn_sort("dc=toto,dc=tata", + self.assertEqual(dn_sort("dc=tata,dc=toto", "dc=toto"), 1) + self.assertEqual(dn_sort("dc=zata", "dc=tata"), 1) + self.assertEqual(dn_sort("dc=toto,dc=tata", "cn=foo,dc=toto,dc=tata"), -1) - self.assertEquals(dn_sort("cn=bar, dc=toto,dc=tata", + self.assertEqual(dn_sort("cn=bar, dc=toto,dc=tata", "cn=foo, dc=toto,dc=tata"), -1) def test_get_diff_sds(self): @@ -81,17 +81,17 @@ class UpgradeProvisionTestCase(TestCaseInTempDir): (A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)(AU;CIIDSA;WP;;;WD)" - self.assertEquals(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), + self.assertEqual(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl1, domsid), domsid), "") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl2, domsid), domsid) - self.assertEquals(txt, "\tOwner mismatch: SA (in ref) BA(in current)\n") + self.assertEqual(txt, "\tOwner mismatch: SA (in ref) BA(in current)\n") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl3, domsid), domsid) - self.assertEquals(txt, "\tGroup mismatch: DU (in ref) BA(in current)\n") + self.assertEqual(txt, "\tGroup mismatch: DU (in ref) BA(in current)\n") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl4, domsid), domsid) @@ -99,25 +99,25 @@ class UpgradeProvisionTestCase(TestCaseInTempDir): is the detail:\n\t\t(A;CI;RPWPCRCCLCLORCWOWDSW;;;BA) ACE is not present in\ the reference\n\t\t(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA) ACE is not present in\ the current\n" - self.assertEquals(txt, txtmsg) + self.assertEqual(txt, txtmsg) txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl5, domsid), domsid) - self.assertEquals(txt, "\tCurrent ACL hasn't a sacl part\n") - self.assertEquals(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), + self.assertEqual(txt, "\tCurrent ACL hasn't a sacl part\n") + self.assertEqual(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl6, domsid), domsid), "") def test_construct_existor_expr(self): res = construct_existor_expr([]) - self.assertEquals(res, "") + self.assertEqual(res, "") res = construct_existor_expr(["foo"]) - self.assertEquals(res, "(|(foo=*))") + self.assertEqual(res, "(|(foo=*))") res = construct_existor_expr(["foo", "bar"]) - self.assertEquals(res, "(|(foo=*)(bar=*))") + self.assertEqual(res, "(|(foo=*)(bar=*))") class UpdateSecretsTests(samba.tests.TestCaseInTempDir): @@ -137,7 +137,7 @@ class UpdateSecretsTests(samba.tests.TestCaseInTempDir): def test_trivial(self): # Test that updating an already up-to-date secretsdb works fine self.secretsdb = self._getCurrentFormatDb() - self.assertEquals(None, + self.assertEqual(None, update_secrets(self.referencedb, self.secretsdb, dummymessage)) def test_update_modules(self): @@ -145,7 +145,7 @@ class UpdateSecretsTests(samba.tests.TestCaseInTempDir): update_secrets(self.referencedb, empty_db, dummymessage) newmodules = empty_db.search(base="@MODULES", scope=SCOPE_BASE) refmodules = self.referencedb.search(base="@MODULES", scope=SCOPE_BASE) - self.assertEquals(newmodules.msgs, refmodules.msgs) + self.assertEqual(newmodules.msgs, refmodules.msgs) def tearDown(self): for name in ["ref.ldb", "secrets.ldb", "secrets.tdb", "secrets.tdb.bak", "secrets.ntdb"]: diff --git a/python/samba/tests/upgradeprovisionneeddc.py b/python/samba/tests/upgradeprovisionneeddc.py index b665e5ba3c7..45a29da0d17 100644 --- a/python/samba/tests/upgradeprovisionneeddc.py +++ b/python/samba/tests/upgradeprovisionneeddc.py @@ -64,8 +64,8 @@ class UpgradeProvisionBasicLdbHelpersTestCase(TestCaseInTempDir): ldbs = get_ldbs(paths, creds, system_session(), lp) names = find_provision_key_parameters(ldbs.sam, ldbs.secrets, ldbs.idmap, paths, smb_conf_path, lp) - self.assertEquals(names.realm, "SAMBA.EXAMPLE.COM") - self.assertEquals(str(names.rootdn).lower(), rootdn.lower()) + self.assertEqual(names.realm, "SAMBA.EXAMPLE.COM") + self.assertEqual(str(names.rootdn).lower(), rootdn.lower()) self.assertNotEquals(names.policyid_dc, None) self.assertNotEquals(names.ntdsguid, "") @@ -125,8 +125,8 @@ class UpgradeProvisionWithLdbTestCase(TestCaseInTempDir): identic_rename(self.ldbs.sam, guestDN) res = self.ldbs.sam.search(expression="(name=Guest)", base=rootdn, scope=ldb.SCOPE_SUBTREE, attrs=["dn"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["dn"]), "CN=Guest,CN=Users,%s" % rootdn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["dn"]), "CN=Guest,CN=Users,%s" % rootdn) def test_delta_update_basesamdb(self): dummysampath = self._getEmptyDbName() diff --git a/python/samba/tests/xattr.py b/python/samba/tests/xattr.py index 5943464c047..d2aa49309f3 100644 --- a/python/samba/tests/xattr.py +++ b/python/samba/tests/xattr.py @@ -66,7 +66,7 @@ class XattrTests(TestCase): try: samba.xattr_native.wrap_setxattr(tempf, "user.unittests", reftxt) text = samba.xattr_native.wrap_getxattr(tempf, "user.unittests") - self.assertEquals(text, reftxt) + self.assertEqual(text, reftxt) except IOError: raise SkipTest("the filesystem where the tests are runned do not support XATTR") os.unlink(tempf) @@ -106,7 +106,7 @@ class XattrTests(TestCase): reftxt) text = samba.xattr_tdb.wrap_getxattr(eadb_path, tempf, "user.unittests") - self.assertEquals(text, reftxt) + self.assertEqual(text, reftxt) finally: os.unlink(tempf) os.unlink(eadb_path) @@ -134,7 +134,7 @@ class XattrTests(TestCase): reftxt) text = samba.posix_eadb.wrap_getxattr(eadb_path, tempf, "user.unittests") - self.assertEquals(text, reftxt) + self.assertEqual(text, reftxt) finally: os.unlink(tempf) os.unlink(eadb_path) diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index daf3849d936..815422c2677 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -208,7 +208,7 @@ class AclAddTests(AclTests): grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() # Make sure we HAVEN'T created any of two objects -- user or group @@ -233,7 +233,7 @@ class AclAddTests(AclTests): grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP) except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() # Make sure we HAVE created the one of two objects -- user @@ -270,7 +270,7 @@ class AclAddTests(AclTests): anonymous.newuser("test_add_anonymous", self.user_pass) except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() @@ -384,7 +384,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -413,7 +413,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e4: (num, _) = e4.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -429,7 +429,7 @@ displayName: test_changed""" self.ldb_user.modify_ldif(ldif) except LdbError as e5: (num, _) = e5.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -457,7 +457,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e6: (num, _) = e6.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -477,7 +477,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -496,7 +496,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e8: (num, _) = e8.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -515,7 +515,7 @@ url: www.samba.org""" self.ldb_user.modify_ldif(ldif) except LdbError as e9: (num, _) = e9.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -531,7 +531,7 @@ adminDescription: blah blah blah""" self.ldb_user.modify_ldif(ldif) except LdbError as e10: (num, _) = e10.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -556,7 +556,7 @@ Member: """ + self.get_user_dn(self.user_with_sm) self.ldb_user2.modify_ldif(ldif) except LdbError as e11: (num, _) = e11.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -579,7 +579,7 @@ Member: CN=test_modify_user2,CN=Users,""" + self.base_dn self.ldb_user2.modify_ldif(ldif) except LdbError as e12: (num, _) = e12.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -600,7 +600,7 @@ Member: CN=test_modify_user2,CN=Users,""" + self.base_dn self.ldb_user2.modify_ldif(ldif) except LdbError as e13: (num, _) = e13.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -648,7 +648,7 @@ Member: CN=test_modify_user2,CN=Users,""" + self.base_dn anonymous.modify(m) except LdbError as e14: (num, _) = e14.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() @@ -733,7 +733,7 @@ class AclSearchTests(AclTests): """Verify access of rootDSE with the correct request""" anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp) res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_BASE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # verify some of the attributes # don't care about values self.assertTrue("ldapServiceName" in res[0]) @@ -752,14 +752,14 @@ class AclSearchTests(AclTests): res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_SUBTREE) except LdbError as e15: (num, _) = e15.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() try: res = anonymous.search(self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) except LdbError as e16: (num, _) = e16.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() try: @@ -767,7 +767,7 @@ class AclSearchTests(AclTests): scope=SCOPE_SUBTREE) except LdbError as e17: (num, _) = e17.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() @@ -781,13 +781,13 @@ class AclSearchTests(AclTests): anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp) res = anonymous.search("OU=test_search_ou2,OU=test_search_ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("dn" in res[0]) self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin, "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn)) res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("dn" in res[0]) self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin, self.configuration_dn)) @@ -807,25 +807,25 @@ class AclSearchTests(AclTests): # regular users must see only ou1 and ou2 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn), Dn(self.ldb_admin, "OU=ou1," + self.base_dn)] res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) # these users should see all ous res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res_list = [x["dn"] for x in res if x["dn"] in self.full_list] - self.assertEquals(sorted(res_list), sorted(self.full_list)) + self.assertEqual(sorted(res_list), sorted(self.full_list)) res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 6) + self.assertEqual(len(res), 6) res_list = [x["dn"] for x in res if x["dn"] in self.full_list] - self.assertEquals(sorted(res_list), sorted(self.full_list)) + self.assertEqual(sorted(res_list), sorted(self.full_list)) def test_search2(self): """Make sure users can't see us if access is explicitly denied""" @@ -841,7 +841,7 @@ class AclSearchTests(AclTests): scope=SCOPE_SUBTREE) # this user should see all ous res_list = [x["dn"] for x in res if x["dn"] in self.full_list] - self.assertEquals(sorted(res_list), sorted(self.full_list)) + self.assertEqual(sorted(res_list), sorted(self.full_list)) # these users should see ou1, 2, 5 and 6 but not 3 and 4 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", @@ -851,13 +851,13 @@ class AclSearchTests(AclTests): Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn), Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)] res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 4) + self.assertEqual(len(res), 4) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) def test_search3(self): """Make sure users can't see ous if access is explicitly denied - 2""" @@ -878,7 +878,7 @@ class AclSearchTests(AclTests): scope=SCOPE_BASE) except LdbError as e18: (num, _) = e18.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) else: self.fail() @@ -891,7 +891,7 @@ class AclSearchTests(AclTests): res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn), Dn(self.ldb_admin, "OU=ou1," + self.base_dn), @@ -901,15 +901,15 @@ class AclSearchTests(AclTests): # should not see ou3 and ou4, but should see ou5 and ou6 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 4) + self.assertEqual(len(res), 4) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 4) + self.assertEqual(len(res), 4) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) def test_search4(self): """There is no difference in visibility if the user is also creator""" @@ -928,15 +928,15 @@ class AclSearchTests(AclTests): Dn(self.ldb_admin, "OU=ou1," + self.base_dn)] res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 2) + self.assertEqual(len(res), 2) res_list = [x["dn"] for x in res if x["dn"] in ok_list] - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) def test_search5(self): """Make sure users can see only attributes they are allowed to see""" @@ -950,16 +950,16 @@ class AclSearchTests(AclTests): res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) ok_list = ['dn'] - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res_list = list(res[0].keys()) - self.assertEquals(res_list, ok_list) + self.assertEqual(res_list, ok_list) res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE, attrs=["ou"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res_list = list(res[0].keys()) - self.assertEquals(res_list, ok_list) + self.assertEqual(res_list, ok_list) # give read property on ou and assert user can only see dn and ou mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid)) @@ -968,9 +968,9 @@ class AclSearchTests(AclTests): res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE) ok_list = ['dn', 'ou'] - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res_list = list(res[0].keys()) - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) # give read property on Public Information and assert user can see ou and other members mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid)) @@ -981,7 +981,7 @@ class AclSearchTests(AclTests): ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory'] res_list = list(res[0].keys()) - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) def test_search6(self): """If an attribute that cannot be read is used in a filter, it is as if the attribute does not exist""" @@ -996,36 +996,36 @@ class AclSearchTests(AclTests): res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)", scope=SCOPE_SUBTREE) # nothing should be returned as ou is not accessible - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # give read property on ou and assert user can only see dn and ou mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid)) self.sd_utils.dacl_add_ace("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, mod) res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) ok_list = ['dn', 'ou'] res_list = list(res[0].keys()) - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) # give read property on Public Information and assert user can see ou and other members mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid)) self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod) res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou2)", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory'] res_list = list(res[0].keys()) - self.assertEquals(sorted(res_list), sorted(ok_list)) + self.assertEqual(sorted(res_list), sorted(ok_list)) def assert_search_on_attr(self, dn, samdb, attr, expected_list): expected_num = len(expected_list) res = samdb.search(dn, expression="(%s=*)" % attr, scope=SCOPE_SUBTREE) - self.assertEquals(len(res), expected_num) + self.assertEqual(len(res), expected_num) res_list = [ x["dn"] for x in res if x["dn"] in expected_list ] - self.assertEquals(sorted(res_list), sorted(expected_list)) + self.assertEqual(sorted(res_list), sorted(expected_list)) def test_search7(self): """Checks object search visibility when users don't have full rights""" @@ -1116,7 +1116,7 @@ class AclDeleteTests(AclTests): self.ldb_user.delete(self.get_user_dn("test_delete_user1")) except LdbError as e19: (num, _) = e19.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -1155,7 +1155,7 @@ class AclDeleteTests(AclTests): anonymous.delete(self.get_user_dn("test_anonymous")) except LdbError as e20: (num, _) = e20.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) else: self.fail() @@ -1211,7 +1211,7 @@ class AclRenameTests(AclTests): "CN=%s,%s,%s" % (self.testuser5, self.ou1, self.base_dn)) except LdbError as e21: (num, _) = e21.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -1369,7 +1369,7 @@ class AclRenameTests(AclTests): self.ldb_user.rename(ou2_dn, ou3_dn) except LdbError as e22: (num, _) = e22.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: # This rename operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() @@ -1401,7 +1401,7 @@ class AclRenameTests(AclTests): self.ldb_admin.rename(user_dn, rename_user_dn) except LdbError as e23: (num, _) = e23.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() # add an allow ace so we can delete this ou @@ -1462,7 +1462,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')). """) except LdbError as e24: (num, _) = e24.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) else: # for some reason we get constraint violation instead of insufficient access error self.fail() @@ -1489,7 +1489,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')). """) except LdbError as e25: (num, _) = e25.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) else: # for some reason we get constraint violation instead of insufficient access error self.fail() @@ -1529,7 +1529,7 @@ dBCSPwd: YYYYYYYYYYYYYYYY """) except LdbError as e26: (num, _) = e26.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) else: self.fail() @@ -1548,7 +1548,7 @@ userPassword: thatsAcomplPASS2 """) except LdbError as e27: (num, _) = e27.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)" @@ -1608,7 +1608,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')). """) except LdbError as e29: (num, _) = e29.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)" @@ -1631,7 +1631,7 @@ userPassword: thatsAcomplPASS1 """) except LdbError as e30: (num, _) = e30.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)" @@ -1646,7 +1646,7 @@ userPassword: thatsAcomplPASS1 # This fails on Windows 2000 domain level with constraint violation except LdbError as e31: (num, _) = e31.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def test_reset_password3(self): """Grant WP and see what happens (unicodePwd)""" @@ -1661,7 +1661,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')). """) except LdbError as e32: (num, _) = e32.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -1678,7 +1678,7 @@ userPassword: thatsAcomplPASS1 """) except LdbError as e33: (num, _) = e33.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() @@ -1707,7 +1707,7 @@ userPassword: thatsAcomplPASS1 # This fails on Windows 2000 domain level with constraint violation except LdbError as e34: (num, _) = e34.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) class AclExtendedTests(AclTests): @@ -1837,7 +1837,7 @@ class AclUndeleteTests(AclTests): self.ldb_admin.delete(self.get_user_dn(new_user)) res = self.ldb_admin.search(base="" % self.GUID_string(guid), scope=SCOPE_BASE, controls=["show_deleted:1"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return str(res[0].dn) def undelete_deleted(self, olddn, newdn): @@ -1868,7 +1868,7 @@ class AclUndeleteTests(AclTests): self.fail() except LdbError as e35: (num, _) = e35.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # seems that permissions on isDeleted and distinguishedName are irrelevant mod = "(OD;;WP;bf96798f-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid) @@ -1885,7 +1885,7 @@ class AclUndeleteTests(AclTests): self.fail() except LdbError as e36: (num, _) = e36.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # undelete in an ou, in which we have no right to create children mod = "(D;;CC;;;%s)" % str(self.sid) @@ -1895,7 +1895,7 @@ class AclUndeleteTests(AclTests): self.fail() except LdbError as e37: (num, _) = e37.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # delete is not required mod = "(D;;SD;;;%s)" % str(self.sid) @@ -1910,7 +1910,7 @@ class AclUndeleteTests(AclTests): self.fail() except LdbError as e38: (num, _) = e38.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) class AclSPNTests(AclTests): @@ -2023,7 +2023,7 @@ class AclSPNTests(AclTests): self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, netbiosdomain)) except LdbError as e39: (num, _) = e39.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1) self.sd_utils.dacl_add_ace(ctx.acct_dn, mod) @@ -2061,30 +2061,30 @@ class AclSPNTests(AclTests): (ctx.myname, ctx.dnsdomain, ctx.dnsdomain)) except LdbError as e40: (num, _) = e40.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/DomainDnsZones.%s" % (ctx.myname, ctx.dnsdomain, ctx.dnsdomain)) except LdbError as e41: (num, _) = e41.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "nosuchservice/%s/%s" % ("abcd", "abcd")) except LdbError as e42: (num, _) = e42.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" % (ctx.myname, ctx.dnsdomain, netbiosdomain)) except LdbError as e43: (num, _) = e43.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s" % (ctx.ntds_guid, ctx.dnsdomain)) except LdbError as e44: (num, _) = e44.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def test_computer_spn(self): # with WP, any value can be set @@ -2129,7 +2129,7 @@ class AclSPNTests(AclTests): self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain)) except LdbError as e45: (num, _) = e45.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1) self.sd_utils.dacl_add_ace(self.computerdn, mod) @@ -2147,42 +2147,42 @@ class AclSPNTests(AclTests): self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain)) except LdbError as e46: (num, _) = e46.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, netbiosdomain)) except LdbError as e47: (num, _) = e47.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, self.dcctx.dnsdomain)) except LdbError as e48: (num, _) = e48.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain)) except LdbError as e49: (num, _) = e49.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "GC/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest)) except LdbError as e50: (num, _) = e50.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain)) except LdbError as e51: (num, _) = e51.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain)) except LdbError as e52: (num, _) = e52.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def test_spn_rwdc(self): self.dc_spn_test(self.dcctx) diff --git a/source4/dsdb/tests/python/deletetest.py b/source4/dsdb/tests/python/deletetest.py index 25a26c77221..a2a19a12650 100755 --- a/source4/dsdb/tests/python/deletetest.py +++ b/source4/dsdb/tests/python/deletetest.py @@ -62,7 +62,7 @@ class BaseDeleteTests(samba.tests.TestCase): scope=SCOPE_BASE, controls=["show_deleted:1"], attrs=["*", "parentGUID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return res[0] def search_dn(self, dn): @@ -73,7 +73,7 @@ class BaseDeleteTests(samba.tests.TestCase): scope=SCOPE_BASE, controls=["show_deleted:1"], attrs=["*", "parentGUID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return res[0] @@ -85,7 +85,7 @@ class BasicDeleteTests(BaseDeleteTests): def del_attr_values(self, delObj): print("Checking attributes for %s" % delObj["dn"]) - self.assertEquals(str(delObj["isDeleted"][0]), "TRUE") + self.assertEqual(str(delObj["isDeleted"][0]), "TRUE") self.assertTrue(not("objectCategory" in delObj)) self.assertTrue(not("sAMAccountType" in delObj)) @@ -111,9 +111,9 @@ class BasicDeleteTests(BaseDeleteTests): name2 = delObj["name"][0] dn_rdn = delObj.dn.get_rdn_value() guid = liveObj["objectGUID"][0] - self.assertEquals(str(rdn2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid)))) - self.assertEquals(str(name2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid)))) - self.assertEquals(str(name2), dn_rdn) + self.assertEqual(str(rdn2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid)))) + self.assertEqual(str(name2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid)))) + self.assertEqual(str(name2), dn_rdn) def delete_deleted(self, ldb, dn): print("Testing the deletion of the already deleted dn %s" % dn) @@ -123,7 +123,7 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) def test_delete_protection(self): """Delete protection tests""" @@ -149,7 +149,7 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) self.ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:1"]) @@ -159,21 +159,21 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) try: res = self.ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn, scope=SCOPE_BASE, attrs=[]) self.fail() except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) try: res = self.ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn, scope=SCOPE_BASE, attrs=[]) self.fail() except LdbError as e4: (num, _) = e4.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn) delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn) @@ -183,7 +183,7 @@ class BasicDeleteTests(BaseDeleteTests): res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["dsServiceName", "dNSHostName"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Delete failing since DC's nTDSDSA object is protected try: @@ -191,11 +191,11 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e5: (num, _) = e5.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) res = self.ldb.search(self.base_dn, attrs=["rIDSetReferences"], expression="(&(objectClass=computer)(dNSHostName=" + str(res[0]["dNSHostName"][0]) + "))") - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Deletes failing since DC's rIDSet object is protected try: @@ -203,13 +203,13 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e6: (num, _) = e6.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.delete(res[0]["rIDSetReferences"][0], ["tree_delete:1"]) self.fail() except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Deletes failing since three main crossRef objects are protected @@ -218,43 +218,43 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e8: (num, _) = e8.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) self.fail() except LdbError as e9: (num, _) = e9.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn) self.fail() except LdbError as e10: (num, _) = e10.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) try: self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) self.fail() except LdbError as e11: (num, _) = e11.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) res = self.ldb.search("cn=Partitions," + self.configuration_dn, attrs=[], expression="(nCName=%s)" % self.base_dn) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) try: self.ldb.delete(res[0].dn) self.fail() except LdbError as e12: (num, _) = e12.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) try: self.ldb.delete(res[0].dn, ["tree_delete:1"]) self.fail() except LdbError as e13: (num, _) = e13.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) # Delete failing since "SYSTEM_FLAG_DISALLOW_DELETE" try: @@ -262,7 +262,7 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e14: (num, _) = e14.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Tree-delete failing since "isCriticalSystemObject" try: @@ -270,7 +270,7 @@ class BasicDeleteTests(BaseDeleteTests): self.fail() except LdbError as e15: (num, _) = e15.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) class BasicTreeDeleteTests(BasicDeleteTests): diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 0a22ac4239a..0ed0c7c9787 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -249,7 +249,7 @@ class SimpleDirsyncTests(DirsyncBaseTests): expression="(distinguishedName=%s)" % str(self.base_dn), attrs=["objectGUID"], controls=["dirsync:1:0:1"]) - self.assertEquals(len(res.msgs), 0) + self.assertEqual(len(res.msgs), 0) # a request on the root of a NC didn't return parentGUID res = self.ldb_admin.search(self.base_dn, @@ -610,7 +610,7 @@ class ExtendedDirsyncTests(SimpleDirsyncTests): controls=["dirsync:1:0:0"]) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail() diff --git a/source4/dsdb/tests/python/dsdb_schema_info.py b/source4/dsdb/tests/python/dsdb_schema_info.py index 26df1e04a45..50b04cdcd7f 100644 --- a/source4/dsdb/tests/python/dsdb_schema_info.py +++ b/source4/dsdb/tests/python/dsdb_schema_info.py @@ -54,7 +54,7 @@ class SchemaInfoTestCase(samba.tests.TestCase): # fetch rootDSE res = self.sam_db.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.schema_dn = res[0]["schemaNamingContext"][0] self.base_dn = res[0]["defaultNamingContext"][0] self.forest_level = int(res[0]["forestFunctionality"][0]) diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py index 9b43daa5891..a90bf367b1b 100755 --- a/source4/dsdb/tests/python/ldap.py +++ b/source4/dsdb/tests/python/ldap.py @@ -121,7 +121,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # Invalid objectclass specified try: @@ -131,7 +131,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # Invalid objectCategory specified try: @@ -142,7 +142,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Multi-valued "systemFlags" try: @@ -153,7 +153,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # We cannot instanciate from an abstract object class ("connectionPoint" # or "leaf"). In the first case we use "connectionPoint" (subclass of @@ -168,7 +168,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -176,7 +176,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Objects instanciated using "satisfied" abstract classes (concrete # subclasses) are allowed @@ -194,7 +194,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Test allowed system flags self.ldb.add({ @@ -205,7 +205,7 @@ class BasicTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["systemFlags"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["systemFlags"][0]), "0") + self.assertEqual(str(res[0]["systemFlags"][0]), "0") delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -237,7 +237,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # We cannot delete classes which weren't specified m = Message() @@ -249,7 +249,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # An invalid class cannot be added m = Message() @@ -261,7 +261,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # We cannot add a the new top-most structural class "user" here since # we are missing at least one new mandatory attribute (in this case @@ -275,7 +275,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # An already specified objectclass cannot be added another time m = Message() @@ -287,7 +287,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) # Auxiliary classes can always be added m = Message() @@ -307,7 +307,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Objectclass replace operations can be performed as well m = Message() @@ -333,7 +333,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # More than one change operation is allowed m = Message() @@ -351,7 +351,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -362,7 +362,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Classes can be removed unless attributes of them are used. m = Message() @@ -400,7 +400,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Remove the previously specified attribute m = Message() @@ -433,7 +433,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Add a new top-most structural class "inetOrgPerson" and remove it # afterwards @@ -475,8 +475,8 @@ class BasicTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["objectClass"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["objectClass"][0]), "top") - self.assertEquals(str(res[0]["objectClass"][len(res[0]["objectClass"]) - 1]), "user") + self.assertEqual(str(res[0]["objectClass"][0]), "top") + self.assertEqual(str(res[0]["objectClass"][len(res[0]["objectClass"]) - 1]), "user") delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -489,7 +489,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.add({ @@ -498,7 +498,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn) delete_force(self.ldb, "cn=Test Secret,cn=system," + self.base_dn) @@ -525,7 +525,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=Test Secret,cn=system," + self.base_dn) @@ -537,7 +537,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) self.ldb.add({ "dn": "cn=ldaptestcontainer," + self.base_dn, @@ -552,7 +552,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn) @@ -568,7 +568,7 @@ class BasicTests(samba.tests.TestCase): attrs=["isCriticalSystemObject"]) self.assertTrue(len(res) == 1) self.assertTrue("isCriticalSystemObject" in res[0]) - self.assertEquals(str(res[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res[0]["isCriticalSystemObject"][0]), "TRUE") def test_invalid_parent(self): """Test adding an object with invalid parent""" @@ -580,7 +580,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123," + self.base_dn) @@ -592,7 +592,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NAMING_VIOLATION) + self.assertEqual(num, ERR_NAMING_VIOLATION) delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn) @@ -610,7 +610,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) self.ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -627,7 +627,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # # When searching the unknown attribute should be ignored @@ -662,7 +662,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # inadequate but schema-valid attribute specified try: @@ -674,7 +674,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) self.ldb.add({ "dn": "cn=ldaptestobject," + self.base_dn, @@ -692,7 +692,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # mandatory attribute delete trial m = Message() @@ -704,7 +704,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # mandatory attribute delete trial m = Message() @@ -716,7 +716,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn) @@ -730,7 +730,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -745,7 +745,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -762,7 +762,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -796,7 +796,7 @@ class BasicTests(samba.tests.TestCase): self.fail("failed to fail to add multiple managedBy attributes") except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) managee = "cn=group2," + ou self.ldb.add({ @@ -813,7 +813,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, managee) @@ -830,7 +830,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) self.ldb.delete(ou, ['tree_delete:1']) @@ -916,7 +916,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX) + self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX) ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -931,7 +931,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX) + self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX) m = Message() @@ -955,7 +955,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -969,7 +969,7 @@ class BasicTests(samba.tests.TestCase): ldb.modify(m) self.fail() except LdbError as e: - self.assertEquals(e.args[0], ERR_CONSTRAINT_VIOLATION) + self.assertEqual(e.args[0], ERR_CONSTRAINT_VIOLATION) def test_empty_messages(self): """Test empty messages""" @@ -981,14 +981,14 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) try: ldb.modify(m) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1004,7 +1004,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -1019,7 +1019,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1034,7 +1034,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1049,7 +1049,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # The head NC flag cannot be set without the write flag try: @@ -1060,7 +1060,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # We cannot manipulate NCs without the head NC flag try: @@ -1071,7 +1071,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) self.ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -1086,7 +1086,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1097,7 +1097,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1107,7 +1107,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1120,7 +1120,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) def test_distinguished_name(self): @@ -1136,7 +1136,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # a wrong "distinguishedName" attribute is obviously tolerated self.ldb.add({ @@ -1163,7 +1163,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1176,7 +1176,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1189,7 +1189,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1202,7 +1202,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1216,7 +1216,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # empty RDN name try: @@ -1224,14 +1224,14 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) try: self.ldb.search("=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # Add @@ -1243,7 +1243,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # empty RDN name try: @@ -1253,7 +1253,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # empty RDN value try: @@ -1263,7 +1263,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # a wrong RDN candidate try: @@ -1273,7 +1273,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NAMING_VIOLATION) + self.assertEqual(num, ERR_NAMING_VIOLATION) delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn) @@ -1301,7 +1301,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # Delete @@ -1311,7 +1311,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # Rename @@ -1322,7 +1322,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # new empty RDN name try: @@ -1331,7 +1331,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # new empty RDN value try: @@ -1340,7 +1340,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NAMING_VIOLATION) + self.assertEqual(num, ERR_NAMING_VIOLATION) # new wrong RDN candidate try: @@ -1349,7 +1349,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn) @@ -1360,7 +1360,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) # names @@ -1373,7 +1373,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_RDN) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1384,7 +1384,7 @@ class BasicTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_RDN) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1413,7 +1413,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn)) def test_rename(self): @@ -1424,7 +1424,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: # inexistent object @@ -1432,7 +1432,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) self.ldb.add({ "dn": "cn=ldaptestuser2,cn=users," + self.base_dn, @@ -1448,7 +1448,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NAMING_VIOLATION) + self.assertEqual(num, ERR_NAMING_VIOLATION) try: # invalid parent @@ -1456,7 +1456,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) try: # invalid target DN syntax @@ -1464,7 +1464,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) try: # invalid RDN name @@ -1472,7 +1472,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn) @@ -1484,7 +1484,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Limited move failing since no "SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE" try: @@ -1492,7 +1492,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Rename failing since no "SYSTEM_FLAG_CONFIG_ALLOW_RENAME" try: @@ -1500,7 +1500,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # It's not really possible to test moves on the schema partition since # there don't exist subcontainers on it. @@ -1511,7 +1511,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Move failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE" try: @@ -1519,7 +1519,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Rename failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME" try: @@ -1527,7 +1527,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Performs some other constraints testing @@ -1536,7 +1536,7 @@ objectClass: container self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) def test_rename_twice(self): """Tests the rename operation twice - this corresponds to a past bug""" @@ -1551,9 +1551,9 @@ objectClass: container "objectclass": "user"}) ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn) res = ldb.search(expression="cn=ldaptestuser5") - self.assertEquals(len(res), 1, "Wrong number of hits for cn=ldaptestuser5") + self.assertEqual(len(res), 1, "Wrong number of hits for cn=ldaptestuser5") res = ldb.search(expression="(&(cn=ldaptestuser5)(objectclass=user))") - self.assertEquals(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))") + self.assertEqual(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))") delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn) def test_objectGUID(self): @@ -1568,7 +1568,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) self.ldb.add({ "dn": "cn=ldaptestcontainer," + self.base_dn, @@ -1585,7 +1585,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn) @@ -1607,7 +1607,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d attrs=["parentGUID"]) """Check if the parentGUID is valid """ - self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]) + self.assertEqual(res1[0]["parentGUID"], res2[0]["objectGUID"]) """Check if it returns nothing when there is no parent object - default NC""" has_parentGUID = False @@ -1642,7 +1642,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d break self.assertTrue(has_another_attribute) self.assertTrue(len(res1[0]["samaccountname"]) == 1) - self.assertEquals(str(res1[0]["samaccountname"][0]), "parentguidtest") + self.assertEqual(str(res1[0]["samaccountname"][0]), "parentguidtest") # Testing parentGUID behaviour on rename\ @@ -1656,7 +1656,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn, scope=SCOPE_BASE, attrs=["parentGUID"]) - self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]) + self.assertEqual(res1[0]["objectGUID"], res2[0]["parentGUID"]) delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn) delete_force(self.ldb, "cn=testotherusers," + self.base_dn) @@ -1824,11 +1824,11 @@ delete: description res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, attrs=["groupType"], expression="groupType=-2147483643") - self.assertEquals(len(res1), len(res2)) + self.assertEqual(len(res1), len(res2)) self.assertTrue(res1.count > 0) - self.assertEquals(str(res1[0]["groupType"][0]), "-2147483643") + self.assertEqual(str(res1[0]["groupType"][0]), "-2147483643") def test_linked_attributes(self): """This tests the linked attribute behaviour""" @@ -1845,7 +1845,7 @@ delete: description "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn}) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1860,7 +1860,7 @@ delete: description self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1877,7 +1877,7 @@ delete: description self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -1888,7 +1888,7 @@ delete: description self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1926,27 +1926,27 @@ delete: description """Test Well known GUID behaviours (including DN+Binary)""" res = self.ldb.search(base=("" % self.base_dn), scope=SCOPE_BASE, attrs=[]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn)) - self.assertEquals(len(res2), 1) + self.assertEqual(len(res2), 1) # Prove that the matching rule is over the whole DN+Binary res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd")) - self.assertEquals(len(res2), 0) + self.assertEqual(len(res2), 0) # Prove that the matching rule is over the whole DN+Binary res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=%s") % res[0].dn) - self.assertEquals(len(res2), 0) + self.assertEqual(len(res2), 0) def test_subschemasubentry(self): """Test subSchemaSubEntry appears when requested, but not when not requested""" res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["subSchemaSubEntry"][0]), "CN=Aggregate," + self.schema_dn) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["subSchemaSubEntry"][0]), "CN=Aggregate," + self.schema_dn) res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("subScheamSubEntry" not in res[0]) def test_all(self): @@ -1985,7 +1985,7 @@ delete: description self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_DN_SYNTAX) + self.assertEqual(num, ERR_INVALID_DN_SYNTAX) try: ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, @@ -1996,7 +1996,7 @@ delete: description self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, "objectClass": "computer", @@ -2005,22 +2005,22 @@ delete: description # Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user)) res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))") - self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res)) - - self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn)) - self.assertEquals(str(res[0]["cn"][0]), "ldaptestcomputer3") - self.assertEquals(str(res[0]["name"][0]), "ldaptestcomputer3") - self.assertEquals(str(res[0]["objectClass"][0]), "top") - self.assertEquals(str(res[0]["objectClass"][1]), "person") - self.assertEquals(str(res[0]["objectClass"][2]), "organizationalPerson") - self.assertEquals(str(res[0]["objectClass"][3]), "user") - self.assertEquals(str(res[0]["objectClass"][4]), "computer") + self.assertEqual(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res)) + + self.assertEqual(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn)) + self.assertEqual(str(res[0]["cn"][0]), "ldaptestcomputer3") + self.assertEqual(str(res[0]["name"][0]), "ldaptestcomputer3") + self.assertEqual(str(res[0]["objectClass"][0]), "top") + self.assertEqual(str(res[0]["objectClass"][1]), "person") + self.assertEqual(str(res[0]["objectClass"][2]), "organizationalPerson") + self.assertEqual(str(res[0]["objectClass"][3]), "user") + self.assertEqual(str(res[0]["objectClass"][4]), "computer") self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) - self.assertEquals(str(res[0]["objectCategory"][0]), ("CN=Computer,%s" % ldb.get_schema_basedn())) - self.assertEquals(int(res[0]["primaryGroupID"][0]), 513) - self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) - self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) + self.assertEqual(str(res[0]["objectCategory"][0]), ("CN=Computer,%s" % ldb.get_schema_basedn())) + self.assertEqual(int(res[0]["primaryGroupID"][0]), 513) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) @@ -2037,7 +2037,7 @@ servicePrincipalName: cifs/ldaptest2computer self.fail() except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ @@ -2056,7 +2056,7 @@ servicePrincipalName: host/ldaptest2computer self.fail() except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) # Testing ranged results ldb.modify_ldif(""" @@ -2103,44 +2103,44 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-*"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=0-19"]), 20) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=30-*"]), 0) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=10-*"]), 20) # pos_11 = res[0]["servicePrincipalName;range=10-*"][18] res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19) - # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=11-*"]), 19) + # self.assertEqual((res[0]["servicePrincipalName;range=11-*"][18]), pos_11) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5) - # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName;range=11-15"]), 5) + # self.assertEqual(res[0]["servicePrincipalName;range=11-15"][4], pos_11) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName"]), 30) - # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11) + self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEqual(len(res[0]["servicePrincipalName"]), 30) + # self.assertEqual(res[0]["servicePrincipalName"][18], pos_11) delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) ldb.add({ @@ -2153,133 +2153,133 @@ servicePrincipalName: host/ldaptest2computer29 # Testing Ambigious Name Resolution # Testing ldb.search for (&(anr=ldap testy)(objectClass=user)) res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))") - self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res)) # Testing ldb.search for (&(anr=testy ldap)(objectClass=user)) res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))") - self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res)) # Testing ldb.search for (&(anr=ldap)(objectClass=user)) res = ldb.search(expression="(&(anr=ldap)(objectClass=user))") - self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res)) # Testing ldb.search for (&(anr==ldap)(objectClass=user)) res = ldb.search(expression="(&(anr==ldap)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res)) - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"][0]), "ldaptestuser") - self.assertEquals(str(res[0]["name"]), "ldaptestuser") + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"][0]), "ldaptestuser") + self.assertEqual(str(res[0]["name"]), "ldaptestuser") # Testing ldb.search for (&(anr=testy)(objectClass=user)) res = ldb.search(expression="(&(anr=testy)(objectClass=user))") - self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res)) # Testing ldb.search for (&(anr=testy ldap)(objectClass=user)) res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))") - self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res)) + self.assertEqual(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res)) # Testing ldb.search for (&(anr==testy ldap)(objectClass=user)) # this test disabled for the moment, as anr with == tests are not understood # res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))") -# self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res)) +# self.assertEqual(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res)) -# self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) -# self.assertEquals(res[0]["cn"][0], "ldaptestuser") -# self.assertEquals(res[0]["name"][0], "ldaptestuser") +# self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) +# self.assertEqual(res[0]["cn"][0], "ldaptestuser") +# self.assertEqual(res[0]["name"][0], "ldaptestuser") # Testing ldb.search for (&(anr==testy ldap)(objectClass=user)) # res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))") -# self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))") +# self.assertEqual(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))") -# self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) -# self.assertEquals(res[0]["cn"][0], "ldaptestuser") -# self.assertEquals(res[0]["name"][0], "ldaptestuser") +# self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) +# self.assertEqual(res[0]["cn"][0], "ldaptestuser") +# self.assertEqual(res[0]["name"][0], "ldaptestuser") # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user)) res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestuser2") - self.assertEquals(str(res[0]["name"]), "ldaptestuser2") + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestuser2") + self.assertEqual(str(res[0]["name"]), "ldaptestuser2") # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user)) # res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))") -# self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))") +# self.assertEqual(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestuser2") - self.assertEquals(str(res[0]["name"]), "ldaptestuser2") + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestuser2") + self.assertEqual(str(res[0]["name"]), "ldaptestuser2") # Testing ldb.search for (&(anr==ldap user2)(objectClass=user)) # res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))") -# self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))") +# self.assertEqual(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestuser2") - self.assertEquals(str(res[0]["name"]), "ldaptestuser2") + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestuser2") + self.assertEqual(str(res[0]["name"]), "ldaptestuser2") # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user)) # res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))") -# self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))") +# self.assertEqual(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))") # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user)) res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))") - self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))") + self.assertEqual(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))") # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes) # res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))") -# self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))") +# self.assertEqual(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))") # Testing Renames attrs = ["objectGUID", "objectSid"] # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user)) res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs) - self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") + self.assertEqual(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") # Check rename works with extended/alternate DN forms ldb.rename("", "cn=ldaptestUSER3,cn=users," + self.base_dn) # Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user)) res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3") - self.assertEquals(str(res[0]["name"]), "ldaptestUSER3") + self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3") + self.assertEqual(str(res[0]["name"]), "ldaptestUSER3") #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))" res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))") - self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))") + self.assertEqual(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3") - self.assertEquals(str(res[0]["name"]), "ldaptestUSER3") + self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3") + self.assertEqual(str(res[0]["name"]), "ldaptestUSER3") #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))" res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))") - self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))") + self.assertEqual(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3") - self.assertEquals(str(res[0]["name"]), "ldaptestUSER3") + self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3") + self.assertEqual(str(res[0]["name"]), "ldaptestUSER3") #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))" res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") - self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") + self.assertEqual(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") # Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") - should not work res = ldb.search(expression="(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") - self.assertEquals(len(res), 0, "Could find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") + self.assertEqual(len(res), 0, "Could find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") # Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") - self.assertEquals(len(res), 1, "Could not find (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") - self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3") - self.assertEquals(str(res[0]["name"]), "ldaptestUSER3") + self.assertEqual(len(res), 1, "Could not find (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") + self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3") + self.assertEqual(str(res[0]["name"]), "ldaptestUSER3") # ensure we cannot add it again try: @@ -2289,7 +2289,7 @@ servicePrincipalName: host/ldaptest2computer29 self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # rename back ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn) @@ -2301,7 +2301,7 @@ servicePrincipalName: host/ldaptest2computer29 self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # ensure can now use that name ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn, @@ -2314,7 +2314,7 @@ servicePrincipalName: host/ldaptest2computer29 self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) try: ldb.rename("cn=ldaptestuser3,cn=users,%s" % self.base_dn, "cn=ldaptestuser3,%s" % ldb.get_config_basedn()) self.fail() @@ -2362,7 +2362,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))") # Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn try: @@ -2372,7 +2372,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.fail(res) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn try: @@ -2381,20 +2381,20 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container" res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn) + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn) - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)) - self.assertEquals(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)) + self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) time.sleep(4) # Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes" res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not consistant with subtree renames?") + self.assertEqual(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not consistant with subtree renames?") # Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn try: @@ -2402,7 +2402,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn try: @@ -2418,21 +2418,21 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) + self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF) # Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn) ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)) @@ -2445,144 +2445,144 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ # Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestuser") - self.assertEquals(str(res[0]["name"]), "ldaptestuser") - self.assertEquals(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user"])) + self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestuser") + self.assertEqual(str(res[0]["name"]), "ldaptestuser") + self.assertEqual(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user"])) self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) - self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,%s" % ldb.get_schema_basedn())) - self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) - self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) - self.assertEquals(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) - self.assertEquals(len(res[0]["memberOf"]), 1) + self.assertEqual(str(res[0]["objectCategory"]), ("CN=Person,%s" % ldb.get_schema_basedn())) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) + self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) + self.assertEqual(len(res[0]["memberOf"]), 1) # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn() res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()) - self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()) + self.assertEqual(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()) - self.assertEquals(res[0].dn, res2[0].dn) + self.assertEqual(res[0].dn, res2[0].dn) # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))" res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))") - self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3)) + self.assertEqual(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3)) - self.assertEquals(res[0].dn, res3[0].dn) + self.assertEqual(res[0].dn, res3[0].dn) if gc_ldb is not None: # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog" res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))") - self.assertEquals(len(res3gc), 1) + self.assertEqual(len(res3gc), 1) - self.assertEquals(res[0].dn, res3gc[0].dn) + self.assertEqual(res[0].dn, res3gc[0].dn) # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control" if gc_ldb is not None: res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"]) - self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog") + self.assertEqual(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog") - self.assertEquals(res[0].dn, res3control[0].dn) + self.assertEqual(res[0].dn, res3control[0].dn) ldb.delete(res[0].dn) # Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer") - self.assertEquals(str(res[0]["name"]), "ldaptestcomputer") - self.assertEquals(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user", b"computer"])) + self.assertEqual(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestcomputer") + self.assertEqual(str(res[0]["name"]), "ldaptestcomputer") + self.assertEqual(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user", b"computer"])) self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) - self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,%s" % ldb.get_schema_basedn())) - self.assertEquals(int(res[0]["primaryGroupID"][0]), 513) - self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) - self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) - self.assertEquals(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) - self.assertEquals(len(res[0]["memberOf"]), 1) + self.assertEqual(str(res[0]["objectCategory"]), ("CN=Computer,%s" % ldb.get_schema_basedn())) + self.assertEqual(int(res[0]["primaryGroupID"][0]), 513) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) + self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) + self.assertEqual(len(res[0]["memberOf"]), 1) # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn() res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()) - self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()) + self.assertEqual(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()) - self.assertEquals(res[0].dn, res2[0].dn) + self.assertEqual(res[0].dn, res2[0].dn) if gc_ldb is not None: # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) in Global Catalog" % gc_ldb.get_schema_basedn() res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % gc_ldb.get_schema_basedn()) - self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) In Global Catalog" % gc_ldb.get_schema_basedn()) + self.assertEqual(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) In Global Catalog" % gc_ldb.get_schema_basedn()) - self.assertEquals(res[0].dn, res2gc[0].dn) + self.assertEqual(res[0].dn, res2gc[0].dn) # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))" res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))") - self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))") + self.assertEqual(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))") - self.assertEquals(res[0].dn, res3[0].dn) + self.assertEqual(res[0].dn, res3[0].dn) if gc_ldb is not None: # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog" res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))") - self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog") + self.assertEqual(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog") - self.assertEquals(res[0].dn, res3gc[0].dn) + self.assertEqual(res[0].dn, res3gc[0].dn) # Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))" res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))") - self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))") + self.assertEqual(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))") - self.assertEquals(res[0].dn, res4[0].dn) + self.assertEqual(res[0].dn, res4[0].dn) # Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))" res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))") - self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))") + self.assertEqual(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))") - self.assertEquals(res[0].dn, res5[0].dn) + self.assertEqual(res[0].dn, res5[0].dn) # Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))" res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))") - self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))") + self.assertEqual(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))") - self.assertEquals(res[0].dn, res6[0].dn) + self.assertEqual(res[0].dn, res6[0].dn) ldb.delete("") # Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))") - self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn) - self.assertEquals(str(res[0]["cn"]), "ldaptest2computer") - self.assertEquals(str(res[0]["name"]), "ldaptest2computer") - self.assertEquals(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user", b"computer"]) + self.assertEqual(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn) + self.assertEqual(str(res[0]["cn"]), "ldaptest2computer") + self.assertEqual(str(res[0]["name"]), "ldaptest2computer") + self.assertEqual(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user", b"computer"]) self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) - self.assertEquals(str(res[0]["objectCategory"][0]), "CN=Computer,%s" % ldb.get_schema_basedn()) - self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) - self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT) + self.assertEqual(str(res[0]["objectCategory"][0]), "CN=Computer,%s" % ldb.get_schema_basedn()) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT) ldb.delete("") attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"] # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))" res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs) - self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") + self.assertEqual(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") - self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) - self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2") - self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2") - self.assertEquals(list(res_user[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"]) + self.assertEqual(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) + self.assertEqual(str(res_user[0]["cn"]), "ldaptestuser2") + self.assertEqual(str(res_user[0]["name"]), "ldaptestuser2") + self.assertEqual(list(res_user[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"]) self.assertTrue("objectSid" in res_user[0]) self.assertTrue("objectGUID" in res_user[0]) self.assertTrue("whenCreated" in res_user[0]) self.assertTrue("nTSecurityDescriptor" in res_user[0]) self.assertTrue("allowedAttributes" in res_user[0]) self.assertTrue("allowedAttributesEffective" in res_user[0]) - self.assertEquals(str(res_user[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) + self.assertEqual(str(res_user[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) ldaptestuser2_sid = res_user[0]["objectSid"][0] ldaptestuser2_guid = res_user[0]["objectGUID"][0] @@ -2590,12 +2590,12 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"] # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2") - self.assertEquals(str(res[0]["name"]), "ldaptestgroup2") - self.assertEquals(list(res[0]["objectClass"]), [b"top", b"group"]) + self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestgroup2") + self.assertEqual(str(res[0]["name"]), "ldaptestgroup2") + self.assertEqual(list(res[0]["objectClass"]), [b"top", b"group"]) self.assertTrue("objectGUID" in res[0]) self.assertTrue("objectSid" in res[0]) self.assertTrue("whenCreated" in res[0]) @@ -2608,7 +2608,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP) res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"]) - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") print(res[0]["member"]) memberUP = [] @@ -2670,11 +2670,11 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ """) res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["member"][0]), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) - self.assertEquals(len(res[0]["member"]), 1) + self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["member"][0]), ("CN=ldaptestuser2,CN=Users," + self.base_dn)) + self.assertEqual(len(res[0]["member"]), 1) ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn)) @@ -2683,21 +2683,21 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"] # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete") - self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) self.assertTrue("member" not in res[0]) # Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") - self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn)) - self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà") - self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà") - self.assertEquals(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"]) + self.assertEqual(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn)) + self.assertEqual(str(res[0]["cn"]), "ldaptestutf8user èùéìòà") + self.assertEqual(str(res[0]["name"]), "ldaptestutf8user èùéìòà") + self.assertEqual(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"]) self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) @@ -2706,11 +2706,11 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ # Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))") # Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))") - self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))") + self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))") # delete "ldaptestutf8user2 " ldb.delete(res[0].dn) @@ -2719,7 +2719,7 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ # Testing that we can't get at the configuration DN from the main search base" res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control" res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"]) @@ -2759,9 +2759,9 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ # Testing objectClass attribute order on "+ self.base_dn res = ldb.search(expression="objectClass=domain", base=self.base_dn, scope=SCOPE_BASE, attrs=["objectClass"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) - self.assertEquals(list(res[0]["objectClass"]), [b"top", b"domain", b"domainDNS"]) + self.assertEqual(list(res[0]["objectClass"]), [b"top", b"domain", b"domainDNS"]) # check enumeration @@ -2851,7 +2851,7 @@ objectClass: posixAccount""" % (self.base_dn)) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) finally: delete_force(self.ldb, user_dn) # @@ -2938,7 +2938,7 @@ nTSecurityDescriptor:: """ + desc_base64) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(ldb, user_dn) @@ -2949,7 +2949,7 @@ nTSecurityDescriptor:: """ + desc_base64) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, user_dn) @@ -2960,7 +2960,7 @@ nTSecurityDescriptor:: """ + desc_base64) self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, user_dn) # @@ -3100,14 +3100,14 @@ nTSecurityDescriptor:: """ + desc_base64 self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) dshstr = dshstr + str(i) else: # There does not seem to be an upper limit self.ldb.set_dsheuristics(dshstr + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") # apart from the above, all char values are accepted self.ldb.set_dsheuristics("123ABC-+!1asdfg@#^") - self.assertEquals(self.ldb.get_dsheuristics(), b"123ABC-+!1asdfg@#^") + self.assertEqual(self.ldb.get_dsheuristics(), b"123ABC-+!1asdfg@#^") finally: # restore old value self.ldb.set_dsheuristics(dsheuristics) @@ -3117,8 +3117,8 @@ nTSecurityDescriptor:: """ + desc_base64 really return something""" res = self.ldb.search(attrs=["cn"], controls=["paged_results:1:10"]) - self.assertEquals(len(res.controls), 1) - self.assertEquals(res.controls[0].oid, "1.2.840.113556.1.4.319") + self.assertEqual(len(res.controls), 1) + self.assertEqual(res.controls[0].oid, "1.2.840.113556.1.4.319") s = str(res.controls[0]) def test_operational(self): @@ -3129,7 +3129,7 @@ nTSecurityDescriptor:: """ + desc_base64 attrs=["createTimeStamp", "modifyTimeStamp", "structuralObjectClass", "whenCreated", "whenChanged"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("createTimeStamp" in res[0]) self.assertTrue("modifyTimeStamp" in res[0]) self.assertTrue("structuralObjectClass" in res[0]) @@ -3173,7 +3173,7 @@ nTSecurityDescriptor:: """ + desc_base64 self.assertTrue(len(res) == 1) self.assertTrue("msTSExpireDate" in res[0]) self.assertTrue(len(res[0]["msTSExpireDate"]) == 1) - self.assertEquals(str(res[0]["msTSExpireDate"][0]), v_get) + self.assertEqual(str(res[0]["msTSExpireDate"][0]), v_get) def test_ldapSearchNoAttributes(self): """Testing ldap search with no attributes""" @@ -3202,30 +3202,30 @@ class BaseDnTests(samba.tests.TestCase): def test_rootdse_attrs(self): """Testing for all rootDSE attributes""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=[]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) def test_highestcommittedusn(self): """Testing for highestCommittedUSN""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0) def test_netlogon(self): """Testing for netlogon via LDAP""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) def test_netlogon_highestcommitted_usn(self): """Testing for netlogon and highestCommittedUSN via LDAP""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon", "highestCommittedUSN"]) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) def test_namingContexts(self): """Testing for namingContexts in rootDSE""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) ncs = set([]) for nc in res[0]["namingContexts"]: @@ -3240,7 +3240,7 @@ class BaseDnTests(samba.tests.TestCase): """Testing the server paths in rootDSE""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["dsServiceName", "serverName"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("CN=Servers" in str(res[0]["dsServiceName"][0])) self.assertTrue("CN=Sites" in str(res[0]["dsServiceName"][0])) @@ -3253,51 +3253,51 @@ class BaseDnTests(samba.tests.TestCase): """Testing the server paths in rootDSE""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["forestFunctionality", "domainFunctionality", "domainControllerFunctionality"]) - self.assertEquals(len(res), 1) - self.assertEquals(len(res[0]["forestFunctionality"]), 1) - self.assertEquals(len(res[0]["domainFunctionality"]), 1) - self.assertEquals(len(res[0]["domainControllerFunctionality"]), 1) + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]["forestFunctionality"]), 1) + self.assertEqual(len(res[0]["domainFunctionality"]), 1) + self.assertEqual(len(res[0]["domainControllerFunctionality"]), 1) self.assertTrue(int(res[0]["forestFunctionality"][0]) <= int(res[0]["domainFunctionality"][0])) self.assertTrue(int(res[0]["domainControllerFunctionality"][0]) >= int(res[0]["domainFunctionality"][0])) res2 = self.ldb.search("", scope=SCOPE_BASE, attrs=["dsServiceName", "serverName"]) - self.assertEquals(len(res2), 1) - self.assertEquals(len(res2[0]["dsServiceName"]), 1) + self.assertEqual(len(res2), 1) + self.assertEqual(len(res2[0]["dsServiceName"]), 1) res3 = self.ldb.search(res2[0]["dsServiceName"][0], scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"]) - self.assertEquals(len(res3), 1) - self.assertEquals(len(res3[0]["msDS-Behavior-Version"]), 1) - self.assertEquals(int(res[0]["domainControllerFunctionality"][0]), int(res3[0]["msDS-Behavior-Version"][0])) + self.assertEqual(len(res3), 1) + self.assertEqual(len(res3[0]["msDS-Behavior-Version"]), 1) + self.assertEqual(int(res[0]["domainControllerFunctionality"][0]), int(res3[0]["msDS-Behavior-Version"][0])) res4 = self.ldb.search(ldb.domain_dn(), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"]) - self.assertEquals(len(res4), 1) - self.assertEquals(len(res4[0]["msDS-Behavior-Version"]), 1) - self.assertEquals(int(res[0]["domainFunctionality"][0]), int(res4[0]["msDS-Behavior-Version"][0])) + self.assertEqual(len(res4), 1) + self.assertEqual(len(res4[0]["msDS-Behavior-Version"]), 1) + self.assertEqual(int(res[0]["domainFunctionality"][0]), int(res4[0]["msDS-Behavior-Version"][0])) res5 = self.ldb.search("cn=partitions,%s" % ldb.get_config_basedn(), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"]) - self.assertEquals(len(res5), 1) - self.assertEquals(len(res5[0]["msDS-Behavior-Version"]), 1) - self.assertEquals(int(res[0]["forestFunctionality"][0]), int(res5[0]["msDS-Behavior-Version"][0])) + self.assertEqual(len(res5), 1) + self.assertEqual(len(res5[0]["msDS-Behavior-Version"]), 1) + self.assertEqual(int(res[0]["forestFunctionality"][0]), int(res5[0]["msDS-Behavior-Version"][0])) def test_dnsHostname(self): """Testing the DNS hostname in rootDSE""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["dnsHostName", "serverName"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res2 = self.ldb.search(res[0]["serverName"][0], scope=SCOPE_BASE, attrs=["dNSHostName"]) - self.assertEquals(len(res2), 1) + self.assertEqual(len(res2), 1) - self.assertEquals(res[0]["dnsHostName"][0], res2[0]["dNSHostName"][0]) + self.assertEqual(res[0]["dnsHostName"][0], res2[0]["dNSHostName"][0]) def test_ldapServiceName(self): """Testing the ldap service name in rootDSE""" res = self.ldb.search("", scope=SCOPE_BASE, attrs=["ldapServiceName", "dnsHostName"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("ldapServiceName" in res[0]) self.assertTrue("dnsHostName" in res[0]) @@ -3305,7 +3305,7 @@ class BaseDnTests(samba.tests.TestCase): given = str(res[0]["ldapServiceName"][0]) expected = "%s:%s$@%s" % (dns_domainname.lower(), hostname.lower(), dns_domainname.upper()) - self.assertEquals(given, expected) + self.assertEqual(given, expected) if "://" not in host: diff --git a/source4/dsdb/tests/python/ldap_schema.py b/source4/dsdb/tests/python/ldap_schema.py index eca7d857698..75115e1e251 100755 --- a/source4/dsdb/tests/python/ldap_schema.py +++ b/source4/dsdb/tests/python/ldap_schema.py @@ -81,7 +81,7 @@ class SchemaTests(samba.tests.TestCase): """Testing we can read the generated schema via LDAP""" res = self.ldb.search("cn=aggregate," + self.schema_dn, scope=SCOPE_BASE, attrs=["objectClasses", "attributeTypes", "dITContentRules"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertTrue("dITContentRules" in res[0]) self.assertTrue("objectClasses" in res[0]) self.assertTrue("attributeTypes" in res[0]) @@ -91,7 +91,7 @@ class SchemaTests(samba.tests.TestCase): # Must keep the "*" form res = self.ldb.search("cn=aggregate," + self.schema_dn, scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("dITContentRules" in res[0]) self.assertFalse("objectClasses" in res[0]) self.assertFalse("attributeTypes" in res[0]) @@ -131,8 +131,8 @@ schemaUpdateNow: 1 res = [] res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["lDAPDisplayName", "schemaIDGUID", "msDS-IntID"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["lDAPDisplayName"][0]), attr_ldap_display_name) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["lDAPDisplayName"][0]), attr_ldap_display_name) self.assertTrue("schemaIDGUID" in res[0]) if "msDS-IntId" in res[0]: msDS_IntId = int(res[0]["msDS-IntId"][0]) @@ -168,7 +168,7 @@ systemOnly: FALSE self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) ldif = """ dn: CN=%s,%s""" % (class_name, self.schema_dn) + """ @@ -193,9 +193,9 @@ systemOnly: FALSE res = [] res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["lDAPDisplayName", "defaultObjectCategory", "schemaIDGUID", "distinguishedName"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["lDAPDisplayName"][0]), class_ldap_display_name) - self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["lDAPDisplayName"][0]), class_ldap_display_name) + self.assertEqual(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) self.assertTrue("schemaIDGUID" in res[0]) ldif = """ @@ -226,7 +226,7 @@ name: """ + object_name + """ # Search for created object obj_res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["replPropertyMetaData"]) - self.assertEquals(len(obj_res), 1) + self.assertEqual(len(obj_res), 1) self.assertTrue("replPropertyMetaData" in obj_res[0]) val = obj_res[0]["replPropertyMetaData"][0] repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, val) @@ -273,9 +273,9 @@ systemOnly: FALSE res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["lDAPDisplayName", "defaultObjectCategory", "schemaIDGUID", "distinguishedName"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["lDAPDisplayName"][0]), class_ldap_display_name) - self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["lDAPDisplayName"][0]), class_ldap_display_name) + self.assertEqual(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) self.assertTrue("schemaIDGUID" in res[0]) ldif = """ @@ -299,7 +299,7 @@ instanceType: 4 # Search for created object res = [] res = self.ldb.search("ou=%s,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["dn"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Delete the object delete_force(self.ldb, "ou=%s,%s" % (object_name, self.base_dn)) @@ -344,7 +344,7 @@ systemOnly: FALSE self.fail("Should have failed to add duplicate attributeID value") except LdbError as e2: (enum, estr) = e2.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_attributeID_governsID(self): """Testing creating a duplicate attribute and class""" @@ -388,7 +388,7 @@ systemOnly: FALSE self.fail("Should have failed to add duplicate governsID conflicting with attributeID value") except LdbError as e3: (enum, estr) = e3.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_cn(self): """Testing creating a duplicate attribute""" @@ -431,7 +431,7 @@ systemOnly: FALSE self.fail("Should have failed to add attribute with duplicate CN") except LdbError as e4: (enum, estr) = e4.args - self.assertEquals(enum, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(enum, ERR_ENTRY_ALREADY_EXISTS) def test_duplicate_implicit_ldapdisplayname(self): """Testing creating a duplicate attribute ldapdisplayname""" @@ -475,7 +475,7 @@ systemOnly: FALSE self.fail("Should have failed to add attribute with duplicate of the implicit ldapDisplayName") except LdbError as e5: (enum, estr) = e5.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_explicit_ldapdisplayname(self): """Testing creating a duplicate attribute ldapdisplayname""" @@ -520,7 +520,7 @@ systemOnly: FALSE self.fail("Should have failed to add attribute with duplicate ldapDisplayName") except LdbError as e6: (enum, estr) = e6.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_explicit_ldapdisplayname_with_class(self): """Testing creating a duplicate attribute ldapdisplayname between @@ -568,7 +568,7 @@ systemOnly: FALSE self.fail("Should have failed to add class with duplicate ldapDisplayName") except LdbError as e7: (enum, estr) = e7.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_via_rename_ldapdisplayname(self): """Testing creating a duplicate attribute ldapdisplayname""" @@ -622,7 +622,7 @@ ldapDisplayName: """ + attr_ldap_display_name + """ self.fail("Should have failed to modify schema to have attribute with duplicate ldapDisplayName") except LdbError as e8: (enum, estr) = e8.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_duplicate_via_rename_attributeID(self): """Testing creating a duplicate attributeID""" @@ -676,7 +676,7 @@ attributeId: """ + attributeID + """ self.fail("Should have failed to modify schema to have attribute with duplicate attributeID") except LdbError as e9: (enum, estr) = e9.args - self.assertEquals(enum, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(enum, ERR_CONSTRAINT_VIOLATION) def test_remove_ldapdisplayname(self): """Testing removing the ldapdisplayname""" @@ -712,7 +712,7 @@ replace: ldapDisplayName self.fail("Should have failed to remove the ldapdisplayname") except LdbError as e10: (enum, estr) = e10.args - self.assertEquals(enum, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(enum, ERR_OBJECT_CLASS_VIOLATION) def test_rename_ldapdisplayname(self): """Testing renaming ldapdisplayname""" @@ -781,7 +781,7 @@ attributeId: """ + attributeID + """.1 self.fail("Should have failed to modify schema to have different attributeID") except LdbError as e11: (enum, estr) = e11.args - self.assertEquals(enum, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(enum, ERR_CONSTRAINT_VIOLATION) def test_change_attributeID_same(self): """Testing change the attributeID to the same value""" @@ -818,7 +818,7 @@ attributeId: """ + attributeID + """ self.fail("Should have failed to modify schema to have the same attributeID") except LdbError as e12: (enum, estr) = e12.args - self.assertEquals(enum, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(enum, ERR_CONSTRAINT_VIOLATION) def test_generated_linkID(self): """ @@ -833,7 +833,7 @@ attributeId: """ + attributeID + """ # linkID generation isn't available before 2003 res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["domainControllerFunctionality"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dc_level = int(res[0]["domainControllerFunctionality"][0]) if dc_level < DS_DOMAIN_FUNCTION_2003: return @@ -895,13 +895,13 @@ systemOnly: FALSE res = self.ldb.search("CN=%s,%s" % (attr_name_1, self.schema_dn), scope=SCOPE_BASE, attrs=["linkID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) linkID_1 = int(res[0]["linkID"][0]) res = self.ldb.search("CN=%s,%s" % (attr_name_2, self.schema_dn), scope=SCOPE_BASE, attrs=["linkID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) linkID_2 = int(res[0]["linkID"][0]) # 0 should never be generated as a linkID @@ -952,7 +952,7 @@ systemOnly: FALSE self.fail("Should have failed to add duplicate linkID value") except LdbError as e15: (enum, estr) = e15.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) # If we add another attribute with the attributeID or lDAPDisplayName # of a forward link in its linkID field, it should add as a backlink @@ -986,9 +986,9 @@ systemOnly: FALSE res = self.ldb.search("CN=%s,%s" % (attr_name_3, self.schema_dn), scope=SCOPE_BASE, attrs=["linkID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) linkID = int(res[0]["linkID"][0]) - self.assertEquals(linkID, linkID_1 + 1) + self.assertEqual(linkID, linkID_1 + 1) attr_name_4 = "test-generated-linkID-backlink-2" + time.strftime("%s", time.gmtime()) + "-" + rand attr_ldap_display_name_4 = attr_name_4.replace("-", "") @@ -1019,9 +1019,9 @@ systemOnly: FALSE res = self.ldb.search("CN=%s,%s" % (attr_name_4, self.schema_dn), scope=SCOPE_BASE, attrs=["linkID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) linkID = int(res[0]["linkID"][0]) - self.assertEquals(linkID, linkID_2 + 1) + self.assertEqual(linkID, linkID_2 + 1) # If we then try to add another backlink in the same way # for the same forwards link, we should fail. @@ -1051,7 +1051,7 @@ systemOnly: FALSE self.fail("Should have failed to add duplicate backlink") except LdbError as e18: (enum, estr) = e18.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) # If we try to supply the attributeID or ldapDisplayName # of an existing backlink in the linkID field of a new link, @@ -1082,7 +1082,7 @@ systemOnly: FALSE self.fail("Should have failed to add backlink of backlink") except LdbError as e19: (enum, estr) = e19.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) attr_name = "test-generated-linkID-backlink-invalid-2" + time.strftime("%s", time.gmtime()) + "-" + rand attr_ldap_display_name = attr_name.replace("-", "") @@ -1109,7 +1109,7 @@ systemOnly: FALSE self.fail("Should have failed to add backlink of backlink") except LdbError as e20: (enum, estr) = e20.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_generated_mAPIID(self): """ @@ -1150,7 +1150,7 @@ systemOnly: FALSE res = self.ldb.search("CN=%s,%s" % (attr_name_1, self.schema_dn), scope=SCOPE_BASE, attrs=["mAPIID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) mAPIID_1 = int(res[0]["mAPIID"][0]) ldif = """ @@ -1187,7 +1187,7 @@ systemOnly: FALSE self.fail("Should have failed to add duplicate mAPIID value") except LdbError as e22: (enum, estr) = e22.args - self.assertEquals(enum, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(enum, ERR_UNWILLING_TO_PERFORM) def test_change_governsID(self): """Testing change the governsID""" @@ -1225,7 +1225,7 @@ governsId: """ + governsID + """.1 self.fail("Should have failed to modify schema to have different governsID") except LdbError as e23: (enum, estr) = e23.args - self.assertEquals(enum, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(enum, ERR_CONSTRAINT_VIOLATION) def test_change_governsID_same(self): """Testing change the governsID""" @@ -1263,7 +1263,7 @@ governsId: """ + governsID + """.1 self.fail("Should have failed to modify schema to have the same governsID") except LdbError as e24: (enum, estr) = e24.args - self.assertEquals(enum, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(enum, ERR_CONSTRAINT_VIOLATION) class SchemaTests_msDS_IntId(samba.tests.TestCase): @@ -1275,7 +1275,7 @@ class SchemaTests_msDS_IntId(samba.tests.TestCase): res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext", "defaultNamingContext", "forestFunctionality"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.schema_dn = res[0]["schemaNamingContext"][0] self.base_dn = res[0]["defaultNamingContext"][0] self.forest_level = int(res[0]["forestFunctionality"][0]) @@ -1346,7 +1346,7 @@ systemOnly: FALSE self.fail("Adding attribute with preset msDS-IntId should fail") except LdbError as e25: (num, _) = e25.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # add the new attribute and update schema self.ldb.add_ldif(ldif) @@ -1356,8 +1356,8 @@ systemOnly: FALSE res = [] res = self.ldb.search(attr_dn, scope=SCOPE_BASE, attrs=["lDAPDisplayName", "msDS-IntId", "systemFlags"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["lDAPDisplayName"][0]), attr_ldap_name) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["lDAPDisplayName"][0]), attr_ldap_name) if self.forest_level >= DS_DOMAIN_FUNCTION_2003: if self._is_schema_base_object(res[0]): self.assertTrue("msDS-IntId" not in res[0]) @@ -1374,7 +1374,7 @@ systemOnly: FALSE self.fail("Modifying msDS-IntId should return error") except LdbError as e26: (num, _) = e26.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # 2. Create attribute with systemFlags = FLAG_SCHEMA_BASE_OBJECT # msDS-IntId should be created if forest functional @@ -1391,7 +1391,7 @@ systemOnly: FALSE self.fail("Adding attribute with preset msDS-IntId should fail") except LdbError as e27: (num, _) = e27.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # add the new attribute and update schema self.ldb.add_ldif(ldif) @@ -1401,8 +1401,8 @@ systemOnly: FALSE res = [] res = self.ldb.search(attr_dn, scope=SCOPE_BASE, attrs=["lDAPDisplayName", "msDS-IntId"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["lDAPDisplayName"][0]), attr_ldap_name) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["lDAPDisplayName"][0]), attr_ldap_name) if self.forest_level >= DS_DOMAIN_FUNCTION_2003: if self._is_schema_base_object(res[0]): self.assertTrue("msDS-IntId" not in res[0]) @@ -1419,7 +1419,7 @@ systemOnly: FALSE self.fail("Modifying msDS-IntId should return error") except LdbError as e28: (num, _) = e28.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def _make_class_ldif(self, class_dn, class_name, sub_oid): ldif = """ @@ -1456,8 +1456,8 @@ systemOnly: FALSE self._ldap_schemaUpdateNow() res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["msDS-IntId"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["msDS-IntId"][0]), "-1993108831") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["msDS-IntId"][0]), "-1993108831") # add a new Class and update schema (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-2-") @@ -1468,7 +1468,7 @@ systemOnly: FALSE # Search for created Class res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["msDS-IntId"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("msDS-IntId" in res[0]) msg = Message() @@ -1479,7 +1479,7 @@ systemOnly: FALSE self.fail("Modifying msDS-IntId should return error") except LdbError as e29: (num, _) = e29.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # 2. Create Class with systemFlags = FLAG_SCHEMA_BASE_OBJECT # msDS-IntId should be created if forest functional @@ -1494,8 +1494,8 @@ systemOnly: FALSE self.ldb.add_ldif(ldif_add) res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["msDS-IntId"]) - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["msDS-IntId"][0]), "-1993108831") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["msDS-IntId"][0]), "-1993108831") # add the new Class and update schema (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-4-") @@ -1507,7 +1507,7 @@ systemOnly: FALSE # Search for created Class res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["msDS-IntId"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("msDS-IntId" in res[0]) msg = Message() @@ -1518,9 +1518,9 @@ systemOnly: FALSE self.fail("Modifying msDS-IntId should return error") except LdbError as e30: (num, _) = e30.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["msDS-IntId"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("msDS-IntId" in res[0]) def test_verify_msDS_IntId(self): @@ -1554,7 +1554,7 @@ class SchemaTests_msDS_isRODC(samba.tests.TestCase): self.ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp, options=ldb_options) res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["defaultNamingContext"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.base_dn = res[0]["defaultNamingContext"][0] def test_objectClass_ntdsdsa(self): @@ -1572,7 +1572,7 @@ class SchemaTests_msDS_isRODC(samba.tests.TestCase): res_check = self.ldb.search(ntds_search_dn, attrs=["objectCategory"]) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) print("Server entry %s doesn't have a NTDS settings object" % res[0]['dn']) else: self.assertTrue("objectCategory" in res_check[0]) diff --git a/source4/dsdb/tests/python/ldap_syntaxes.py b/source4/dsdb/tests/python/ldap_syntaxes.py index ff319553c05..d8efb3a105e 100755 --- a/source4/dsdb/tests/python/ldap_syntaxes.py +++ b/source4/dsdb/tests/python/ldap_syntaxes.py @@ -78,8 +78,8 @@ systemOnly: FALSE # search for created attribute res = [] res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) - self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name) + self.assertEqual(len(res), 1) + self.assertEqual(res[0]["lDAPDisplayName"][0], attr_ldap_display_name) self.assertTrue("schemaIDGUID" in res[0]) class_name = "test-Class-DN-String" + time.strftime("%s", time.gmtime()) @@ -104,9 +104,9 @@ systemOnly: FALSE # search for created objectclass res = [] res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) - self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name) - self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) + self.assertEqual(len(res), 1) + self.assertEqual(res[0]["lDAPDisplayName"][0], class_ldap_display_name) + self.assertEqual(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) self.assertTrue("schemaIDGUID" in res[0]) # store the class and the attribute @@ -138,8 +138,8 @@ systemOnly: FALSE # search for created attribute res = [] res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) - self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name) + self.assertEqual(len(res), 1) + self.assertEqual(res[0]["lDAPDisplayName"][0], attr_ldap_display_name) self.assertTrue("schemaIDGUID" in res[0]) class_name = "test-Class-DN-Binary" + time.strftime("%s", time.gmtime()) @@ -164,9 +164,9 @@ systemOnly: FALSE # search for created objectclass res = [] res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res), 1) - self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name) - self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) + self.assertEqual(len(res), 1) + self.assertEqual(res[0]["lDAPDisplayName"][0], class_ldap_display_name) + self.assertEqual(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0]) self.assertTrue("schemaIDGUID" in res[0]) # store the class and the attribute @@ -202,19 +202,19 @@ name: """ + object_name + """ res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=%s)" % (self.dn_string_attribute, self.base_dn)) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # search by specifying the string part only res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=S:5:ABCDE)" % self.dn_string_attribute) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # search by DN+Stirng res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=S:5:ABCDE:%s)" % (self.dn_string_attribute, self.base_dn)) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # add object with wrong format object_name2 = "obj-DN-String2" + time.strftime("%s", time.gmtime()) @@ -224,7 +224,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX) + self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX) # add object with the same dn but with different string value in case ldif = self._get_object_ldif(object_name1, self.dn_string_class_name, self.dn_string_class_ldap_display_name, @@ -233,7 +233,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with the same dn but with different string value ldif = self._get_object_ldif(object_name1, self.dn_string_class_name, self.dn_string_class_ldap_display_name, @@ -242,7 +242,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with the same dn but with different dn and string value ldif = self._get_object_ldif(object_name1, self.dn_string_class_name, self.dn_string_class_ldap_display_name, @@ -251,7 +251,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with the same dn but with different dn value ldif = self._get_object_ldif(object_name1, self.dn_string_class_name, self.dn_string_class_ldap_display_name, @@ -260,7 +260,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e4: (num, _) = e4.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with GUID instead of DN object_name3 = "obj-DN-String3" + time.strftime("%s", time.gmtime()) @@ -270,7 +270,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e5: (num, _) = e5.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # add object with SID instead of DN object_name4 = "obj-DN-String4" + time.strftime("%s", time.gmtime()) @@ -280,7 +280,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e6: (num, _) = e6.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # add object with random string instead of DN object_name5 = "obj-DN-String5" + time.strftime("%s", time.gmtime()) @@ -290,7 +290,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def test_dn_binary(self): # add obeject with correct value @@ -303,19 +303,19 @@ name: """ + object_name + """ res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=%s)" % (self.dn_binary_attribute, self.base_dn)) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # search by specifying the binary part res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=B:4:1234)" % self.dn_binary_attribute) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) # search by DN+Binary res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=B:4:1234:%s)" % (self.dn_binary_attribute, self.base_dn)) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # add object with wrong format - 5 bytes instead of 4, 8, 16, 32... object_name2 = "obj-DN-Binary2" + time.strftime("%s", time.gmtime()) @@ -325,7 +325,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e8: (num, _) = e8.args - self.assertEquals(num, ERR_INVALID_ATTRIBUTE_SYNTAX) + self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX) # add object with the same dn but with different binary value ldif = self._get_object_ldif(object_name1, self.dn_binary_class_name, self.dn_binary_class_ldap_display_name, @@ -334,7 +334,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e9: (num, _) = e9.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with the same dn but with different binary and dn value ldif = self._get_object_ldif(object_name1, self.dn_binary_class_name, self.dn_binary_class_ldap_display_name, @@ -343,7 +343,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e10: (num, _) = e10.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with the same dn but with different dn value ldif = self._get_object_ldif(object_name1, self.dn_binary_class_name, self.dn_binary_class_ldap_display_name, @@ -352,7 +352,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e11: (num, _) = e11.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # add object with GUID instead of DN object_name3 = "obj-DN-Binary3" + time.strftime("%s", time.gmtime()) @@ -362,7 +362,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e12: (num, _) = e12.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # add object with SID instead of DN object_name4 = "obj-DN-Binary4" + time.strftime("%s", time.gmtime()) @@ -372,7 +372,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e13: (num, _) = e13.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # add object with random string instead of DN object_name5 = "obj-DN-Binary5" + time.strftime("%s", time.gmtime()) @@ -382,7 +382,7 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError as e14: (num, _) = e14.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/dsdb/tests/python/notification.py b/source4/dsdb/tests/python/notification.py index 9e5f7dc9d5d..9d463eee258 100755 --- a/source4/dsdb/tests/python/notification.py +++ b/source4/dsdb/tests/python/notification.py @@ -71,7 +71,7 @@ class LDAPNotificationTest(samba.tests.TestCase): self.base_dn = self.ldb.domain_dn() res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.user_sid_dn = "" % str(ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0])) @@ -146,7 +146,7 @@ otherLoginWorkstations: AFTER" self.fail() except LdbError as e10: (num, _) = e10.args - self.assertEquals(num, ERR_TIME_LIMIT_EXCEEDED) + self.assertEqual(num, ERR_TIME_LIMIT_EXCEEDED) self.assertIsNotNone(msg3) self.ldb.modify_ldif(""" @@ -211,7 +211,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_TIME_LIMIT_EXCEEDED) + self.assertEqual(num, ERR_TIME_LIMIT_EXCEEDED) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -226,7 +226,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_TIME_LIMIT_EXCEEDED) + self.assertEqual(num, ERR_TIME_LIMIT_EXCEEDED) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -241,7 +241,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -256,7 +256,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e4: (num, _) = e4.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -271,7 +271,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e5: (num, _) = e5.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -286,7 +286,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e6: (num, _) = e6.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -301,7 +301,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: hnd = self.ldb.search_iterator(base=self.base_dn, @@ -316,7 +316,7 @@ delete: otherLoginWorkstations self.fail() except LdbError as e8: (num, _) = e8.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) res = self.ldb.search(base=self.ldb.get_schema_basedn(), expression="(objectClass=attributeSchema)", @@ -343,7 +343,7 @@ delete: otherLoginWorkstations (num, _) = e9.args if num != ERR_UNWILLING_TO_PERFORM: print("va[%s]" % va) - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: va = "noneAttributeName" @@ -361,7 +361,7 @@ delete: otherLoginWorkstations (num, _) = e11.args if num != ERR_UNWILLING_TO_PERFORM: print("va[%s]" % va) - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) if "://" not in url: diff --git a/source4/dsdb/tests/python/password_lockout.py b/source4/dsdb/tests/python/password_lockout.py index efbdeb2ed90..cbe15c33742 100755 --- a/source4/dsdb/tests/python/password_lockout.py +++ b/source4/dsdb/tests/python/password_lockout.py @@ -217,7 +217,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -262,7 +262,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e1: (num, msg) = e1.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -290,7 +290,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e2: (num, msg) = e2.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -318,7 +318,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e3: (num, msg) = e3.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -344,7 +344,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e4: (num, msg) = e4.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -370,7 +370,7 @@ userPassword: thatsAcomplPASS2x self.fail() except LdbError as e5: (num, msg) = e5.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -414,7 +414,7 @@ userPassword: thatsAcomplPASS2x self.fail() except LdbError as e6: (num, msg) = e6.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -460,7 +460,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) self.fail() except LdbError as e7: (num, msg) = e7.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -522,7 +522,7 @@ userPassword: thatsAcomplPASS2XYZ self.fail() except LdbError as e8: (num, msg) = e8.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -549,7 +549,7 @@ userPassword: thatsAcomplPASS2XYZ self.fail() except LdbError as e9: (num, msg) = e9.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -679,7 +679,7 @@ userPassword: thatsAcomplPASS2XYZ self.fail("Invalid SAMR change_password accepted") except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value - self.assertEquals(enum, ntstatus.NT_STATUS_WRONG_PASSWORD) + self.assertEqual(enum, ntstatus.NT_STATUS_WRONG_PASSWORD) # check the status of the account is updated after each bad attempt account_flags = 0 @@ -713,7 +713,7 @@ userPassword: thatsAcomplPASS2XYZ self.fail("Invalid SAMR change_password accepted") except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value - self.assertEquals(enum, ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT) + self.assertEqual(enum, ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT) res = self._check_account(userdn, badPwdCount=lockout_threshold, @@ -801,7 +801,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')). self.fail() except LdbError as e10: (num, msg) = e10.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -852,7 +852,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e11: (num, msg) = e11.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -894,7 +894,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e12: (num, msg) = e12.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) # this is strange, why do we have lockoutTime=badPasswordTime here? @@ -923,7 +923,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e13: (num, msg) = e13.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -949,7 +949,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e14: (num, msg) = e14.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -975,7 +975,7 @@ unicodePwd:: """ + base64.b64encode(invalid_utf16).decode('utf8') + """ self.fail() except LdbError as e15: (num, msg) = e15.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000775' in msg, msg) res = self._check_account(userdn, @@ -1040,7 +1040,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e16: (num, msg) = e16.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -1067,7 +1067,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e17: (num, msg) = e17.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -1108,7 +1108,7 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """ self.fail() except LdbError as e18: (num, msg) = e18.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg, msg) res = self._check_account(userdn, @@ -1240,7 +1240,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e19: (num, msg) = e19.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # Windows (2008 at least) seems to have some small bug here: it # returns "0000056A" on longer (always wrong) previous passwords. self.assertTrue('00000056' in msg, msg) diff --git a/source4/dsdb/tests/python/password_lockout_base.py b/source4/dsdb/tests/python/password_lockout_base.py index 597633a6f73..17ae807faf6 100644 --- a/source4/dsdb/tests/python/password_lockout_base.py +++ b/source4/dsdb/tests/python/password_lockout_base.py @@ -24,7 +24,7 @@ class BasePasswordTestCase(PasswordTestCase): self.assertTrue("objectSid" in res[0]) (domain_sid, rid) = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]).split() - self.assertEquals(self.domain_sid, domain_sid) + self.assertEqual(self.domain_sid, domain_sid) return self.samr.OpenUser(self.samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, rid) @@ -163,9 +163,9 @@ class BasePasswordTestCase(PasswordTestCase): if msDSUserAccountControlComputed & dsdb.UF_PASSWORD_EXPIRED: expected_acb_info |= samr.ACB_PW_EXPIRED - self.assertEquals(uinfo3.acct_flags, expected_acb_info) - self.assertEquals(uinfo3.last_logon, lastLogon) - self.assertEquals(uinfo3.logon_count, logonCount) + self.assertEqual(uinfo3.acct_flags, expected_acb_info) + self.assertEqual(uinfo3.last_logon, lastLogon) + self.assertEqual(uinfo3.logon_count, logonCount) expected_bad_password_count = 0 if badPwdCount is not None: @@ -173,25 +173,25 @@ class BasePasswordTestCase(PasswordTestCase): if effective_bad_password_count is None: effective_bad_password_count = expected_bad_password_count - self.assertEquals(uinfo3.bad_password_count, expected_bad_password_count) + self.assertEqual(uinfo3.bad_password_count, expected_bad_password_count) if not badPwdCountOnly: - self.assertEquals(uinfo5.acct_flags, expected_acb_info) - self.assertEquals(uinfo5.bad_password_count, effective_bad_password_count) - self.assertEquals(uinfo5.last_logon, lastLogon) - self.assertEquals(uinfo5.logon_count, logonCount) + self.assertEqual(uinfo5.acct_flags, expected_acb_info) + self.assertEqual(uinfo5.bad_password_count, effective_bad_password_count) + self.assertEqual(uinfo5.last_logon, lastLogon) + self.assertEqual(uinfo5.logon_count, logonCount) - self.assertEquals(uinfo16.acct_flags, expected_acb_info) + self.assertEqual(uinfo16.acct_flags, expected_acb_info) - self.assertEquals(uinfo21.acct_flags, expected_acb_info) - self.assertEquals(uinfo21.bad_password_count, effective_bad_password_count) - self.assertEquals(uinfo21.last_logon, lastLogon) - self.assertEquals(uinfo21.logon_count, logonCount) + self.assertEqual(uinfo21.acct_flags, expected_acb_info) + self.assertEqual(uinfo21.bad_password_count, effective_bad_password_count) + self.assertEqual(uinfo21.last_logon, lastLogon) + self.assertEqual(uinfo21.logon_count, logonCount) # check LDAP again and make sure the samr.QueryUserInfo # doesn't have any impact. res2 = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) - self.assertEquals(res[0], res2[0]) + self.assertEqual(res[0], res2[0]) # in order to prevent some time resolution problems we sleep for # 10 micro second @@ -252,7 +252,7 @@ userPassword: """ + userpass + """ self.fail() except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) # Succeed to reset everything to 0 ldb = SamDB(url=self.host_url, credentials=creds, lp=self.lp) @@ -266,7 +266,7 @@ userPassword: """ + userpass + """ except LdbError as e1: (num, msg) = e1.args if errno is not None: - self.assertEquals(num, errno, ("Login failed in the wrong way" + self.assertEqual(num, errno, ("Login failed in the wrong way" "(got err %d, expected %d)" % (num, errno))) @@ -467,7 +467,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ except LdbError as e2: (num, msg) = e2.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=2, @@ -490,7 +490,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ except LdbError as e3: (num, msg) = e3.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -511,7 +511,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e4: (num, msg) = e4.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -530,7 +530,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e5: (num, msg) = e5.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -549,7 +549,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e6: (num, msg) = e6.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -609,7 +609,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e7: (num, msg) = e7.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=1, @@ -629,7 +629,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e8: (num, msg) = e8.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=2, @@ -661,7 +661,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """ self.fail() except LdbError as e9: (num, msg) = e9.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=1, diff --git a/source4/dsdb/tests/python/password_settings.py b/source4/dsdb/tests/python/password_settings.py index 5d6deaeebe5..fcb671690c3 100644 --- a/source4/dsdb/tests/python/password_settings.py +++ b/source4/dsdb/tests/python/password_settings.py @@ -107,7 +107,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail("Password '%s' should have been rejected" % password) except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_CONSTRAINT_VIOLATION, msg) + self.assertEqual(num, ldb.ERR_CONSTRAINT_VIOLATION, msg) self.assertTrue('0000052D' in msg, msg) def assert_password_valid(self, user, password): @@ -415,7 +415,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_NAMING_VIOLATION, msg) + self.assertEqual(num, ldb.ERR_NAMING_VIOLATION, msg) # Windows returns 2099 (Illegal superior), Samba returns 2037 # (Naming violation - "not a valid child class") self.assertTrue('00002099' in msg or '00002037' in msg, msg) @@ -428,7 +428,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_NAMING_VIOLATION, msg) + self.assertEqual(num, ldb.ERR_NAMING_VIOLATION, msg) self.assertTrue('00002099' in msg or '00002037' in msg, msg) base_dn = self.ldb.get_default_basedn() @@ -645,7 +645,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) + self.assertEqual(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) # create a PSO as the admin user priv_pso = PasswordSettings("priv-PSO", self.ldb, password_len=20) @@ -658,7 +658,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) + self.assertEqual(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) self.assertTrue('00002098' in msg, msg) self.set_attribute(priv_pso.dn, "msDS-PSOAppliesTo", user.dn, @@ -670,7 +670,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) + self.assertEqual(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) self.assertTrue('00002098' in msg, msg) priv_pso.set_precedence(100, samdb=self.ldb) @@ -703,7 +703,7 @@ class PasswordSettingsTestCase(PasswordTestCase): self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) + self.assertEqual(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, msg) self.assertTrue('00002098' in msg, msg) # ...but can be performed by the admin user @@ -796,7 +796,7 @@ unicodePwd:: %s self.fail() except ldb.LdbError as e: (num, msg) = e.args - self.assertEquals(num, ldb.ERR_CONSTRAINT_VIOLATION, msg) + self.assertEqual(num, ldb.ERR_CONSTRAINT_VIOLATION, msg) self.assertTrue('0000052D' in msg, msg) # check setting a password that meets the PSO settings works diff --git a/source4/dsdb/tests/python/passwords.py b/source4/dsdb/tests/python/passwords.py index b5a91ddfbbd..5025962e6ea 100755 --- a/source4/dsdb/tests/python/passwords.py +++ b/source4/dsdb/tests/python/passwords.py @@ -105,7 +105,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # Windows (2008 at least) seems to have some small bug here: it # returns "0000056A" on longer (always wrong) previous passwords. self.assertTrue('00000056' in msg) @@ -134,7 +134,7 @@ add: userPassword self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # Enables the user account self.ldb.enable_account("(sAMAccountName=testuser)") @@ -165,7 +165,7 @@ add: userPassword self.fail() except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) def test_unicodePwd_hash_change(self): """Performs a password hash change operation on 'unicodePwd' which should be prevented""" @@ -184,7 +184,7 @@ unicodePwd: YYYYYYYYYYYYYYYY self.fail() except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) def test_unicodePwd_clear_set(self): """Performs a password cleartext set operation on 'unicodePwd'""" @@ -220,7 +220,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS4\"".encode('utf-16-le')). self.fail() except LdbError as e4: (num, msg) = e4.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg) # A change to the same password again will not work (password history) @@ -236,7 +236,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')). self.fail() except LdbError as e5: (num, msg) = e5.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('0000052D' in msg) def test_dBCSPwd_hash_set(self): @@ -252,7 +252,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')). self.fail() except LdbError as e6: (num, _) = e6.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) def test_dBCSPwd_hash_change(self): """Performs a password hash change operation on 'dBCSPwd' which should be prevented""" @@ -270,7 +270,7 @@ dBCSPwd: YYYYYYYYYYYYYYYY self.fail() except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) def test_userPassword_clear_set(self): """Performs a password cleartext set operation on 'userPassword'""" @@ -310,7 +310,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e8: (num, msg) = e8.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg) # A change to the same password again will not work (password history) @@ -326,7 +326,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e9: (num, msg) = e9.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('0000052D' in msg) def test_clearTextPassword_clear_set(self): @@ -381,7 +381,7 @@ clearTextPassword:: """ + base64.b64encode("thatsAcomplPASS4".encode('utf-16-le' (num, msg) = e12.args # "NO_SUCH_ATTRIBUTE" is returned by Windows -> ignore it if num != ERR_NO_SUCH_ATTRIBUTE: - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('00000056' in msg) # A change to the same password again will not work (password history) @@ -399,7 +399,7 @@ clearTextPassword:: """ + base64.b64encode("thatsAcomplPASS2".encode('utf-16-le' (num, msg) = e13.args # "NO_SUCH_ATTRIBUTE" is returned by Windows -> ignore it if num != ERR_NO_SUCH_ATTRIBUTE: - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) self.assertTrue('0000052D' in msg) def test_failures(self): @@ -415,7 +415,7 @@ userPassword: thatsAcomplPASS1 self.fail() except LdbError as e14: (num, _) = e14.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb2.modify_ldif(""" @@ -427,7 +427,7 @@ userPassword: thatsAcomplPASS1 self.fail() except LdbError as e15: (num, _) = e15.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.modify_ldif(""" @@ -438,7 +438,7 @@ delete: userPassword self.fail() except LdbError as e16: (num, _) = e16.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb2.modify_ldif(""" @@ -449,7 +449,7 @@ delete: userPassword self.fail() except LdbError as e17: (num, _) = e17.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.modify_ldif(""" @@ -461,7 +461,7 @@ userPassword: thatsAcomplPASS1 self.fail() except LdbError as e18: (num, _) = e18.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb2.modify_ldif(""" @@ -473,7 +473,7 @@ userPassword: thatsAcomplPASS1 self.fail() except LdbError as e19: (num, _) = e19.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: self.ldb.modify_ldif(""" @@ -488,7 +488,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e20: (num, _) = e20.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb2.modify_ldif(""" @@ -503,7 +503,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e21: (num, _) = e21.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.modify_ldif(""" @@ -518,7 +518,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e22: (num, _) = e22.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb2.modify_ldif(""" @@ -533,7 +533,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e23: (num, _) = e23.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.modify_ldif(""" @@ -549,7 +549,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e24: (num, _) = e24.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb2.modify_ldif(""" @@ -565,7 +565,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e25: (num, _) = e25.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: self.ldb.modify_ldif(""" @@ -581,7 +581,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e26: (num, _) = e26.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb2.modify_ldif(""" @@ -597,7 +597,7 @@ userPassword: thatsAcomplPASS2 self.fail() except LdbError as e27: (num, _) = e27.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: self.ldb.modify_ldif(""" @@ -613,7 +613,7 @@ userPassword: thatsAcomplPASS3 self.fail() except LdbError as e28: (num, _) = e28.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb2.modify_ldif(""" @@ -629,7 +629,7 @@ userPassword: thatsAcomplPASS3 self.fail() except LdbError as e29: (num, _) = e29.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # Reverse order does work self.ldb2.modify_ldif(""" @@ -653,7 +653,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS3\"".encode('utf-16-le')). # this passes against s4 except LdbError as e30: (num, _) = e30.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) try: self.ldb2.modify_ldif(""" @@ -667,7 +667,7 @@ userPassword: thatsAcomplPASS4 # this passes against s4 except LdbError as e31: (num, _) = e31.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) # Several password changes at once are allowed self.ldb.modify_ldif(""" @@ -716,7 +716,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e32: (num, _) = e32.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.add({ @@ -726,7 +726,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e33: (num, _) = e33.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.add({ @@ -736,7 +736,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e34: (num, _) = e34.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) try: self.ldb.add({ @@ -759,7 +759,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e36: (num, _) = e36.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -769,7 +769,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e37: (num, _) = e37.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -779,7 +779,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e38: (num, _) = e38.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -800,7 +800,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e40: (num, _) = e40.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -810,7 +810,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e41: (num, _) = e41.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -820,7 +820,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e42: (num, _) = e42.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -841,7 +841,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e44: (num, _) = e44.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -851,7 +851,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e45: (num, _) = e45.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -861,7 +861,7 @@ userPassword: thatsAcomplPASS4 self.fail() except LdbError as e46: (num, _) = e46.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -892,7 +892,7 @@ userPassword: thatsAcomplPASS4 scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) - self.assertEquals(str(res[0]["userPassword"][0]), "myPassword") + self.assertEqual(str(res[0]["userPassword"][0]), "myPassword") m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -904,7 +904,7 @@ userPassword: thatsAcomplPASS4 scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) - self.assertEquals(str(res[0]["userPassword"][0]), "myPassword2") + self.assertEqual(str(res[0]["userPassword"][0]), "myPassword2") m = Message() m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -930,7 +930,7 @@ userPassword: thatsAcomplPASS4 scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) - self.assertEquals(str(res[0]["userPassword"][0]), "myPassword3") + self.assertEqual(str(res[0]["userPassword"][0]), "myPassword3") # Set the test "dSHeuristics" to deactivate "userPassword" pwd changes self.ldb.set_dsheuristics("000000002") @@ -945,7 +945,7 @@ userPassword: thatsAcomplPASS4 scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) - self.assertEquals(str(res[0]["userPassword"][0]), "myPassword4") + self.assertEqual(str(res[0]["userPassword"][0]), "myPassword4") # Reset the test "dSHeuristics" (reactivate "userPassword" pwd changes) self.ldb.set_dsheuristics("000000001") @@ -1042,7 +1042,7 @@ userPassword: thatsAcomplPASS4 # userPassword can be read self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) - self.assertEquals(str(res[0]["userPassword"][0]), "thatsAcomplPASS2") + self.assertEqual(str(res[0]["userPassword"][0]), "thatsAcomplPASS2") # Reset the test "dSHeuristics" (reactivate "userPassword" pwd changes) self.ldb.set_dsheuristics("000000001") @@ -1090,7 +1090,7 @@ userPassword: thatsAcomplPASS1 """) except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) else: self.fail() @@ -1125,7 +1125,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS3\"".encode('utf-16-le')). """) except LdbError as e: (num, msg) = e.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) else: self.fail() diff --git a/source4/dsdb/tests/python/rodc_rwdc.py b/source4/dsdb/tests/python/rodc_rwdc.py index f8b21b8af21..0340042e19d 100644 --- a/source4/dsdb/tests/python/rodc_rwdc.py +++ b/source4/dsdb/tests/python/rodc_rwdc.py @@ -478,7 +478,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): except LdbError as e1: (num, msg) = e1.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=2, @@ -501,7 +501,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): except LdbError as e2: (num, msg) = e2.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -522,7 +522,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e3: (num, msg) = e3.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -541,7 +541,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e4: (num, msg) = e4.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -560,7 +560,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e5: (num, msg) = e5.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=3, @@ -613,7 +613,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e6: (num, msg) = e6.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=1, @@ -633,7 +633,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e7: (num, msg) = e7.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=2, @@ -665,7 +665,7 @@ class RodcRwdcCachedTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e8: (num, msg) = e8.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) res = self._check_account(userdn, badPwdCount=1, @@ -1177,7 +1177,7 @@ class RodcRwdcTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e11: (num, msg) = e11.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) # Succeed to reset everything to 0 success_creds = self.insta_creds(self.template_creds, @@ -1207,7 +1207,7 @@ class RodcRwdcTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e12: (num, msg) = e12.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) # Succeed to reset everything to 0 ldb = SamDB(url=self.host_url, credentials=self.lockout1ntlm_creds, lp=self.lp) @@ -1232,7 +1232,7 @@ class RodcRwdcTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e13: (num, msg) = e13.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) # Succeed to reset everything to 0 success_creds = self.insta_creds(self.template_creds, @@ -1262,7 +1262,7 @@ class RodcRwdcTests(password_lockout_base.BasePasswordTestCase): self.fail() except LdbError as e14: (num, msg) = e14.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) # Succeed to reset everything to 0 ldb = SamDB(url=self.host_url, credentials=self.lockout1ntlm_creds, lp=self.lp) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 99d308648df..8220cf8b44f 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -128,7 +128,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e9: (num, _) = e9.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Try to create a user with an invalid account name @@ -140,7 +140,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e10: (num, _) = e10.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Try to create a user with an invalid primary group @@ -152,7 +152,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e11: (num, _) = e11.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Try to Create a user with a valid primary group @@ -164,7 +164,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e12: (num, _) = e12.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Test to see how we should behave when the user account doesn't @@ -178,7 +178,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e13: (num, _) = e13.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Test to see how we should behave when the account isn't a user m = Message() @@ -190,7 +190,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e14: (num, _) = e14.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Test default primary groups on add operations @@ -201,7 +201,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -213,7 +213,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -229,7 +229,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -243,7 +243,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -282,7 +282,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested # since such accounts aren't directly creatable (ACCESS_DENIED) @@ -296,7 +296,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -309,7 +309,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -322,7 +322,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS) # Read-only DC accounts are only creatable by # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore @@ -360,7 +360,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e15: (num, _) = e15.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # But to reset the actual "sAMAccountName" should still be possible res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, @@ -396,7 +396,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e16: (num, _) = e16.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Try to make group 1 primary - should be denied since it is not yet # secondary @@ -409,7 +409,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e17: (num, _) = e17.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Make group 1 secondary m = Message() @@ -431,7 +431,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e18: (num, _) = e18.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # Try to add group 1 also as secondary - should be denied m = Message() @@ -443,7 +443,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e19: (num, _) = e19.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # Try to add invalid member to group 1 - should be denied m = Message() @@ -456,7 +456,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e20: (num, _) = e20.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Make group 2 secondary m = Message() @@ -487,7 +487,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["member"]) self.assertTrue(len(res1) == 1) self.assertTrue(len(res1[0]["member"]) == 1) - self.assertEquals(str(res1[0]["member"][0]).lower(), + self.assertEqual(str(res1[0]["member"][0]).lower(), ("cn=ldaptestuser,cn=users," + self.base_dn).lower()) res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn, @@ -505,7 +505,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e21: (num, _) = e21.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Delete invalid group member m = Message() @@ -517,7 +517,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e22: (num, _) = e22.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Also this should be denied try: @@ -528,7 +528,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e23: (num, _) = e23.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Recreate user accounts @@ -558,7 +558,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e24: (num, _) = e24.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # Already added, but as res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, @@ -575,7 +575,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e25: (num, _) = e25.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) # Invalid member m = Message() @@ -587,7 +587,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e26: (num, _) = e26.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Invalid member m = Message() @@ -600,7 +600,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e27: (num, _) = e27.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Invalid member m = Message() @@ -614,7 +614,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e28: (num, _) = e28.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn) @@ -654,7 +654,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e29: (num, _) = e29.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) # Delete protection tests @@ -669,7 +669,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -679,7 +679,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -690,7 +690,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e30: (num, _) = e30.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -703,7 +703,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e31: (num, _) = e31.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -714,7 +714,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e32: (num, _) = e32.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -725,7 +725,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e33: (num, _) = e33.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -736,7 +736,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e34: (num, _) = e34.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) # Delete protection tests @@ -754,7 +754,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -764,7 +764,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -781,7 +781,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e35: (num, _) = e35.args - self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE) + self.assertEqual(num, ERR_UNDEFINED_ATTRIBUTE_TYPE) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) ldb.add({ @@ -831,7 +831,7 @@ class SamTests(samba.tests.TestCase): obj_sid = get_string(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])) rid = security.dom_sid(obj_sid).split()[1] - self.assertEquals(primary_group_token, rid) + self.assertEqual(primary_group_token, rid) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -841,7 +841,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e36: (num, _) = e36.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -909,7 +909,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e37: (num, _) = e37.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) try: @@ -920,7 +920,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e38: (num, _) = e38.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) ldb.add({ @@ -931,7 +931,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -943,7 +943,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -955,7 +955,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_LOCAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -967,7 +967,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_GLOBAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -979,7 +979,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_UNIVERSAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -991,7 +991,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_LOCAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1009,7 +1009,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Invalid attribute @@ -1022,7 +1022,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e39: (num, _) = e39.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Security groups @@ -1038,7 +1038,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Change to "local" (shouldn't work) @@ -1053,7 +1053,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e40: (num, _) = e40.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change to "universal" @@ -1067,7 +1067,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) # Change back to "global" @@ -1082,7 +1082,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Change back to "universal" @@ -1097,7 +1097,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) # Change to "local" @@ -1112,7 +1112,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_LOCAL_GROUP) # Change to "global" (shouldn't work) @@ -1127,7 +1127,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e41: (num, _) = e41.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change to "builtin local" (shouldn't work) @@ -1141,7 +1141,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e42: (num, _) = e42.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1158,7 +1158,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) # Change to "builtin local" (shouldn't work) @@ -1173,7 +1173,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e43: (num, _) = e43.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change back to "global" @@ -1187,7 +1187,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Change to "builtin local" (shouldn't work) @@ -1202,7 +1202,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e44: (num, _) = e44.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Distribution groups @@ -1218,7 +1218,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_GLOBAL_GROUP) # Change to local (shouldn't work) @@ -1233,7 +1233,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e45: (num, _) = e45.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change to "universal" @@ -1247,7 +1247,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_UNIVERSAL_GROUP) # Change back to "global" @@ -1262,7 +1262,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_GLOBAL_GROUP) # Change back to "universal" @@ -1277,7 +1277,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_UNIVERSAL_GROUP) # Change to "local" @@ -1292,7 +1292,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_LOCAL_GROUP) # Change to "global" (shouldn't work) @@ -1307,7 +1307,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e46: (num, _) = e46.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change back to "universal" @@ -1322,7 +1322,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e47: (num, _) = e47.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) # Make group 2 secondary m = Message() @@ -1335,7 +1335,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_UNIVERSAL_GROUP) # Change back to "global" @@ -1350,7 +1350,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_GLOBAL_GROUP) # Both group types: this performs only random checks - all possibilities @@ -1368,7 +1368,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Change to "local" (shouldn't work) @@ -1383,7 +1383,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e48: (num, _) = e48.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change to "universal" @@ -1397,7 +1397,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_UNIVERSAL_GROUP) # Change back to "global" @@ -1412,7 +1412,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) # Change back to "universal" @@ -1427,7 +1427,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) # Change to "local" @@ -1442,7 +1442,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_DISTRIBUTION_LOCAL_GROUP) # Change to "global" (shouldn't work) @@ -1457,7 +1457,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e49: (num, _) = e49.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # Change back to "universal" @@ -1471,7 +1471,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_UNIVERSAL_GROUP) # Change back to "global" @@ -1486,7 +1486,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_SECURITY_GLOBAL_GROUP) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -1536,7 +1536,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e50: (num, msg) = e50.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) self.assertTrue('00000057' in msg) try: @@ -1547,7 +1547,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e51: (num, msg) = e51.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) self.assertTrue('00000057' in msg) ldb.add({ @@ -1611,7 +1611,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e52: (num, msg) = e52.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) self.assertTrue('00002085' in msg) try: @@ -1627,7 +1627,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e53: (num, msg) = e53.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) self.assertTrue('00002085' in msg) m = Message() @@ -1663,7 +1663,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e54: (num, msg) = e54.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) self.assertTrue('00000057' in msg) m = Message() @@ -1827,7 +1827,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e56: (num, msg) = e56.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) self.assertTrue(error_msg_sasl_wrong_pw in msg) if not requires_strong_auth: @@ -1836,7 +1836,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e4: (num, msg) = e4.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw) m = Message() @@ -1855,7 +1855,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e57: (num, msg) = e57.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) assertLDAPErrorMsg(msg, error_msg_sasl_wrong_pw) try: @@ -1863,7 +1863,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e58: (num, msg) = e58.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) assertLDAPErrorMsg(msg, error_msg_sasl_must_change) if not requires_strong_auth: @@ -1872,7 +1872,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e5: (num, msg) = e5.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw) try: @@ -1880,7 +1880,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e6: (num, msg) = e6.args - self.assertEquals(num, ERR_INVALID_CREDENTIALS) + self.assertEqual(num, ERR_INVALID_CREDENTIALS) assertLDAPErrorMsg(msg, error_msg_simple_must_change) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -1907,7 +1907,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) @@ -1928,7 +1928,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -1945,7 +1945,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0) self.assertFalse("lockoutTime" in res1[0]) @@ -1960,7 +1960,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e59: (num, _) = e59.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) try: @@ -1971,7 +1971,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e60: (num, _) = e60.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) try: @@ -1981,7 +1981,7 @@ class SamTests(samba.tests.TestCase): "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)}) except LdbError as e61: (num, _) = e61.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) try: @@ -1991,7 +1991,7 @@ class SamTests(samba.tests.TestCase): "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)}) except LdbError as e62: (num, _) = e62.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) try: @@ -2002,7 +2002,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e63: (num, _) = e63.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Modify operation @@ -2016,7 +2016,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0) @@ -2035,7 +2035,7 @@ class SamTests(samba.tests.TestCase): ldb.modify(m) except LdbError as e64: (num, _) = e64.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: m = Message() @@ -2046,7 +2046,7 @@ class SamTests(samba.tests.TestCase): ldb.modify(m) except LdbError as e65: (num, _) = e65.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -2059,7 +2059,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) @@ -2074,7 +2074,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0) @@ -2096,7 +2096,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0) @@ -2113,7 +2113,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e66: (num, _) = e66.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) try: m = Message() @@ -2125,7 +2125,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e67: (num, _) = e67.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -2144,12 +2144,12 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e68: (num, _) = e68.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) m = Message() @@ -2162,7 +2162,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) try: @@ -2175,7 +2175,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e69: (num, _) = e69.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # With a computer object @@ -2195,7 +2195,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) @@ -2216,7 +2216,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2233,7 +2233,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0) self.assertFalse("lockoutTime" in res1[0]) @@ -2248,7 +2248,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e70: (num, _) = e70.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) ldb.add({ @@ -2259,7 +2259,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2270,7 +2270,7 @@ class SamTests(samba.tests.TestCase): "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)}) except LdbError as e71: (num, _) = e71.args - self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) try: @@ -2281,7 +2281,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e72: (num, _) = e72.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) # Modify operation @@ -2295,7 +2295,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0) @@ -2315,7 +2315,7 @@ class SamTests(samba.tests.TestCase): ldb.modify(m) except LdbError as e73: (num, _) = e73.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: m = Message() @@ -2326,7 +2326,7 @@ class SamTests(samba.tests.TestCase): ldb.modify(m) except LdbError as e74: (num, _) = e74.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2339,7 +2339,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) @@ -2354,7 +2354,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0) @@ -2376,7 +2376,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0) @@ -2393,7 +2393,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e75: (num, _) = e75.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2405,7 +2405,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) m = Message() @@ -2418,7 +2418,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) m = Message() @@ -2431,7 +2431,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) m = Message() @@ -2444,7 +2444,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) m = Message() @@ -2457,7 +2457,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) m = Message() @@ -2470,7 +2470,7 @@ class SamTests(samba.tests.TestCase): res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["sAMAccountType"][0]), + self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) try: @@ -2483,7 +2483,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e76: (num, _) = e76.args - self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) # "primaryGroupID" does not change if account type remains the same @@ -2500,7 +2500,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["userAccountControl"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["userAccountControl"][0]), + self.assertEqual(int(res1[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) m = Message() @@ -2527,7 +2527,7 @@ class SamTests(samba.tests.TestCase): attrs=["userAccountControl", "primaryGroupID"]) self.assertTrue(len(res1) == 1) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_ADMINS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_ADMINS) # For a workstation account @@ -2535,7 +2535,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) m = Message() m.dn = Dn(ldb, "") @@ -2560,7 +2560,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["primaryGroupID"]) self.assertTrue(len(res1) == 1) - self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) + self.assertEqual(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) @@ -2953,7 +2953,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2966,7 +2966,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2979,7 +2979,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") # Modification tests @@ -2993,7 +2993,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3005,7 +3005,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3018,7 +3018,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3030,7 +3030,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3042,7 +3042,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "TRUE") m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3054,7 +3054,7 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3095,12 +3095,12 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["dNSHostName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom") + self.assertEqual(str(res[0]["dNSHostName"][0]), "testname2.testdom") res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname.testdom") m = Message() @@ -3112,7 +3112,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname.testdom") m = Message() @@ -3124,7 +3124,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2.testdom2") m = Message() @@ -3136,7 +3136,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2.testdom2") m = Message() @@ -3148,7 +3148,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2.testdom2") m = Message() @@ -3169,7 +3169,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname3.testdom3") m = Message() @@ -3184,7 +3184,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2.testdom2") m = Message() @@ -3240,12 +3240,12 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname$") + self.assertEqual(str(res[0]["sAMAccountName"][0]), "testname$") res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname") m = Message() @@ -3257,7 +3257,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname") m = Message() @@ -3269,7 +3269,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname") m = Message() @@ -3281,7 +3281,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/test$name") m = Message() @@ -3293,7 +3293,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2") m = Message() @@ -3308,7 +3308,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname3") m = Message() @@ -3323,7 +3323,7 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["servicePrincipalName"][0]), + self.assertEqual(str(res[0]["servicePrincipalName"][0]), "HOST/testname2") m = Message() @@ -3365,8 +3365,8 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom") - self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$") + self.assertEqual(str(res[0]["dNSHostName"][0]), "testname2.testdom") + self.assertEqual(str(res[0]["sAMAccountName"][0]), "testname2$") self.assertTrue(str(res[0]["servicePrincipalName"][0]) == "HOST/testname2" or str(res[0]["servicePrincipalName"][1]) == "HOST/testname2") self.assertTrue(str(res[0]["servicePrincipalName"][0]) == "HOST/testname2.testdom" or @@ -3393,8 +3393,8 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom") - self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$") + self.assertEqual(str(res[0]["dNSHostName"][0]), "testname2.testdom") + self.assertEqual(str(res[0]["sAMAccountName"][0]), "testname2$") self.assertTrue(len(res[0]["servicePrincipalName"]) == 2) self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]]) self.assertTrue("HOST/testname2.testdom" in [str(x) for x in res[0]["servicePrincipalName"]]) @@ -3408,7 +3408,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e77: (num, _) = e77.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -3419,8 +3419,8 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom") - self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$") + self.assertEqual(str(res[0]["dNSHostName"][0]), "testname2.testdom") + self.assertEqual(str(res[0]["sAMAccountName"][0]), "testname2$") self.assertTrue(len(res[0]["servicePrincipalName"]) == 3) self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]]) self.assertTrue("HOST/testname3" in [str(x) for x in res[0]["servicePrincipalName"]]) @@ -3437,8 +3437,8 @@ class SamTests(samba.tests.TestCase): res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn, scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"]) self.assertTrue(len(res) == 1) - self.assertEquals(str(res[0]["dNSHostName"][0]), "testname3.testdom") - self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$") + self.assertEqual(str(res[0]["dNSHostName"][0]), "testname3.testdom") + self.assertEqual(str(res[0]["sAMAccountName"][0]), "testname2$") self.assertTrue(len(res[0]["servicePrincipalName"]) == 3) self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]]) self.assertTrue("HOST/testname3" in [str(x) for x in res[0]["servicePrincipalName"]]) @@ -3461,7 +3461,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(len(res) == 1) self.assertTrue("description" in res[0]) self.assertTrue(len(res[0]["description"]) == 1) - self.assertEquals(str(res[0]["description"][0]), "desc1") + self.assertEqual(str(res[0]["description"][0]), "desc1") delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3489,7 +3489,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e78: (num, _) = e78.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3514,7 +3514,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(len(res) == 1) self.assertTrue("description" in res[0]) self.assertTrue(len(res[0]["description"]) == 1) - self.assertEquals(str(res[0]["description"][0]), "desc1") + self.assertEqual(str(res[0]["description"][0]), "desc1") delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3534,7 +3534,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(len(res) == 1) self.assertTrue("description" in res[0]) self.assertTrue(len(res[0]["description"]) == 1) - self.assertEquals(str(res[0]["description"][0]), "desc1") + self.assertEqual(str(res[0]["description"][0]), "desc1") m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3545,7 +3545,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e79: (num, _) = e79.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3556,7 +3556,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e80: (num, _) = e80.args - self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) + self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3577,7 +3577,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e81: (num, _) = e81.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3588,7 +3588,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e82: (num, _) = e82.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3601,7 +3601,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(len(res) == 1) self.assertTrue("description" in res[0]) self.assertTrue(len(res[0]["description"]) == 1) - self.assertEquals(str(res[0]["description"][0]), "desc1") + self.assertEqual(str(res[0]["description"][0]), "desc1") m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3614,7 +3614,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(len(res) == 1) self.assertTrue("description" in res[0]) self.assertTrue(len(res[0]["description"]) == 1) - self.assertEquals(str(res[0]["description"][0]), "desc2") + self.assertEqual(str(res[0]["description"][0]), "desc2") delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3635,7 +3635,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e83: (num, _) = e83.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) try: self.ldb.add({ @@ -3645,7 +3645,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e84: (num, _) = e84.args - self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) # We are able to set it to a valid "nTDSDSA" entry if the server is # capable of handling the role @@ -3669,7 +3669,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e85: (num, _) = e85.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -3679,7 +3679,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e86: (num, _) = e86.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) # We are able to set it to a valid "nTDSDSA" entry if the server is # capable of handling the role @@ -3715,7 +3715,7 @@ class SamTests(samba.tests.TestCase): self.ldb.delete(pr_object[0] + "," + pr_object[1] + self.base_dn) except LdbError as e7: (num, _) = e7.args - self.assertEquals(num, ERR_OTHER) + self.assertEqual(num, ERR_OTHER) else: self.fail("Deleted " + pr_object[0]) diff --git a/source4/dsdb/tests/python/sec_descriptor.py b/source4/dsdb/tests/python/sec_descriptor.py index a495356ac48..8edf5e092d7 100755 --- a/source4/dsdb/tests/python/sec_descriptor.py +++ b/source4/dsdb/tests/python/sec_descriptor.py @@ -75,7 +75,7 @@ class DescriptorTests(samba.tests.TestCase): self.ldb_admin.search(base=class_dn, attrs=["name"]) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) break ldif = """ @@ -1985,31 +1985,31 @@ class RightsAttributesTests(DescriptorTests): res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["sDRightsEffective"]) # user whould have no rights at all - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["sDRightsEffective"][0]), "0") + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["sDRightsEffective"][0]), "0") # give the user Write DACL and see what happens mod = "(A;CI;WD;;;%s)" % str(user_sid) self.sd_utils.dacl_add_ace(object_dn, mod) res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["sDRightsEffective"]) # user whould have DACL_SECURITY_INFORMATION - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["sDRightsEffective"][0]), ("%d") % SECINFO_DACL) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["sDRightsEffective"][0]), ("%d") % SECINFO_DACL) # give the user Write Owners and see what happens mod = "(A;CI;WO;;;%s)" % str(user_sid) self.sd_utils.dacl_add_ace(object_dn, mod) res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["sDRightsEffective"]) # user whould have DACL_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["sDRightsEffective"][0]), ("%d") % (SECINFO_DACL | SECINFO_GROUP | SECINFO_OWNER)) + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["sDRightsEffective"][0]), ("%d") % (SECINFO_DACL | SECINFO_GROUP | SECINFO_OWNER)) # no way to grant security privilege bu adding ACE's so we use a memeber of Domain Admins _ldb = self.get_ldb_connection("testuser_attr2", "samba123@") res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["sDRightsEffective"]) # user whould have DACL_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION - self.assertEquals(len(res), 1) - self.assertEquals(str(res[0]["sDRightsEffective"][0]), + self.assertEqual(len(res), 1) + self.assertEqual(str(res[0]["sDRightsEffective"][0]), ("%d") % (SECINFO_DACL | SECINFO_GROUP | SECINFO_OWNER | SECINFO_SACL)) def test_allowedChildClassesEffective(self): @@ -2024,7 +2024,7 @@ class RightsAttributesTests(DescriptorTests): res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["allowedChildClassesEffective"]) # there should be no allowed child classes - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("allowedChildClassesEffective" in res[0].keys()) # give the user the right to create children of type user mod = "(OA;CI;CC;bf967aba-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) @@ -2032,9 +2032,9 @@ class RightsAttributesTests(DescriptorTests): res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["allowedChildClassesEffective"]) # allowedChildClassesEffective should only have one value, user - self.assertEquals(len(res), 1) - self.assertEquals(len(res[0]["allowedChildClassesEffective"]), 1) - self.assertEquals(str(res[0]["allowedChildClassesEffective"][0]), "user") + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]["allowedChildClassesEffective"]), 1) + self.assertEqual(str(res[0]["allowedChildClassesEffective"][0]), "user") def test_allowedAttributesEffective(self): object_dn = "OU=test_domain_ou1," + self.base_dn @@ -2048,7 +2048,7 @@ class RightsAttributesTests(DescriptorTests): res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["allowedAttributesEffective"]) # there should be no allowed attributes - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.assertFalse("allowedAttributesEffective" in res[0].keys()) # give the user the right to write displayName and managedBy mod2 = "(OA;CI;WP;bf967953-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) @@ -2059,8 +2059,8 @@ class RightsAttributesTests(DescriptorTests): res = _ldb.search(base=object_dn, expression="", scope=SCOPE_BASE, attrs=["allowedAttributesEffective"]) # value should only contain user and managedBy - self.assertEquals(len(res), 1) - self.assertEquals(len(res[0]["allowedAttributesEffective"]), 2) + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]["allowedAttributesEffective"]), 2) self.assertTrue(b"displayName" in res[0]["allowedAttributesEffective"]) self.assertTrue(b"managedBy" in res[0]["allowedAttributesEffective"]) diff --git a/source4/dsdb/tests/python/sort.py b/source4/dsdb/tests/python/sort.py index 4593c8c7450..a85957f697d 100644 --- a/source4/dsdb/tests/python/sort.py +++ b/source4/dsdb/tests/python/sort.py @@ -230,7 +230,7 @@ class BaseSortTests(samba.tests.TestCase): print("unnormalised:", [x[attr][0] for x in res]) print("unnormalised: «%s»" % '» «'.join(str(x[attr][0]) for x in res)) - self.assertEquals(expected_order, received_order) + self.assertEqual(expected_order, received_order) def _test_server_sort_binary(self): for attr in self.binary_sorted_keys: @@ -247,7 +247,7 @@ class BaseSortTests(samba.tests.TestCase): print(attr) print(expected_order) print(received_order) - self.assertEquals(expected_order, received_order) + self.assertEqual(expected_order, received_order) def _test_server_sort_us_english(self): # Windows doesn't support many matching rules, but does allow @@ -278,7 +278,7 @@ class BaseSortTests(samba.tests.TestCase): print("unnormalised: «%s»" % '» «'.join(str(x[attr][0]) for x in res)) - self.assertEquals(expected_order, received_order) + self.assertEqual(expected_order, received_order) def _test_server_sort_different_attr(self): @@ -337,7 +337,7 @@ class BaseSortTests(samba.tests.TestCase): print("Try with --elements=27 (or similar).") print('-' * 72) - self.assertEquals(expected_order, received_order) + self.assertEqual(expected_order, received_order) for x in res: if sort_attr in x: self.fail('the search for %s should not return %s' % diff --git a/source4/dsdb/tests/python/token_group.py b/source4/dsdb/tests/python/token_group.py index 652533272c8..7e314627a32 100755 --- a/source4/dsdb/tests/python/token_group.py +++ b/source4/dsdb/tests/python/token_group.py @@ -67,7 +67,7 @@ class StaticTokenTest(samba.tests.TestCase): self.base_dn = self.ldb.domain_dn() res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.user_sid_dn = "" % str(ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0])) @@ -91,7 +91,7 @@ class StaticTokenTest(samba.tests.TestCase): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) print("Getting tokenGroups from rootDSE") tokengroups = [] @@ -110,7 +110,7 @@ class StaticTokenTest(samba.tests.TestCase): def test_dn_tokenGroups(self): print("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: @@ -273,13 +273,13 @@ class DynamicTokenTest(samba.tests.TestCase): self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass) res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0]) self.user_sid_dn = "" % str(self.user_sid) res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) self.test_user_dn = res[0].dn @@ -323,7 +323,7 @@ class DynamicTokenTest(samba.tests.TestCase): self.fail(msg="This test is only valid on ldap") res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) print("Getting tokenGroups from rootDSE") tokengroups = [] @@ -342,7 +342,7 @@ class DynamicTokenTest(samba.tests.TestCase): def test_dn_tokenGroups(self): print("Getting tokenGroups from user DN") res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: @@ -450,7 +450,7 @@ class DynamicTokenTest(samba.tests.TestCase): tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroups']: @@ -537,7 +537,7 @@ class DynamicTokenTest(samba.tests.TestCase): tokenGroupsSet = set() res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) dn_tokengroups = [] for sid in res[0]['tokenGroupsGlobalAndUniversal']: diff --git a/source4/dsdb/tests/python/tombstone_reanimation.py b/source4/dsdb/tests/python/tombstone_reanimation.py index 9cca5436295..3c15c8e176f 100755 --- a/source4/dsdb/tests/python/tombstone_reanimation.py +++ b/source4/dsdb/tests/python/tombstone_reanimation.py @@ -65,7 +65,7 @@ class RestoredObjectAttributesBaseTestCase(samba.tests.TestCase): res = self.samdb.search(base="" % self.GUID_string(guid), scope=SCOPE_BASE, attrs=attrs, controls=["show_deleted:1"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return res[0] def search_dn(self, dn): @@ -73,7 +73,7 @@ class RestoredObjectAttributesBaseTestCase(samba.tests.TestCase): base=dn, scope=SCOPE_BASE, controls=["show_recycled:1"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return res[0] def _create_object(self, msg): @@ -160,14 +160,14 @@ class RestoredObjectAttributesBaseTestCase(samba.tests.TestCase): for o in repl.ctr.array: e = expected[i] (attid, version) = e - self.assertEquals(attid, o.attid, + self.assertEqual(attid, o.attid, "(LDAP) Wrong attid " "for expected value %d, wanted 0x%08x got 0x%08x, " "repl: \n%s" % (i, attid, o.attid, ndr_print(repl))) # Allow version to be skipped when it does not matter if version is not None: - self.assertEquals(o.version, version, + self.assertEqual(o.version, version, "(LDAP) Wrong version for expected value %d, " "attid 0x%08x, " "wanted %d got %d, repl: \n%s" @@ -208,7 +208,7 @@ class BaseRestoreObjectTestCase(RestoredObjectAttributesBaseTestCase): self.samdb.modify(msg) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) + self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) def test_undelete(self): print("Testing standard undelete operation") @@ -246,14 +246,14 @@ class BaseRestoreObjectTestCase(RestoredObjectAttributesBaseTestCase): self.fail() except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) try: self.samdb.rename(str(objDeleted1.dn), usr1, ["show_deleted:1"]) self.fail() except LdbError as e2: (num, _) = e2.args - self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) def test_undelete_with_mod(self): print("Testing standard undelete operation with modification of additional attributes") @@ -313,7 +313,7 @@ class BaseRestoreObjectTestCase(RestoredObjectAttributesBaseTestCase): self.fail() except LdbError as e3: (num, _) = e3.args - self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS) + self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS) def test_undelete_cross_nc(self): print("Cross NC undelete") @@ -345,14 +345,14 @@ class BaseRestoreObjectTestCase(RestoredObjectAttributesBaseTestCase): self.fail() except LdbError as e4: (num, _) = e4.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # try to undelete from config to base dn try: self.restore_deleted_object(self.samdb, objDeleted2.dn, c4) self.fail() except LdbError as e5: (num, _) = e5.args - self.assertEquals(num, ERR_OPERATIONS_ERROR) + self.assertEqual(num, ERR_OPERATIONS_ERROR) # assert undeletion will work in same nc self.restore_deleted_object(self.samdb, objDeleted1.dn, c4) self.restore_deleted_object(self.samdb, objDeleted2.dn, c3) diff --git a/source4/dsdb/tests/python/urgent_replication.py b/source4/dsdb/tests/python/urgent_replication.py index 5e304cfc989..6ec698d0bbb 100755 --- a/source4/dsdb/tests/python/urgent_replication.py +++ b/source4/dsdb/tests/python/urgent_replication.py @@ -41,7 +41,7 @@ class UrgentReplicationTests(samba.tests.TestCase): ldb.delete(dn, ["relax:0"]) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) def setUp(self): super(UrgentReplicationTests, self).setUp() @@ -96,7 +96,7 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should be enabled when creation res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when modifying m = Message() @@ -110,7 +110,7 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should be enabled when deleting self.delete_force(self.ldb, "cn=NTDS Settings test,cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn) res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) self.delete_force(self.ldb, "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn) @@ -129,7 +129,7 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should be enabled when creating res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when modifying m = Message() @@ -143,7 +143,7 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should be enabled when deleting self.delete_force(self.ldb, "cn=test crossRef,CN=Partitions,CN=Configuration," + self.base_dn) res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) def test_attributeSchema_object(self): """Test if the urgent replication is activated when handling an attributeSchema object""" @@ -167,7 +167,7 @@ name: test attributeSchema""") # urgent replication should be enabled when creating res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying m = Message() @@ -176,7 +176,7 @@ name: test attributeSchema""") "lDAPDisplayName") self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) def test_classSchema_object(self): """Test if the urgent replication is activated when handling a classSchema object.""" @@ -205,7 +205,7 @@ defaultHidingValue: TRUE""") # urgent replication should be enabled when creating res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) except LdbError: print("Not testing urgent replication when creating classSchema object ...\n") @@ -217,7 +217,7 @@ defaultHidingValue: TRUE""") "lDAPDisplayName") self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) def test_secret_object(self): """Test if the urgent replication is activated when handling a secret object.""" @@ -231,7 +231,7 @@ defaultHidingValue: TRUE""") # urgent replication should be enabled when creating res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying m = Message() @@ -240,7 +240,7 @@ defaultHidingValue: TRUE""") "currentValue") self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when deleting self.delete_force(self.ldb, "cn=test secret,cn=System," + self.base_dn) @@ -262,7 +262,7 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) # urgent replication should be enabled when creating res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying m = Message() @@ -271,7 +271,7 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) "systemFlags") self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when deleting self.delete_force(self.ldb, "CN=RID Manager test,CN=System," + self.base_dn) @@ -301,7 +301,7 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) "userAccountControl") self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying lockoutTime m = Message() @@ -310,7 +310,7 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) "lockoutTime") self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying pwdLastSet m = Message() @@ -319,7 +319,7 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) "pwdLastSet") self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) - self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) + self.assertEqual(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when modifying a not-urgent # attribute diff --git a/source4/dsdb/tests/python/vlv.py b/source4/dsdb/tests/python/vlv.py index 5caebafb94b..90a29ab6ec2 100644 --- a/source4/dsdb/tests/python/vlv.py +++ b/source4/dsdb/tests/python/vlv.py @@ -411,7 +411,7 @@ class VLVTests(VLVTestsBase): print("start %d end %d" % (start, end)) print("expected: %s" % expected_results) print("got : %s" % results) - self.assertEquals(expected_results, results) + self.assertEqual(expected_results, results) def test_server_vlv_with_cookie(self): attrs = [x for x in self.users[0].keys() if x not in @@ -542,7 +542,7 @@ class VLVTests(VLVTestsBase): expected_results = expected_order[start: end] - self.assertEquals(expected_results, results) + self.assertEqual(expected_results, results) def test_vlv_gte_with_expression(self): """What happens when we run the VLV with an expression?""" @@ -622,7 +622,7 @@ class VLVTests(VLVTestsBase): if expected_results != results: print("attr %s before %d after %d offset %d" % (attr, before, after, offset)) - self.assertEquals(expected_results, results) + self.assertEqual(expected_results, results) n = len(self.users) if random.random() < 0.1 + (n < 5) * 0.05: @@ -671,7 +671,7 @@ class VLVTests(VLVTestsBase): controls=[sort_control, vlv_search]) results = [x[attr][0].upper() for x in res] - #self.assertEquals(expected_order, results) + #self.assertEqual(expected_order, results) dn_order = [str(x['dn']) for x in res] values = results[:] @@ -694,7 +694,7 @@ class VLVTests(VLVTestsBase): dn_expected = dn_order[offset - before - 1: offset + after] - self.assertEquals(dn_expected, dn_results) + self.assertEqual(dn_expected, dn_results) results = [x[attr][0].upper() for x in res] @@ -1028,7 +1028,7 @@ class VLVTests(VLVTestsBase): expected_results = expected_order[start: end] - self.assertEquals(expected_results, results) + self.assertEqual(expected_results, results) def test_server_vlv_gte_no_cookie(self): attrs = [x for x in self.users[0].keys() if x not in @@ -1072,7 +1072,7 @@ class VLVTests(VLVTestsBase): print("\nattr %s offset %d before %d " "after %d gte %s" % (attr, offset, before, after, gte)) - self.assertEquals(expected_results, results) + self.assertEqual(expected_results, results) def test_multiple_searches(self): """The maximum number of concurrent vlv searches per connection is diff --git a/source4/torture/drs/python/cracknames.py b/source4/torture/drs/python/cracknames.py index c35a2680ff9..e4884ea0f63 100644 --- a/source4/torture/drs/python/cracknames.py +++ b/source4/torture/drs/python/cracknames.py @@ -83,8 +83,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779, drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_OK) user_guid = ctr.array[0].result_name @@ -94,8 +94,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID, name_format) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_OK, "Expected 0, got %s, desired format is %s" % (ctr.array[0].status, name_format)) @@ -104,8 +104,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): name_format, drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_OK, "Expected 0, got %s, offered format is %s" % (ctr.array[0].status, name_format)) @@ -134,8 +134,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779, drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_OK) user_guid = ctr.array[0].result_name @@ -144,8 +144,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID, drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) self.ldb_dc1.delete(user) @@ -172,8 +172,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779, drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_OK) user_guid = ctr.array[0].result_name @@ -182,8 +182,8 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase): drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID, drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) - self.assertEquals(ctr.count, 1) - self.assertEquals(ctr.array[0].status, + self.assertEqual(ctr.count, 1) + self.assertEqual(ctr.array[0].status, drsuapi.DRSUAPI_DS_NAME_STATUS_NOT_FOUND) self.ldb_dc1.delete(user) diff --git a/source4/torture/drs/python/delete_object.py b/source4/torture/drs/python/delete_object.py index 1022489a767..395877ad76a 100644 --- a/source4/torture/drs/python/delete_object.py +++ b/source4/torture/drs/python/delete_object.py @@ -65,7 +65,7 @@ class DrsDeleteObjectTestCase(drs_base.DrsBaseTestCase): res = sam_ldb.search(base=self.domain_dn, expression=expression, controls=["show_deleted:1"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) user_cur = res[0] # Deleted Object base DN dodn = self._deleted_objects_dn(sam_ldb) @@ -75,7 +75,7 @@ class DrsDeleteObjectTestCase(drs_base.DrsBaseTestCase): name_orig = str(obj_orig["name"][0]) name_cur = str(user_cur["name"][0]) if is_deleted: - self.assertEquals(str(user_cur["isDeleted"][0]), "TRUE") + self.assertEqual(str(user_cur["isDeleted"][0]), "TRUE") self.assertFalse("objectCategory" in user_cur) self.assertFalse("sAMAccountType" in user_cur) self.assertFalse("description" in user_cur) @@ -83,17 +83,17 @@ class DrsDeleteObjectTestCase(drs_base.DrsBaseTestCase): self.assertFalse("member" in user_cur) self.assertTrue(dodn in str(user_cur["dn"]), "User %s is deleted but it is not located under %s (found at %s)!" % (name_orig, dodn, user_cur["dn"])) - self.assertEquals(name_cur, name_orig + "\nDEL:" + guid_str) - self.assertEquals(name_cur, user_cur.dn.get_rdn_value()) - self.assertEquals(cn_cur, cn_orig + "\nDEL:" + guid_str) - self.assertEquals(name_cur, cn_cur) + self.assertEqual(name_cur, name_orig + "\nDEL:" + guid_str) + self.assertEqual(name_cur, user_cur.dn.get_rdn_value()) + self.assertEqual(cn_cur, cn_orig + "\nDEL:" + guid_str) + self.assertEqual(name_cur, cn_cur) else: self.assertFalse("isDeleted" in user_cur) - self.assertEquals(name_cur, name_orig) - self.assertEquals(name_cur, user_cur.dn.get_rdn_value()) - self.assertEquals(cn_cur, cn_orig) - self.assertEquals(name_cur, cn_cur) - self.assertEquals(obj_orig["dn"], user_cur["dn"]) + self.assertEqual(name_cur, name_orig) + self.assertEqual(name_cur, user_cur.dn.get_rdn_value()) + self.assertEqual(cn_cur, cn_orig) + self.assertEqual(name_cur, cn_cur) + self.assertEqual(obj_orig["dn"], user_cur["dn"]) self.assertTrue(dodn not in str(user_cur["dn"])) return user_cur @@ -118,7 +118,7 @@ class DrsDeleteObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.domain_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -274,7 +274,7 @@ class DrsDeleteObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.domain_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] diff --git a/source4/torture/drs/python/drs_base.py b/source4/torture/drs/python/drs_base.py index 0a48d63676c..33fb1b3a89a 100644 --- a/source4/torture/drs/python/drs_base.py +++ b/source4/torture/drs/python/drs_base.py @@ -98,14 +98,14 @@ class DrsBaseTestCase(SambaToolCmdTest): res = sam_ldb.search(base=wkdn, scope=SCOPE_BASE, controls=["show_deleted:1"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return str(res[0]["dn"]) def _lost_and_found_dn(self, sam_ldb, nc): wkdn = "" % (dsdb.DS_GUID_LOSTANDFOUND_CONTAINER, nc) res = sam_ldb.search(base=wkdn, scope=SCOPE_BASE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) return str(res[0]["dn"]) def _make_obj_name(self, prefix): @@ -147,7 +147,7 @@ class DrsBaseTestCase(SambaToolCmdTest): (result, out, err) = self.runsubcmd(*samba_tool_cmdline) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") def _enable_inbound_repl(self, DC): # make base command line @@ -156,7 +156,7 @@ class DrsBaseTestCase(SambaToolCmdTest): samba_tool_cmd += [DC, "--dsa-option=-DISABLE_INBOUND_REPL"] (result, out, err) = self.runsubcmd(*samba_tool_cmd) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") def _disable_inbound_repl(self, DC): # make base command line @@ -165,7 +165,7 @@ class DrsBaseTestCase(SambaToolCmdTest): samba_tool_cmd += [DC, "--dsa-option=+DISABLE_INBOUND_REPL"] (result, out, err) = self.runsubcmd(*samba_tool_cmd) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") def _enable_all_repl(self, DC): self._enable_inbound_repl(DC) @@ -175,7 +175,7 @@ class DrsBaseTestCase(SambaToolCmdTest): samba_tool_cmd += [DC, "--dsa-option=-DISABLE_OUTBOUND_REPL"] (result, out, err) = self.runsubcmd(*samba_tool_cmd) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") def _disable_all_repl(self, DC): self._disable_inbound_repl(DC) @@ -185,7 +185,7 @@ class DrsBaseTestCase(SambaToolCmdTest): samba_tool_cmd += [DC, "--dsa-option=+DISABLE_OUTBOUND_REPL"] (result, out, err) = self.runsubcmd(*samba_tool_cmd) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") def _get_highest_hwm_utdv(self, ldb_conn): res = ldb_conn.search("", scope=ldb.SCOPE_BASE, attrs=["highestCommittedUSN"]) diff --git a/source4/torture/drs/python/fsmo.py b/source4/torture/drs/python/fsmo.py index f846ca71611..b548fbca26a 100644 --- a/source4/torture/drs/python/fsmo.py +++ b/source4/torture/drs/python/fsmo.py @@ -70,7 +70,7 @@ class DrsFsmoTestCase(drs_base.DrsBaseTestCase): cmd_line_auth) self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") if not noop: self.assertTrue("FSMO transfer of '%s' role successful" % role in out) else: diff --git a/source4/torture/drs/python/getnc_exop.py b/source4/torture/drs/python/getnc_exop.py index 6d60d977ea5..87571ca252b 100644 --- a/source4/torture/drs/python/getnc_exop.py +++ b/source4/torture/drs/python/getnc_exop.py @@ -238,7 +238,7 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): self.fail("Expected DsGetNCChanges to fail with WERR_DS_CANT_FIND_EXPECTED_NC") except WERRORError as e1: (enum, estr) = e1.args - self.assertEquals(enum, werror.WERR_DS_CANT_FIND_EXPECTED_NC) + self.assertEqual(enum, werror.WERR_DS_CANT_FIND_EXPECTED_NC) def test_link_utdv_hwm(self): """Test verify the DRS_GET_ANC behavior.""" diff --git a/source4/torture/drs/python/getncchanges.py b/source4/torture/drs/python/getncchanges.py index 1f6a53aa00b..7bb6e4d14aa 100644 --- a/source4/torture/drs/python/getncchanges.py +++ b/source4/torture/drs/python/getncchanges.py @@ -83,7 +83,7 @@ class DrsReplicaSyncIntegrityTestCase(drs_base.DrsBaseTestCase): """Adds an OU object""" self.test_ldb_dc.add({"dn": dn, "objectclass": objectclass}) res = self.test_ldb_dc.search(base=dn, scope=SCOPE_BASE) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) def modify_object(self, dn, attr, value): """Modifies an object's USN by adding an attribute value to it""" diff --git a/source4/torture/drs/python/repl_move.py b/source4/torture/drs/python/repl_move.py index 624c95e40fc..31dec3849a7 100644 --- a/source4/torture/drs/python/repl_move.py +++ b/source4/torture/drs/python/repl_move.py @@ -117,11 +117,11 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): for o in repl.ctr.array: e = expected[i] (attid, orig_dsa, version) = e - self.assertEquals(attid, o.attid, + self.assertEqual(attid, o.attid, "(LDAP) Wrong attid " "for expected value %d, wanted 0x%08x got 0x%08x" % (i, attid, o.attid)) - self.assertEquals(o.originating_invocation_id, + self.assertEqual(o.originating_invocation_id, misc.GUID(orig_dsa), "(LDAP) Wrong originating_invocation_id " "for expected value %d, attid 0x%08x, wanted %s got %s" @@ -130,7 +130,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): o.originating_invocation_id)) # Allow version to be skipped when it does not matter if version is not None: - self.assertEquals(o.version, version, + self.assertEqual(o.version, version, "(LDAP) Wrong version for expected value %d, " "attid 0x%08x, " "wanted %d got %d" @@ -184,12 +184,12 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): e = expected[i] (attid, orig_dsa, version) = e - self.assertEquals(attid, drs_attid.attid, + self.assertEqual(attid, drs_attid.attid, "(DRS) Wrong attid " "for expected value %d, wanted 0x%08x got 0x%08x" % (i, attid, drs_attid.attid)) - self.assertEquals(o.originating_invocation_id, + self.assertEqual(o.originating_invocation_id, misc.GUID(orig_dsa), "(DRS) Wrong originating_invocation_id " "for expected value %d, attid 0x%08x, wanted %s got %s" @@ -198,7 +198,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): o.originating_invocation_id)) # Allow version to be skipped when it does not matter if version is not None: - self.assertEquals(o.version, version, + self.assertEqual(o.version, version, "(DRS) Wrong version for expected value %d, " "attid 0x%08x, " "wanted %d got %d" @@ -215,7 +215,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): controls=["show_deleted:1"], attrs=["*", "parentGUID", "replPropertyMetaData"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) user_cur = res[0] rdn_orig = str(obj_orig[user_cur.dn.get_rdn_name()][0]) rdn_cur = str(user_cur[user_cur.dn.get_rdn_name()][0]) @@ -226,16 +226,16 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): # now check properties of the user if is_deleted: self.assertTrue("isDeleted" in user_cur) - self.assertEquals(rdn_cur.split('\n')[0], rdn_orig) - self.assertEquals(name_cur.split('\n')[0], name_orig) - self.assertEquals(dn_cur.get_rdn_value().split('\n')[0], + self.assertEqual(rdn_cur.split('\n')[0], rdn_orig) + self.assertEqual(name_cur.split('\n')[0], name_orig) + self.assertEqual(dn_cur.get_rdn_value().split('\n')[0], dn_orig.get_rdn_value()) self.assertEqual(name_cur, rdn_cur) else: self.assertFalse("isDeleted" in user_cur) - self.assertEquals(rdn_cur, rdn_orig) - self.assertEquals(name_cur, name_orig) - self.assertEquals(dn_cur, dn_orig) + self.assertEqual(rdn_cur, rdn_orig) + self.assertEqual(name_cur, name_orig) + self.assertEqual(dn_cur, dn_orig) self.assertEqual(name_cur, rdn_cur) parent_cur = user_cur["parentGUID"][0] try: @@ -277,7 +277,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -318,7 +318,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -550,7 +550,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -591,7 +591,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] moved_metadata = [ @@ -629,7 +629,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 0) + self.assertEqual(len(ldb_res), 0) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -733,7 +733,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -774,7 +774,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -913,7 +913,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -954,7 +954,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -1094,7 +1094,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -1167,7 +1167,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -1418,7 +1418,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -1438,7 +1438,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -1483,7 +1483,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1502,7 +1502,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_moved_orig = ldb_res[0] ou_moved_dn = ldb_res[0]["dn"] @@ -1548,7 +1548,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1567,7 +1567,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_moved_orig = ldb_res[0] ou_moved_dn = ldb_res[0]["dn"] @@ -1613,7 +1613,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1632,7 +1632,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_moved_orig = ldb_res[0] ou_moved_dn = ldb_res[0]["dn"] @@ -1679,7 +1679,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1698,7 +1698,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_moved_orig = ldb_res[0] ou_moved_dn = ldb_res[0]["dn"] @@ -1744,7 +1744,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1792,7 +1792,7 @@ class DrsMoveObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_BASE, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) ou_orig = ldb_res[0] ou_dn = ldb_res[0]["dn"] @@ -1911,7 +1911,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): res = sam_ldb.search(base='' % guid_str, controls=["show_deleted:1"], attrs=["*", "parentGUID"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) user_cur = res[0] cn_orig = str(obj_orig["cn"][0]) cn_cur = str(user_cur["cn"][0]) @@ -1922,16 +1922,16 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # now check properties of the user if is_deleted: self.assertTrue("isDeleted" in user_cur) - self.assertEquals(cn_cur.split('\n')[0], cn_orig) - self.assertEquals(name_cur.split('\n')[0], name_orig) - self.assertEquals(dn_cur.get_rdn_value().split('\n')[0], + self.assertEqual(cn_cur.split('\n')[0], cn_orig) + self.assertEqual(name_cur.split('\n')[0], name_orig) + self.assertEqual(dn_cur.get_rdn_value().split('\n')[0], dn_orig.get_rdn_value()) self.assertEqual(name_cur, cn_cur) else: self.assertFalse("isDeleted" in user_cur) - self.assertEquals(cn_cur, cn_orig) - self.assertEquals(name_cur, name_orig) - self.assertEquals(dn_cur, dn_orig) + self.assertEqual(cn_cur, cn_orig) + self.assertEqual(name_cur, name_orig) + self.assertEqual(dn_cur, dn_orig) self.assertEqual(name_cur, cn_cur) self.assertEqual(name_cur, user_cur.dn.get_rdn_value()) @@ -1958,7 +1958,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -1977,7 +1977,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou2_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2015,7 +2015,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2038,7 +2038,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn3, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2062,7 +2062,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2110,7 +2110,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2133,7 +2133,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=new_dn3, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2155,7 +2155,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2165,7 +2165,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # check user info on DC2 - should be valid user user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_moved_orig, is_deleted=False) - self.assertEquals(user_cur["parentGUID"], user_moved_orig["parentGUID"]) + self.assertEqual(user_cur["parentGUID"], user_moved_orig["parentGUID"]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -2200,7 +2200,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2219,7 +2219,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou2_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2261,7 +2261,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2270,7 +2270,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): self._net_drs_replicate(DC=self.dnsname_dc2, fromDC=self.dnsname_dc1, forced=True) # check user info on DC2 - should be valid user user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_moved_orig, is_deleted=False) - self.assertEquals(user_cur["parentGUID"][0], user_moved_orig["parentGUID"][0]) + self.assertEqual(user_cur["parentGUID"][0], user_moved_orig["parentGUID"][0]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -2301,7 +2301,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou1_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2323,7 +2323,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): ldb_res = self.ldb_dc1.search(base=self.ou2_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved_orig = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2363,7 +2363,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2377,7 +2377,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # check user info on DC2 - should be valid user user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_orig, is_deleted=False) - self.assertEquals(user_cur["parentGUID"], user_orig["parentGUID"]) + self.assertEqual(user_cur["parentGUID"], user_orig["parentGUID"]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -2410,7 +2410,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2424,7 +2424,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2433,7 +2433,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # check user info on DC2 - should be valid user user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_moved, is_deleted=False) - self.assertEquals(user_cur["parentGUID"], user_moved["parentGUID"]) + self.assertEqual(user_cur["parentGUID"], user_moved["parentGUID"]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -2466,7 +2466,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2505,7 +2505,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2514,7 +2514,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # check user info on DC2 - should be under the OU2 from DC1 user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_moved, is_deleted=False) - self.assertEquals(user_cur["parentGUID"], user_moved["parentGUID"]) + self.assertEqual(user_cur["parentGUID"], user_moved["parentGUID"]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) @@ -2546,7 +2546,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_orig = ldb_res[0] user_dn = ldb_res[0]["dn"] @@ -2583,7 +2583,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % username, attrs=["*", "parentGUID"]) - self.assertEquals(len(ldb_res), 1) + self.assertEqual(len(ldb_res), 1) user_moved = ldb_res[0] user_moved_dn = ldb_res[0]["dn"] @@ -2592,7 +2592,7 @@ class DrsMoveBetweenTreeOfObjectTestCase(drs_base.DrsBaseTestCase): # check user info on DC2 - should be under the OU2 from DC1 user_cur = self._check_obj(sam_ldb=self.ldb_dc2, obj_orig=user_moved, is_deleted=False) - self.assertEquals(user_cur["parentGUID"], user_moved["parentGUID"]) + self.assertEqual(user_cur["parentGUID"], user_moved["parentGUID"]) # delete user on DC1 self.ldb_dc1.delete('' % self._GUID_string(user_orig["objectGUID"][0])) diff --git a/source4/torture/drs/python/repl_rodc.py b/source4/torture/drs/python/repl_rodc.py index f27f02814af..21e70b8bc6f 100644 --- a/source4/torture/drs/python/repl_rodc.py +++ b/source4/torture/drs/python/repl_rodc.py @@ -199,7 +199,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e: (enum, estr) = e.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED # send the same request again and we should get the same response try: @@ -207,7 +207,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e1: (enum, estr) = e1.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED # Retry with Administrator credentials, ignores password replication groups (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, 10, req10) @@ -512,7 +512,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e3: (enum, estr) = e3.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED req10 = self._getnc_req10(dest_dsa=str(self.rodc_ctx.ntds_guid), invocation_id=self.ldb_dc1.get_invocation_id(), @@ -527,7 +527,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e4: (enum, estr) = e4.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED def test_msDSRevealedUsers_local_deny_allow(self): """ @@ -597,7 +597,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e5: (enum, estr) = e5.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED m = ldb.Message() m.dn = ldb.Dn(self.ldb_dc1, self.computer_dn) @@ -614,7 +614,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as e6: (enum, estr) = e6.args - self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED + self.assertEqual(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED def _assert_in_revealed_users(self, user_dn, attrlist): res = self.ldb_dc1.search(scope=ldb.SCOPE_BASE, base=self.computer_dn, @@ -632,7 +632,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): packed_attrs.append(dsdb_dn.get_bytes()) actual_attrids.append(metadata.attid) - self.assertEquals(sorted(actual_attrids), sorted(attrlist)) + self.assertEqual(sorted(actual_attrids), sorted(attrlist)) return (packed_attrs, unpacked_attrs) @@ -641,16 +641,16 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): def _assert_attrlist_changed(self, list_1, list_2, changed_attributes, num_changes=1, expected_new_usn=True): for i in range(len(list_2)): - self.assertEquals(list_1[i].attid, list_2[i].attid) - self.assertEquals(list_1[i].originating_invocation_id, list_2[i].originating_invocation_id) - self.assertEquals(list_1[i].version + num_changes, list_2[i].version) + self.assertEqual(list_1[i].attid, list_2[i].attid) + self.assertEqual(list_1[i].originating_invocation_id, list_2[i].originating_invocation_id) + self.assertEqual(list_1[i].version + num_changes, list_2[i].version) if expected_new_usn: self.assertTrue(list_1[i].originating_usn < list_2[i].originating_usn) self.assertTrue(list_1[i].local_usn < list_2[i].local_usn) else: - self.assertEquals(list_1[i].originating_usn, list_2[i].originating_usn) - self.assertEquals(list_1[i].local_usn, list_2[i].local_usn) + self.assertEqual(list_1[i].originating_usn, list_2[i].originating_usn) + self.assertEqual(list_1[i].local_usn, list_2[i].local_usn) if list_1[i].attid in changed_attributes: # We do the changes too quickly, so unless we put sleeps @@ -659,7 +659,7 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase): pass #self.assertTrue(list_1[i].originating_change_time < list_2[i].originating_change_time) else: - self.assertEquals(list_1[i].originating_change_time, list_2[i].originating_change_time) + self.assertEqual(list_1[i].originating_change_time, list_2[i].originating_change_time) def _create_rodc(self, ctx): ctx.nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn] diff --git a/source4/torture/drs/python/repl_schema.py b/source4/torture/drs/python/repl_schema.py index ee42fd1da10..b46a87af51e 100644 --- a/source4/torture/drs/python/repl_schema.py +++ b/source4/torture/drs/python/repl_schema.py @@ -166,7 +166,7 @@ class DrsReplSchemaTestCase(drs_base.DrsBaseTestCase): res_dc1 = self.ldb_dc1.search(base=obj_dn, scope=SCOPE_BASE, attrs=["*"]) - self.assertEquals(len(res_dc1), 1, + self.assertEqual(len(res_dc1), 1, "%s doesn't exists on %s" % (obj_dn, self.dnsname_dc1)) try: res_dc2 = self.ldb_dc2.search(base=obj_dn, @@ -177,7 +177,7 @@ class DrsReplSchemaTestCase(drs_base.DrsBaseTestCase): if enum == ERR_NO_SUCH_OBJECT: self.fail("%s doesn't exists on %s" % (obj_dn, self.dnsname_dc2)) raise - self.assertEquals(len(res_dc2), 1, + self.assertEqual(len(res_dc2), 1, "%s doesn't exists on %s" % (obj_dn, self.dnsname_dc2)) def test_class(self): diff --git a/source4/torture/drs/python/repl_secdesc.py b/source4/torture/drs/python/repl_secdesc.py index 58212907e23..3c36ba68910 100644 --- a/source4/torture/drs/python/repl_secdesc.py +++ b/source4/torture/drs/python/repl_secdesc.py @@ -80,7 +80,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(dn), self.sd_utils_dc2.get_sd_as_sddl(dn)) def test_acl_inheirt_new_object(self): @@ -113,7 +113,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(dn), self.sd_utils_dc2.get_sd_as_sddl(dn)) def test_acl_inherit_existing_object(self): @@ -160,7 +160,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(dn), self.sd_utils_dc2.get_sd_as_sddl(dn)) def test_acl_inheirt_existing_object_1_pass(self): @@ -198,7 +198,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(dn), self.sd_utils_dc2.get_sd_as_sddl(dn)) def test_acl_inheirt_renamed_object(self): @@ -256,7 +256,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): # Confirm inherited ACLs are identical and were inherited self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(sub_ou_dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(sub_ou_dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(sub_ou_dn), self.sd_utils_dc2.get_sd_as_sddl(sub_ou_dn)) @@ -330,14 +330,14 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): # Confirm set ACLs (on l3 ) are identical and were inherited self.assertIn(self.mod_becomes, self.sd_utils_dc2.get_sd_as_sddl(sub3_ou_dn_final)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(sub3_ou_dn_final), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(sub3_ou_dn_final), self.sd_utils_dc2.get_sd_as_sddl(sub3_ou_dn_final)) # Confirm inherited ACLs (from l3 to l4) are identical # and where inherited self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(sub4_ou_dn_final)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(sub4_ou_dn_final), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(sub4_ou_dn_final), self.sd_utils_dc2.get_sd_as_sddl(sub4_ou_dn_final)) @@ -382,7 +382,7 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): for child in children: self.assertIn(self.mod_inherits_as, self.sd_utils_dc2.get_sd_as_sddl(child.dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(sub_ou_dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(sub_ou_dn), self.sd_utils_dc2.get_sd_as_sddl(child.dn)) # Replicate back @@ -396,5 +396,5 @@ class ReplAclTestCase(drs_base.DrsBaseTestCase): for child in children: self.assertIn(self.mod_inherits_as, self.sd_utils_dc1.get_sd_as_sddl(child.dn)) - self.assertEquals(self.sd_utils_dc1.get_sd_as_sddl(child.dn), + self.assertEqual(self.sd_utils_dc1.get_sd_as_sddl(child.dn), self.sd_utils_dc2.get_sd_as_sddl(child.dn)) diff --git a/source4/torture/drs/python/replica_sync.py b/source4/torture/drs/python/replica_sync.py index f787c8f0f11..62545be6fee 100644 --- a/source4/torture/drs/python/replica_sync.py +++ b/source4/torture/drs/python/replica_sync.py @@ -70,12 +70,12 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): self.ldb_dc2.delete(dn, ["tree_delete:1"]) except LdbError as e: (num, _) = e.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) try: self.ldb_dc1.delete(dn, ["tree_delete:1"]) except LdbError as e1: (num, _) = e1.args - self.assertEquals(num, ERR_NO_SUCH_OBJECT) + self.assertEqual(num, ERR_NO_SUCH_OBJECT) def _cleanup_object(self, guid): """Cleans up a test object, if it still exists""" @@ -133,13 +133,13 @@ objectClass: organizationalUnit res = sam_ldb.search(base='' % guid, controls=["show_deleted:1"], attrs=["isDeleted", "objectCategory", "ou"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) ou_cur = res[0] # Deleted Object base DN dodn = self._deleted_objects_dn(sam_ldb) # now check properties of the user name_cur = ou_cur["ou"][0] - self.assertEquals(ou_cur["isDeleted"][0], b"TRUE") + self.assertEqual(ou_cur["isDeleted"][0], b"TRUE") self.assertTrue(not("objectCategory" in ou_cur)) self.assertTrue(dodn in str(ou_cur["dn"]), "OU %s is deleted but it is not located under %s!" % (name_cur, dodn)) diff --git a/source4/torture/drs/python/replica_sync_rodc.py b/source4/torture/drs/python/replica_sync_rodc.py index 8dc48a9b916..b904e17575c 100644 --- a/source4/torture/drs/python/replica_sync_rodc.py +++ b/source4/torture/drs/python/replica_sync_rodc.py @@ -70,13 +70,13 @@ objectClass: organizationalUnit res = sam_ldb.search(base='' % guid, controls=["show_deleted:1"], attrs=["isDeleted", "objectCategory", "ou"]) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) ou_cur = res[0] # Deleted Object base DN dodn = self._deleted_objects_dn(sam_ldb) # now check properties of the user name_cur = ou_cur["ou"][0] - self.assertEquals(ou_cur["isDeleted"][0], "TRUE") + self.assertEqual(ou_cur["isDeleted"][0], "TRUE") self.assertTrue(not("objectCategory" in ou_cur)) self.assertTrue(dodn in str(ou_cur["dn"]), "OU %s is deleted but it is not located under %s!" % (name_cur, dodn)) diff --git a/source4/torture/drs/python/ridalloc_exop.py b/source4/torture/drs/python/ridalloc_exop.py index f02ae11072a..3c7b39b280a 100644 --- a/source4/torture/drs/python/ridalloc_exop.py +++ b/source4/torture/drs/python/ridalloc_exop.py @@ -295,7 +295,7 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): (result, out, err) = self.runsubcmd("fsmo", "seize", "--role", "rid", "-H", ldb_url, "-s", smbconf, "--force") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # 3. Assert we get the RID Set res = new_ldb.search(base=server_ref_dn, @@ -580,7 +580,7 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): scope=ldb.SCOPE_BASE, attrs=['rIDNextRid', 'rIDAllocationPool']) last_allocated_rid = int(rid_set_res[0]["rIDNextRid"][0]) - self.assertEquals(last_allocated_rid, last_rid - 10) + self.assertEqual(last_allocated_rid, last_rid - 10) # 9. Assert that the range wasn't thrown away @@ -623,7 +623,7 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): # 4. Seize the RID Manager role (result, out, err) = self.runsubcmd("fsmo", "seize", "--role", "rid", "-H", ldb_url, "-s", smbconf, "--force") self.assertCmdSuccess(result, out, err) - self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEqual(err, "", "Shouldn't be any error messages") # 5. Add a new user (triggers RID set work) new_ldb.newuser("ridalloctestuser", "P@ssword!") diff --git a/source4/torture/drs/python/samba_tool_drs_no_dns.py b/source4/torture/drs/python/samba_tool_drs_no_dns.py index b9cab49e82b..326181a7fd7 100644 --- a/source4/torture/drs/python/samba_tool_drs_no_dns.py +++ b/source4/torture/drs/python/samba_tool_drs_no_dns.py @@ -117,29 +117,29 @@ class SambaToolDrsNoDnsTests(drs_base.DrsBaseTestCase): # Show that Has-Master-NCs is fixed by samba_upgradedns res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % forestdns_dn) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % domaindns_dn) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) self.check_output("samba_upgradedns -s %s" % (new_dc_config_file)) res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % forestdns_dn) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % domaindns_dn) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Show that replica locations is fixed by dbcheck res = samdb.search(controls=["search_options:1:2"], expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" % (server_ds_name, forestdns_dn)) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) res = samdb.search(controls=["search_options:1:2"], expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" % (server_ds_name, domaindns_dn)) - self.assertEquals(len(res), 0) + self.assertEqual(len(res), 0) try: # This fixes any forward-link-backward-link issues with the tools @@ -157,26 +157,26 @@ class SambaToolDrsNoDnsTests(drs_base.DrsBaseTestCase): # Check all ForestDNS connections and backlinks res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % forestdns_dn) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = samdb.search(base=forestdns_dn, expression="(msds-masteredby=%s)" % server_ds_name) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = samdb.search(controls=["search_options:1:2"], expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" % (server_ds_name, forestdns_dn)) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Check all DomainDNS connections and backlinks res = samdb.search(base=server_ds_name, expression="(msds-hasmasterncs=%s)" % domaindns_dn) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = samdb.search(base=domaindns_dn, expression="(msds-masteredby=%s)" % server_ds_name) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) res = samdb.search(controls=["search_options:1:2"], expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" % (server_ds_name, domaindns_dn)) - self.assertEquals(len(res), 1) + self.assertEqual(len(res), 1) # Demote the DC we created in the test self.check_output("samba-tool domain demote --remove-other-dead-server=%s -H ldap://%s %s -s %s" -- 2.25.1 From d135cb9fb14a602f57fe8e0dbb2f46ae2159b822 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 18 Jan 2020 08:06:45 +0100 Subject: [PATCH 386/645] s3/auth: use set_current_user_info() in auth3_generate_session_info_pac() This delays reloading config slightly, but I don't see how could affect observable behaviour other then log messages coming from the functions in between the different locations for lp_load_with_shares() like make_session_info_krb5() are sent to a different logfile if "log file" uses %U. Signed-off-by: Ralph Boehme Reviewed-by: Andreas Schneider (cherry picked from commit dc4b1e39ce1f2201a2d6ae2d4cffef2448f69a62) --- source3/auth/auth_generic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 9243a0ba02d..0e9500ac08d 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -159,12 +159,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, } } - /* setup the string used by %U */ - sub_set_smb_name(username); - - /* reload services so that the new %U is taken into account */ - lp_load_with_shares(get_dyn_CONFIGFILE()); - status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, @@ -176,6 +170,14 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, goto done; } + /* setup the string used by %U */ + set_current_user_info((*session_info)->unix_info->sanitized_username, + (*session_info)->unix_info->unix_name, + (*session_info)->info->domain_name); + + /* reload services so that the new %U is taken into account */ + lp_load_with_shares(get_dyn_CONFIGFILE()); + DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n", ntuser, ntdomain, rhost)); -- 2.25.1 From f8a97ff8090ab5e0e04859326a11cd2b86da1066 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 8 Dec 2020 22:00:55 +1300 Subject: [PATCH 387/645] CVE-2020-25718 ldb/attrib_handler casefold: simplify space dropping As seen in CVE-2021-20277, ldb_handler_fold() has been making mistakes when collapsing spaces down to a single space. This patch fixes the way it handles internal spaces (CVE-2021-20277 was about leading spaces), and involves a rewrite of the parsing loop. The bug has a detailed description of the problem. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14656 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Apr 7 03:16:39 UTC 2021 on sn-devel-184 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 24ddc1ca9cad95673bdd8023d99867707b37085f) --- lib/ldb/common/attrib_handlers.c | 53 +++++++++++++++----------------- lib/ldb/tests/ldb_match_test.c | 2 ++ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c index c6ef5ad477b..f0fd4f50d8d 100644 --- a/lib/ldb/common/attrib_handlers.c +++ b/lib/ldb/common/attrib_handlers.c @@ -54,8 +54,8 @@ int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - char *s, *t; - size_t l; + char *s, *t, *start; + bool in_space; if (!in || !out || !(in->data)) { return -1; @@ -67,36 +67,33 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, return -1; } - s = (char *)(out->data); - - /* remove trailing spaces if any */ - l = strlen(s); - while (l > 0 && s[l - 1] == ' ') l--; - s[l] = '\0'; - - /* remove leading spaces if any */ - if (*s == ' ') { - for (t = s; *s == ' '; s++, l--) ; - - /* remove leading spaces by moving down the string */ - memmove(t, s, l); - - s = t; + start = (char *)(out->data); + in_space = true; + t = start; + for (s = start; *s != '\0'; s++) { + if (*s == ' ') { + if (in_space) { + /* + * We already have one (or this is the start) + * and we don't want to add more + */ + continue; + } + in_space = true; + } else { + in_space = false; + } + *t = *s; + t++; } - /* check middle spaces */ - while ((t = strchr(s, ' ')) != NULL) { - for (s = t; *s == ' '; s++) ; - - if ((s - t) > 1) { - l = strlen(s); - - /* remove all spaces but one by moving down the string */ - memmove(t + 1, s, l); - } + if (in_space && t != start) { + /* the loop will have left a single trailing space */ + t--; } + *t = '\0'; - out->length = strlen((char *)out->data); + out->length = t - start; return 0; } diff --git a/lib/ldb/tests/ldb_match_test.c b/lib/ldb/tests/ldb_match_test.c index fbf4106fa78..eb5d9fcee20 100644 --- a/lib/ldb/tests/ldb_match_test.c +++ b/lib/ldb/tests/ldb_match_test.c @@ -183,6 +183,8 @@ static void test_wildcard_match(void **state) struct wildcard_test tests[] = { TEST_ENTRY(" 1 0", "1*0*", true, true), TEST_ENTRY(" 1 0", "1 *0", true, true), + TEST_ENTRY(" 1 0", "*1 0", true, true), + TEST_ENTRY("1 0", "*1 0", true, true), TEST_ENTRY("The value.......end", "*end", true, true), TEST_ENTRY("The value.......end", "*fend", false, true), TEST_ENTRY("The value.......end", "*eel", false, true), -- 2.25.1 From 65a7b0c37d000f20eb3781265b9cf22305952400 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 3 Mar 2021 19:17:36 +1300 Subject: [PATCH 388/645] CVE-2020-25718 ldb_match: trailing chunk must match end of string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A wildcard search is divided into chunks by the asterisks. While most chunks match the first suitable string, the last chunk matches the last possible string (unless there is a trailing asterisk, in which case this distinction is moot). We always knew this in our hearts, but we tried to do it in a funny complicated way that stepped through the string, comparing here and there, leading to CVE-2019-3824 and missed matches (bug 14044). With this patch, we just jump to the end of the string and compare it. As well as being correct, this should also improve performance, as the previous algorithm involved a quadratic loop of erroneous memmem()s. See https://tools.ietf.org/html/rfc4517 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14044 Signed-off-by: Douglas Bagnall Reviewed-by: Björn Jacke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit cc098f1cad04b2cfec4ddd6b2511cd5a600f31c6) --- lib/ldb/common/ldb_match.c | 80 +++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index 829afa77e71..da595615bd9 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -295,8 +295,9 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, uint8_t *p; chunk = tree->u.substring.chunks[c]; - if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; - + if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) { + goto mismatch; + } /* * Empty strings are returned as length 0. Ensure * we can cope with this. @@ -304,52 +305,41 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, if (cnk.length == 0) { goto mismatch; } - /* - * Values might be binary blobs. Don't use string - * search, but memory search instead. - */ - p = memmem((const void *)val.data,val.length, - (const void *)cnk.data, cnk.length); - if (p == NULL) goto mismatch; - - /* - * At this point we know cnk.length <= val.length as - * otherwise there could be no match - */ + if (cnk.length > val.length) { + goto mismatch; + } - if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { - uint8_t *g; - uint8_t *end = val.data + val.length; - do { /* greedy */ - - /* - * haystack is a valid pointer in val - * because the memmem() can only - * succeed if the needle (cnk.length) - * is <= haystacklen - * - * p will be a pointer at least - * cnk.length from the end of haystack - */ - uint8_t *haystack - = p + cnk.length; - size_t haystacklen - = end - (haystack); - - g = memmem(haystack, - haystacklen, - (const uint8_t *)cnk.data, - cnk.length); - if (g) { - p = g; - } - } while(g); + if ( (tree->u.substring.chunks[c + 1]) == NULL && + (! tree->u.substring.end_with_wildcard) ) { + /* + * The last bit, after all the asterisks, must match + * exactly the last bit of the string. + */ + int cmp; + p = val.data + val.length - cnk.length; + cmp = memcmp(p, + cnk.data, + cnk.length); + if (cmp != 0) { + goto mismatch; + } + } else { + /* + * Values might be binary blobs. Don't use string + * search, but memory search instead. + */ + p = memmem((const void *)val.data, val.length, + (const void *)cnk.data, cnk.length); + if (p == NULL) { + goto mismatch; + } + /* move val to the end of the match */ + p += cnk.length; + val.length -= (p - val.data); + val.data = p; } - val.length = val.length - (p - (uint8_t *)(val.data)) - cnk.length; - val.data = (uint8_t *)(p + cnk.length); c++; - talloc_free(cnk.data); - cnk.data = NULL; + TALLOC_FREE(cnk.data); } /* last chunk may not have reached end of string */ -- 2.25.1 From 3345f594163bd153fe74a228aa43d56dd0d38c70 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Sat, 6 Mar 2021 16:05:15 +1300 Subject: [PATCH 389/645] CVE-2020-25718 ldb: fix ldb_comparison_fold off-by-one overrun We run one character over in comparing all the bytes in two ldb_vals. In almost all circumstances both ldb_vals would have an allocated '\0' in the overrun position, but it is best not to rely on that. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 2b2f4f519454beb6f2a46705675a62274019fc09) --- lib/ldb/common/attrib_handlers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c index f0fd4f50d8d..6a885065f77 100644 --- a/lib/ldb/common/attrib_handlers.c +++ b/lib/ldb/common/attrib_handlers.c @@ -334,8 +334,8 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) break; if (*s1 == ' ') { - while (n1 && s1[0] == s1[1]) { s1++; n1--; } - while (n2 && s2[0] == s2[1]) { s2++; n2--; } + while (n1 > 1 && s1[0] == s1[1]) { s1++; n1--; } + while (n2 > 1 && s2[0] == s2[1]) { s2++; n2--; } } s1++; s2++; n1--; n2--; -- 2.25.1 From 5c1d6a95c2669f68a0b6ee0bf169ea71d92efcfe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 19 Jan 2021 16:53:55 +0100 Subject: [PATCH 390/645] CVE-2020-25718 pyldb: catch potential overflow error in py_timestring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pair-Programmed-With: Björn Baumbach Signed-off-by: Stefan Metzmacher Signed-off-by: Björn Baumbach Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 71e8b24b8a031de26b21539e36a60f459257d2fd) --- lib/ldb/common/ldb_msg.c | 1 + lib/ldb/pyldb.c | 7 +++++++ lib/ldb/tests/python/api.py | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 7131f013f71..57dfc5a04c2 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -1272,6 +1272,7 @@ char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t) if (r != 17) { talloc_free(ts); + errno = EOVERFLOW; return NULL; } diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 6816c24ce96..27670113b77 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -4228,6 +4228,13 @@ static PyObject *py_timestring(PyObject *module, PyObject *args) if (!PyArg_ParseTuple(args, "l", &t_val)) return NULL; tresult = ldb_timestring(NULL, (time_t) t_val); + if (tresult == NULL) { + /* + * Most likely EOVERFLOW from gmtime() + */ + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } ret = PyUnicode_FromString(tresult); talloc_free(tresult); return ret; diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 675b5859af8..8d154aac6ad 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -5,10 +5,12 @@ import os from unittest import TestCase import sys +sys.path.insert(0, "bin/python") import gc import time import ldb import shutil +import errno PY3 = sys.version_info > (3, 0) @@ -42,10 +44,27 @@ class NoContextTests(TestCase): self.assertEqual("19700101000000.0Z", ldb.timestring(0)) self.assertEqual("20071119191012.0Z", ldb.timestring(1195499412)) + self.assertEqual("00000101000000.0Z", ldb.timestring(-62167219200)) + self.assertEqual("99991231235959.0Z", ldb.timestring(253402300799)) + + # should result with OSError EOVERFLOW from gmtime() + with self.assertRaises(OSError) as err: + ldb.timestring(-62167219201) + self.assertEqual(err.exception.errno, errno.EOVERFLOW) + with self.assertRaises(OSError) as err: + ldb.timestring(253402300800) + self.assertEqual(err.exception.errno, errno.EOVERFLOW) + with self.assertRaises(OSError) as err: + ldb.timestring(0x7fffffffffffffff) + self.assertEqual(err.exception.errno, errno.EOVERFLOW) + def test_string_to_time(self): self.assertEqual(0, ldb.string_to_time("19700101000000.0Z")) self.assertEqual(1195499412, ldb.string_to_time("20071119191012.0Z")) + self.assertEqual(-62167219200, ldb.string_to_time("00000101000000.0Z")) + self.assertEqual(253402300799, ldb.string_to_time("99991231235959.0Z")) + def test_binary_encode(self): encoded = ldb.binary_encode(b'test\\x') decoded = ldb.binary_decode(encoded) -- 2.25.1 From 26d73026382fde256242c552ebdcbe69e08d5b9e Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 3 Mar 2021 19:54:37 +1300 Subject: [PATCH 391/645] CVE-2020-25718 ldb_match: remove redundant check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already ensure the no-trailing-asterisk case ends at the end of the string. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14044 Signed-off-by: Douglas Bagnall Reviewed-by: Björn Jacke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit fa93339978040eab52b2722c1716028b48d8d084) --- lib/ldb/common/ldb_match.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index da595615bd9..2f4d41f3441 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -342,8 +342,6 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, TALLOC_FREE(cnk.data); } - /* last chunk may not have reached end of string */ - if ( (! tree->u.substring.end_with_wildcard) && (val.length != 0) ) goto mismatch; talloc_free(save_p); *matched = true; return LDB_SUCCESS; -- 2.25.1 From 06fae27526b7c7e79c50687b8c8a5a1bcde86d00 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 28 May 2021 14:15:43 +1200 Subject: [PATCH 392/645] CVE-2020-25718 pyldb: Fix Message.items() for a message containing elements Previously, message elements were being freed before the call to Py_BuildValue(), resulting in an exception being raised. Additionally, only the first element of the returned list was ever assigned to. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 3e4ec0a90a222c1cff4a91912afc703ca4cbbb0e) --- lib/ldb/pyldb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 27670113b77..aeb55802908 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -3536,13 +3536,13 @@ static PyObject *py_ldb_msg_items(PyLdbMessageObject *self, PyObject *value = NULL; PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements); int res = 0; - Py_CLEAR(py_el); value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); + Py_CLEAR(py_el); if (value == NULL ) { Py_CLEAR(l); return NULL; } - res = PyList_SetItem(l, 0, value); + res = PyList_SetItem(l, j, value); if (res == -1) { Py_CLEAR(l); return NULL; -- 2.25.1 From c7a44e02bc0b67cda45aa6eb25da5e5853e8284f Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 1 Feb 2021 14:21:21 +0100 Subject: [PATCH 393/645] CVE-2020-25718 lib:ldb: Add missing break in switch statement error: unannotated fall-through between switch labels [-Werror,-Wimplicit-fallthrough] Signed-off-by: Andreas Schneider Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 1ffacac547a8ce29c6696dda73991a8db7e34dfd) --- lib/ldb/ldb_map/ldb_map_inbound.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ldb/ldb_map/ldb_map_inbound.c b/lib/ldb/ldb_map/ldb_map_inbound.c index 861c4c1622d..324295737da 100644 --- a/lib/ldb/ldb_map/ldb_map_inbound.c +++ b/lib/ldb/ldb_map/ldb_map_inbound.c @@ -262,6 +262,7 @@ static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *a LDB_ERR_OPERATIONS_ERROR); } + break; default: /* ignore referrals */ break; -- 2.25.1 From 409738be6f89a88c7fc06c1df39a56ba3a7b601f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Sat, 19 Dec 2020 11:43:56 +1300 Subject: [PATCH 394/645] CVE-2020-25718 ldb.h: remove undefined async_ctx function signatures These functions do not exist. Signed-off-by: Douglas Bagnall Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 1a05b58edaf96e7da707f9ad0a237551dbe13eb5) --- lib/ldb/include/ldb.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index 3cba0f4d543..849bce4f11f 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -1093,18 +1093,6 @@ int ldb_global_init(void); */ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx); -typedef void (*ldb_async_timeout_fn) (void *); -typedef bool (*ldb_async_callback_fn) (void *); -typedef int (*ldb_async_ctx_add_op_fn)(void *, time_t, void *, ldb_async_timeout_fn, ldb_async_callback_fn); -typedef int (*ldb_async_ctx_wait_op_fn)(void *); - -void ldb_async_ctx_set_private_data(struct ldb_context *ldb, - void *private_data); -void ldb_async_ctx_set_add_op(struct ldb_context *ldb, - ldb_async_ctx_add_op_fn add_op); -void ldb_async_ctx_set_wait_op(struct ldb_context *ldb, - ldb_async_ctx_wait_op_fn wait_op); - /** Connect to a database. -- 2.25.1 From f9ff5ecb1a257acb95f13b2ccfc718890fbac40e Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Sat, 6 Mar 2021 09:57:44 +1300 Subject: [PATCH 395/645] CVE-2020-25718 ldb: correct comments in attrib_handers val_to_int64 c.f. the identical static function in lib/ldb-samba/ldif_handlers.c Signed-off-by: Douglas Bagnall Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 46e6f6ef8436df7e083f34556c25f66f65ea1ce5) --- lib/ldb/common/attrib_handlers.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c index 6a885065f77..febf2f414ca 100644 --- a/lib/ldb/common/attrib_handlers.c +++ b/lib/ldb/common/attrib_handlers.c @@ -97,7 +97,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, return 0; } -/* length limited conversion of a ldb_val to a int32_t */ +/* length limited conversion of a ldb_val to an int64_t */ static int val_to_int64(const struct ldb_val *in, int64_t *v) { char *end; @@ -110,8 +110,6 @@ static int val_to_int64(const struct ldb_val *in, int64_t *v) strncpy(buf, (char *)in->data, in->length); buf[in->length] = 0; - /* We've to use "strtoll" here to have the intended overflows. - * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ *v = (int64_t) strtoll(buf, &end, 0); if (*end != 0) { return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; -- 2.25.1 From 5394fa20964433612f313286fd7db5801417e8db Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 29 Jan 2021 13:49:02 +1300 Subject: [PATCH 396/645] CVE-2020-25718 ldb: improve comments for ldb_module_connect_backend() There is no flags argument. There are more URI forms. Signed-off-by: Douglas Bagnall Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 48068a58df0313cd904f27e2c918ee10275ae373) --- lib/ldb/common/ldb_modules.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ldb/common/ldb_modules.c b/lib/ldb/common/ldb_modules.c index cc067abdfe0..4366f05e066 100644 --- a/lib/ldb/common/ldb_modules.c +++ b/lib/ldb/common/ldb_modules.c @@ -173,11 +173,15 @@ int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn, bool /* Return the ldb module form of a database. - The URL can either be one of the following forms - ldb://path - ldapi://path - - flags is made up of LDB_FLG_* + The URL looks something like this: + tdb://PATH + ldb://PATH + mdb://PATH + ldapi://PATH + PATH (unadorned PATH defaults to tdb://) + + for a complete list of backends (including possibly unmaintained ones) grep + for calls to ldb_register_backend(). the options are passed uninterpreted to the backend, and are backend specific. -- 2.25.1 From 4abe4c29e1f58e3e56e198866a2b18a70b63a036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Baumbach?= Date: Mon, 18 Jan 2021 16:48:21 +0100 Subject: [PATCH 397/645] CVE-2020-25718 pyldb: fix a typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Baumbach Reviewed-by: Rowland penny BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 6fcde09f093db5d26c582a3c28531265f06b9fde) --- lib/ldb/pyldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index aeb55802908..ae15f85fd3f 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -4315,7 +4315,7 @@ static PyMethodDef py_ldb_global_methods[] = { "S.string_to_time(string) -> int\n\n" "Parse a LDAP time string into a UNIX timestamp." }, { "valid_attr_name", py_valid_attr_name, METH_VARARGS, - "S.valid_attr_name(name) -> bool\n\nn" + "S.valid_attr_name(name) -> bool\n\n" "Check whether the supplied name is a valid attribute name." }, { "binary_encode", py_binary_encode, METH_VARARGS, "S.binary_encode(string) -> string\n\n" -- 2.25.1 From 03d1bf2aca0eb41816838fe148c464a3d488f821 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 17 Dec 2020 11:56:08 +0100 Subject: [PATCH 398/645] CVE-2020-25718 lib:ldb: Use C99 initializers for builtin_popt_options[] Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit a593065c7f22e17434f33d0132cc6a7073acf414) --- lib/ldb/tools/cmdline.c | 250 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 225 insertions(+), 25 deletions(-) diff --git a/lib/ldb/tools/cmdline.c b/lib/ldb/tools/cmdline.c index b0f4c5c2141..b2fbb854910 100644 --- a/lib/ldb/tools/cmdline.c +++ b/lib/ldb/tools/cmdline.c @@ -34,31 +34,231 @@ enum ldb_cmdline_options { CMDLINE_RELAX=1 }; static struct poptOption builtin_popt_options[] = { POPT_AUTOHELP - { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, - { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" }, - { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" }, - { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" }, - { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL }, - { "trace", 0, POPT_ARG_NONE, &options.tracing, 0, "enable tracing", NULL }, - { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL }, - { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL }, - { "modules-path", 0, POPT_ARG_STRING, &options.modules_path, 0, "modules path", "PATH" }, - { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, - { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, - { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL }, - { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, - { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, - { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, - { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL }, - { "show-binary", 0, POPT_ARG_NONE, &options.show_binary, 0, "display binary LDIF", NULL }, - { "paged", 0, POPT_ARG_NONE, NULL, 'P', "use a paged search", NULL }, - { "show-deleted", 0, POPT_ARG_NONE, NULL, 'D', "show deleted objects", NULL }, - { "show-recycled", 0, POPT_ARG_NONE, NULL, 'R', "show recycled objects", NULL }, - { "show-deactivated-link", 0, POPT_ARG_NONE, NULL, 'd', "show deactivated links", NULL }, - { "reveal", 0, POPT_ARG_NONE, NULL, 'r', "reveal ldb internals", NULL }, - { "relax", 0, POPT_ARG_NONE, NULL, CMDLINE_RELAX, "pass relax control", NULL }, - { "cross-ncs", 0, POPT_ARG_NONE, NULL, 'N', "search across NC boundaries", NULL }, - { "extended-dn", 0, POPT_ARG_NONE, NULL, 'E', "show extended DNs", NULL }, + { + .longName = "url", + .shortName = 'H', + .argInfo = POPT_ARG_STRING, + .arg = &options.url, + .val = 0, + .descrip = "database URL", + .argDescrip = "URL" + }, + { + .longName = "basedn", + .shortName = 'b', + .argInfo = POPT_ARG_STRING, + .arg = &options.basedn, + .val = 0, + .descrip = "base DN", + .argDescrip = "DN" + }, + { + .longName = "editor", + .shortName = 'e', + .argInfo = POPT_ARG_STRING, + .arg = &options.editor, + .val = 0, + .descrip = "external editor", + .argDescrip = "PROGRAM" + }, + { + .longName = "scope", + .shortName = 's', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 's', + .descrip = "search scope", + .argDescrip = "SCOPE" + }, + { + .longName = "verbose", + .shortName = 'v', + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'v', + .descrip = "increase verbosity", + .argDescrip = NULL + }, + { + .longName = "trace", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = &options.tracing, + .val = 0, + .descrip = "enable tracing", + .argDescrip = NULL + }, + { + .longName = "interactive", + .shortName = 'i', + .argInfo = POPT_ARG_NONE, + .arg = &options.interactive, + .val = 0, + .descrip = "input from stdin", + .argDescrip = NULL + }, + { + .longName = "recursive", + .shortName = 'r', + .argInfo = POPT_ARG_NONE, + .arg = &options.recursive, + .val = 0, + .descrip = "recursive delete", + .argDescrip = NULL + }, + { + .longName = "modules-path", + .shortName = 0, + .argInfo = POPT_ARG_STRING, + .arg = &options.modules_path, + .val = 0, + .descrip = "modules path", + .argDescrip = "PATH" + }, + { + .longName = "num-searches", + .shortName = 0, + .argInfo = POPT_ARG_INT, + .arg = &options.num_searches, + .val = 0, + .descrip = "number of test searches", + .argDescrip = NULL + }, + { + .longName = "num-records", + .shortName = 0, + .argInfo = POPT_ARG_INT, + .arg = &options.num_records, + .val = 0, + .descrip = "number of test records", + .argDescrip = NULL + }, + { + .longName = "all", + .shortName = 'a', + .argInfo = POPT_ARG_NONE, + .arg = &options.all_records, + .val = 0, + .descrip = "(|(objectClass=*)(distinguishedName=*))", + .argDescrip = NULL + }, + { + .longName = "nosync", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = &options.nosync, + .val = 0, + .descrip = "non-synchronous transactions", + .argDescrip = NULL + }, + { + .longName = "sorted", + .shortName = 'S', + .argInfo = POPT_ARG_NONE, + .arg = &options.sorted, + .val = 0, + .descrip = "sort attributes", + .argDescrip = NULL + }, + { + .longName = NULL, + .shortName = 'o', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'o', + .descrip = "ldb_connect option", + .argDescrip = "OPTION" + }, + { + .longName = "controls", + .shortName = 0, + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'c', + .descrip = "controls", + .argDescrip = NULL + }, + { + .longName = "show-binary", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = &options.show_binary, + .val = 0, + .descrip = "display binary LDIF", + .argDescrip = NULL + }, + { + .longName = "paged", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'P', + .descrip = "use a paged search", + .argDescrip = NULL + }, + { + .longName = "show-deleted", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'D', + .descrip = "show deleted objects", + .argDescrip = NULL + }, + { + .longName = "show-recycled", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'R', + .descrip = "show recycled objects", + .argDescrip = NULL + }, + { + .longName = "show-deactivated-link", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'd', + .descrip = "show deactivated links", + .argDescrip = NULL + }, + { + .longName = "reveal", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'r', + .descrip = "reveal ldb internals", + .argDescrip = NULL + }, + { + .longName = "relax", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = CMDLINE_RELAX, + .descrip = "pass relax control", + .argDescrip = NULL + }, + { + .longName = "cross-ncs", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'N', + .descrip = "search across NC boundaries", + .argDescrip = NULL + }, + { + .longName = "extended-dn", + .shortName = 0, + .argInfo = POPT_ARG_NONE, + .arg = NULL, + .val = 'E', + .descrip = "show extended DNs", + .argDescrip = NULL + }, {0} }; -- 2.25.1 From 4bb023c7ee31090103e4e94a80ebefa81d76189e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 17 Dec 2020 19:16:13 +0100 Subject: [PATCH 399/645] CVE-2020-25718 lib:ldb-samba: Improve calculate_popt_array_length() Note that memcmp() doesn't work well with padding bytes. So avoid it! (gdb) ptype/o struct poptOption /* offset | size */ type = struct poptOption { /* 0 | 8 */ const char *longName; /* 8 | 1 */ char shortName; /* XXX 3-byte hole */ /* 12 | 4 */ unsigned int argInfo; /* 16 | 8 */ void *arg; /* 24 | 4 */ int val; /* XXX 4-byte hole */ /* 32 | 8 */ const char *descrip; /* 40 | 8 */ const char *argDescrip; /* total size (bytes): 48 */ Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit c2c7c1f50a8acb3169e19ba4329aa78839b66def) --- lib/ldb-samba/samba_extensions.c | 27 ++++++++++++++++++++++----- lib/ldb/tools/cmdline.c | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/ldb-samba/samba_extensions.c b/lib/ldb-samba/samba_extensions.c index 65a4079ec97..60aa1a332b5 100644 --- a/lib/ldb-samba/samba_extensions.c +++ b/lib/ldb-samba/samba_extensions.c @@ -34,15 +34,32 @@ #include "popt.h" +static bool is_popt_table_end(const struct poptOption *o) +{ + if (o->longName == NULL && + o->shortName =='\0' && + o->arg == NULL) { + return true; + } + + return false; +} /* work out the length of a popt array */ -static unsigned calculate_popt_array_length(struct poptOption *opts) +static size_t calculate_popt_array_length(struct poptOption *opts) { - unsigned i; - struct poptOption zero_opt = { 0 }; - for (i=0; memcmp(&zero_opt, &opts[i], sizeof(zero_opt)) != 0; i++) ; + size_t i = 0; + + for (i = 0; i < UINT32_MAX; i++) { + struct poptOption *o = &(opts[i]); + + if (is_popt_table_end(o)) { + break; + } + } + return i; } @@ -61,7 +78,7 @@ static int extensions_hook(struct ldb_context *ldb, enum ldb_module_hook_type t) { switch (t) { case LDB_MODULE_HOOK_CMDLINE_OPTIONS: { - unsigned len1, len2; + size_t len1, len2; struct poptOption **popt_options = ldb_module_popt_options(ldb); struct poptOption *new_array; diff --git a/lib/ldb/tools/cmdline.c b/lib/ldb/tools/cmdline.c index b2fbb854910..306bca6555a 100644 --- a/lib/ldb/tools/cmdline.c +++ b/lib/ldb/tools/cmdline.c @@ -259,7 +259,7 @@ static struct poptOption builtin_popt_options[] = { .descrip = "show extended DNs", .argDescrip = NULL }, - {0} + POPT_TABLEEND }; void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f) -- 2.25.1 From 997ef6f3d524ea0d999ef6bc6023b8c1ad8b312f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 24 Jul 2020 12:41:29 +1200 Subject: [PATCH 400/645] CVE-2020-25718 ldb_controls: control_to_string avoids crash Otherwise a malformed control with unexpected NULL data will segfault ldb_control_to_string(), though this is not very likely to affect anyone in practice as converting controls to strings is rarely necessary. If it happens at all in Samba it is in Python code. Found by Honggfuzz using fuzz_ldb_parse_control. Signed-off-by: Douglas Bagnall Reviewed-by: Andreas Schneider Autobuild-User(master): Douglas Bagnall Autobuild-Date(master): Wed Jul 29 04:43:23 UTC 2020 on sn-devel-184 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit 2aace18f170644da9c293342a6df5e5b2ae8da25) --- lib/ldb/common/ldb_controls.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ldb/common/ldb_controls.c b/lib/ldb/common/ldb_controls.c index 4af06a436ab..3435bbbce24 100644 --- a/lib/ldb/common/ldb_controls.c +++ b/lib/ldb/common/ldb_controls.c @@ -286,6 +286,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) { struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control); char *cookie; + if (rep_control == NULL) { + return NULL; + } cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len); if (cookie == NULL) { @@ -312,6 +315,10 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr char *cookie; + if (rep_control == NULL) { + return NULL; + } + cookie = ldb_base64_encode(mem_ctx, (char *)rep_control->contextId, rep_control->ctxid_len); @@ -334,6 +341,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data, struct ldb_sort_resp_control); + if (rep_control == NULL) { + return NULL; + } res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s", LDB_CONTROL_SORT_RESP_NAME, control->critical, @@ -347,6 +357,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr struct ldb_asq_control *rep_control = talloc_get_type(control->data, struct ldb_asq_control); + if (rep_control == NULL) { + return NULL; + } res = talloc_asprintf(mem_ctx, "%s:%d:%d", LDB_CONTROL_SORT_RESP_NAME, control->critical, @@ -360,6 +373,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr struct ldb_dirsync_control *rep_control = talloc_get_type(control->data, struct ldb_dirsync_control); + if (rep_control == NULL) { + return NULL; + } cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len); if (cookie == NULL) { @@ -380,6 +396,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr struct ldb_dirsync_control *rep_control = talloc_get_type(control->data, struct ldb_dirsync_control); + if (rep_control == NULL) { + return NULL; + } cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len); if (cookie == NULL) { @@ -399,6 +418,9 @@ char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *contr if (strcmp(control->oid, LDB_CONTROL_VERIFY_NAME_OID) == 0) { struct ldb_verify_name_control *rep_control = talloc_get_type(control->data, struct ldb_verify_name_control); + if (rep_control == NULL) { + return NULL; + } if (rep_control->gc != NULL) { res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s", LDB_CONTROL_VERIFY_NAME_NAME, -- 2.25.1 From 04df5430d04878bf693799bc496f6be7ccb5fd58 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 4 Jan 2021 13:12:30 +0100 Subject: [PATCH 401/645] CVE-2020-25718 lib: Add "hex_byte()" to replace.h This is required in quite a few places, and replace.h has things like ZERO_STRUCT already, so this is not completely outplaced. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit c8d9ce3f7c8c486ab21e320a0adcb71311dcb453) --- lib/replace/replace.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/replace/replace.h b/lib/replace/replace.h index 3f6b1380e0c..6c2744ab86d 100644 --- a/lib/replace/replace.h +++ b/lib/replace/replace.h @@ -963,6 +963,22 @@ bool nss_wrapper_hosts_enabled(void); bool socket_wrapper_enabled(void); bool uid_wrapper_enabled(void); +static inline bool _hexcharval(char c, uint8_t *val) +{ + if ((c >= '0') && (c <= '9')) { *val = c - '0'; return true; } + if ((c >= 'a') && (c <= 'f')) { *val = c - 'a' + 10; return true; } + if ((c >= 'A') && (c <= 'F')) { *val = c - 'A' + 10; return true; } + return false; +} + +static inline bool hex_byte(const char *in, uint8_t *out) +{ + uint8_t hi=0, lo=0; + bool ok = _hexcharval(in[0], &hi) && _hexcharval(in[1], &lo); + *out = (hi<<4)+lo; + return ok; +} + /* Needed for Solaris atomic_add_XX functions. */ #if defined(HAVE_SYS_ATOMIC_H) #include -- 2.25.1 From 08da34226f3d04100e8156e9b10de195f36fe7e7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 4 Jan 2021 13:55:01 +0100 Subject: [PATCH 402/645] CVE-2020-25718 ldb: Use hex_byte() in ldb_binary_decode() Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit b6a57c49c00a778f954aaf10db6ebe6dca8f5ae2) --- lib/ldb/common/ldb_parse.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/lib/ldb/common/ldb_parse.c b/lib/ldb/common/ldb_parse.c index 7e15206b168..f0045ad2093 100644 --- a/lib/ldb/common/ldb_parse.c +++ b/lib/ldb/common/ldb_parse.c @@ -53,26 +53,6 @@ */ #define LDB_MAX_PARSE_TREE_DEPTH 128 -static int ldb_parse_hex2char(const char *x) -{ - if (isxdigit(x[0]) && isxdigit(x[1])) { - const char h1 = x[0], h2 = x[1]; - int c = 0; - - if (h1 >= 'a') c = h1 - (int)'a' + 10; - else if (h1 >= 'A') c = h1 - (int)'A' + 10; - else if (h1 >= '0') c = h1 - (int)'0'; - c = c << 4; - if (h2 >= 'a') c += h2 - (int)'a' + 10; - else if (h2 >= 'A') c += h2 - (int)'A' + 10; - else if (h2 >= '0') c += h2 - (int)'0'; - - return c; - } - - return -1; -} - /* a filter is defined by: ::= '(' ')' @@ -101,10 +81,11 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str) for (i=j=0;i Date: Mon, 19 Oct 2020 02:39:46 +0200 Subject: [PATCH 403/645] CVE-2020-25718 ldb_kv_index: fix empty initializer compile warning Signed-off-by: Bjoern Jacke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 (cherry picked from commit c862ad64aea31d1d5ec66385bb50d9b97e609071) --- lib/ldb/ldb_key_value/ldb_kv_index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index a7e341552ea..4886901caee 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -2239,7 +2239,7 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv, struct ldb_message *filtered_msg; unsigned int i; unsigned int num_keys = 0; - uint8_t previous_guid_key[LDB_KV_GUID_KEY_SIZE] = {}; + uint8_t previous_guid_key[LDB_KV_GUID_KEY_SIZE] = {0}; struct ldb_val *keys = NULL; /* -- 2.25.1 From 859c1f01a568467556d583a0123ae7b03ace7459 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 16:01:04 +0200 Subject: [PATCH 404/645] CVE-2020-25717 winbind.idl: rename wbint_TransID.type to wbint_TransID.type_hint This makes it clear that it's a hint from the parent to the child. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 1576421dbdd2cfe9a47516224cb54bf15ba51132) --- librpc/idl/winbind.idl | 2 +- source3/winbindd/wb_sids2xids.c | 5 ++--- source3/winbindd/winbindd_dual_srv.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl index 258dd284ad5..a2bc81a9333 100644 --- a/librpc/idl/winbind.idl +++ b/librpc/idl/winbind.idl @@ -40,7 +40,7 @@ interface winbind ); typedef struct { - id_type type; + id_type type_hint; uint32 domain_index; uint32 rid; unixid xid; diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index e6698f94789..ff2135b4b50 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -222,7 +222,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &t->rid); - t->type = lsa_SidType_to_id_type(n->sid_type); + t->type_hint = lsa_SidType_to_id_type(n->sid_type); domain_index = init_lsa_ref_domain_list( state, &state->idmap_doms, domain_name, &dom_sid); if (domain_index == -1) { @@ -232,7 +232,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) t->domain_index = domain_index; t->xid.id = UINT32_MAX; - t->xid.type = t->type; + t->xid.type = ID_TYPE_NOT_SPECIFIED; } TALLOC_FREE(names); @@ -337,7 +337,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) for (i=0; inum_ids; i++) { if (dst->ids[i].domain_index == state->dom_index) { - dst->ids[i].type = src->ids[src_idx].type; dst->ids[i].xid = src->ids[src_idx].xid; src_idx += 1; } diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 13345caa41b..0a48201a2b0 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -199,7 +199,7 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p, sid_compose(m->sid, d->sid, ids[i].rid); m->status = ID_UNKNOWN; - m->xid = (struct unixid) { .type = ids[i].type }; + m->xid = (struct unixid) { .type = ids[i].type_hint }; } status = dom->methods->sids_to_unixids(dom, id_map_ptrs); -- 2.25.1 From d62d1e4479b12b040c92f3754cc7b0e45a0a949a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 16:46:44 +0200 Subject: [PATCH 405/645] CVE-2020-25717 s3:passdb: use ID_TYPE_* instead of WBC_ID_TYPE_* Currently these enums have the same values, but that will change in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 58e9b62222ad62c81cdf11d704859a227cb2902b) --- source3/passdb/lookup_sid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 6887b6ebb62..9a7a8cdb122 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1435,14 +1435,14 @@ done: */ for (i=0; i Date: Thu, 21 Mar 2019 12:29:00 +0100 Subject: [PATCH 406/645] CVE-2020-25717 test_idmap_tdb_common: correctly initialize the idmap domain with an init function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit f5eec89011cf7b577375d83247524587f170b592) --- source3/torture/test_idmap_tdb_common.c | 50 ++++++++++++++++--------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/source3/torture/test_idmap_tdb_common.c b/source3/torture/test_idmap_tdb_common.c index 5ecb978990d..f881babcc52 100644 --- a/source3/torture/test_idmap_tdb_common.c +++ b/source3/torture/test_idmap_tdb_common.c @@ -110,12 +110,21 @@ static bool open_db(struct idmap_tdb_common_context *ctx) return true; } -static struct idmap_tdb_common_context *createcontext(TALLOC_CTX *memctx) +static NTSTATUS idmap_test_tdb_db_init(struct idmap_domain *dom) { struct idmap_tdb_common_context *ret; - ret = talloc_zero(memctx, struct idmap_tdb_common_context); + DBG_DEBUG("called for domain '%s'\n", dom->name); + + ret = talloc_zero(dom, struct idmap_tdb_common_context); + if (ret == NULL) { + return NT_STATUS_NO_MEMORY; + } ret->rw_ops = talloc_zero(ret, struct idmap_rw_ops); + if (ret->rw_ops == NULL) { + TALLOC_FREE(ret); + return NT_STATUS_NO_MEMORY; + } ret->max_id = HIGH_ID; ret->hwmkey_uid = HWM_USER; @@ -125,25 +134,33 @@ static struct idmap_tdb_common_context *createcontext(TALLOC_CTX *memctx) ret->rw_ops->set_mapping = idmap_tdb_common_set_mapping; if (!open_db(ret)) { - return NULL; + TALLOC_FREE(ret); + return NT_STATUS_INTERNAL_ERROR; }; - return ret; + dom->private_data = ret; + + return NT_STATUS_OK; } static struct idmap_domain *createdomain(TALLOC_CTX *memctx) { struct idmap_domain *dom; + struct idmap_methods *m; dom = talloc_zero(memctx, struct idmap_domain); dom->name = "*"; dom->low_id = LOW_ID; dom->high_id = HIGH_ID; dom->read_only = false; - dom->methods = talloc_zero(dom, struct idmap_methods); - dom->methods->sids_to_unixids = idmap_tdb_common_sids_to_unixids; - dom->methods->unixids_to_sids = idmap_tdb_common_unixids_to_sids; - dom->methods->allocate_id = idmap_tdb_common_get_new_id; + m = talloc_zero(dom, struct idmap_methods); + *m = (struct idmap_methods) { + .init = idmap_test_tdb_db_init, + .sids_to_unixids = idmap_tdb_common_sids_to_unixids, + .unixids_to_sids = idmap_tdb_common_unixids_to_sids, + .allocate_id = idmap_tdb_common_get_new_id, + }; + dom->methods = m; return dom; } @@ -965,20 +982,20 @@ out: bool run_idmap_tdb_common_test(int dummy) { bool result; - struct idmap_tdb_common_context *ctx; struct idmap_domain *dom; - - TALLOC_CTX *memctx = talloc_new(NULL); TALLOC_CTX *stack = talloc_stackframe(); + TALLOC_CTX *memctx = talloc_new(stack); + NTSTATUS status; - ctx = createcontext(memctx); - if(!ctx) { + dom = createdomain(memctx); + if (dom == NULL) { return false; } - dom = createdomain(memctx); - - dom->private_data = ctx; + status = dom->methods->init(dom); + if (!NT_STATUS_IS_OK(status)) { + return false; + } /* test a single allocation from pool (no mapping) */ result = test_getnewid1(memctx, dom); @@ -1022,7 +1039,6 @@ bool run_idmap_tdb_common_test(int dummy) result = test_getnewid2(memctx, dom); CHECKRESULT(result); - talloc_free(memctx); talloc_free(stack); return true; -- 2.25.1 From 3cdf61136f9141a297d6372e35431800b2e3c388 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 12:30:37 +0100 Subject: [PATCH 407/645] CVE-2020-25717 winbindd/idmap: apply const to struct idmap_methods pointers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 95b0dac0af5bc7ee85c6c8099dda135c36c9684b) --- source3/include/idmap.h | 2 +- source3/winbindd/idmap.c | 6 +++--- source3/winbindd/idmap_ad.c | 2 +- source3/winbindd/idmap_autorid.c | 2 +- source3/winbindd/idmap_hash/idmap_hash.c | 2 +- source3/winbindd/idmap_ldap.c | 2 +- source3/winbindd/idmap_nss.c | 3 +-- source3/winbindd/idmap_passdb.c | 7 +------ source3/winbindd/idmap_proto.h | 2 +- source3/winbindd/idmap_rfc2307.c | 2 +- source3/winbindd/idmap_rid.c | 2 +- source3/winbindd/idmap_script.c | 2 +- source3/winbindd/idmap_tdb.c | 2 +- source3/winbindd/idmap_tdb2.c | 2 +- 14 files changed, 16 insertions(+), 22 deletions(-) diff --git a/source3/include/idmap.h b/source3/include/idmap.h index 8d80643e6e9..dce60f1f76d 100644 --- a/source3/include/idmap.h +++ b/source3/include/idmap.h @@ -42,7 +42,7 @@ struct idmap_domain { * so don't rely on this being filled out everywhere! */ struct dom_sid dom_sid; - struct idmap_methods *methods; + const struct idmap_methods *methods; NTSTATUS (*query_user)(struct idmap_domain *domain, struct wbint_userinfo *info); uint32_t low_id; diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index bfac7f86432..eee28992929 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -40,7 +40,7 @@ static_decl_idmap; struct idmap_backend { const char *name; - struct idmap_methods *methods; + const struct idmap_methods *methods; struct idmap_backend *prev, *next; }; static struct idmap_backend *backends = NULL; @@ -285,7 +285,7 @@ static bool idmap_found_domain_backend(const char *domname, return false; } -static struct idmap_methods *get_methods(const char *name) +static const struct idmap_methods *get_methods(const char *name) { struct idmap_backend *b; @@ -309,7 +309,7 @@ bool idmap_is_offline(void) **********************************************************************/ NTSTATUS smb_register_idmap(int version, const char *name, - struct idmap_methods *methods) + const struct idmap_methods *methods) { struct idmap_backend *entry; diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c index 3bfeeee2d74..5cd258d49c4 100644 --- a/source3/winbindd/idmap_ad.c +++ b/source3/winbindd/idmap_ad.c @@ -1003,7 +1003,7 @@ static NTSTATUS idmap_ad_sids_to_unixids_retry(struct idmap_domain *dom, return status; } -static struct idmap_methods ad_methods = { +static const struct idmap_methods ad_methods = { .init = idmap_ad_initialize, .unixids_to_sids = idmap_ad_unixids_to_sids_retry, .sids_to_unixids = idmap_ad_sids_to_unixids_retry, diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c index 1d0f0fafb82..636852119b2 100644 --- a/source3/winbindd/idmap_autorid.c +++ b/source3/winbindd/idmap_autorid.c @@ -919,7 +919,7 @@ done: return status; } -static struct idmap_methods autorid_methods = { +static const struct idmap_methods autorid_methods = { .init = idmap_autorid_initialize, .unixids_to_sids = idmap_autorid_unixids_to_sids, .sids_to_unixids = idmap_autorid_sids_to_unixids, diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 1747b7c56c1..267ff3e5edc 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -331,7 +331,7 @@ static NTSTATUS nss_hash_close(void) Dispatch Tables for IDMap and NssInfo Methods ********************************************************************/ -static struct idmap_methods hash_idmap_methods = { +static const struct idmap_methods hash_idmap_methods = { .init = idmap_hash_initialize, .unixids_to_sids = unixids_to_sids, .sids_to_unixids = sids_to_unixids, diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 86cb6f1bc51..82f425ec9d0 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -1093,7 +1093,7 @@ done: Close the idmap ldap instance **********************************/ -static struct idmap_methods idmap_ldap_methods = { +static const struct idmap_methods idmap_ldap_methods = { .init = idmap_ldap_db_init, .unixids_to_sids = idmap_ldap_unixids_to_sids, diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c index 3fe98cbc729..9e1efefeb24 100644 --- a/source3/winbindd/idmap_nss.c +++ b/source3/winbindd/idmap_nss.c @@ -195,8 +195,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma Close the idmap tdb instance **********************************/ -static struct idmap_methods nss_methods = { - +static const struct idmap_methods nss_methods = { .init = idmap_nss_int_init, .unixids_to_sids = idmap_nss_unixids_to_sids, .sids_to_unixids = idmap_nss_sids_to_unixids, diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c index 75fc732cca0..758f31a2c9d 100644 --- a/source3/winbindd/idmap_passdb.c +++ b/source3/winbindd/idmap_passdb.c @@ -75,12 +75,7 @@ static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma return NT_STATUS_OK; } -/********************************** - Close the idmap tdb instance -**********************************/ - -static struct idmap_methods passdb_methods = { - +static const struct idmap_methods passdb_methods = { .init = idmap_pdb_init, .unixids_to_sids = idmap_pdb_unixids_to_sids, .sids_to_unixids = idmap_pdb_sids_to_unixids, diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h index a36d6c2f5bb..adc04430a67 100644 --- a/source3/winbindd/idmap_proto.h +++ b/source3/winbindd/idmap_proto.h @@ -29,7 +29,7 @@ bool idmap_is_offline(void); NTSTATUS smb_register_idmap(int version, const char *name, - struct idmap_methods *methods); + const struct idmap_methods *methods); void idmap_close(void); NTSTATUS idmap_allocate_uid(struct unixid *id); NTSTATUS idmap_allocate_gid(struct unixid *id); diff --git a/source3/winbindd/idmap_rfc2307.c b/source3/winbindd/idmap_rfc2307.c index e3bf58d8165..a747ff1f3bf 100644 --- a/source3/winbindd/idmap_rfc2307.c +++ b/source3/winbindd/idmap_rfc2307.c @@ -836,7 +836,7 @@ err: return status; } -static struct idmap_methods rfc2307_methods = { +static const struct idmap_methods rfc2307_methods = { .init = idmap_rfc2307_initialize, .unixids_to_sids = idmap_rfc2307_unixids_to_sids, .sids_to_unixids = idmap_rfc2307_sids_to_unixids, diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c index e5bb1fa856c..33f049695f4 100644 --- a/source3/winbindd/idmap_rid.c +++ b/source3/winbindd/idmap_rid.c @@ -168,7 +168,7 @@ static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_ma return NT_STATUS_OK; } -static struct idmap_methods rid_methods = { +static const struct idmap_methods rid_methods = { .init = idmap_rid_initialize, .unixids_to_sids = idmap_rid_unixids_to_sids, .sids_to_unixids = idmap_rid_sids_to_unixids, diff --git a/source3/winbindd/idmap_script.c b/source3/winbindd/idmap_script.c index f382f896b35..a56ad7b93fb 100644 --- a/source3/winbindd/idmap_script.c +++ b/source3/winbindd/idmap_script.c @@ -665,7 +665,7 @@ failed: return ret; } -static struct idmap_methods db_methods = { +static const struct idmap_methods db_methods = { .init = idmap_script_db_init, .unixids_to_sids = idmap_script_unixids_to_sids, .sids_to_unixids = idmap_script_sids_to_unixids, diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index c3215c4dd9b..1ec2be0d789 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -426,7 +426,7 @@ failed: return ret; } -static struct idmap_methods db_methods = { +static const struct idmap_methods db_methods = { .init = idmap_tdb_db_init, .unixids_to_sids = idmap_tdb_common_unixids_to_sids, .sids_to_unixids = idmap_tdb_common_sids_to_unixids, diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index eceab9c0784..f2731f9a04a 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -598,7 +598,7 @@ failed: } -static struct idmap_methods db_methods = { +static const struct idmap_methods db_methods = { .init = idmap_tdb2_db_init, .unixids_to_sids = idmap_tdb_common_unixids_to_sids, .sids_to_unixids = idmap_tdb_common_sids_to_unixids, -- 2.25.1 From e251bfdb4189d5b30a71052dd3788fb9ebfcae25 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 12:30:37 +0100 Subject: [PATCH 408/645] CVE-2020-25717 winbindd/idmap: apply const to struct nss_info_methods pointers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 7518a0ca32cade2b8b9eac0e2b5416ae685ffcff) --- source3/include/nss_info.h | 6 +++--- source3/winbindd/idmap_ad_nss.c | 6 +++--- source3/winbindd/idmap_hash/idmap_hash.c | 2 +- source3/winbindd/nss_info.c | 7 ++++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source3/include/nss_info.h b/source3/include/nss_info.h index 448f8847be9..94df56ee7db 100644 --- a/source3/include/nss_info.h +++ b/source3/include/nss_info.h @@ -38,7 +38,7 @@ struct nss_function_entry { struct nss_function_entry *prev, *next; const char *name; - struct nss_info_methods *methods; + const struct nss_info_methods *methods; }; /* List of configured domains. Each domain points @@ -50,7 +50,7 @@ struct nss_domain_entry { const char *domain; NTSTATUS init_status; - struct nss_function_entry *backend; + const struct nss_function_entry *backend; /* hold state on a per domain basis */ @@ -75,7 +75,7 @@ struct nss_info_methods { NTSTATUS smb_register_idmap_nss(int version, const char *name, - struct nss_info_methods *methods); + const struct nss_info_methods *methods); NTSTATUS nss_map_to_alias( TALLOC_CTX *mem_ctx, const char *domain, const char *name, char **alias ); diff --git a/source3/winbindd/idmap_ad_nss.c b/source3/winbindd/idmap_ad_nss.c index 0fd2b51e156..96fee84997f 100644 --- a/source3/winbindd/idmap_ad_nss.c +++ b/source3/winbindd/idmap_ad_nss.c @@ -370,19 +370,19 @@ done: /* The SFU and RFC2307 NSS plugins share everything but the init function which sets the intended schema model to use */ -static struct nss_info_methods nss_rfc2307_methods = { +static const struct nss_info_methods nss_rfc2307_methods = { .init = nss_rfc2307_init, .map_to_alias = nss_ad_map_to_alias, .map_from_alias = nss_ad_map_from_alias, }; -static struct nss_info_methods nss_sfu_methods = { +static const struct nss_info_methods nss_sfu_methods = { .init = nss_sfu_init, .map_to_alias = nss_ad_map_to_alias, .map_from_alias = nss_ad_map_from_alias, }; -static struct nss_info_methods nss_sfu20_methods = { +static const struct nss_info_methods nss_sfu20_methods = { .init = nss_sfu20_init, .map_to_alias = nss_ad_map_to_alias, .map_from_alias = nss_ad_map_from_alias, diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 267ff3e5edc..be0ba45a044 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -337,7 +337,7 @@ static const struct idmap_methods hash_idmap_methods = { .sids_to_unixids = sids_to_unixids, }; -static struct nss_info_methods hash_nss_methods = { +static const struct nss_info_methods hash_nss_methods = { .init = nss_hash_init, .map_to_alias = nss_hash_map_to_alias, .map_from_alias = nss_hash_map_from_alias, diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c index 1a8325ce7dc..9c502e84ef0 100644 --- a/source3/winbindd/nss_info.c +++ b/source3/winbindd/nss_info.c @@ -46,7 +46,8 @@ static struct nss_function_entry *nss_get_backend(const char *name ) Allow a module to register itself as a backend. **********************************************************************/ - NTSTATUS smb_register_idmap_nss(int version, const char *name, struct nss_info_methods *methods) + NTSTATUS smb_register_idmap_nss(int version, const char *name, + const struct nss_info_methods *methods) { struct nss_function_entry *entry; @@ -319,7 +320,7 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) const char *name, char **alias ) { struct nss_domain_entry *p; - struct nss_info_methods *m; + const struct nss_info_methods *m; if ( (p = find_nss_domain( domain )) == NULL ) { DEBUG(4,("nss_map_to_alias: Failed to find nss domain pointer for %s\n", @@ -340,7 +341,7 @@ static struct nss_domain_entry *find_nss_domain( const char *domain ) const char *alias, char **name ) { struct nss_domain_entry *p; - struct nss_info_methods *m; + const struct nss_info_methods *m; if ( (p = find_nss_domain( domain )) == NULL ) { DEBUG(4,("nss_map_from_alias: Failed to find nss domain pointer for %s\n", -- 2.25.1 From d04e2c7c947ced7fdc2720384937bf3dad431968 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 13:52:17 +0200 Subject: [PATCH 409/645] CVE-2020-25717 wb_queryuser: avoid idmap_child() and use idmap_child_handle() instead This is the only aspect we need here. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 7dbe5b4897448aa71b5a8a2175850b4010316b88) --- source3/winbindd/wb_queryuser.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 2eb61406fc5..2e36643454b 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -77,7 +77,7 @@ static void wb_queryuser_got_uid(struct tevent_req *subreq) req, struct wb_queryuser_state); struct wbint_userinfo *info = state->info; struct netr_SamInfo3 *info3; - struct winbindd_child *child; + struct dcerpc_binding_handle *child_binding_handle = NULL; struct unixid xid; NTSTATUS status; @@ -138,10 +138,9 @@ static void wb_queryuser_got_uid(struct tevent_req *subreq) return; } - child = idmap_child(); - + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( - state, state->ev, child->binding_handle, info); + state, state->ev, child_binding_handle, info); if (tevent_req_nomem(subreq, req)) { return; } @@ -156,7 +155,7 @@ static void wb_queryuser_got_domain(struct tevent_req *subreq) req, struct wb_queryuser_state); struct wbint_userinfo *info = state->info; enum lsa_SidType type; - struct winbindd_child *child; + struct dcerpc_binding_handle *child_binding_handle = NULL; NTSTATUS status; status = wb_lookupsid_recv(subreq, state, &type, @@ -186,10 +185,9 @@ static void wb_queryuser_got_domain(struct tevent_req *subreq) return; } - child = idmap_child(); - + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( - state, state->ev, child->binding_handle, info); + state, state->ev, child_binding_handle, info); if (tevent_req_nomem(subreq, req)) { return; } @@ -270,7 +268,7 @@ static void wb_queryuser_got_dc(struct tevent_req *subreq) req, struct wb_queryuser_state); struct wbint_userinfo *info = state->info; struct netr_DsRGetDCNameInfo *dcinfo; - struct winbindd_child *child; + struct dcerpc_binding_handle *child_binding_handle = NULL; NTSTATUS status; status = wb_dsgetdcname_recv(subreq, state, &dcinfo); @@ -286,10 +284,9 @@ static void wb_queryuser_got_dc(struct tevent_req *subreq) return; } - child = idmap_child(); - + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( - state, state->ev, child->binding_handle, info); + state, state->ev, child_binding_handle, info); if (tevent_req_nomem(subreq, req)) { return; } -- 2.25.1 From 4e60db568e55c1df74da36a039af6b05652a81e9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 12:35:09 +0200 Subject: [PATCH 410/645] CVE-2020-25717 wb_xids2sids: avoid idmap_child() and use idmap_child_handle() instead This is the only aspect we need here. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 5cc21a9d319e00397ad98900d81ffb9d1d70514f) --- source3/winbindd/wb_xids2sids.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c index 929a3b8e425..f88c9be58a8 100644 --- a/source3/winbindd/wb_xids2sids.c +++ b/source3/winbindd/wb_xids2sids.c @@ -270,7 +270,7 @@ static struct tevent_req *wb_xids2sids_dom_send( { struct tevent_req *req, *subreq; struct wb_xids2sids_dom_state *state; - struct winbindd_child *child; + struct dcerpc_binding_handle *child_binding_handle = NULL; size_t i; req = tevent_req_create(mem_ctx, &state, @@ -317,9 +317,9 @@ static struct tevent_req *wb_xids2sids_dom_send( return tevent_req_post(req, ev); } - child = idmap_child(); + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_UnixIDs2Sids_send( - state, ev, child->binding_handle, dom_map->name, dom_map->sid, + state, ev, child_binding_handle, dom_map->name, dom_map->sid, state->num_dom_xids, state->dom_xids, state->dom_sids); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); @@ -396,7 +396,7 @@ static void wb_xids2sids_dom_gotdc(struct tevent_req *subreq) subreq, struct tevent_req); struct wb_xids2sids_dom_state *state = tevent_req_data( req, struct wb_xids2sids_dom_state); - struct winbindd_child *child = idmap_child(); + struct dcerpc_binding_handle *child_binding_handle = NULL; struct netr_DsRGetDCNameInfo *dcinfo; NTSTATUS status; @@ -413,9 +413,9 @@ static void wb_xids2sids_dom_gotdc(struct tevent_req *subreq) return; } - child = idmap_child(); + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_UnixIDs2Sids_send( - state, state->ev, child->binding_handle, state->dom_map->name, + state, state->ev, child_binding_handle, state->dom_map->name, state->dom_map->sid, state->num_dom_xids, state->dom_xids, state->dom_sids); if (tevent_req_nomem(subreq, req)) { -- 2.25.1 From 7743ff28fcfafa630ba39dbf8d8cbfe4ae501117 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Sep 2020 15:49:34 +0200 Subject: [PATCH 411/645] CVE-2020-25717 wb_sids2xids: avoid idmap_child() and use idmap_child_handle() instead This is the only aspect we need here. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 1694de1ae6ce63377d0afc47e84e55e4745905d7) --- source3/winbindd/wb_sids2xids.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index ff2135b4b50..b47856520ea 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -238,8 +238,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) TALLOC_FREE(names); TALLOC_FREE(domains); - child_binding_handle = idmap_child_handle(); - state->dom_ids = wb_sids2xids_extract_for_domain_index( state, &state->ids, state->dom_index); if (tevent_req_nomem(state->dom_ids, req)) { @@ -252,6 +250,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) .max_size = 1 }; + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_Sids2UnixIDs_send( state, state->ev, child_binding_handle, &state->idmap_dom, state->dom_ids); @@ -290,8 +289,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status, result; - struct winbindd_child *child; - + struct dcerpc_binding_handle *child_binding_handle = NULL; struct wbint_TransIDArray *src, *dst; uint32_t i, src_idx; @@ -352,8 +350,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) return; } - child = idmap_child(); - state->dom_ids = wb_sids2xids_extract_for_domain_index( state, &state->ids, state->dom_index); if (tevent_req_nomem(state->dom_ids, req)) { @@ -366,8 +362,9 @@ static void wb_sids2xids_done(struct tevent_req *subreq) .max_size = 1 }; + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_Sids2UnixIDs_send( - state, state->ev, child->binding_handle, &state->idmap_dom, + state, state->ev, child_binding_handle, &state->idmap_dom, state->dom_ids); if (tevent_req_nomem(subreq, req)) { return; @@ -381,7 +378,7 @@ static void wb_sids2xids_gotdc(struct tevent_req *subreq) subreq, struct tevent_req); struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); - struct winbindd_child *child = idmap_child(); + struct dcerpc_binding_handle *child_binding_handle = NULL; struct netr_DsRGetDCNameInfo *dcinfo; NTSTATUS status; @@ -404,8 +401,9 @@ static void wb_sids2xids_gotdc(struct tevent_req *subreq) } } + child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_Sids2UnixIDs_send( - state, state->ev, child->binding_handle, &state->idmap_dom, + state, state->ev, child_binding_handle, &state->idmap_dom, state->dom_ids); if (tevent_req_nomem(subreq, req)) { return; -- 2.25.1 From fdb37eda219652b62c4e99dc8affabe2930749bc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 14:06:04 +0200 Subject: [PATCH 412/645] CVE-2020-25717 winbindd: add and use idmap_child_pid() We should avoid calling idmap_child() as much as possible. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 2103543629004a3a22e7bf60305bb15bf3b316be) --- source3/winbindd/winbindd_cm.c | 12 ++++++------ source3/winbindd/winbindd_dual.c | 6 +++--- source3/winbindd/winbindd_idmap.c | 5 +++++ source3/winbindd/winbindd_proto.h | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0e671ca22be..3c82156e564 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -463,11 +463,11 @@ void set_domain_offline(struct winbindd_domain *domain) primary domain goes offline */ if ( domain->primary ) { - struct winbindd_child *idmap = idmap_child(); + pid_t idmap_pid = idmap_child_pid(); - if ( idmap->pid != 0 ) { + if (idmap_pid != 0) { messaging_send_buf(global_messaging_context(), - pid_to_procid(idmap->pid), + pid_to_procid(idmap_pid), MSG_WINBIND_OFFLINE, (const uint8_t *)domain->name, strlen(domain->name)+1); @@ -549,11 +549,11 @@ static void set_domain_online(struct winbindd_domain *domain) primary domain comes online */ if ( domain->primary ) { - struct winbindd_child *idmap = idmap_child(); + pid_t idmap_pid = idmap_child_pid(); - if ( idmap->pid != 0 ) { + if (idmap_pid != 0) { messaging_send_buf(global_messaging_context(), - pid_to_procid(idmap->pid), + pid_to_procid(idmap_pid), MSG_WINBIND_ONLINE, (const uint8_t *)domain->name, strlen(domain->name)+1); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 9f14dfdb4f1..5cfc92dd054 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1071,11 +1071,11 @@ void winbind_msg_online(struct messaging_context *msg_ctx, primary domain comes back online */ if ( domain->primary ) { - struct winbindd_child *idmap = idmap_child(); + pid_t idmap_pid = idmap_child_pid(); - if ( idmap->pid != 0 ) { + if (idmap_pid != 0) { messaging_send_buf(msg_ctx, - pid_to_procid(idmap->pid), + pid_to_procid(idmap_pid), MSG_WINBIND_ONLINE, (const uint8_t *)domain->name, strlen(domain->name)+1); diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 2ee436bc7dc..965a7839f17 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -34,6 +34,11 @@ struct winbindd_child *idmap_child(void) return &static_idmap_child; } +pid_t idmap_child_pid(void) +{ + return static_idmap_child.pid; +} + struct dcerpc_binding_handle *idmap_child_handle(void) { return static_idmap_child.binding_handle; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 6d4ffa726f1..ce391ab7ec5 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -366,6 +366,7 @@ NTSTATUS winbindd_print_groupmembers(struct db_context *members, void init_idmap_child(void); struct winbindd_child *idmap_child(void); +pid_t idmap_child_pid(void); struct dcerpc_binding_handle *idmap_child_handle(void); struct idmap_domain *idmap_find_domain_with_sid(const char *domname, const struct dom_sid *sid); -- 2.25.1 From 4bd966b70d5e9e16eb8b65e7d80f82696f56d6f4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 14:06:04 +0200 Subject: [PATCH 413/645] CVE-2020-25717 winbindd: add and use is_idmap_child() We should avoid calling idmap_child() as much as possible. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit cd9a9702c1f97c47bd3447e2014eeff3e56268cf) --- source3/winbindd/winbindd_dual.c | 4 ++-- source3/winbindd/winbindd_idmap.c | 9 +++++++++ source3/winbindd/winbindd_proto.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 5cfc92dd054..7fc482c838a 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1775,7 +1775,7 @@ static bool fork_domain_child(struct winbindd_child *child) if (child_domain != NULL) { setproctitle("domain child [%s]", child_domain->name); - } else if (child == idmap_child()) { + } else if (is_idmap_child(child)) { setproctitle("idmap child"); } @@ -1825,7 +1825,7 @@ static bool fork_domain_child(struct winbindd_child *child) * We are in idmap child, make sure that we set the * check_online_event to bring primary domain online. */ - if (child == idmap_child()) { + if (is_idmap_child(child)) { set_domain_online_request(primary_domain); } diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 965a7839f17..bd5f3a67aad 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -34,6 +34,15 @@ struct winbindd_child *idmap_child(void) return &static_idmap_child; } +bool is_idmap_child(const struct winbindd_child *child) +{ + if (child == &static_idmap_child) { + return true; + } + + return false; +} + pid_t idmap_child_pid(void) { return static_idmap_child.pid; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index ce391ab7ec5..97c38018aac 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -366,6 +366,7 @@ NTSTATUS winbindd_print_groupmembers(struct db_context *members, void init_idmap_child(void); struct winbindd_child *idmap_child(void); +bool is_idmap_child(const struct winbindd_child *child); pid_t idmap_child_pid(void); struct dcerpc_binding_handle *idmap_child_handle(void); struct idmap_domain *idmap_find_domain_with_sid(const char *domname, -- 2.25.1 From ef2f274fbd78fdc4741b7761b7f87aa8c33faf56 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 12:16:00 +0200 Subject: [PATCH 414/645] CVE-2020-25717 winbindd: add generic wb_parent_idmap_setup_send/recv() helpers This is more or less a copy of wb_xids2sids_init_dom_maps_send/recv, but it's more generic and doesn't imply global state. It also closes a initialization race by using a tevent_queue to serialize the calls. In the next commits we'll replace wb_xids2sids_init_dom_maps_send/recv. We'll also use the new function in the wb_sids2xids code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 209e81a2ea8c972ee57e2f0c9579da843c0e2ac7) --- source3/winbindd/winbindd.h | 13 ++ source3/winbindd/winbindd_idmap.c | 314 ++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 5 + 3 files changed, 332 insertions(+) diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index a72d6aa7830..480ba4f1282 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -189,6 +189,19 @@ struct winbindd_domain { struct winbindd_domain *prev, *next; }; +struct wb_parent_idmap_config_dom { + unsigned low_id; + unsigned high_id; + const char *name; + struct dom_sid sid; +}; + +struct wb_parent_idmap_config { + struct tevent_queue *queue; + uint32_t num_doms; + struct wb_parent_idmap_config_dom *doms; +}; + struct wb_acct_info { const char *acct_name; /* account name */ const char *acct_desc; /* account name */ diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index bd5f3a67aad..487f27fd94d 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -23,12 +23,21 @@ #include "includes.h" #include "winbindd.h" +#include "../libcli/security/security.h" +#include "passdb/lookup_sid.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND static struct winbindd_child static_idmap_child; +/* + * Map idmap ranges to domain names, taken from smb.conf. This is + * stored in the parent winbind and used to assemble xids2sids/sids2xids calls + * into per-idmap-domain chunks. + */ +static struct wb_parent_idmap_config static_parent_idmap_config; + struct winbindd_child *idmap_child(void) { return &static_idmap_child; @@ -73,3 +82,308 @@ void init_idmap_child(void) idmap_dispatch_table, "log.winbindd", "idmap"); } + +struct wb_parent_idmap_setup_state { + struct tevent_context *ev; + struct wb_parent_idmap_config *cfg; + size_t dom_idx; +}; + +static void wb_parent_idmap_setup_cleanup(struct tevent_req *req, + enum tevent_req_state req_state) +{ + struct wb_parent_idmap_setup_state *state = + tevent_req_data(req, + struct wb_parent_idmap_setup_state); + + if (req_state == TEVENT_REQ_DONE) { + state->cfg = NULL; + return; + } + + if (state->cfg == NULL) { + return; + } + + state->cfg->num_doms = 0; + TALLOC_FREE(state->cfg->doms); + state->cfg = NULL; +} + +static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq); +static bool wb_parent_idmap_setup_scan_config(const char *domname, + void *private_data); +static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req); +static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq); + +struct tevent_req *wb_parent_idmap_setup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev) +{ + struct tevent_req *req = NULL; + struct wb_parent_idmap_setup_state *state = NULL; + struct tevent_req *subreq = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct wb_parent_idmap_setup_state); + if (req == NULL) { + return NULL; + } + *state = (struct wb_parent_idmap_setup_state) { + .ev = ev, + .cfg = &static_parent_idmap_config, + .dom_idx = 0, + }; + + if (state->cfg->queue == NULL) { + state->cfg->queue = tevent_queue_create(NULL, + "wb_parent_idmap_config_queue"); + if (tevent_req_nomem(state->cfg->queue, req)) { + return tevent_req_post(req, ev); + } + } + + subreq = tevent_queue_wait_send(state, state->ev, state->cfg->queue); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, + wb_parent_idmap_setup_queue_wait_done, + req); + + return req; +} + +static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct wb_parent_idmap_setup_state *state = + tevent_req_data(req, + struct wb_parent_idmap_setup_state); + bool ok; + + /* + * Note we don't call TALLOC_FREE(subreq) here in order to block the + * queue until tevent_req_received() in wb_parent_idmap_setup_recv() + * will destroy it implicitly. + */ + ok = tevent_queue_wait_recv(subreq); + if (!ok) { + DBG_ERR("tevent_queue_wait_recv() failed\n"); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + if (state->cfg->num_doms != 0) { + /* + * If we're not the first one we're done. + */ + tevent_req_done(req); + return; + } + + /* + * From this point we start changing state->cfg, + * which is &static_parent_idmap_config, + * so we better setup a cleanup function + * to undo the changes on failure. + */ + tevent_req_set_cleanup_fn(req, wb_parent_idmap_setup_cleanup); + + /* + * Put the passdb idmap domain first. We always need to try + * there first. + */ + state->cfg->doms = talloc_zero_array(NULL, + struct wb_parent_idmap_config_dom, + 1); + if (tevent_req_nomem(state->cfg->doms, req)) { + return; + } + state->cfg->doms[0].low_id = 0; + state->cfg->doms[0].high_id = UINT_MAX; + state->cfg->doms[0].name = talloc_strdup(state->cfg->doms, + get_global_sam_name()); + if (tevent_req_nomem(state->cfg->doms[0].name, req)) { + return; + } + state->cfg->num_doms += 1; + + lp_scan_idmap_domains(wb_parent_idmap_setup_scan_config, req); + if (!tevent_req_is_in_progress(req)) { + return; + } + + wb_parent_idmap_setup_lookupname_next(req); +} + +static bool wb_parent_idmap_setup_scan_config(const char *domname, + void *private_data) +{ + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); + struct wb_parent_idmap_setup_state *state = + tevent_req_data(req, + struct wb_parent_idmap_setup_state); + struct wb_parent_idmap_config_dom *map = NULL; + size_t i; + const char *range; + unsigned low_id, high_id; + int ret; + + range = idmap_config_const_string(domname, "range", NULL); + if (range == NULL) { + DBG_DEBUG("No range for domain %s found\n", domname); + return false; + } + + ret = sscanf(range, "%u - %u", &low_id, &high_id); + if (ret != 2) { + DBG_DEBUG("Invalid range spec \"%s\" for domain %s\n", + range, domname); + return false; + } + + if (low_id > high_id) { + DBG_DEBUG("Invalid range %u - %u for domain %s\n", + low_id, high_id, domname); + return false; + } + + for (i=0; icfg->num_doms; i++) { + if (strequal(domname, state->cfg->doms[i].name)) { + map = &state->cfg->doms[i]; + break; + } + } + + if (map == NULL) { + struct wb_parent_idmap_config_dom *tmp; + char *name; + + name = talloc_strdup(state, domname); + if (name == NULL) { + DBG_ERR("talloc failed\n"); + return false; + } + + tmp = talloc_realloc( + NULL, state->cfg->doms, struct wb_parent_idmap_config_dom, + state->cfg->num_doms+1); + if (tmp == NULL) { + DBG_ERR("talloc failed\n"); + return false; + } + state->cfg->doms = tmp; + + map = &state->cfg->doms[state->cfg->num_doms]; + state->cfg->num_doms += 1; + ZERO_STRUCTP(map); + map->name = talloc_move(state->cfg->doms, &name); + } + + map->low_id = low_id; + map->high_id = high_id; + + return false; +} + +static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req) +{ + struct wb_parent_idmap_setup_state *state = + tevent_req_data(req, + struct wb_parent_idmap_setup_state); + struct wb_parent_idmap_config_dom *dom = + &state->cfg->doms[state->dom_idx]; + struct tevent_req *subreq = NULL; + + next_domain: + if (state->dom_idx == state->cfg->num_doms) { + tevent_req_done(req); + return; + } + + if (strequal(dom->name, "*")) { + state->dom_idx++; + goto next_domain; + } + + subreq = wb_lookupname_send(state, + state->ev, + dom->name, + dom->name, + "", + LOOKUP_NAME_NO_NSS); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + wb_parent_idmap_setup_lookupname_done, + req); +} + +static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct wb_parent_idmap_setup_state *state = + tevent_req_data(req, + struct wb_parent_idmap_setup_state); + struct wb_parent_idmap_config_dom *dom = + &state->cfg->doms[state->dom_idx]; + enum lsa_SidType type; + NTSTATUS status; + + status = wb_lookupname_recv(subreq, &dom->sid, &type); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("Lookup domain name '%s' failed '%s'\n", + dom->name, + nt_errstr(status)); + + state->dom_idx++; + wb_parent_idmap_setup_lookupname_next(req); + return; + } + + if (type != SID_NAME_DOMAIN) { + struct dom_sid_buf buf; + + DBG_ERR("SID %s for idmap domain name '%s' " + "not a domain SID\n", + dom_sid_str_buf(&dom->sid, &buf), + dom->name); + + ZERO_STRUCT(dom->sid); + } + + state->dom_idx++; + wb_parent_idmap_setup_lookupname_next(req); + + return; +} + +NTSTATUS wb_parent_idmap_setup_recv(struct tevent_req *req, + const struct wb_parent_idmap_config **_cfg) +{ + const struct wb_parent_idmap_config *cfg = &static_parent_idmap_config; + NTSTATUS status; + + *_cfg = NULL; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + + /* + * Note state->cfg is already set to NULL by + * wb_parent_idmap_setup_cleanup() + */ + *_cfg = cfg; + tevent_req_received(req); + return NT_STATUS_OK; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 97c38018aac..8923bb3124f 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -364,6 +364,11 @@ NTSTATUS winbindd_print_groupmembers(struct db_context *members, /* The following definitions come from winbindd/winbindd_idmap.c */ +struct tevent_req *wb_parent_idmap_setup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev); +NTSTATUS wb_parent_idmap_setup_recv(struct tevent_req *req, + const struct wb_parent_idmap_config **_cfg); + void init_idmap_child(void); struct winbindd_child *idmap_child(void); bool is_idmap_child(const struct winbindd_child *child); -- 2.25.1 From 893e3dc8042957156d7bb6d6349dc52deb393d14 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 12:31:13 +0200 Subject: [PATCH 415/645] CVE-2020-25717 wb_xids2sids: make use of the new wb_parent_idmap_setup_send/recv() helpers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit a8f57c94fc2294c309ecb18ea79d0acac86c495b) --- source3/winbindd/wb_xids2sids.c | 255 +++----------------------------- 1 file changed, 17 insertions(+), 238 deletions(-) diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c index f88c9be58a8..c68939b2bcd 100644 --- a/source3/winbindd/wb_xids2sids.c +++ b/source3/winbindd/wb_xids2sids.c @@ -25,231 +25,13 @@ #include "librpc/gen_ndr/ndr_netlogon.h" #include "passdb/lookup_sid.h" -struct wb_xids2sids_dom_map { - unsigned low_id; - unsigned high_id; - const char *name; - struct dom_sid sid; -}; - -/* - * Map idmap ranges to domain names, taken from smb.conf. This is - * stored in the parent winbind and used to assemble xid2sid calls - * into per-idmap-domain chunks. - */ -static struct wb_xids2sids_dom_map *dom_maps; - -static bool wb_xids2sids_add_dom(const char *domname, - void *private_data) -{ - struct wb_xids2sids_dom_map *map = NULL; - size_t num_maps = talloc_array_length(dom_maps); - size_t i; - const char *range; - unsigned low_id, high_id; - int ret; - - range = idmap_config_const_string(domname, "range", NULL); - if (range == NULL) { - DBG_DEBUG("No range for domain %s found\n", domname); - return false; - } - - ret = sscanf(range, "%u - %u", &low_id, &high_id); - if (ret != 2) { - DBG_DEBUG("Invalid range spec \"%s\" for domain %s\n", - range, domname); - return false; - } - - if (low_id > high_id) { - DBG_DEBUG("Invalid range %u - %u for domain %s\n", - low_id, high_id, domname); - return false; - } - - for (i=0; iname = talloc_move(dom_maps, &name); - } - - map->low_id = low_id; - map->high_id = high_id; - - return false; -} - -struct wb_xids2sids_init_dom_maps_state { - struct tevent_context *ev; - struct tevent_req *req; - size_t dom_idx; -}; - -static void wb_xids2sids_init_dom_maps_lookupname_next( - struct wb_xids2sids_init_dom_maps_state *state); - -static void wb_xids2sids_init_dom_maps_lookupname_done( - struct tevent_req *subreq); - -static struct tevent_req *wb_xids2sids_init_dom_maps_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev) -{ - struct tevent_req *req = NULL; - struct wb_xids2sids_init_dom_maps_state *state = NULL; - - req = tevent_req_create(mem_ctx, &state, - struct wb_xids2sids_init_dom_maps_state); - if (req == NULL) { - return NULL; - } - *state = (struct wb_xids2sids_init_dom_maps_state) { - .ev = ev, - .req = req, - .dom_idx = 0, - }; - - if (dom_maps != NULL) { - tevent_req_done(req); - return tevent_req_post(req, ev); - } - /* - * Put the passdb idmap domain first. We always need to try - * there first. - */ - - dom_maps = talloc_zero_array(NULL, struct wb_xids2sids_dom_map, 1); - if (tevent_req_nomem(dom_maps, req)) { - return tevent_req_post(req, ev); - } - dom_maps[0].low_id = 0; - dom_maps[0].high_id = UINT_MAX; - dom_maps[0].name = talloc_strdup(dom_maps, get_global_sam_name()); - if (tevent_req_nomem(dom_maps[0].name, req)) { - TALLOC_FREE(dom_maps); - return tevent_req_post(req, ev); - } - - lp_scan_idmap_domains(wb_xids2sids_add_dom, NULL); - - wb_xids2sids_init_dom_maps_lookupname_next(state); - if (!tevent_req_is_in_progress(req)) { - tevent_req_post(req, ev); - } - return req; -} - -static void wb_xids2sids_init_dom_maps_lookupname_next( - struct wb_xids2sids_init_dom_maps_state *state) -{ - struct tevent_req *subreq = NULL; - - if (state->dom_idx == talloc_array_length(dom_maps)) { - tevent_req_done(state->req); - return; - } - - if (strequal(dom_maps[state->dom_idx].name, "*")) { - state->dom_idx++; - if (state->dom_idx == talloc_array_length(dom_maps)) { - tevent_req_done(state->req); - return; - } - } - - subreq = wb_lookupname_send(state, - state->ev, - dom_maps[state->dom_idx].name, - dom_maps[state->dom_idx].name, - "", - LOOKUP_NAME_NO_NSS); - if (tevent_req_nomem(subreq, state->req)) { - return; - } - tevent_req_set_callback(subreq, - wb_xids2sids_init_dom_maps_lookupname_done, - state->req); -} - -static void wb_xids2sids_init_dom_maps_lookupname_done( - struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct wb_xids2sids_init_dom_maps_state *state = tevent_req_data( - req, struct wb_xids2sids_init_dom_maps_state); - enum lsa_SidType type; - NTSTATUS status; - - status = wb_lookupname_recv(subreq, - &dom_maps[state->dom_idx].sid, - &type); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - DBG_WARNING("Lookup domain name '%s' failed '%s'\n", - dom_maps[state->dom_idx].name, - nt_errstr(status)); - - state->dom_idx++; - wb_xids2sids_init_dom_maps_lookupname_next(state); - return; - } - - if (type != SID_NAME_DOMAIN) { - struct dom_sid_buf buf; - - DBG_WARNING("SID %s for idmap domain name '%s' " - "not a domain SID\n", - dom_sid_str_buf(&dom_maps[state->dom_idx].sid, - &buf), - dom_maps[state->dom_idx].name); - - ZERO_STRUCT(dom_maps[state->dom_idx].sid); - } - - state->dom_idx++; - wb_xids2sids_init_dom_maps_lookupname_next(state); - - return; -} - -static NTSTATUS wb_xids2sids_init_dom_maps_recv(struct tevent_req *req) -{ - return tevent_req_simple_recv_ntstatus(req); -} - struct wb_xids2sids_dom_state { struct tevent_context *ev; struct unixid *all_xids; const bool *cached; size_t num_all_xids; struct dom_sid *all_sids; - struct wb_xids2sids_dom_map *dom_map; + const struct wb_parent_idmap_config_dom *dom_map; bool tried_dclookup; size_t num_dom_xids; @@ -262,7 +44,7 @@ static void wb_xids2sids_dom_gotdc(struct tevent_req *subreq); static struct tevent_req *wb_xids2sids_dom_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct wb_xids2sids_dom_map *dom_map, + const struct wb_parent_idmap_config_dom *dom_map, struct unixid *xids, const bool *cached, size_t num_xids, @@ -334,7 +116,7 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq) subreq, struct tevent_req); struct wb_xids2sids_dom_state *state = tevent_req_data( req, struct wb_xids2sids_dom_state); - struct wb_xids2sids_dom_map *dom_map = state->dom_map; + const struct wb_parent_idmap_config_dom *dom_map = state->dom_map; NTSTATUS status, result; size_t i; size_t dom_sid_idx; @@ -437,10 +219,11 @@ struct wb_xids2sids_state { bool *cached; size_t dom_idx; + const struct wb_parent_idmap_config *cfg; }; +static void wb_xids2sids_idmap_setup_done(struct tevent_req *subreq); static void wb_xids2sids_done(struct tevent_req *subreq); -static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq); struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -495,38 +278,32 @@ struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx, } } - subreq = wb_xids2sids_init_dom_maps_send( - state, state->ev); + subreq = wb_parent_idmap_setup_send(state, state->ev); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, wb_xids2sids_init_dom_maps_done, req); + tevent_req_set_callback(subreq, wb_xids2sids_idmap_setup_done, req); return req; } -static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq) +static void wb_xids2sids_idmap_setup_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); struct wb_xids2sids_state *state = tevent_req_data( req, struct wb_xids2sids_state); - size_t num_domains; NTSTATUS status; - status = wb_xids2sids_init_dom_maps_recv(subreq); + status = wb_parent_idmap_setup_recv(subreq, &state->cfg); TALLOC_FREE(subreq); if (tevent_req_nterror(req, status)) { return; } - - num_domains = talloc_array_length(dom_maps); - if (num_domains == 0) { - tevent_req_done(req); - return; - } + SMB_ASSERT(state->cfg->num_doms > 0); subreq = wb_xids2sids_dom_send( - state, state->ev, &dom_maps[state->dom_idx], + state, state->ev, + &state->cfg->doms[state->dom_idx], state->xids, state->cached, state->num_xids, state->sids); if (tevent_req_nomem(subreq, req)) { return; @@ -541,7 +318,6 @@ static void wb_xids2sids_done(struct tevent_req *subreq) subreq, struct tevent_req); struct wb_xids2sids_state *state = tevent_req_data( req, struct wb_xids2sids_state); - size_t num_domains = talloc_array_length(dom_maps); size_t i; NTSTATUS status; @@ -553,10 +329,13 @@ static void wb_xids2sids_done(struct tevent_req *subreq) state->dom_idx += 1; - if (state->dom_idx < num_domains) { + if (state->dom_idx < state->cfg->num_doms) { + const struct wb_parent_idmap_config_dom *dom_map = + &state->cfg->doms[state->dom_idx]; + subreq = wb_xids2sids_dom_send(state, state->ev, - &dom_maps[state->dom_idx], + dom_map, state->xids, state->cached, state->num_xids, -- 2.25.1 From e249265d26d6263d2183092535c3a9af58e01dfb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 12:52:40 +0200 Subject: [PATCH 416/645] CVE-2020-25717 wb_sids2xids: call wb_parent_idmap_setup_send/recv as the first step This isn't really used yet, but it will in the next commits. Also idmap_child_handle() will soon assert that wb_parent_idmap_setup_send/recv() was called before it's used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit d42aaeba6e0820acd17f204ff7ab6d1aede1b303) --- source3/winbindd/wb_sids2xids.c | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index b47856520ea..59f6ba5891e 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -29,6 +29,8 @@ struct wb_sids2xids_state { struct tevent_context *ev; + const struct wb_parent_idmap_config *cfg; + struct dom_sid *sids; uint32_t num_sids; @@ -58,7 +60,7 @@ struct wb_sids2xids_state { struct wbint_TransIDArray ids; }; - +static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq); static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map); static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq); static void wb_sids2xids_done(struct tevent_req *subreq); @@ -126,15 +128,39 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - subreq = wb_lookupsids_send(state, ev, state->non_cached, - state->num_non_cached); + subreq = wb_parent_idmap_setup_send(state, state->ev); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req); + tevent_req_set_callback(subreq, wb_sids2xids_idmap_setup_done, req); return req; } +static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_sids2xids_state *state = tevent_req_data( + req, struct wb_sids2xids_state); + NTSTATUS status; + + status = wb_parent_idmap_setup_recv(subreq, &state->cfg); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + SMB_ASSERT(state->cfg->num_doms > 0); + + subreq = wb_lookupsids_send(state, + state->ev, + state->non_cached, + state->num_non_cached); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req); +} + static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map) { struct unixid id; -- 2.25.1 From de3aaebb2fb226e807b4b36bed9dca214dfa84aa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 13:52:17 +0200 Subject: [PATCH 417/645] CVE-2020-25717 wb_queryuser: explain why wb_parent_idmap_setup_send/recv is not needed BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 82fd07793f065e150729848566e7c30f4f4d472e) --- source3/winbindd/wb_queryuser.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 2e36643454b..9db51909c02 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -138,6 +138,11 @@ static void wb_queryuser_got_uid(struct tevent_req *subreq) return; } + /* + * Note wb_sids2xids_send/recv was called before, + * so we're sure that wb_parent_idmap_setup_send/recv + * was already called. + */ child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( state, state->ev, child_binding_handle, info); @@ -185,6 +190,11 @@ static void wb_queryuser_got_domain(struct tevent_req *subreq) return; } + /* + * Note wb_sids2xids_send/recv was called before, + * so we're sure that wb_parent_idmap_setup_send/recv + * was already called. + */ child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( state, state->ev, child_binding_handle, info); @@ -284,6 +294,11 @@ static void wb_queryuser_got_dc(struct tevent_req *subreq) return; } + /* + * Note wb_sids2xids_send/recv was called before, + * so we're sure that wb_parent_idmap_setup_send/recv + * was already called. + */ child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_GetNssInfo_send( state, state->ev, child_binding_handle, info); -- 2.25.1 From 1715742d00729555382c1b103f0af78583eb57a6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 14:12:17 +0200 Subject: [PATCH 418/645] CVE-2020-25717 winbindd: assert wb_parent_idmap_setup_send/recv() was called before idmap_child_handle() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit b8c74b7b46d1c7f6b66e565ee08f8c88d6dc2cc4) --- source3/winbindd/winbindd_idmap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 487f27fd94d..14836e3b8a0 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -59,6 +59,11 @@ pid_t idmap_child_pid(void) struct dcerpc_binding_handle *idmap_child_handle(void) { + /* + * The caller needs to use wb_parent_idmap_setup_send/recv + * before talking to the idmap child! + */ + SMB_ASSERT(static_parent_idmap_config.num_doms > 0); return static_idmap_child.binding_handle; } -- 2.25.1 From 3be26e56411b8a02be89486b757f025a56c8166f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 15:42:42 +0200 Subject: [PATCH 419/645] CVE-2020-25717 winbindd: defer the setup_child() from init_idmap_child() At startup we trigger a wb_parent_idmap_setup_send() and make sure setup_child() is called just before wb_parent_idmap_setup_recv() finished. This makes sure our view of the idmap config in the parent matches what we have in the child. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 28e020c0a863411cfa95e3b1ed943d922b8635bd) --- source3/winbindd/winbindd_idmap.c | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c index 14836e3b8a0..3e2461478a9 100644 --- a/source3/winbindd/winbindd_idmap.c +++ b/source3/winbindd/winbindd_idmap.c @@ -81,11 +81,44 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { } }; +static void init_idmap_child_done(struct tevent_req *subreq); + void init_idmap_child(void) { - setup_child(NULL, &static_idmap_child, - idmap_dispatch_table, - "log.winbindd", "idmap"); + struct tevent_req *subreq = NULL; + + subreq = wb_parent_idmap_setup_send(global_event_context(), + global_event_context()); + if (subreq == NULL) { + /* + * This is only an optimization, so we're free to + * to ignore errors + */ + DBG_ERR("wb_parent_idmap_setup_send() failed\n"); + return; + } + tevent_req_set_callback(subreq, init_idmap_child_done, NULL); + DBG_DEBUG("wb_parent_idmap_setup_send() started\n"); +} + +static void init_idmap_child_done(struct tevent_req *subreq) +{ + const struct wb_parent_idmap_config *cfg = NULL; + NTSTATUS status; + + status = wb_parent_idmap_setup_recv(subreq, &cfg); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + /* + * This is only an optimization, so we're free to + * to ignore errors + */ + DBG_ERR("wb_parent_idmap_setup_recv() failed %s\n", + nt_errstr(status)); + return; + } + + DBG_DEBUG("wb_parent_idmap_setup_recv() finished\n"); } struct wb_parent_idmap_setup_state { @@ -306,6 +339,12 @@ static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req) next_domain: if (state->dom_idx == state->cfg->num_doms) { + /* + * We're done, so start the idmap child + */ + setup_child(NULL, &static_idmap_child, + idmap_dispatch_table, + "log.winbindd", "idmap"); tevent_req_done(req); return; } -- 2.25.1 From 1715b92a2c258bf7ca147b102c649e3e5794fd53 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 3 Jul 2020 16:39:26 +0200 Subject: [PATCH 420/645] CVE-2020-25717 wb_sids2xids: split out wb_sids2xids_next_sids2unix() Put the code that calls the per-domain idmap backend in its own function. This makes further reconstruction easier. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Ralph Boehme Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 79c1d3aaf6d465a8edd1871edb85211f8715fea1) --- source3/winbindd/wb_sids2xids.c | 34 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 59f6ba5891e..725fd857ef5 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -65,6 +65,7 @@ static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map); static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq); static void wb_sids2xids_done(struct tevent_req *subreq); static void wb_sids2xids_gotdc(struct tevent_req *subreq); +static void wb_sids2xids_next_sids2unix(struct tevent_req *req); struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -194,7 +195,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) req, struct wb_sids2xids_state); struct lsa_RefDomainList *domains = NULL; struct lsa_TransNameArray *names = NULL; - struct dcerpc_binding_handle *child_binding_handle = NULL; NTSTATUS status; uint32_t i; @@ -264,6 +264,16 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) TALLOC_FREE(names); TALLOC_FREE(domains); + wb_sids2xids_next_sids2unix(req); +} + +static void wb_sids2xids_next_sids2unix(struct tevent_req *req) +{ + struct wb_sids2xids_state *state = tevent_req_data( + req, struct wb_sids2xids_state); + struct tevent_req *subreq = NULL; + struct dcerpc_binding_handle *child_binding_handle = NULL; + state->dom_ids = wb_sids2xids_extract_for_domain_index( state, &state->ids, state->dom_index); if (tevent_req_nomem(state->dom_ids, req)) { @@ -315,7 +325,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status, result; - struct dcerpc_binding_handle *child_binding_handle = NULL; struct wbint_TransIDArray *src, *dst; uint32_t i, src_idx; @@ -376,26 +385,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) return; } - state->dom_ids = wb_sids2xids_extract_for_domain_index( - state, &state->ids, state->dom_index); - if (tevent_req_nomem(state->dom_ids, req)) { - return; - } - - state->idmap_dom = (struct lsa_RefDomainList) { - .count = 1, - .domains = &state->idmap_doms.domains[state->dom_index], - .max_size = 1 - }; - - child_binding_handle = idmap_child_handle(); - subreq = dcerpc_wbint_Sids2UnixIDs_send( - state, state->ev, child_binding_handle, &state->idmap_dom, - state->dom_ids); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_sids2xids_done, req); + wb_sids2xids_next_sids2unix(req); } static void wb_sids2xids_gotdc(struct tevent_req *subreq) -- 2.25.1 From e15b1c9f6fbaeda7ceea1fb61294f7f3f8f43baa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Sep 2020 16:45:03 +0200 Subject: [PATCH 421/645] CVE-2020-25717 wb_sids2xids: maintain struct wbint_TransIDArray all_ids as cache Entries with domain_index == UINT32_MAX are valid cache entries. In the following commits we'll fill in missing entries step by step until all entries are marked as filled. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 04956350a5725325954b2caba662ecd6dace7829) --- source3/winbindd/wb_sids2xids.c | 49 ++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 725fd857ef5..770a7f0d8b0 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -34,7 +34,7 @@ struct wb_sids2xids_state { struct dom_sid *sids; uint32_t num_sids; - struct id_map *cached; + struct wbint_TransIDArray all_ids; struct dom_sid *non_cached; uint32_t num_non_cached; @@ -75,6 +75,7 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, struct tevent_req *req, *subreq; struct wb_sids2xids_state *state; uint32_t i; + uint32_t num_valid = 0; req = tevent_req_create(mem_ctx, &state, struct wb_sids2xids_state); @@ -95,8 +96,9 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, sid_copy(&state->sids[i], &sids[i]); } - state->cached = talloc_zero_array(state, struct id_map, num_sids); - if (tevent_req_nomem(state->cached, req)) { + state->all_ids.num_ids = num_sids; + state->all_ids.ids = talloc_zero_array(state, struct wbint_TransID, num_sids); + if (tevent_req_nomem(state->all_ids.ids, req)) { return tevent_req_post(req, ev); } @@ -111,20 +113,53 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, * the same index. */ for (i=0; inum_sids; i++) { + struct wbint_TransID *cur_id = &state->all_ids.ids[i]; + struct dom_sid domain_sid; struct dom_sid_buf buf; + struct id_map map = { .status = ID_UNMAPPED, }; + uint32_t rid = 0; + bool in_cache; + + sid_copy(&domain_sid, &state->sids[i]); + sid_split_rid(&domain_sid, &rid); + + /* + * Start with an invalid entry. + */ + *cur_id = (struct wbint_TransID) { + .type_hint = ID_TYPE_NOT_SPECIFIED, + .domain_index = UINT32_MAX - 1, /* invalid */ + .rid = rid, + .xid = { + .id = UINT32_MAX, + .type = ID_TYPE_NOT_SPECIFIED, + }, + }; DEBUG(10, ("SID %d: %s\n", (int)i, dom_sid_str_buf(&state->sids[i], &buf))); - if (wb_sids2xids_in_cache(&state->sids[i], &state->cached[i])) { + in_cache = wb_sids2xids_in_cache(&state->sids[i], &map); + if (in_cache) { + /* + * We used to ignore map.status and just rely + * on map.xid.type. + * + * Lets keep this logic for now... + */ + + cur_id->xid = map.xid; + cur_id->domain_index = UINT32_MAX; /* this marks it as filled entry */ + num_valid += 1; continue; } + sid_copy(&state->non_cached[state->num_non_cached], &state->sids[i]); state->num_non_cached += 1; } - if (state->num_non_cached == 0) { + if (num_valid == num_sids) { tevent_req_done(req); return tevent_req_post(req, ev); } @@ -453,8 +488,8 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, xid.id = UINT32_MAX; - if (state->cached[i].sid != NULL) { - xid = state->cached[i].xid; + if (state->all_ids.ids[i].domain_index == UINT32_MAX) { + xid = state->all_ids.ids[i].xid; } else { xid = state->ids.ids[num_non_cached].xid; -- 2.25.1 From 55b7819a2f4705450bbe5c223d9098b460c8159b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Sep 2020 17:45:24 +0200 Subject: [PATCH 422/645] CVE-2020-25717 wb_sids2xids: rename 'non_cached' to 'lookup_sids' This array is used to pass to wb_lookupsids_send() and that will be the only reason to have this in future. For now it's used for all non cached sids, but that will also change in the next commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 797b11f198e819300007997ce536bc6d05f19843) --- source3/winbindd/wb_sids2xids.c | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 770a7f0d8b0..2a30eee2c7b 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -36,8 +36,8 @@ struct wb_sids2xids_state { struct wbint_TransIDArray all_ids; - struct dom_sid *non_cached; - uint32_t num_non_cached; + uint32_t lookup_count; + struct dom_sid *lookup_sids; /* * Domain array to use for the idmap call. The output from @@ -102,8 +102,8 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - state->non_cached = talloc_array(state, struct dom_sid, num_sids); - if (tevent_req_nomem(state->non_cached, req)) { + state->lookup_sids = talloc_zero_array(state, struct dom_sid, num_sids); + if (tevent_req_nomem(state->lookup_sids, req)) { return tevent_req_post(req, ev); } @@ -154,9 +154,9 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, continue; } - sid_copy(&state->non_cached[state->num_non_cached], + sid_copy(&state->lookup_sids[state->lookup_count], &state->sids[i]); - state->num_non_cached += 1; + state->lookup_count += 1; } if (num_valid == num_sids) { @@ -189,8 +189,8 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) subreq = wb_lookupsids_send(state, state->ev, - state->non_cached, - state->num_non_cached); + state->lookup_sids, + state->lookup_count); if (tevent_req_nomem(subreq, req)) { return; } @@ -239,15 +239,15 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) return; } - state->ids.num_ids = state->num_non_cached; + state->ids.num_ids = state->lookup_count; state->ids.ids = talloc_array(state, struct wbint_TransID, - state->num_non_cached); + state->ids.num_ids); if (tevent_req_nomem(state->ids.ids, req)) { return; } - for (i=0; inum_non_cached; i++) { - const struct dom_sid *sid = &state->non_cached[i]; + for (i=0; ilookup_count; i++) { + const struct dom_sid *sid = &state->lookup_sids[i]; struct dom_sid dom_sid; struct lsa_TranslatedName *n = &names->names[i]; struct wbint_TransID *t = &state->ids.ids[i]; @@ -468,7 +468,7 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status; - uint32_t i, num_non_cached; + uint32_t i, lookup_count = 0; if (tevent_req_is_nterror(req, &status)) { DEBUG(5, ("wb_sids_to_xids failed: %s\n", nt_errstr(status))); @@ -481,8 +481,6 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, return NT_STATUS_INTERNAL_ERROR; } - num_non_cached = 0; - for (i=0; inum_sids; i++) { struct unixid xid; @@ -491,13 +489,13 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, if (state->all_ids.ids[i].domain_index == UINT32_MAX) { xid = state->all_ids.ids[i].xid; } else { - xid = state->ids.ids[num_non_cached].xid; + xid = state->ids.ids[lookup_count].xid; idmap_cache_set_sid2unixid( - &state->non_cached[num_non_cached], + &state->lookup_sids[lookup_count], &xid); - num_non_cached += 1; + lookup_count += 1; } xids[i] = xid; -- 2.25.1 From 42332155869435af8cf990f3e79f2159a5d69c24 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 13:19:14 +0200 Subject: [PATCH 423/645] CVE-2020-25717 wb_sids2xids: move more checks to wb_sids2xids_next_sids2unix() For the first run this is a no-op, but it simplified the caller. We'll call wb_sids2xids_next_sids2unix() in a few more places in future and it's easier to have this all within wb_sids2xids_next_sids2unix(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 231c8d04b19a1c17937f988d142ca5c0f889d4e0) --- source3/winbindd/wb_sids2xids.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 2a30eee2c7b..b934425f4fd 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -309,6 +309,13 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) struct tevent_req *subreq = NULL; struct dcerpc_binding_handle *child_binding_handle = NULL; + state->tried_dclookup = false; + + if (state->dom_index == state->idmap_doms.count) { + tevent_req_done(req); + return; + } + state->dom_ids = wb_sids2xids_extract_for_domain_index( state, &state->ids, state->dom_index); if (tevent_req_nomem(state->dom_ids, req)) { @@ -413,12 +420,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) TALLOC_FREE(state->dom_ids); state->dom_index += 1; - state->tried_dclookup = false; - - if (state->dom_index == state->idmap_doms.count) { - tevent_req_done(req); - return; - } wb_sids2xids_next_sids2unix(req); } -- 2.25.1 From 757084903560c1aec3217ffebffcb671d27563c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 13:36:43 +0200 Subject: [PATCH 424/645] CVE-2020-25717 wb_sids2xids: inline wb_sids2xids_extract_for_domain_index() into wb_sids2xids_next_sids2unix() Instead of re-creating the dom_ids element, we just use a pre-allocated map_ids_in array. This is a bit tricky as we need to use map_ids_out as a copy of map_ids_in, because the _ids argument of dcerpc_wbint_Sids2UnixIDs_send() in [in,out], which means that _ids->ids is changed between dcerpc_wbint_Sids2UnixIDs_send() and dcerpc_wbint_Sids2UnixIDs_recv()! If the domain doesn't need any mappings, we'll move to the next domain early, for now this can't happend but it will in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit f6bb0ed21f82f2cf1f238f9f00cd049ecf8673af) --- source3/winbindd/wb_sids2xids.c | 115 +++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index b934425f4fd..aefb9f93ccb 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -39,6 +39,9 @@ struct wb_sids2xids_state { uint32_t lookup_count; struct dom_sid *lookup_sids; + struct wbint_TransIDArray map_ids_in; + struct wbint_TransIDArray map_ids_out; + /* * Domain array to use for the idmap call. The output from * lookupsids cannot be used directly since for migrated @@ -53,7 +56,6 @@ struct wb_sids2xids_state { struct lsa_RefDomainList idmap_doms; uint32_t dom_index; - struct wbint_TransIDArray *dom_ids; struct lsa_RefDomainList idmap_dom; bool tried_dclookup; @@ -107,6 +109,11 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + state->map_ids_in.ids = talloc_zero_array(state, struct wbint_TransID, num_sids); + if (tevent_req_nomem(state->map_ids_in.ids, req)) { + return tevent_req_post(req, ev); + } + /* * Extract those sids that can not be resolved from cache * into a separate list to be handed to id mapping, keeping @@ -218,9 +225,6 @@ static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map) } static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type); -static struct wbint_TransIDArray *wb_sids2xids_extract_for_domain_index( - TALLOC_CTX *mem_ctx, const struct wbint_TransIDArray *src, - uint32_t domain_index); static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) { @@ -308,7 +312,11 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) req, struct wb_sids2xids_state); struct tevent_req *subreq = NULL; struct dcerpc_binding_handle *child_binding_handle = NULL; + const struct wbint_TransIDArray *src = NULL; + struct wbint_TransIDArray *dst = NULL; + uint32_t si; + next_domain: state->tried_dclookup = false; if (state->dom_index == state->idmap_doms.count) { @@ -316,10 +324,23 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) return; } - state->dom_ids = wb_sids2xids_extract_for_domain_index( - state, &state->ids, state->dom_index); - if (tevent_req_nomem(state->dom_ids, req)) { - return; + src = &state->ids; + dst = &state->map_ids_in; + dst->num_ids = 0; + + for (si=0; si < src->num_ids; si++) { + if (src->ids[si].domain_index != state->dom_index) { + continue; + } + + dst->ids[dst->num_ids] = src->ids[si]; + dst->ids[dst->num_ids].domain_index = 0; + dst->num_ids += 1; + } + + if (dst->num_ids == 0) { + state->dom_index += 1; + goto next_domain; } state->idmap_dom = (struct lsa_RefDomainList) { @@ -328,10 +349,23 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) .max_size = 1 }; + /* + * dcerpc_wbint_Sids2UnixIDs_send/recv will + * allocate a new array for the response + * and overwrite _ids->ids pointer. + * + * So we better make a temporary copy + * of state->map_ids_in (which contains the request array) + * into state->map_ids_out. + * + * That makes it possible to reuse the pre-allocated + * state->map_ids_in.ids array. + */ + state->map_ids_out = state->map_ids_in; child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_Sids2UnixIDs_send( state, state->ev, child_binding_handle, &state->idmap_dom, - state->dom_ids); + &state->map_ids_out); if (tevent_req_nomem(subreq, req)) { return; } @@ -394,7 +428,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) return; } - src = state->dom_ids; + src = &state->map_ids_out; src_idx = 0; dst = &state->ids; @@ -405,11 +439,17 @@ static void wb_sids2xids_done(struct tevent_req *subreq) /* * All we can do here is to report "not mapped" */ + src = &state->map_ids_in; for (i=0; inum_ids; i++) { src->ids[i].xid.type = ID_TYPE_NOT_SPECIFIED; } } + if (src->num_ids != state->map_ids_in.num_ids) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + for (i=0; inum_ids; i++) { if (dst->ids[i].domain_index == state->dom_index) { dst->ids[i].xid = src->ids[src_idx].xid; @@ -417,7 +457,17 @@ static void wb_sids2xids_done(struct tevent_req *subreq) } } - TALLOC_FREE(state->dom_ids); + state->map_ids_in.num_ids = 0; + if (NT_STATUS_IS_OK(status)) { + /* + * If we got a valid response, we expect + * state->map_ids_out.ids to be a new allocated + * array, which we want to free early. + */ + SMB_ASSERT(state->map_ids_out.ids != state->map_ids_in.ids); + TALLOC_FREE(state->map_ids_out.ids); + } + state->map_ids_out = (struct wbint_TransIDArray) { .num_ids = 0, }; state->dom_index += 1; @@ -453,10 +503,23 @@ static void wb_sids2xids_gotdc(struct tevent_req *subreq) } } + /* + * dcerpc_wbint_Sids2UnixIDs_send/recv will + * allocate a new array for the response + * and overwrite _ids->ids pointer. + * + * So we better make a temporary copy + * of state->map_ids_in (which contains the request array) + * into state->map_ids_out. + * + * That makes it possible to reuse the pre-allocated + * state->map_ids_in.ids array. + */ + state->map_ids_out = state->map_ids_in; child_binding_handle = idmap_child_handle(); subreq = dcerpc_wbint_Sids2UnixIDs_send( state, state->ev, child_binding_handle, &state->idmap_dom, - state->dom_ids); + &state->map_ids_out); if (tevent_req_nomem(subreq, req)) { return; } @@ -504,31 +567,3 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, return NT_STATUS_OK; } - -static struct wbint_TransIDArray *wb_sids2xids_extract_for_domain_index( - TALLOC_CTX *mem_ctx, const struct wbint_TransIDArray *src, - uint32_t domain_index) -{ - struct wbint_TransIDArray *ret; - uint32_t i; - - ret = talloc_zero(mem_ctx, struct wbint_TransIDArray); - if (ret == NULL) { - return NULL; - } - ret->ids = talloc_array(ret, struct wbint_TransID, src->num_ids); - if (ret->ids == NULL) { - TALLOC_FREE(ret); - return NULL; - } - - for (i=0; inum_ids; i++) { - if (src->ids[i].domain_index == domain_index) { - ret->ids[ret->num_ids] = src->ids[i]; - ret->ids[ret->num_ids].domain_index = 0; - ret->num_ids += 1; - } - } - - return ret; -} -- 2.25.1 From 121816e0615141e694ec96c11a0641a84f42e898 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 13:54:24 +0200 Subject: [PATCH 425/645] CVE-2020-25717 wb_sids2xids: refactor wb_sids2xids_done() a bit Here we don't change the logic. It will make the following changes easier. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit cda61f592a0b33d36da8da9b6837312396cceec4) --- source3/winbindd/wb_sids2xids.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index aefb9f93ccb..d6655402b57 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -401,8 +401,10 @@ static void wb_sids2xids_done(struct tevent_req *subreq) struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status, result; - struct wbint_TransIDArray *src, *dst; - uint32_t i, src_idx; + const struct wbint_TransIDArray *src = NULL; + struct wbint_TransIDArray *dst = NULL; + uint32_t si; + uint32_t di; status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result); TALLOC_FREE(subreq); @@ -429,7 +431,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) } src = &state->map_ids_out; - src_idx = 0; dst = &state->ids; if (any_nt_status_not_ok(status, result, &status)) { @@ -440,8 +441,8 @@ static void wb_sids2xids_done(struct tevent_req *subreq) * All we can do here is to report "not mapped" */ src = &state->map_ids_in; - for (i=0; inum_ids; i++) { - src->ids[i].xid.type = ID_TYPE_NOT_SPECIFIED; + for (si=0; si < src->num_ids; si++) { + src->ids[si].xid.type = ID_TYPE_NOT_SPECIFIED; } } @@ -450,11 +451,19 @@ static void wb_sids2xids_done(struct tevent_req *subreq) return; } - for (i=0; inum_ids; i++) { - if (dst->ids[i].domain_index == state->dom_index) { - dst->ids[i].xid = src->ids[src_idx].xid; - src_idx += 1; + si = 0; + for (di=0; di < dst->num_ids; di++) { + if (dst->ids[di].domain_index != state->dom_index) { + continue; + } + + if (si >= src->num_ids) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; } + + dst->ids[di].xid = src->ids[si].xid; + si += 1; } state->map_ids_in.num_ids = 0; -- 2.25.1 From 334630eab163ef3c96c67ee0c51f649821f619ca Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 13:58:26 +0200 Subject: [PATCH 426/645] CVE-2020-25717 wb_sids2xids: change 'i' to 'li' in wb_sids2xids_lookupsids_done() With all the indexes we have into various array, this makes clear 'li' is the index into the state->lookup_sids array. This makes the following changes easier to review. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 19c8b6a8b188e45a6342a3d1308085800388a38e) --- source3/winbindd/wb_sids2xids.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index d6655402b57..f01e36e6e55 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -235,7 +235,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) struct lsa_RefDomainList *domains = NULL; struct lsa_TransNameArray *names = NULL; NTSTATUS status; - uint32_t i; + uint32_t li; status = wb_lookupsids_recv(subreq, state, &domains, &names); TALLOC_FREE(subreq); @@ -250,11 +250,11 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) return; } - for (i=0; ilookup_count; i++) { - const struct dom_sid *sid = &state->lookup_sids[i]; + for (li = 0; li < state->lookup_count; li++) { + const struct dom_sid *sid = &state->lookup_sids[li]; struct dom_sid dom_sid; - struct lsa_TranslatedName *n = &names->names[i]; - struct wbint_TransID *t = &state->ids.ids[i]; + struct lsa_TranslatedName *n = &names->names[li]; + struct wbint_TransID *t = &state->ids.ids[li]; int domain_index; const char *domain_name = NULL; -- 2.25.1 From 0259d52c28c0633e144eb8e4f3196c3cad35e700 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 14:17:37 +0200 Subject: [PATCH 427/645] CVE-2020-25717 wb_sids2xids: directly use state->all_ids to collect results In order to translate the indexes from state->lookup_sids[] for wb_lookupsids_send/recv() and state->map_ids.ids[] for dcerpc_wbint_Sids2UnixIDs_send/recv() back to state->all_ids.ids[] or state->sids[] we have state->tmp_idx[]. This simplifies wb_sids2xids_recv() a lot and make further restructuring much easier. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 374acc2e5fcc3c4b40f41906d0349499e3304841) --- source3/winbindd/wb_sids2xids.c | 66 +++++++++++---------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index f01e36e6e55..cdbc70a0b49 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -36,6 +36,9 @@ struct wb_sids2xids_state { struct wbint_TransIDArray all_ids; + /* Used to translated the idx back into all_ids.ids[idx] */ + uint32_t *tmp_idx; + uint32_t lookup_count; struct dom_sid *lookup_sids; @@ -58,8 +61,6 @@ struct wb_sids2xids_state { uint32_t dom_index; struct lsa_RefDomainList idmap_dom; bool tried_dclookup; - - struct wbint_TransIDArray ids; }; static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq); @@ -104,6 +105,11 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + state->tmp_idx = talloc_zero_array(state, uint32_t, num_sids); + if (tevent_req_nomem(state->tmp_idx, req)) { + return tevent_req_post(req, ev); + } + state->lookup_sids = talloc_zero_array(state, struct dom_sid, num_sids); if (tevent_req_nomem(state->lookup_sids, req)) { return tevent_req_post(req, ev); @@ -161,6 +167,7 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, continue; } + state->tmp_idx[state->lookup_count] = i; sid_copy(&state->lookup_sids[state->lookup_count], &state->sids[i]); state->lookup_count += 1; @@ -243,18 +250,12 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) return; } - state->ids.num_ids = state->lookup_count; - state->ids.ids = talloc_array(state, struct wbint_TransID, - state->ids.num_ids); - if (tevent_req_nomem(state->ids.ids, req)) { - return; - } - for (li = 0; li < state->lookup_count; li++) { const struct dom_sid *sid = &state->lookup_sids[li]; struct dom_sid dom_sid; struct lsa_TranslatedName *n = &names->names[li]; - struct wbint_TransID *t = &state->ids.ids[li]; + uint32_t ai = state->tmp_idx[li]; + struct wbint_TransID *t = &state->all_ids.ids[ai]; int domain_index; const char *domain_name = NULL; @@ -295,9 +296,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) return; } t->domain_index = domain_index; - - t->xid.id = UINT32_MAX; - t->xid.type = ID_TYPE_NOT_SPECIFIED; } TALLOC_FREE(names); @@ -324,7 +322,7 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) return; } - src = &state->ids; + src = &state->all_ids; dst = &state->map_ids_in; dst->num_ids = 0; @@ -333,6 +331,7 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) continue; } + state->tmp_idx[dst->num_ids] = si; dst->ids[dst->num_ids] = src->ids[si]; dst->ids[dst->num_ids].domain_index = 0; dst->num_ids += 1; @@ -404,7 +403,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq) const struct wbint_TransIDArray *src = NULL; struct wbint_TransIDArray *dst = NULL; uint32_t si; - uint32_t di; status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result); TALLOC_FREE(subreq); @@ -431,7 +429,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) } src = &state->map_ids_out; - dst = &state->ids; + dst = &state->all_ids; if (any_nt_status_not_ok(status, result, &status)) { DBG_DEBUG("status=%s, result=%s\n", nt_errstr(status), @@ -451,19 +449,12 @@ static void wb_sids2xids_done(struct tevent_req *subreq) return; } - si = 0; - for (di=0; di < dst->num_ids; di++) { - if (dst->ids[di].domain_index != state->dom_index) { - continue; - } + for (si=0; si < src->num_ids; si++) { + uint32_t di = state->tmp_idx[si]; - if (si >= src->num_ids) { - tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); - return; + if (src->ids[si].xid.type != ID_TYPE_NOT_SPECIFIED) { + dst->ids[di].xid = src->ids[si].xid; } - - dst->ids[di].xid = src->ids[si].xid; - si += 1; } state->map_ids_in.num_ids = 0; @@ -541,7 +532,7 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status; - uint32_t i, lookup_count = 0; + uint32_t i; if (tevent_req_is_nterror(req, &status)) { DEBUG(5, ("wb_sids_to_xids failed: %s\n", nt_errstr(status))); @@ -555,23 +546,10 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, } for (i=0; inum_sids; i++) { - struct unixid xid; - - xid.id = UINT32_MAX; - - if (state->all_ids.ids[i].domain_index == UINT32_MAX) { - xid = state->all_ids.ids[i].xid; - } else { - xid = state->ids.ids[lookup_count].xid; - - idmap_cache_set_sid2unixid( - &state->lookup_sids[lookup_count], - &xid); - - lookup_count += 1; + xids[i] = state->all_ids.ids[i].xid; + if (state->all_ids.ids[i].domain_index != UINT32_MAX) { + idmap_cache_set_sid2unixid(&state->sids[i], &xids[i]); } - - xids[i] = xid; } return NT_STATUS_OK; -- 2.25.1 From 25823f52188516ec63b220ac03012bb7f8979263 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Sep 2020 23:06:02 +0200 Subject: [PATCH 428/645] CVE-2020-25717 wb_sids2xids: fill cache as soon as possible After adding entries to the cache we can mark them as filled from the cache by setting its domain_index to UINT32_MAX. This will allow further changes to fill the results into state->all_ids in steps. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 3f4626ea6d235470195918b77af35ac2cfeb227c) --- source3/winbindd/wb_sids2xids.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index cdbc70a0b49..21bf5f901f3 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -455,6 +455,8 @@ static void wb_sids2xids_done(struct tevent_req *subreq) if (src->ids[si].xid.type != ID_TYPE_NOT_SPECIFIED) { dst->ids[di].xid = src->ids[si].xid; } + dst->ids[di].domain_index = UINT32_MAX; /* mark as valid */ + idmap_cache_set_sid2unixid(&state->sids[di], &dst->ids[di].xid); } state->map_ids_in.num_ids = 0; @@ -547,9 +549,6 @@ NTSTATUS wb_sids2xids_recv(struct tevent_req *req, for (i=0; inum_sids; i++) { xids[i] = state->all_ids.ids[i].xid; - if (state->all_ids.ids[i].domain_index != UINT32_MAX) { - idmap_cache_set_sid2unixid(&state->sids[i], &xids[i]); - } } return NT_STATUS_OK; -- 2.25.1 From 3fcb4a03a510fb564f9ec5d2983d5ac134c0165f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 10 Sep 2020 17:13:14 +0200 Subject: [PATCH 429/645] CVE-2020-25717 wb_sids2xids: build state->idmap_doms based on wb_parent_idmap_config In future we'll try to avoid wb_lookupsids_send() and only call it if needed. The domain name passed should be only relevant to find the correct idmap backend, and these should all be available in wb_parent_idmap_config as it was created before the idmap child was forked. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit c55f4f37589130a0d8952489da175bbcf53f6748) --- source3/winbindd/wb_sids2xids.c | 101 +++++++++++++++++++------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 21bf5f901f3..3a3d47abbe5 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -193,6 +193,7 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) struct wb_sids2xids_state *state = tevent_req_data( req, struct wb_sids2xids_state); NTSTATUS status; + uint32_t i; status = wb_parent_idmap_setup_recv(subreq, &state->cfg); TALLOC_FREE(subreq); @@ -201,6 +202,66 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) } SMB_ASSERT(state->cfg->num_doms > 0); + /* + * Now we build a list with all domain + * with non cached entries + */ + for (i=0; inum_sids; i++) { + struct wbint_TransID *t = &state->all_ids.ids[i]; + struct dom_sid domain_sid; + const char *domain_name = NULL; + int domain_index; + uint32_t rid = 0; + uint32_t di; + + if (t->domain_index == UINT32_MAX) { + /* ignore already filled entries */ + continue; + } + + sid_copy(&domain_sid, &state->sids[i]); + sid_split_rid(&domain_sid, &rid); + + for (di = 0; di < state->cfg->num_doms; di++) { + struct wb_parent_idmap_config_dom *dom = + &state->cfg->doms[di]; + bool match; + + match = dom_sid_equal(&domain_sid, + &dom->sid); + if (!match) { + continue; + } + + domain_name = dom->name; + break; + } + if (domain_name == NULL) { + struct winbindd_domain *wb_domain = NULL; + + /* + * Try to fill the name if we already know it + */ + wb_domain = find_domain_from_sid_noinit(&state->sids[i]); + if (wb_domain != NULL) { + domain_name = wb_domain->name; + } + } + if (domain_name == NULL) { + domain_name = ""; + } + + domain_index = init_lsa_ref_domain_list(state, + &state->idmap_doms, + domain_name, + &domain_sid); + if (domain_index == -1) { + tevent_req_oom(req); + return; + } + t->domain_index = domain_index; + } + subreq = wb_lookupsids_send(state, state->ev, state->lookup_sids, @@ -251,51 +312,11 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) } for (li = 0; li < state->lookup_count; li++) { - const struct dom_sid *sid = &state->lookup_sids[li]; - struct dom_sid dom_sid; struct lsa_TranslatedName *n = &names->names[li]; uint32_t ai = state->tmp_idx[li]; struct wbint_TransID *t = &state->all_ids.ids[ai]; - int domain_index; - const char *domain_name = NULL; - - if (n->sid_index != UINT32_MAX) { - const struct lsa_DomainInfo *info; - bool match; - - info = &domains->domains[n->sid_index]; - match = dom_sid_in_domain(info->sid, sid); - if (match) { - domain_name = info->name.string; - } - } - if (domain_name == NULL) { - struct winbindd_domain *wb_domain = NULL; - - /* - * This is needed to handle Samba DCs - * which always return sid_index == UINT32_MAX for - * unknown sids. - */ - wb_domain = find_domain_from_sid_noinit(sid); - if (wb_domain != NULL) { - domain_name = wb_domain->name; - } - } - if (domain_name == NULL) { - domain_name = ""; - } - sid_copy(&dom_sid, sid); - sid_split_rid(&dom_sid, &t->rid); t->type_hint = lsa_SidType_to_id_type(n->sid_type); - domain_index = init_lsa_ref_domain_list( - state, &state->idmap_doms, domain_name, &dom_sid); - if (domain_index == -1) { - tevent_req_oom(req); - return; - } - t->domain_index = domain_index; } TALLOC_FREE(names); -- 2.25.1 From 254078c1ad567d525a5d0daf9c21604121617e87 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Sep 2020 17:26:11 +0200 Subject: [PATCH 430/645] CVE-2020-25717 winbindd: allow idmap backends to mark entries with ID_[TYPE_WB_]REQUIRE_TYPE This must only be used between winbindd parent and child! It must not leak into outside world. Some backends require ID_TYPE_UID or ID_TYPE_GID as type_hint, while others may only need ID_TYPE_BOTH in order to validate that the domain exists. This will allow us to skip the wb_lookupsids_send/recv in the winbindd parent in future and only do that on demand. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 493f5d6b078e0b0f80d1ef25043e2834cb4fcb87) --- librpc/idl/idmap.idl | 23 +++++++++++++++++-- source3/passdb/lookup_sid.c | 7 ++++++ source3/winbindd/idmap_autorid.c | 6 ++--- source3/winbindd/idmap_ldap.c | 29 ++++++++++++++++++++++++ source3/winbindd/idmap_rw.c | 32 +++++++++++++++++++++++++-- source3/winbindd/idmap_tdb_common.c | 22 +++++++++++++++++- source3/winbindd/wb_sids2xids.c | 11 +++++++++ source3/winbindd/winbindd_dual_srv.c | 6 +++++ source3/winbindd/winbindd_getgroups.c | 7 ++++++ 9 files changed, 135 insertions(+), 8 deletions(-) diff --git a/librpc/idl/idmap.idl b/librpc/idl/idmap.idl index 54fd888dcab..e58e39210c7 100644 --- a/librpc/idl/idmap.idl +++ b/librpc/idl/idmap.idl @@ -11,7 +11,18 @@ interface idmap ID_TYPE_NOT_SPECIFIED, ID_TYPE_UID, ID_TYPE_GID, - ID_TYPE_BOTH + ID_TYPE_BOTH, + /* + * This are internal between winbindd + * parent and child. + * + * It means the idmap backend/child requires a valid type_hint + * for wbint_Sids2UnixIDs(): + * + * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists + * - ID_TYPE_BOTH means that only the domain exist + */ + ID_TYPE_WB_REQUIRE_TYPE } id_type; typedef [public] struct { @@ -23,7 +34,15 @@ interface idmap ID_UNKNOWN, ID_MAPPED, ID_UNMAPPED, - ID_EXPIRED + ID_EXPIRED, + /* + * This means the idmap backend requires a valid type_hint + * in order to map a sid to a unix id. + * + * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists + * - ID_TYPE_BOTH means that only the domain exist + */ + ID_REQUIRE_TYPE } id_mapping; typedef [public] struct { diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 9a7a8cdb122..5fa89e025be 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1444,6 +1444,13 @@ done: break; case ID_TYPE_NOT_SPECIFIED: break; + case ID_TYPE_WB_REQUIRE_TYPE: + /* + * these are internal between winbindd + * parent and child. + */ + smb_panic(__location__); + break; } } diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c index 636852119b2..d97494360b0 100644 --- a/source3/winbindd/idmap_autorid.c +++ b/source3/winbindd/idmap_autorid.c @@ -670,9 +670,9 @@ static NTSTATUS idmap_autorid_sid_to_id(struct idmap_tdb_common_context *common, * range. */ - DBG_NOTICE("Allocating range for domain %s refused\n", range.domsid); - map->status = ID_UNMAPPED; - return NT_STATUS_NONE_MAPPED; + DBG_NOTICE("Allocating range for domain %s required type_hint\n", range.domsid); + map->status = ID_REQUIRE_TYPE; + return NT_STATUS_SOME_NOT_MAPPED; allocate: ret = idmap_autorid_acquire_range(autorid_db, &range); diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 82f425ec9d0..bc757f3c74e 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -250,6 +250,17 @@ static NTSTATUS idmap_ldap_allocate_id_internal(struct idmap_domain *dom, LDAP_ATTR_GIDNUMBER); break; + case ID_TYPE_BOTH: + /* + * This is not supported here yet and + * already handled in idmap_rw_new_mapping() + */ + FALL_THROUGH; + case ID_TYPE_NOT_SPECIFIED: + /* + * This is handled in idmap_rw_new_mapping() + */ + FALL_THROUGH; default: DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); return NT_STATUS_INVALID_PARAMETER; @@ -867,6 +878,7 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, const char **attr_list; char *filter = NULL; bool multi = False; + size_t num_required = 0; int idx = 0; int bidx = 0; int count; @@ -1075,7 +1087,21 @@ again: ids[i]->status = ID_UNMAPPED; if (ids[i]->sid != NULL) { ret = idmap_ldap_new_mapping(dom, ids[i]); + DBG_DEBUG("idmap_ldap_new_mapping returned %s\n", + nt_errstr(ret)); + if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) { + if (ids[i]->status == ID_REQUIRE_TYPE) { + num_required += 1; + continue; + } + } if (!NT_STATUS_IS_OK(ret)) { + /* + * If we can't create + * a new mapping it's unlikely + * that it will work for the + * next entry. + */ goto done; } } @@ -1083,6 +1109,9 @@ again: } ret = NT_STATUS_OK; + if (num_required > 0) { + ret = STATUS_SOME_UNMAPPED; + } done: talloc_free(memctx); diff --git a/source3/winbindd/idmap_rw.c b/source3/winbindd/idmap_rw.c index 700a946fc62..71bfc14e204 100644 --- a/source3/winbindd/idmap_rw.c +++ b/source3/winbindd/idmap_rw.c @@ -39,11 +39,39 @@ NTSTATUS idmap_rw_new_mapping(struct idmap_domain *dom, return NT_STATUS_INVALID_PARAMETER; } - if ((map->xid.type != ID_TYPE_UID) && (map->xid.type != ID_TYPE_GID)) { + if (map->sid == NULL) { return NT_STATUS_INVALID_PARAMETER; } - if (map->sid == NULL) { + switch (map->xid.type) { + case ID_TYPE_NOT_SPECIFIED: + /* + * We need to know if we need a user or group mapping. + * Ask the winbindd parent to provide a valid type hint. + */ + DBG_INFO("%s ID_TYPE_NOT_SPECIFIED => ID_REQUIRE_TYPE\n", + dom_sid_str_buf(map->sid, &buf)); + map->status = ID_REQUIRE_TYPE; + return NT_STATUS_SOME_NOT_MAPPED; + + case ID_TYPE_BOTH: + /* + * For now we still require + * an explicit type as hint + * and don't support ID_TYPE_BOTH + */ + DBG_INFO("%s ID_TYPE_BOTH => ID_REQUIRE_TYPE\n", + dom_sid_str_buf(map->sid, &buf)); + map->status = ID_REQUIRE_TYPE; + return NT_STATUS_SOME_NOT_MAPPED; + + case ID_TYPE_UID: + break; + + case ID_TYPE_GID: + break; + + default: return NT_STATUS_INVALID_PARAMETER; } diff --git a/source3/winbindd/idmap_tdb_common.c b/source3/winbindd/idmap_tdb_common.c index 34269e3fe56..0df8f2f3103 100644 --- a/source3/winbindd/idmap_tdb_common.c +++ b/source3/winbindd/idmap_tdb_common.c @@ -118,6 +118,17 @@ static NTSTATUS idmap_tdb_common_allocate_id(struct idmap_domain *dom, hwmtype = "GID"; break; + case ID_TYPE_BOTH: + /* + * This is not supported here yet and + * already handled in idmap_rw_new_mapping() + */ + FALL_THROUGH; + case ID_TYPE_NOT_SPECIFIED: + /* + * This is handled in idmap_rw_new_mapping() + */ + FALL_THROUGH; default: DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type)); return NT_STATUS_INVALID_PARAMETER; @@ -529,7 +540,7 @@ static NTSTATUS idmap_tdb_common_sids_to_unixids_action(struct db_context *db, void *private_data) { struct idmap_tdb_common_sids_to_unixids_context *state = private_data; - size_t i, num_mapped = 0; + size_t i, num_mapped = 0, num_required = 0; NTSTATUS ret = NT_STATUS_OK; DEBUG(10, ("idmap_tdb_common_sids_to_unixids: " @@ -579,6 +590,12 @@ static NTSTATUS idmap_tdb_common_sids_to_unixids_action(struct db_context *db, state->ids[i]); DBG_DEBUG("idmap_tdb_common_new_mapping returned %s\n", nt_errstr(ret)); + if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) { + if (state->ids[i]->status == ID_REQUIRE_TYPE) { + num_required += 1; + continue; + } + } if (!NT_STATUS_IS_OK(ret)) { ret = STATUS_SOME_UNMAPPED; continue; @@ -598,6 +615,9 @@ done: } else { ret = NT_STATUS_OK; } + if (num_required > 0) { + ret = STATUS_SOME_UNMAPPED; + } } return ret; diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 3a3d47abbe5..35b6675520e 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -473,6 +473,17 @@ static void wb_sids2xids_done(struct tevent_req *subreq) for (si=0; si < src->num_ids; si++) { uint32_t di = state->tmp_idx[si]; + if (src->ids[si].xid.type == ID_TYPE_WB_REQUIRE_TYPE) { + /* + * This should not happen yet, as we always + * do a lookupsids and fill type_hint. + * + * Make sure we don't expose ID_TYPE_WB_REQUIRE_TYPE + * outside of winbindd! + */ + src->ids[si].xid.type = ID_TYPE_NOT_SPECIFIED; + } + if (src->ids[si].xid.type != ID_TYPE_NOT_SPECIFIED) { dst->ids[di].xid = src->ids[si].xid; } diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 0a48201a2b0..fc30cb998fa 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -226,6 +226,12 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p, for (i=0; istatus == ID_REQUIRE_TYPE) { + ids[i].xid.id = UINT32_MAX; + ids[i].xid.type = ID_TYPE_WB_REQUIRE_TYPE; + continue; + } + if (!idmap_unix_id_is_in_range(m->xid.id, dom)) { DBG_DEBUG("id %"PRIu32" is out of range " "%"PRIu32"-%"PRIu32" for domain %s\n", diff --git a/source3/winbindd/winbindd_getgroups.c b/source3/winbindd/winbindd_getgroups.c index 63206c28134..7182156578b 100644 --- a/source3/winbindd/winbindd_getgroups.c +++ b/source3/winbindd/winbindd_getgroups.c @@ -202,6 +202,13 @@ static void winbindd_getgroups_sid2gid_done(struct tevent_req *subreq) case ID_TYPE_BOTH: include_gid = true; break; + case ID_TYPE_WB_REQUIRE_TYPE: + /* + * these are internal between winbindd + * parent and child. + */ + smb_panic(__location__); + break; } if (!include_gid) { -- 2.25.1 From c727234626ce01cd8d564316bca0d9add6360c8e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 Sep 2020 16:24:49 +0200 Subject: [PATCH 431/645] CVE-2020-25717 wb_sids2xids: defer/skip wb_lookupsids* unless we get ID_TYPE_WB_REQUIRE_TYPE We try to give a valid hint for predefined sids and pass ID_TYPE_BOTH as a hint that the domain part of the sid is valid. In most cases the idmap child/backend does not require a type_hint as mappings already exist. This is a speed up as we no longer need to contact a domain controller. It's also possible to accept kerberos authentication without reaching out to a domain controller at all (if the idmap backend doesn't need a hint). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Reviewed-by: Gary Lockyer Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri Oct 23 04:47:26 UTC 2020 on sn-devel-184 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 54b4d2d3cb307019a260d15c6e6b4a3fb7fc337c) --- source3/winbindd/wb_sids2xids.c | 177 ++++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 19 deletions(-) diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 35b6675520e..650d104254a 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -69,6 +69,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq); static void wb_sids2xids_done(struct tevent_req *subreq); static void wb_sids2xids_gotdc(struct tevent_req *subreq); static void wb_sids2xids_next_sids2unix(struct tevent_req *req); +static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type); struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -166,11 +167,6 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, num_valid += 1; continue; } - - state->tmp_idx[state->lookup_count] = i; - sid_copy(&state->lookup_sids[state->lookup_count], - &state->sids[i]); - state->lookup_count += 1; } if (num_valid == num_sids) { @@ -222,6 +218,25 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) sid_copy(&domain_sid, &state->sids[i]); sid_split_rid(&domain_sid, &rid); + if (t->type_hint == ID_TYPE_NOT_SPECIFIED) { + const char *tmp_name = NULL; + enum lsa_SidType sid_type = SID_NAME_USE_NONE; + const struct dom_sid *tmp_authority_sid = NULL; + const char *tmp_authority_name = NULL; + + /* + * Try to get a type hint from for predefined sids + */ + status = dom_sid_lookup_predefined_sid(&state->sids[i], + &tmp_name, + &sid_type, + &tmp_authority_sid, + &tmp_authority_name); + if (NT_STATUS_IS_OK(status)) { + t->type_hint = lsa_SidType_to_id_type(sid_type); + } + } + for (di = 0; di < state->cfg->num_doms; di++) { struct wb_parent_idmap_config_dom *dom = &state->cfg->doms[di]; @@ -251,6 +266,18 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) domain_name = ""; } + if (t->type_hint == ID_TYPE_NOT_SPECIFIED) { + if (domain_name[0] != '\0') { + /* + * We know the domain, we indicate this + * by passing ID_TYPE_BOTH as a hint + * + * Maybe that's already enough for the backend + */ + t->type_hint = ID_TYPE_BOTH; + } + } + domain_index = init_lsa_ref_domain_list(state, &state->idmap_doms, domain_name, @@ -262,14 +289,15 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) t->domain_index = domain_index; } - subreq = wb_lookupsids_send(state, - state->ev, - state->lookup_sids, - state->lookup_count); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req); + /* + * We defer lookupsids because it requires domain controller + * interaction. + * + * First we ask the idmap child without explicit type hints. + * In most cases mappings already exist in the backend and + * a type_hint is not needed. + */ + wb_sids2xids_next_sids2unix(req); } static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map) @@ -292,8 +320,6 @@ static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map) return false; } -static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type); - static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( @@ -311,17 +337,83 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) return; } + if (domains == NULL) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + if (names == NULL) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + for (li = 0; li < state->lookup_count; li++) { struct lsa_TranslatedName *n = &names->names[li]; uint32_t ai = state->tmp_idx[li]; struct wbint_TransID *t = &state->all_ids.ids[ai]; + enum id_type type_hint; + + type_hint = lsa_SidType_to_id_type(n->sid_type); + if (type_hint != ID_TYPE_NOT_SPECIFIED) { + /* + * We know it's a valid user or group. + */ + t->type_hint = type_hint; + continue; + } + + if (n->sid_index == UINT32_MAX) { + /* + * The domain is not known, there's + * no point to try mapping again. + * mark is done and add a negative cache + * entry. + */ + t->domain_index = UINT32_MAX; /* mark as valid */ + idmap_cache_set_sid2unixid(&state->sids[ai], &t->xid); + continue; + } - t->type_hint = lsa_SidType_to_id_type(n->sid_type); + if (n->sid_index >= domains->count) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + if (domains->domains[n->sid_index].name.string == NULL) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + if (domains->domains[n->sid_index].sid == NULL) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + if (t->type_hint != ID_TYPE_NOT_SPECIFIED) { + /* + * We already tried with a type hint there's + * no point to try mapping again with ID_TYPE_BOTH. + * + * Mark is done and add a negative cache entry. + */ + t->domain_index = UINT32_MAX; /* mark as valid */ + idmap_cache_set_sid2unixid(&state->sids[ai], &t->xid); + continue; + } + + /* + * We only know the domain exists, but the user doesn't + */ + t->type_hint = ID_TYPE_BOTH; } TALLOC_FREE(names); TALLOC_FREE(domains); + /* + * Now that we have type_hints for the remaining sids, + * we need to restart with the first domain. + */ + state->dom_index = 0; wb_sids2xids_next_sids2unix(req); } @@ -339,7 +431,45 @@ static void wb_sids2xids_next_sids2unix(struct tevent_req *req) state->tried_dclookup = false; if (state->dom_index == state->idmap_doms.count) { - tevent_req_done(req); + if (state->lookup_count != 0) { + /* + * We already called wb_lookupsids_send() + * before, so we're done. + */ + tevent_req_done(req); + return; + } + + for (si=0; si < state->num_sids; si++) { + struct wbint_TransID *t = &state->all_ids.ids[si]; + + if (t->domain_index == UINT32_MAX) { + /* ignore already filled entries */ + continue; + } + + state->tmp_idx[state->lookup_count] = si; + sid_copy(&state->lookup_sids[state->lookup_count], + &state->sids[si]); + state->lookup_count += 1; + } + + if (state->lookup_count == 0) { + /* + * no wb_lookupsids_send() needed... + */ + tevent_req_done(req); + return; + } + + subreq = wb_lookupsids_send(state, + state->ev, + state->lookup_sids, + state->lookup_count); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req); return; } @@ -474,9 +604,18 @@ static void wb_sids2xids_done(struct tevent_req *subreq) uint32_t di = state->tmp_idx[si]; if (src->ids[si].xid.type == ID_TYPE_WB_REQUIRE_TYPE) { + if (state->lookup_count == 0) { + /* + * The backend asks for more information + * (a type_hint), we'll do a lookupsids + * later. + */ + continue; + } + /* - * This should not happen yet, as we always - * do a lookupsids and fill type_hint. + * lookupsids was not able to provide a type_hint that + * satisfied the backend. * * Make sure we don't expose ID_TYPE_WB_REQUIRE_TYPE * outside of winbindd! -- 2.25.1 From f49229b56878fcdb593605042a2fb94dbd5b6bc8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Oct 2020 12:21:57 +0200 Subject: [PATCH 432/645] CVE-2020-25717 s3:idmap_hash: reliable return ID_TYPE_BOTH idmap_hash used to bounce back the requested type, which was ID_TYPE_UID, ID_TYPE_GID or ID_TYPE_NOT_SPECIFIED before as the winbindd parent always used a lookupsids. When the lookupsids failed because of an unknown domain, the idmap child weren't requested at all and the caller sees ID_TYPE_NOT_SPECIFIED. This module should have supported ID_TYPE_BOTH since samba-4.1.0, similar to idmap_rid and idmap_autorid. Now that the winbindd parent will pass ID_TYPE_BOTH in order to indicate that the domain exists, it's better to always return ID_TYPE_BOTH instead of a random mix of ID_TYPE_UID, ID_TYPE_GID or ID_TYPE_BOTH. In order to request a type_hint it will return ID_REQUIRE_TYPE for ID_TYPE_NOT_SPECIFIED, which means that the parent at least assures that the domain sid exists. And the caller still gets ID_TYPE_NOT_SPECIFIED if the domain doesn't exist. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 Signed-off-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Fri Jan 22 11:32:46 UTC 2021 on sn-devel-184 (cherry picked from commit d8339056eef2845805f573bd8b0f3323370ecc8f) Reviewed-by: Ralph Boehme Autobuild-User(v4-14-test): Karolin Seeger Autobuild-Date(v4-14-test): Wed Jan 27 17:06:51 UTC 2021 on sn-devel-184 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 99673b77b069674a6145552eb870de8829dfa503) --- source3/winbindd/idmap_hash/idmap_hash.c | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index be0ba45a044..d0bed7631a6 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -261,6 +261,25 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, ids[i]->status = ID_UNMAPPED; + if (ids[i]->xid.type == ID_TYPE_NOT_SPECIFIED) { + /* + * idmap_hash used to bounce back the requested type, + * which was ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_NOT_SPECIFIED before as the winbindd parent + * always used a lookupsids. When the lookupsids + * failed because of an unknown domain, the idmap child + * weren't requested at all and the caller sees + * ID_TYPE_NOT_SPECIFIED. + * + * Now that the winbindd parent will pass ID_TYPE_BOTH + * in order to indicate that the domain exists. + * We should ask the parent to fallback to lookupsids + * if the domain is not known yet. + */ + ids[i]->status = ID_REQUIRE_TYPE; + continue; + } + sid_copy(&sid, ids[i]->sid); sid_split_rid(&sid, &rid); @@ -270,6 +289,22 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, /* Check that both hashes are non-zero*/ if (h_domain && h_rid) { + /* + * idmap_hash used to bounce back the requested type, + * which was ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_NOT_SPECIFIED before as the winbindd parent + * always used a lookupsids. + * + * This module should have supported ID_TYPE_BOTH since + * samba-4.1.0, similar to idmap_rid and idmap_autorid. + * + * Now that the winbindd parent will pass ID_TYPE_BOTH + * in order to indicate that the domain exists, it's + * better to always return ID_TYPE_BOTH instead of a + * random mix of ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_BOTH. + */ + ids[i]->xid.type = ID_TYPE_BOTH; ids[i]->xid.id = combine_hashes(h_domain, h_rid); ids[i]->status = ID_MAPPED; } -- 2.25.1 From 15c08ba91c726073b140204e68432fa89e242520 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 31 Aug 2021 17:04:56 +0200 Subject: [PATCH 433/645] CVE-2020-25717 winbindd: call wb_parent_idmap_setup_send() in wb_queryuser_send() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14804 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 39c2ec72cb77945c3eb611fb1d7d7e9aad52bdfd) BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 7d1dd87a6538f8c7f1e4938b0ff52cbd231fff90) --- source3/winbindd/wb_queryuser.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 9db51909c02..f5bc96f03f6 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -25,10 +25,12 @@ struct wb_queryuser_state { struct tevent_context *ev; - struct wbint_userinfo *info; + struct wbint_userinfo *info; + const struct wb_parent_idmap_config *idmap_cfg; bool tried_dclookup; }; +static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq); static void wb_queryuser_got_uid(struct tevent_req *subreq); static void wb_queryuser_got_domain(struct tevent_req *subreq); static void wb_queryuser_got_dc(struct tevent_req *subreq); @@ -60,13 +62,35 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, sid_copy(&info->user_sid, user_sid); + subreq = wb_parent_idmap_setup_send(state, state->ev); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_queryuser_idmap_setup_done, req); + return req; +} + +static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_queryuser_state *state = tevent_req_data( + req, struct wb_queryuser_state); + NTSTATUS status; + + status = wb_parent_idmap_setup_recv(subreq, &state->idmap_cfg); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + subreq = wb_sids2xids_send( state, state->ev, &state->info->user_sid, 1); if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + return; } tevent_req_set_callback(subreq, wb_queryuser_got_uid, req); - return req; + return; } static void wb_queryuser_got_uid(struct tevent_req *subreq) -- 2.25.1 From 9b0e023ee9f8d37e9703dfacb3976143de5ce5ee Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 20 Aug 2021 15:04:49 +0200 Subject: [PATCH 434/645] CVE-2020-25717 winbind: ensure wb_parent_idmap_setup_send() gets called in winbindd_allocate_uid_send() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14804 RN: winbindd can crash because idmap child state is not fully initialized Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Thu Sep 2 15:20:06 UTC 2021 on sn-devel-184 (cherry picked from commit d0f6d54354b02f5591706814fbd1e4844788fdfa) BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 446f89510f2e55a551e2975a6cbf01c6a023ba0c) --- source3/winbindd/winbindd_allocate_uid.c | 44 +++++++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/winbindd_allocate_uid.c b/source3/winbindd/winbindd_allocate_uid.c index 69ce61c872e..64711f1b661 100644 --- a/source3/winbindd/winbindd_allocate_uid.c +++ b/source3/winbindd/winbindd_allocate_uid.c @@ -22,9 +22,11 @@ #include "librpc/gen_ndr/ndr_winbind_c.h" struct winbindd_allocate_uid_state { + struct tevent_context *ev; uint64_t uid; }; +static void winbindd_allocate_uid_initialized(struct tevent_req *subreq); static void winbindd_allocate_uid_done(struct tevent_req *subreq); struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx, @@ -34,25 +36,57 @@ struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct winbindd_allocate_uid_state *state; - struct dcerpc_binding_handle *child_binding_handle = NULL; req = tevent_req_create(mem_ctx, &state, struct winbindd_allocate_uid_state); if (req == NULL) { return NULL; } + state->ev = ev; DEBUG(3, ("allocate_uid\n")); - child_binding_handle = idmap_child_handle(); + subreq = wb_parent_idmap_setup_send(state, ev); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, winbindd_allocate_uid_initialized, req); + return req; +} + +static void winbindd_allocate_uid_initialized(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct dcerpc_binding_handle *child_binding_handle = NULL; + struct winbindd_allocate_uid_state *state = tevent_req_data( + req, struct winbindd_allocate_uid_state); + const struct wb_parent_idmap_config *cfg = NULL; + NTSTATUS status; + + status = wb_parent_idmap_setup_recv(subreq, &cfg); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + if (cfg->num_doms == 0) { + /* + * idmap_tdb also returns UNSUCCESSFUL if a range is full + */ + tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); + return; + } + + child_binding_handle = idmap_child_handle(); - subreq = dcerpc_wbint_AllocateUid_send(state, ev, child_binding_handle, + subreq = dcerpc_wbint_AllocateUid_send(state, + state->ev, + child_binding_handle, &state->uid); if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + return; } tevent_req_set_callback(subreq, winbindd_allocate_uid_done, req); - return req; } static void winbindd_allocate_uid_done(struct tevent_req *subreq) -- 2.25.1 From ac79ed672ebdedb9dc0c8c3a9cf792492ee20b54 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 11 Nov 2020 14:42:55 +0200 Subject: [PATCH 435/645] CVE-2020-25717 auth_sam: use pdb_get_domain_info to look up DNS forest information When Samba is used as a part of FreeIPA domain controller, Windows clients for a trusted AD forest may try to authenticate (perform logon operation) as a REALM\name user account. Fix auth_sam plugins to accept DNS forest name if we are running on a DC with PASSDB module providing domain information (e.g. pdb_get_domain_info() returning non-NULL structure). Right now, only FreeIPA or Samba AD DC PASSDB backends return this information but Samba AD DC configuration is explicitly ignored by the two auth_sam (strict and netlogon3) modules. Detailed logs below: [2020/11/11 09:23:53.281296, 1, pid=42677, effective(65534, 65534), real(65534, 0), class=rpc_parse] ../../librpc/ndr/ndr.c:482(ndr_print_function_debug) netr_LogonSamLogonWithFlags: struct netr_LogonSamLogonWithFlags in: struct netr_LogonSamLogonWithFlags server_name : * server_name : '\\master.ipa.test' computer_name : * computer_name : 'AD1' credential : * credential: struct netr_Authenticator cred: struct netr_Credential data : 529f4b087c5f6546 timestamp : Wed Nov 11 09:23:55 AM 2020 UTC return_authenticator : * return_authenticator: struct netr_Authenticator cred: struct netr_Credential data : 204f28f622010000 timestamp : Fri May 2 06:37:50 AM 1986 UTC logon_level : NetlogonNetworkTransitiveInformation (6) logon : * logon : union netr_LogonLevel(case 6) network : * network: struct netr_NetworkInfo identity_info: struct netr_IdentityInfo domain_name: struct lsa_String length : 0x0010 (16) size : 0x01fe (510) string : * string : 'IPA.TEST' parameter_control : 0x00002ae0 (10976) 0: MSV1_0_CLEARTEXT_PASSWORD_ALLOWED 0: MSV1_0_UPDATE_LOGON_STATISTICS 0: MSV1_0_RETURN_USER_PARAMETERS 0: MSV1_0_DONT_TRY_GUEST_ACCOUNT 1: MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT 1: MSV1_0_RETURN_PASSWORD_EXPIRY 1: MSV1_0_USE_CLIENT_CHALLENGE 0: MSV1_0_TRY_GUEST_ACCOUNT_ONLY 1: MSV1_0_RETURN_PROFILE_PATH 0: MSV1_0_TRY_SPECIFIED_DOMAIN_ONLY 1: MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 0: MSV1_0_DISABLE_PERSONAL_FALLBACK 1: MSV1_0_ALLOW_FORCE_GUEST 0: MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED 0: MSV1_0_USE_DOMAIN_FOR_ROUTING_ONLY 0: MSV1_0_ALLOW_MSVCHAPV2 0: MSV1_0_S4U2SELF 0: MSV1_0_CHECK_LOGONHOURS_FOR_S4U 0: MSV1_0_SUBAUTHENTICATION_DLL_EX logon_id : 0x0000000000884ef2 (8933106) account_name: struct lsa_String length : 0x000e (14) size : 0x000e (14) string : * string : 'idmuser' workstation: struct lsa_String length : 0x0000 (0) size : 0x0000 (0) string : * string : '' challenge : 417207867bd33c74 nt: struct netr_ChallengeResponse length : 0x00c0 (192) size : 0x00c0 (192) data : * data: ARRAY(192) [0000] A5 24 62 6E 31 DF 69 66 9E DC 54 D6 63 4C D6 2F .$bn1.if ..T.cL./ [0010] 01 01 00 00 00 00 00 00 50 37 D7 60 0C B8 D6 01 ........ P7.`.... [0020] 15 1B 38 4F 47 95 4D 62 00 00 00 00 02 00 0E 00 ..8OG.Mb ........ [0030] 57 00 49 00 4E 00 32 00 30 00 31 00 36 00 01 00 W.I.N.2. 0.1.6... [0040] 06 00 41 00 44 00 31 00 04 00 18 00 77 00 69 00 ..A.D.1. ....w.i. [0050] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e. [0060] 73 00 74 00 03 00 20 00 61 00 64 00 31 00 2E 00 s.t... . a.d.1... [0070] 77 00 69 00 6E 00 32 00 30 00 31 00 36 00 2E 00 w.i.n.2. 0.1.6... [0080] 74 00 65 00 73 00 74 00 05 00 18 00 77 00 69 00 t.e.s.t. ....w.i. [0090] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e. [00A0] 73 00 74 00 07 00 08 00 50 37 D7 60 0C B8 D6 01 s.t..... P7.`.... [00B0] 06 00 04 00 02 00 00 00 00 00 00 00 00 00 00 00 ........ ........ lm: struct netr_ChallengeResponse length : 0x0018 (24) size : 0x0018 (24) data : * data : 000000000000000000000000000000000000000000000000 validation_level : 0x0006 (6) flags : * flags : 0x00000000 (0) 0: NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT 0: NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP 0: NETLOGON_SAMLOGON_FLAG_RODC_TO_OTHER_DOMAIN 0: NETLOGON_SAMLOGON_FLAG_RODC_NTLM_REQUEST In such case checks for a workgroup name will not match the DNS forest name used in the username specification: [2020/11/11 09:23:53.283055, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:200(auth_check_ntlm_password) check_ntlm_password: Checking password for unmapped user [IPA.TEST]\[idmuser]@[] with the new password interface [2020/11/11 09:23:53.283073, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:203(auth_check_ntlm_password) check_ntlm_password: mapped user is: [IPA.TEST]\[idmuser]@[] [2020/11/11 09:23:53.283082, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:213(auth_check_ntlm_password) check_ntlm_password: auth_context challenge created by fixed [2020/11/11 09:23:53.283091, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:216(auth_check_ntlm_password) challenge is: [2020/11/11 09:23:53.283099, 5, pid=42677, effective(65534, 65534), real(65534, 0)] ../../lib/util/util.c:678(dump_data) [0000] 41 72 07 86 7B D3 3C 74 Ar..{. Reviewed-by: Andreas Schneider BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 2a8b672652dcbcf55ec59be537773d76f0f14d0a) --- source3/auth/auth_sam.c | 45 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index 3c12f959faf..e8e0d543f8c 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -22,6 +22,7 @@ #include "includes.h" #include "auth.h" +#include "passdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -142,10 +143,28 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context, break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - if ( !is_local_name && !is_my_domain ) { - DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", - effective_domain)); - return NT_STATUS_NOT_IMPLEMENTED; + if (!is_local_name && !is_my_domain) { + /* If we are running on a DC that has PASSDB module with domain + * information, check if DNS forest name is matching the domain + * name. This is the case of FreeIPA domain controller when + * trusted AD DCs attempt to authenticate FreeIPA users using + * the forest root domain (which is the only domain in FreeIPA). + */ + struct pdb_domain_info *dom_info = NULL; + + dom_info = pdb_get_domain_info(mem_ctx); + if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { + is_my_domain = strequal(user_info->mapped.domain_name, + dom_info->dns_forest); + } + + TALLOC_FREE(dom_info); + if (!is_my_domain) { + DEBUG(6,("check_samstrict_security: %s is not one " + "of my local names or domain name (DC)\n", + effective_domain)); + return NT_STATUS_NOT_IMPLEMENTED; + } } break; @@ -230,6 +249,24 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context, } is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup()); + if (!is_my_domain) { + /* If we are running on a DC that has PASSDB module with domain + * information, check if DNS forest name is matching the domain + * name. This is the case of FreeIPA domain controller when + * trusted AD DCs attempt to authenticate FreeIPA users using + * the forest root domain (which is the only domain in FreeIPA). + */ + struct pdb_domain_info *dom_info = NULL; + dom_info = pdb_get_domain_info(mem_ctx); + + if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { + is_my_domain = strequal(user_info->mapped.domain_name, + dom_info->dns_forest); + } + + TALLOC_FREE(dom_info); + } + if (!is_my_domain) { DBG_INFO("%s is not our domain name (DC for %s)\n", effective_domain, lp_workgroup()); -- 2.25.1 From 43fadfdd295ae17c065fad9e1403285d4893282f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 10 Nov 2020 17:35:24 +0200 Subject: [PATCH 436/645] CVE-2020-25717 lookup_name: allow lookup names prefixed with DNS forest root for FreeIPA DC In FreeIPA deployment with active Global Catalog service, when a two-way trust to Active Directory forest is established, Windows systems can look up FreeIPA users and groups. When using a security tab in Windows Explorer on AD side, a lookup over a trusted forest might come as realm\name instead of NetBIOS domain name: -------------------------------------------------------------------- [2020/01/13 11:12:39.859134, 1, pid=33253, effective(1732401004, 1732401004), real(1732401004, 0), class=rpc_parse] ../../librpc/ndr/ndr.c:471(ndr_print_function_debug) lsa_LookupNames3: struct lsa_LookupNames3 in: struct lsa_LookupNames3 handle : * handle: struct policy_handle handle_type : 0x00000000 (0) uuid : 0000000e-0000-0000-1c5e-a750e5810000 num_names : 0x00000001 (1) names: ARRAY(1) names: struct lsa_String length : 0x001e (30) size : 0x0020 (32) string : * string : 'ipa.test\admins' sids : * sids: struct lsa_TransSidArray3 count : 0x00000000 (0) sids : NULL level : LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 (6) count : * count : 0x00000000 (0) lookup_options : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES (0) client_revision : LSA_CLIENT_REVISION_2 (2) -------------------------------------------------------------------- If we are running as a DC and PASSDB supports returning domain info (pdb_get_domain_info() returns a valid structure), check domain of the name in lookup_name() against DNS forest name and allow the request to be done against the primary domain. This corresponds to FreeIPA's use of Samba as a DC. For normal domain members a realm-based lookup falls back to a lookup over to its own domain controller with the help of winbindd. Signed-off-by: Alexander Bokovoy Reviewed-by: Stefan Metzmacher Autobuild-User(master): Alexander Bokovoy Autobuild-Date(master): Wed Nov 11 10:59:01 UTC 2020 on sn-devel-184 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 31c703766fd2b89737826fb7e9a707f0622bb8cd) --- source3/passdb/lookup_sid.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 5fa89e025be..eb8ddae4283 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -114,17 +114,36 @@ bool lookup_name(TALLOC_CTX *mem_ctx, full_name, domain, name)); DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); - if (((flags & LOOKUP_NAME_DOMAIN) || (flags == 0)) && - strequal(domain, get_global_sam_name())) - { + if ((flags & LOOKUP_NAME_DOMAIN) || (flags == 0)) { + bool check_global_sam = false; + + check_global_sam = strequal(domain, get_global_sam_name()); + + /* If we are running on a DC that has PASSDB module with domain + * information, check if DNS forest name is matching the domain + * name. This is the case of FreeIPA domain controller when + * trusted AD DC looks up users found in a Global Catalog of + * the forest root domain. */ + if (!check_global_sam && (IS_DC)) { + struct pdb_domain_info *dom_info = NULL; + dom_info = pdb_get_domain_info(tmp_ctx); + + if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { + check_global_sam = strequal(domain, dom_info->dns_forest); + } - /* It's our own domain, lookup the name in passdb */ - if (lookup_global_sam_name(name, flags, &rid, &type)) { - sid_compose(&sid, get_global_sam_sid(), rid); - goto ok; + TALLOC_FREE(dom_info); + } + + if (check_global_sam) { + /* It's our own domain, lookup the name in passdb */ + if (lookup_global_sam_name(name, flags, &rid, &type)) { + sid_compose(&sid, get_global_sam_sid(), rid); + goto ok; + } + TALLOC_FREE(tmp_ctx); + return false; } - TALLOC_FREE(tmp_ctx); - return false; } if ((flags & LOOKUP_NAME_BUILTIN) && -- 2.25.1 From dbbce7628334b7da581af7473f53358b2d3d4da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Sun, 18 Oct 2020 21:07:14 +0200 Subject: [PATCH 437/645] CVE-2020-25717 auth_generic: fix empty initializer compile warning Signed-off-by: Bjoern Jacke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit cce4e8012c5eafb6d98111b92923d748d72d077b) --- source3/auth/auth_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 0e9500ac08d..8af74481034 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -66,7 +66,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, if (pac_blob) { #ifdef HAVE_KRB5 - struct wbcAuthUserParams params = {}; + struct wbcAuthUserParams params = { 0 }; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; wbcErr wbc_err; -- 2.25.1 From 2c4a2a24a5f9d21c7458e508e946e81d8a1d9a79 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Apr 2021 10:05:59 +0200 Subject: [PATCH 438/645] CVE-2020-25717 auth3: Simplify check_samba4_security() First set up "server_info" in a local variable and once it's fully set up, assign it to the out parameter "pserver_info". Pointer dereferencing obfuscates the code for me. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 062a0c14c6ee0b74e7619af73747df59c5e67672) --- source3/auth/auth_samba4.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/source3/auth/auth_samba4.c b/source3/auth/auth_samba4.c index 6dee9c6f411..418e2cfa56d 100644 --- a/source3/auth/auth_samba4.c +++ b/source3/auth/auth_samba4.c @@ -107,11 +107,12 @@ static struct server_id *new_server_id_task(TALLOC_CTX *mem_ctx) * services the AD DC. It is tested via pdbtest. */ -static NTSTATUS check_samba4_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +static NTSTATUS check_samba4_security( + const struct auth_context *auth_context, + void *my_private_data, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **pserver_info) { TALLOC_CTX *frame = talloc_stackframe(); struct netr_SamInfo3 *info3 = NULL; @@ -119,6 +120,7 @@ static NTSTATUS check_samba4_security(const struct auth_context *auth_context, struct auth_user_info_dc *user_info_dc; struct auth4_context *auth4_context; uint8_t authoritative = 0; + struct auth_serversupplied_info *server_info = NULL; nt_status = make_auth4_context_s4(auth_context, mem_ctx, &auth4_context); if (!NT_STATUS_IS_OK(nt_status)) { @@ -160,17 +162,19 @@ static NTSTATUS check_samba4_security(const struct auth_context *auth_context, } if (user_info->flags & USER_INFO_INFO3_AND_NO_AUTHZ) { - *server_info = make_server_info(mem_ctx); - if (*server_info == NULL) { + server_info = make_server_info(mem_ctx); + if (server_info == NULL) { nt_status = NT_STATUS_NO_MEMORY; goto done; } - (*server_info)->info3 = talloc_steal(*server_info, info3); - + server_info->info3 = talloc_move(server_info, &info3); } else { - nt_status = make_server_info_info3(mem_ctx, user_info->client.account_name, - user_info->mapped.domain_name, server_info, - info3); + nt_status = make_server_info_info3( + mem_ctx, + user_info->client.account_name, + user_info->mapped.domain_name, + &server_info, + info3); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("make_server_info_info3 failed: %s\n", nt_errstr(nt_status))); @@ -178,6 +182,7 @@ static NTSTATUS check_samba4_security(const struct auth_context *auth_context, } } + *pserver_info = server_info; nt_status = NT_STATUS_OK; done: -- 2.25.1 From ae377f2668b16fb343b28e1c3aa0225b08af4b3d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Apr 2021 15:14:01 +0000 Subject: [PATCH 439/645] CVE-2020-25717 auth: Simplify DEBUG statements in make_auth3_context_for_ntlm() Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 8536bf7fce41c43bbed25f7ed4ce5775a1b9c0d5) --- source3/auth/auth.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source3/auth/auth.c b/source3/auth/auth.c index e8bb9d7821a..12f7917b38d 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -529,28 +529,28 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) { const char *methods = NULL; + const char *role = NULL; switch (lp_server_role()) { case ROLE_ACTIVE_DIRECTORY_DC: - DEBUG(5,("Making default auth method list for server role = " - "'active directory domain controller'\n")); + role = "'active directory domain controller'"; methods = "samba4"; break; case ROLE_DOMAIN_MEMBER: - DEBUG(5,("Making default auth method list for server role = 'domain member'\n")); + role = "'domain member'"; methods = "anonymous sam winbind sam_ignoredomain"; break; case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: - DEBUG(5,("Making default auth method list for DC\n")); + role = "'DC'"; methods = "anonymous sam winbind sam_ignoredomain"; break; case ROLE_STANDALONE: - DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = yes\n")); if (lp_encrypt_passwords()) { + role = "'standalone server', encrypt passwords = yes"; methods = "anonymous sam_ignoredomain"; } else { - DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = no\n")); + role = "'standalone server', encrypt passwords = no"; methods = "anonymous unix"; } break; @@ -559,6 +559,9 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx, return NT_STATUS_UNSUCCESSFUL; } + DBG_INFO("Making default auth method list for server role = %s\n", + role); + return make_auth_context_specific(mem_ctx, auth_context, methods); } -- 2.25.1 From 484382c9787592fe7f4348383db210c7733b3a7c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Apr 2021 21:48:32 +0200 Subject: [PATCH 440/645] CVE-2020-25717 auth4: Make auth_anonymous pseudo-async Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 759573136876ef2b1b1c7484f99570d7de957e0d) --- source4/auth/ntlm/auth_anonymous.c | 66 ++++++++++++++++++++++++++---- source4/auth/ntlm/wscript_build | 2 +- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/source4/auth/ntlm/auth_anonymous.c b/source4/auth/ntlm/auth_anonymous.c index 83aeb431f5f..a25aacaa137 100644 --- a/source4/auth/ntlm/auth_anonymous.c +++ b/source4/auth/ntlm/auth_anonymous.c @@ -20,9 +20,11 @@ */ #include "includes.h" +#include #include "auth/auth.h" #include "auth/ntlm/auth_proto.h" #include "param/param.h" +#include "lib/util/tevent_ntstatus.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -84,19 +86,65 @@ static NTSTATUS anonymous_want_check(struct auth_method_context *ctx, * anonymou logons to be dealt with in one place. Non-anonymou logons 'fail' * and pass onto the next module. **/ -static NTSTATUS anonymous_check_password(struct auth_method_context *ctx, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_user_info_dc **_user_info_dc, - bool *authoritative) + +struct anonymous_check_password_state { + struct auth_user_info_dc *user_info_dc; +}; + +static struct tevent_req *anonymous_check_password_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct auth_method_context *ctx, + const struct auth_usersupplied_info *user_info) +{ + struct tevent_req *req = NULL; + struct anonymous_check_password_state *state = NULL; + NTSTATUS status; + + req = tevent_req_create( + mem_ctx, + &state, + struct anonymous_check_password_state); + if (req == NULL) { + return NULL; + } + + status = auth_anonymous_user_info_dc( + state, + lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), + &state->user_info_dc); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + tevent_req_done(req); + return tevent_req_post(req, ev); +} + +static NTSTATUS anonymous_check_password_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct auth_user_info_dc **interim_info, + bool *authoritative) { - return auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), _user_info_dc); + struct anonymous_check_password_state *state = tevent_req_data( + req, struct anonymous_check_password_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + *interim_info = talloc_move(mem_ctx, &state->user_info_dc); + tevent_req_received(req); + return NT_STATUS_OK; } + static const struct auth_operations anonymous_auth_ops = { - .name = "anonymous", - .want_check = anonymous_want_check, - .check_password = anonymous_check_password + .name = "anonymous", + .want_check = anonymous_want_check, + .check_password_send = anonymous_check_password_send, + .check_password_recv = anonymous_check_password_recv, }; _PUBLIC_ NTSTATUS auth4_anonymous_init(TALLOC_CTX *ctx) diff --git a/source4/auth/ntlm/wscript_build b/source4/auth/ntlm/wscript_build index 04a760c3e49..6ea0c4d7e3a 100644 --- a/source4/auth/ntlm/wscript_build +++ b/source4/auth/ntlm/wscript_build @@ -12,7 +12,7 @@ bld.SAMBA_MODULE('auth4_anonymous', source='auth_anonymous.c', subsystem='auth4', init_function='auth4_anonymous_init', - deps='talloc' + deps='tevent' ) -- 2.25.1 From 164d5e573d160dd74842c8cdf70aa30d9dd8c76d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Apr 2021 22:22:18 +0200 Subject: [PATCH 441/645] CVE-2020-25717 auth4: Make auth_developer pseudo-async This is a simpler approach to really just wrap the code. Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 43a1e42815718591faa8d526319b96d089a758fa) --- source4/auth/ntlm/auth_developer.c | 61 +++++++++++++++++++++++++++++- source4/auth/ntlm/wscript_build | 2 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/source4/auth/ntlm/auth_developer.c b/source4/auth/ntlm/auth_developer.c index b655283975b..551f0ae1605 100644 --- a/source4/auth/ntlm/auth_developer.c +++ b/source4/auth/ntlm/auth_developer.c @@ -20,9 +20,11 @@ */ #include "includes.h" +#include #include "auth/auth.h" #include "auth/ntlm/auth_proto.h" #include "libcli/security/security.h" +#include "lib/util/tevent_ntstatus.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -135,10 +137,67 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, return nt_status; } +struct name_to_ntstatus_check_password_state { + struct auth_user_info_dc *user_info_dc; + bool authoritative; +}; + +static struct tevent_req *name_to_ntstatus_check_password_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct auth_method_context *ctx, + const struct auth_usersupplied_info *user_info) +{ + struct tevent_req *req = NULL; + struct name_to_ntstatus_check_password_state *state = NULL; + NTSTATUS status; + + req = tevent_req_create( + mem_ctx, + &state, + struct name_to_ntstatus_check_password_state); + if (req == NULL) { + return NULL; + } + + status = name_to_ntstatus_check_password( + ctx, + state, + user_info, + &state->user_info_dc, + &state->authoritative); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + tevent_req_done(req); + return tevent_req_post(req, ev); +} + +static NTSTATUS name_to_ntstatus_check_password_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct auth_user_info_dc **interim_info, + bool *authoritative) +{ + struct name_to_ntstatus_check_password_state *state = tevent_req_data( + req, struct name_to_ntstatus_check_password_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + *interim_info = talloc_move(mem_ctx, &state->user_info_dc); + *authoritative = state->authoritative; + tevent_req_received(req); + return NT_STATUS_OK; +} + static const struct auth_operations name_to_ntstatus_auth_ops = { .name = "name_to_ntstatus", .want_check = name_to_ntstatus_want_check, - .check_password = name_to_ntstatus_check_password + .check_password_send = name_to_ntstatus_check_password_send, + .check_password_recv = name_to_ntstatus_check_password_recv, }; _PUBLIC_ NTSTATUS auth4_developer_init(TALLOC_CTX *ctx) diff --git a/source4/auth/ntlm/wscript_build b/source4/auth/ntlm/wscript_build index 6ea0c4d7e3a..1ee8d79563a 100644 --- a/source4/auth/ntlm/wscript_build +++ b/source4/auth/ntlm/wscript_build @@ -28,7 +28,7 @@ bld.SAMBA_MODULE('auth4_developer', source='auth_developer.c', subsystem='auth4', init_function='auth4_developer_init', - deps='talloc' + deps='tevent' ) -- 2.25.1 From 536fee051f0160acac71bc9b4889cd6b70fd61a8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Apr 2021 21:59:55 +0200 Subject: [PATCH 442/645] CVE-2020-25717 auth4: Make auth_unix pseudo-async Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit a6f42ab8a778b9863990da3112c2e868cd006303) --- source4/auth/ntlm/auth_unix.c | 85 ++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/source4/auth/ntlm/auth_unix.c b/source4/auth/ntlm/auth_unix.c index 67cd5f3dc44..cfe4f1a073f 100644 --- a/source4/auth/ntlm/auth_unix.c +++ b/source4/auth/ntlm/auth_unix.c @@ -27,6 +27,7 @@ #include "lib/tsocket/tsocket.h" #include "../libcli/auth/pam_errors.h" #include "param/param.h" +#include "lib/util/tevent_ntstatus.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -713,46 +714,78 @@ static NTSTATUS authunix_want_check(struct auth_method_context *ctx, return NT_STATUS_OK; } -static NTSTATUS authunix_check_password(struct auth_method_context *ctx, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_user_info_dc **user_info_dc, - bool *authoritative) +struct authunix_check_password_state { + struct auth_user_info_dc *user_info_dc; +}; + +static struct tevent_req *authunix_check_password_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct auth_method_context *ctx, + const struct auth_usersupplied_info *user_info) { - TALLOC_CTX *check_ctx; - NTSTATUS nt_status; - struct passwd *pwd; + struct tevent_req *req = NULL; + struct authunix_check_password_state *state = NULL; + struct passwd *pwd = NULL; + NTSTATUS status; - if (user_info->password_state != AUTH_PASSWORD_PLAIN) { - return NT_STATUS_INVALID_PARAMETER; + req = tevent_req_create( + mem_ctx, + &state, + struct authunix_check_password_state); + if (req == NULL) { + return NULL; } - check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password"); - if (check_ctx == NULL) { - return NT_STATUS_NO_MEMORY; + if (user_info->password_state != AUTH_PASSWORD_PLAIN) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } - nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(check_ctx); - return nt_status; + status = check_unix_password( + state, ctx->auth_ctx->lp_ctx, user_info, &pwd); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - nt_status = authunix_make_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), - user_info, pwd, user_info_dc); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(check_ctx); - return nt_status; + status = authunix_make_user_info_dc( + state, + lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), + user_info, + pwd, + &state->user_info_dc); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - talloc_free(check_ctx); + tevent_req_done(req); + return tevent_req_post(req, ev); +} + +static NTSTATUS authunix_check_password_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct auth_user_info_dc **interim_info, + bool *authoritative) +{ + struct authunix_check_password_state *state = tevent_req_data( + req, struct authunix_check_password_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + *interim_info = talloc_move(mem_ctx, &state->user_info_dc); + tevent_req_received(req); return NT_STATUS_OK; } static const struct auth_operations unix_ops = { - .name = "unix", - .want_check = authunix_want_check, - .check_password = authunix_check_password + .name = "unix", + .want_check = authunix_want_check, + .check_password_send = authunix_check_password_send, + .check_password_recv = authunix_check_password_recv, }; _PUBLIC_ NTSTATUS auth4_unix_init(TALLOC_CTX *ctx) -- 2.25.1 From ed5e4985eba717288c35953dc277b9097328eb34 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 15 Apr 2021 10:04:21 +0200 Subject: [PATCH 443/645] CVE-2020-25717 auth4: Make auth_sam pseudo-async Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit f852fb4cd4e2bcd676a9ea104c5bf00979771eed) --- source4/auth/ntlm/auth_sam.c | 69 ++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index 70eddc12c53..e4ebeae7523 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -36,6 +36,7 @@ #include "lib/messaging/irpc.h" #include "libcli/auth/libcli_auth.h" #include "libds/common/roles.h" +#include "lib/util/tevent_ntstatus.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -732,6 +733,68 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx return NT_STATUS_OK; } +struct authsam_check_password_state { + struct auth_user_info_dc *user_info_dc; + bool authoritative; +}; + +static struct tevent_req *authsam_check_password_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct auth_method_context *ctx, + const struct auth_usersupplied_info *user_info) +{ + struct tevent_req *req = NULL; + struct authsam_check_password_state *state = NULL; + NTSTATUS status; + + req = tevent_req_create( + mem_ctx, &state, struct authsam_check_password_state); + if (req == NULL) { + return NULL; + } + /* + * authsam_check_password_internals() sets this to false in + * the rodc case, otherwise it leaves it untouched. Default to + * "we're authoritative". + */ + state->authoritative = true; + + status = authsam_check_password_internals( + ctx, + state, + user_info, + &state->user_info_dc, + &state->authoritative); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + tevent_req_done(req); + return tevent_req_post(req, ev); +} + +static NTSTATUS authsam_check_password_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct auth_user_info_dc **interim_info, + bool *authoritative) +{ + struct authsam_check_password_state *state = tevent_req_data( + req, struct authsam_check_password_state); + NTSTATUS status; + + *authoritative = state->authoritative; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + *interim_info = talloc_move(mem_ctx, &state->user_info_dc); + tevent_req_received(req); + return NT_STATUS_OK; +} + static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info) @@ -887,14 +950,16 @@ static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx, static const struct auth_operations sam_ignoredomain_ops = { .name = "sam_ignoredomain", .want_check = authsam_ignoredomain_want_check, - .check_password = authsam_check_password_internals, + .check_password_send = authsam_check_password_send, + .check_password_recv = authsam_check_password_recv, .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper, }; static const struct auth_operations sam_ops = { .name = "sam", .want_check = authsam_want_check, - .check_password = authsam_check_password_internals, + .check_password_send = authsam_check_password_send, + .check_password_recv = authsam_check_password_recv, .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper, }; -- 2.25.1 From db6a8d993e9c1e8c41b7bc6c3c58ffdac5b68fba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Apr 2021 22:24:44 +0200 Subject: [PATCH 444/645] CVE-2020-25717 auth4: Remove sync check_password from auth_operations Remove complexity in the data structures, and pushes the async-ness one level down. Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 254af19ba89b4c42e5f45ec731e6577d2fcc6736) --- source4/auth/auth.h | 4 ---- source4/auth/ntlm/auth.c | 44 ++++------------------------------------ 2 files changed, 4 insertions(+), 44 deletions(-) diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 51895c9259f..3f9fb1ae3cb 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -61,10 +61,6 @@ struct auth_operations { /* Given the user supplied info, check a password */ - NTSTATUS (*check_password)(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_user_info_dc **interim_info, - bool *authoritative); struct tevent_req *(*check_password_send)(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct auth_method_context *ctx, diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c index ead5326705e..1aa2e3b065f 100644 --- a/source4/auth/ntlm/auth.c +++ b/source4/auth/ntlm/auth.c @@ -331,7 +331,6 @@ static void auth_check_password_next(struct tevent_req *req) struct auth_check_password_state *state = tevent_req_data(req, struct auth_check_password_state); struct tevent_req *subreq = NULL; - bool authoritative = true; NTSTATUS status; if (state->method == NULL) { @@ -356,47 +355,12 @@ static void auth_check_password_next(struct tevent_req *req) return; } - if (state->method->ops->check_password_send != NULL) { - subreq = state->method->ops->check_password_send(state, - state->ev, - state->method, - state->user_info); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, - auth_check_password_done, - req); - return; - } - - if (state->method->ops->check_password == NULL) { - tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - status = state->method->ops->check_password(state->method, - state, - state->user_info, - &state->user_info_dc, - &authoritative); - if (!authoritative || - NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { - DEBUG(11,("auth_check_password_send: " - "%s passes to the next method\n", - state->method->ops->name)); - state->method = state->method->next; - auth_check_password_next(req); - return; - } - - /* the backend has handled the request */ - - if (tevent_req_nterror(req, status)) { + subreq = state->method->ops->check_password_send( + state, state->ev, state->method, state->user_info); + if (tevent_req_nomem(subreq, req)) { return; } - - tevent_req_done(req); + tevent_req_set_callback(subreq, auth_check_password_done, req); } static void auth_check_password_done(struct tevent_req *subreq) -- 2.25.1 From a0a0546956850e8a5ed8108c810feaa208f52f25 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 2 Nov 2021 15:39:53 +0100 Subject: [PATCH 445/645] CVE-2020-25719 selftest/knownfail_mit_kdc: Add pointless knownfail to allow a later cherry-pick to apply cleanly BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 --- selftest/knownfail_mit_kdc | 1 + 1 file changed, 1 insertion(+) diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 0f845fb9b1c..4fc68ffd854 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -276,6 +276,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_ldap_service_ticket\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) # +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required\(ad_dc\) # -- 2.25.1 From 85749c4a7b9bc79d60ee4f5d2a83eeadf01d6ef5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Sep 2021 21:48:13 +1200 Subject: [PATCH 446/645] CVE-2020-25722 selftest: Move self.assertRaisesLdbError() to samba.tests.TestCase This is easier to reason with regarding which cases should work and which cases should fail, avoiding issues where more success than expected would be OK because a self.fail() was missed in a try: block. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Jeremy Allison (cherry picked from commit 298515cac2f35082483c2b4e4b7dbfe4df1d2e0c) --- python/samba/tests/__init__.py | 25 +++++++++++++++++++ .../dsdb/tests/python/linked_attributes.py | 21 ---------------- source4/dsdb/tests/python/subtree_rename.py | 25 ------------------- 3 files changed, 25 insertions(+), 46 deletions(-) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index d895802c34f..f4745519617 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -298,6 +298,31 @@ class TestCase(unittest.TestCase): self.fail(msg) + def assertRaisesLdbError(self, errcode, message, f, *args, **kwargs): + """Assert a function raises a particular LdbError.""" + try: + f(*args, **kwargs) + except ldb.LdbError as e: + (num, msg) = e.args + if num != errcode: + lut = {v: k for k, v in vars(ldb).items() + if k.startswith('ERR_') and isinstance(v, int)} + self.fail("%s, expected " + "LdbError %s, (%d) " + "got %s (%d) " + "%s" % (message, + lut.get(errcode), errcode, + lut.get(num), num, + msg)) + else: + lut = {v: k for k, v in vars(ldb).items() + if k.startswith('ERR_') and isinstance(v, int)} + self.fail("%s, expected " + "LdbError %s, (%d) " + "but we got success" % (message, + lut.get(errcode), + errcode)) + class LdbTestCase(TestCase): """Trivial test case for running tests against a LDB.""" diff --git a/source4/dsdb/tests/python/linked_attributes.py b/source4/dsdb/tests/python/linked_attributes.py index d015065ab04..b14fefc46c1 100644 --- a/source4/dsdb/tests/python/linked_attributes.py +++ b/source4/dsdb/tests/python/linked_attributes.py @@ -166,27 +166,6 @@ class LATests(samba.tests.TestCase): attrs=['objectGUID']) return str(misc.GUID(res[0]['objectGUID'][0])) - def assertRaisesLdbError(self, errcode, msg, f, *args, **kwargs): - """Assert a function raises a particular LdbError.""" - try: - f(*args, **kwargs) - except ldb.LdbError as e: - (num, msg) = e.args - if num != errcode: - lut = {v: k for k, v in vars(ldb).items() - if k.startswith('ERR_') and isinstance(v, int)} - self.fail("%s, expected " - "LdbError %s, (%d) " - "got %s (%d)" % (msg, - lut.get(errcode), errcode, - lut.get(num), num)) - else: - lut = {v: k for k, v in vars(ldb).items() - if k.startswith('ERR_') and isinstance(v, int)} - self.fail("%s, expected " - "LdbError %s, (%d) " - "but we got success" % (msg, lut.get(errcode), errcode)) - def _test_la_backlinks(self, reveal=False): tag = 'backlinks' kwargs = {} diff --git a/source4/dsdb/tests/python/subtree_rename.py b/source4/dsdb/tests/python/subtree_rename.py index c4f6bc7a160..e422c2e2b01 100644 --- a/source4/dsdb/tests/python/subtree_rename.py +++ b/source4/dsdb/tests/python/subtree_rename.py @@ -201,31 +201,6 @@ class SubtreeRenameTests(samba.tests.TestCase): attrs=['objectGUID']) return str(misc.GUID(res[0]['objectGUID'][0])) - def assertRaisesLdbError(self, errcode, message, f, *args, **kwargs): - """Assert a function raises a particular LdbError.""" - try: - f(*args, **kwargs) - except ldb.LdbError as e: - (num, msg) = e.args - if num != errcode: - lut = {v: k for k, v in vars(ldb).items() - if k.startswith('ERR_') and isinstance(v, int)} - self.fail("%s, expected " - "LdbError %s, (%d) " - "got %s (%d) " - "%s" % (message, - lut.get(errcode), errcode, - lut.get(num), num, - msg)) - else: - lut = {v: k for k, v in vars(ldb).items() - if k.startswith('ERR_') and isinstance(v, int)} - self.fail("%s, expected " - "LdbError %s, (%d) " - "but we got success" % (message, - lut.get(errcode), - errcode)) - def test_la_move_ou_tree(self): tag = 'move_tree' -- 2.25.1 From d969a62e5bfc67c602da27f77699683caf68b8b6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 10:07:31 +1200 Subject: [PATCH 447/645] CVE-2020-25722 selftest: Modernise user_account_control.py tests use a common self.OU We set and use a single self.OU to ensure consistancy and reduce string duplication. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit 8b078bbf8717b9407cdbc1588dd065164ab78e1b) --- .../dsdb/tests/python/user_account_control.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 2d62d4c32b1..cb614b165e5 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -90,7 +90,7 @@ class UserAccountControlTests(samba.tests.TestCase): def add_computer_ldap(self, computername, others=None, samdb=None): if samdb is None: samdb = self.samdb - dn = "CN=%s,OU=test_computer_ou1,%s" % (computername, self.base_dn) + dn = "CN=%s,%s" % (computername, self.OU) domainname = ldb.Dn(self.samdb, self.samdb.domain_dn()).canonical_str().replace("/", "") samaccountname = "%s$" % computername dnshostname = "%s.%s" % (computername, domainname) @@ -131,8 +131,9 @@ class UserAccountControlTests(samba.tests.TestCase): self.unpriv_user_pw = "samba123@" self.unpriv_creds = self.get_creds(self.unpriv_user, self.unpriv_user_pw) - delete_force(self.admin_samdb, "CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) - delete_force(self.admin_samdb, "OU=test_computer_ou1,%s" % (self.base_dn)) + self.OU = "OU=test_computer_ou1,%s" % (self.base_dn) + + delete_force(self.admin_samdb, self.OU, controls=["tree_delete:0"]) delete_force(self.admin_samdb, "CN=%s,CN=Users,%s" % (self.unpriv_user, self.base_dn)) self.admin_samdb.newuser(self.unpriv_user, self.unpriv_user_pw) @@ -151,27 +152,27 @@ class UserAccountControlTests(samba.tests.TestCase): self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid) self.sd_utils = sd_utils.SDUtils(self.admin_samdb) + self.admin_samdb.create_ou(self.OU) - self.admin_samdb.create_ou("OU=test_computer_ou1," + self.base_dn) self.unpriv_user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) self.add_computer_ldap("testcomputer-t") - self.sd_utils.modify_sd_on_dn("OU=test_computer_ou1," + self.base_dn, old_sd) + self.sd_utils.modify_sd_on_dn(self.OU, old_sd) self.computernames = ["testcomputer-0"] # Get the SD of the template account, then force it to match # what we expect for SeMachineAccountPrivilege accounts, so we # can confirm we created the accounts correctly - self.sd_reference_cc = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) + self.sd_reference_cc = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,%s" % (self.OU)) - self.sd_reference_modify = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) + self.sd_reference_modify = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,%s" % (self.OU)) for ace in self.sd_reference_modify.dacl.aces: if ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED and ace.trustee == self.unpriv_user_sid: ace.access_mask = ace.access_mask | security.SEC_ADS_SELF_WRITE | security.SEC_ADS_WRITE_PROP @@ -191,9 +192,8 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) - - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) + self.sd_utils.dacl_add_ace(self.OU, mod) computername = self.computernames[0] sd = ldb.MessageElement((ndr_pack(self.sd_reference_modify)), @@ -276,9 +276,9 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) computername = self.computernames[0] self.add_computer_ldap(computername) @@ -392,9 +392,9 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) computername = self.computernames[0] self.add_computer_ldap(computername) @@ -446,9 +446,9 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) computername = self.computernames[0] self.add_computer_ldap(computername, others={"userAccountControl": [str(account_type)]}) @@ -621,9 +621,9 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) invalid_bits = set([UF_TEMP_DUPLICATE_ACCOUNT, UF_PARTIAL_SECRETS_ACCOUNT]) # These bits are privileged, but authenticated users have that CAR by default, so this is a pain to test @@ -637,7 +637,7 @@ class UserAccountControlTests(samba.tests.TestCase): for bit in bits: try: self.add_computer_ldap(computername, others={"userAccountControl": [str(bit)]}) - delete_force(self.admin_samdb, "CN=%s,OU=test_computer_ou1,%s" % (computername, self.base_dn)) + delete_force(self.admin_samdb, "CN=%s,%s" % (computername, self.OU)) if bit in priv_bits: self.fail("Unexpectdly able to set userAccountControl bit 0x%08X on %s" % (bit, computername)) @@ -659,9 +659,9 @@ class UserAccountControlTests(samba.tests.TestCase): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) - old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) + old_sd = self.sd_utils.read_sd_on_dn(self.OU) - self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) + self.sd_utils.dacl_add_ace(self.OU, mod) try: # When creating a new object, you can not ever set the primaryGroupID self.add_computer_ldap(computername, others={"primaryGroupID": [str(security.DOMAIN_RID_ADMINS)]}) -- 2.25.1 From 0078342f24f1e2abcb05403eaf273559ec6ac68b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 10:10:56 +1200 Subject: [PATCH 448/645] CVE-2020-25722 selftest: Use addCleanup rather than tearDown in user_account_control.py self.addCleanup() is called regardless of the test failure or error status and so is more reliable, particularly during development. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit 8c455268165f0bbfce17407df2c1746a0e03f828) --- source4/dsdb/tests/python/user_account_control.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index cb614b165e5..81664079adf 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -144,6 +144,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.unpriv_user_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) self.unpriv_user_dn = res[0].dn + self.addCleanup(self.admin_samdb.delete, self.unpriv_user_dn) self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp) @@ -153,6 +154,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.sd_utils = sd_utils.SDUtils(self.admin_samdb) self.admin_samdb.create_ou(self.OU) + self.addCleanup(self.admin_samdb.delete, self.OU, ["tree_delete:1"]) self.unpriv_user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid) @@ -180,14 +182,6 @@ class UserAccountControlTests(samba.tests.TestCase): # Now reconnect without domain admin rights self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp) - def tearDown(self): - super(UserAccountControlTests, self).tearDown() - for computername in self.computernames: - delete_force(self.admin_samdb, "CN=%s,OU=test_computer_ou1,%s" % (computername, self.base_dn)) - delete_force(self.admin_samdb, "CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) - delete_force(self.admin_samdb, "OU=test_computer_ou1,%s" % (self.base_dn)) - delete_force(self.admin_samdb, "CN=%s,CN=Users,%s" % (self.unpriv_user, self.base_dn)) - def test_add_computer_sd_cc(self): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) -- 2.25.1 From 799886c104786de3fb1c0c79155d5e03d3453a84 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 13:03:15 +1200 Subject: [PATCH 449/645] CVE-2020-25722 pydsdb: Add API to return strings of known UF_ flags Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit fb6c0b9e2a10c9559d3e056bb020bd2c990da998) --- libds/common/flag_mapping.c | 50 +++++++++++++++++++++++++++++ libds/common/flag_mapping.h | 1 + libds/common/flags.h | 5 +++ python/samba/tests/dsdb_api.py | 57 ++++++++++++++++++++++++++++++++++ selftest/tests.py | 1 + source4/dsdb/pydsdb.c | 30 ++++++++++++++++++ 6 files changed, 144 insertions(+) create mode 100644 python/samba/tests/dsdb_api.py diff --git a/libds/common/flag_mapping.c b/libds/common/flag_mapping.c index ddc8ec5c198..020922db659 100644 --- a/libds/common/flag_mapping.c +++ b/libds/common/flag_mapping.c @@ -164,3 +164,53 @@ uint32_t ds_uf2prim_group_rid(uint32_t uf) return prim_group_rid; } + +#define FLAG(x) { .name = #x, .uf = x } +struct { + const char *name; + uint32_t uf; +} user_account_control_name_map[] = { + FLAG(UF_SCRIPT), + FLAG(UF_ACCOUNTDISABLE), + FLAG(UF_00000004), + FLAG(UF_HOMEDIR_REQUIRED), + FLAG(UF_LOCKOUT), + FLAG(UF_PASSWD_NOTREQD), + FLAG(UF_PASSWD_CANT_CHANGE), + FLAG(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED), + + FLAG(UF_TEMP_DUPLICATE_ACCOUNT), + FLAG(UF_NORMAL_ACCOUNT), + FLAG(UF_00000400), + FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT), + + FLAG(UF_WORKSTATION_TRUST_ACCOUNT), + FLAG(UF_SERVER_TRUST_ACCOUNT), + FLAG(UF_00004000), + FLAG(UF_00008000), + + FLAG(UF_DONT_EXPIRE_PASSWD), + FLAG(UF_MNS_LOGON_ACCOUNT), + FLAG(UF_SMARTCARD_REQUIRED), + FLAG(UF_TRUSTED_FOR_DELEGATION), + + FLAG(UF_NOT_DELEGATED), + FLAG(UF_USE_DES_KEY_ONLY), + FLAG(UF_DONT_REQUIRE_PREAUTH), + FLAG(UF_PASSWORD_EXPIRED), + FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION), + FLAG(UF_NO_AUTH_DATA_REQUIRED), + FLAG(UF_PARTIAL_SECRETS_ACCOUNT), + FLAG(UF_USE_AES_KEYS) +}; + +const char *dsdb_user_account_control_flag_bit_to_string(uint32_t uf) +{ + int i; + for (i=0; i < ARRAY_SIZE(user_account_control_name_map); i++) { + if (uf == user_account_control_name_map[i].uf) { + return user_account_control_name_map[i].name; + } + } + return NULL; +} diff --git a/libds/common/flag_mapping.h b/libds/common/flag_mapping.h index ae721da894a..f08d5593af6 100644 --- a/libds/common/flag_mapping.h +++ b/libds/common/flag_mapping.h @@ -31,5 +31,6 @@ uint32_t ds_uf2atype(uint32_t uf); uint32_t ds_gtype2atype(uint32_t gtype); enum lsa_SidType ds_atype_map(uint32_t atype); uint32_t ds_uf2prim_group_rid(uint32_t uf); +const char *dsdb_user_account_control_flag_bit_to_string(uint32_t uf); #endif /* __LIBDS_COMMON_FLAG_MAPPING_H__ */ diff --git a/libds/common/flags.h b/libds/common/flags.h index d436f2bafd8..75e04b0c488 100644 --- a/libds/common/flags.h +++ b/libds/common/flags.h @@ -18,6 +18,8 @@ along with this program. If not, see . */ +/* Please keep this list in sync with the flag_mapping.c and pydsdb.c */ + /* User flags for "userAccountControl" */ #define UF_SCRIPT 0x00000001 /* NT or Lan Manager Login script must be executed */ #define UF_ACCOUNTDISABLE 0x00000002 @@ -53,6 +55,9 @@ #define UF_PARTIAL_SECRETS_ACCOUNT 0x04000000 #define UF_USE_AES_KEYS 0x08000000 +/* Please keep this list in sync with the flag_mapping.c and pydsdb.c */ + + #define UF_TRUST_ACCOUNT_MASK (\ UF_INTERDOMAIN_TRUST_ACCOUNT |\ UF_WORKSTATION_TRUST_ACCOUNT |\ diff --git a/python/samba/tests/dsdb_api.py b/python/samba/tests/dsdb_api.py new file mode 100644 index 00000000000..997407917af --- /dev/null +++ b/python/samba/tests/dsdb_api.py @@ -0,0 +1,57 @@ +# Unix SMB/CIFS implementation. Tests for dsdb +# Copyright (C) Andrew Bartlett 2021 +# +# 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 . +# + +"""Tests for samba.dsdb.""" + +from samba.tests import TestCase, DynamicTestCase +from samba.dsdb import user_account_control_flag_bit_to_string +import samba + + +@DynamicTestCase +class DsdbFlagTests(TestCase): + + @classmethod + def setUpDynamicTestCases(cls): + + for x in dir(samba.dsdb): + if x.startswith("UF_"): + cls.generate_dynamic_test("test", + x, + x, + getattr(samba.dsdb, x)) + + + def _test_with_args(self, uf_string, uf_bit): + self.assertEqual(user_account_control_flag_bit_to_string(uf_bit), + uf_string) + + + def test_not_a_flag(self): + self.assertRaises(KeyError, + user_account_control_flag_bit_to_string, + 0xabcdef) + + def test_too_long(self): + self.assertRaises(OverflowError, + user_account_control_flag_bit_to_string, + 0xabcdefffff) + + def test_way_too_long(self): + self.assertRaises(OverflowError, + user_account_control_flag_bit_to_string, + 0xabcdeffffffffffff) diff --git a/selftest/tests.py b/selftest/tests.py index b9b95d800cc..10648b19155 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -86,6 +86,7 @@ planpythontestsuite("none", "samba.tests.s3registry") planpythontestsuite("none", "samba.tests.s3windb") planpythontestsuite("none", "samba.tests.s3idmapdb") planpythontestsuite("none", "samba.tests.samba3sam") +planpythontestsuite("none", "samba.tests.dsdb_api") planpythontestsuite( "none", "wafsamba.tests.test_suite", extra_path=[os.path.join(samba4srcdir, "..", "buildtools"), diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index ac1563f2305..609a3b2ba7c 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -33,6 +33,7 @@ #include "lib/util/dlinklist.h" #include "dsdb/kcc/garbage_collect_tombstones.h" #include "dsdb/kcc/scavenge_dns_records.h" +#include "libds/common/flag_mapping.h" /* FIXME: These should be in a header file somewhere */ @@ -1400,6 +1401,30 @@ static PyObject *py_dsdb_load_udv_v2(PyObject *self, PyObject *args) return pylist; } +static PyObject *py_dsdb_user_account_control_flag_bit_to_string(PyObject *self, PyObject *args) +{ + const char *str; + long long uf; + if (!PyArg_ParseTuple(args, "L", &uf)) { + return NULL; + } + + if (uf > UINT32_MAX) { + return PyErr_Format(PyExc_OverflowError, "No UF_ flags are over UINT32_MAX"); + } + if (uf < 0) { + return PyErr_Format(PyExc_KeyError, "No UF_ flags are less then zero"); + } + + str = dsdb_user_account_control_flag_bit_to_string(uf); + if (str == NULL) { + return PyErr_Format(PyExc_KeyError, + "No such UF_ flag 0x%08x", + (unsigned int)uf); + } + return PyUnicode_FromString(str); +} + static PyMethodDef py_dsdb_methods[] = { { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name, METH_VARARGS, "Get the server site name as a string"}, @@ -1479,6 +1504,11 @@ static PyMethodDef py_dsdb_methods[] = { "_dsdb_allocate_rid(samdb)" " -> RID" }, { "_dsdb_load_udv_v2", (PyCFunction)py_dsdb_load_udv_v2, METH_VARARGS, NULL }, + { "user_account_control_flag_bit_to_string", + (PyCFunction)py_dsdb_user_account_control_flag_bit_to_string, + METH_VARARGS, + "user_account_control_flag_bit_to_string(bit)" + " -> string name" }, {0} }; -- 2.25.1 From 7c4b293ce34015ecdd3f76e3a8770d48bc618335 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 14:37:06 +1200 Subject: [PATCH 450/645] CVE-2020-25722 selftest: Use @DynamicTestCase in user_account_control test_uac_bits_unrelated_modify() This is a nice easy example of how the test generation code works, and it combined nicely with the earlier patch to return string names from the UF_ constants. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit 8701ce492fc3a209035b152961d8c17e801b082a) --- .../dsdb/tests/python/user_account_control.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 81664079adf..4ef43502c8c 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -27,7 +27,7 @@ from samba.samdb import SamDB from samba.dcerpc import samr, security, lsa from samba.credentials import Credentials from samba.ndr import ndr_unpack, ndr_pack -from samba.tests import delete_force +from samba.tests import delete_force, DynamicTestCase from samba import gensec, sd_utils from samba.credentials import DONT_USE_KERBEROS from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError @@ -41,6 +41,7 @@ from samba.dsdb import UF_SCRIPT, UF_ACCOUNTDISABLE, UF_00000004, UF_HOMEDIR_REQ UF_TRUSTED_FOR_DELEGATION, UF_NOT_DELEGATED, UF_USE_DES_KEY_ONLY, UF_DONT_REQUIRE_PREAUTH, \ UF_PASSWORD_EXPIRED, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, UF_NO_AUTH_DATA_REQUIRED, \ UF_PARTIAL_SECRETS_ACCOUNT, UF_USE_AES_KEYS +from samba import dsdb parser = optparse.OptionParser("user_account_control.py [options] ") @@ -86,7 +87,15 @@ bits = [UF_SCRIPT, UF_ACCOUNTDISABLE, UF_00000004, UF_HOMEDIR_REQUIRED, account_types = set([UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT]) +@DynamicTestCase class UserAccountControlTests(samba.tests.TestCase): + @classmethod + def setUpDynamicTestCases(cls): + for account_type in [UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT]: + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + cls.generate_dynamic_test("test_uac_bits_unrelated_modify", + account_type_str, account_type) + def add_computer_ldap(self, computername, others=None, samdb=None): if samdb is None: samdb = self.samdb @@ -436,7 +445,7 @@ class UserAccountControlTests(samba.tests.TestCase): else: self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) - def uac_bits_unrelated_modify_helper(self, account_type): + def _test_uac_bits_unrelated_modify_with_args(self, account_type): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) @@ -603,12 +612,6 @@ class UserAccountControlTests(samba.tests.TestCase): UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD, "bit 0X%08x should have been removed" % bit) - def test_uac_bits_unrelated_modify_normal(self): - self.uac_bits_unrelated_modify_helper(UF_NORMAL_ACCOUNT) - - def test_uac_bits_unrelated_modify_workstation(self): - self.uac_bits_unrelated_modify_helper(UF_WORKSTATION_TRUST_ACCOUNT) - def test_uac_bits_add(self): computername = self.computernames[0] -- 2.25.1 From e941fa557c1f85887b24ef3849dbc54d09a3f4b3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 14:51:27 +1200 Subject: [PATCH 451/645] CVE-2020-25722 selftest: Replace internal loop in test_uac_bits_add() using @DynamicTestClass This generates a single test per bit which is easier to debug. Elsewhere we use this pattern where we want to be able to put some cases in a knownfail, which is otherwise not possible. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit 60f1b6cf0ef0bf6736d8db9c53fa48fe9f3d8e75) --- .../dsdb/tests/python/user_account_control.py | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 4ef43502c8c..1a396740df0 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -96,6 +96,16 @@ class UserAccountControlTests(samba.tests.TestCase): cls.generate_dynamic_test("test_uac_bits_unrelated_modify", account_type_str, account_type) + for bit in bits: + try: + bit_str = dsdb.user_account_control_flag_bit_to_string(bit) + except KeyError: + bit_str = hex(bit) + + cls.generate_dynamic_test("test_uac_bits_add", + bit_str, bit, bit_str) + + def add_computer_ldap(self, computername, others=None, samdb=None): if samdb is None: samdb = self.samdb @@ -612,7 +622,7 @@ class UserAccountControlTests(samba.tests.TestCase): UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD, "bit 0X%08x should have been removed" % bit) - def test_uac_bits_add(self): + def _test_uac_bits_add_with_args(self, bit, bit_str): computername = self.computernames[0] user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) @@ -631,24 +641,30 @@ class UserAccountControlTests(samba.tests.TestCase): priv_bits = set([UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT, UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION]) - for bit in bits: - try: - self.add_computer_ldap(computername, others={"userAccountControl": [str(bit)]}) - delete_force(self.admin_samdb, "CN=%s,%s" % (computername, self.OU)) - if bit in priv_bits: - self.fail("Unexpectdly able to set userAccountControl bit 0x%08X on %s" % (bit, computername)) - - except LdbError as e4: - (enum, estr) = e4.args - if bit in invalid_bits: - self.assertEqual(enum, ldb.ERR_OTHER, "Invalid bit 0x%08X was able to be set on %s" % (bit, computername)) - # No point going on, try the next bit - continue - elif bit in priv_bits: - self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) - continue - else: - self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, computername, estr)) + try: + self.add_computer_ldap(computername, others={"userAccountControl": [str(bit)]}) + delete_force(self.admin_samdb, "CN=%s,%s" % (computername, self.OU)) + if bit in priv_bits: + self.fail("Unexpectdly able to set userAccountControl bit 0x%08X (%s) on %s" + % (bit, bit_str, computername)) + + except LdbError as e4: + (enum, estr) = e4.args + if bit in invalid_bits: + self.assertEqual(enum, + ldb.ERR_OTHER, + "Invalid bit 0x%08X (%s) was able to be set on %s" + % (bit, + bit_str, + computername)) + elif bit in priv_bits: + self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail("Unable to set userAccountControl bit 0x%08X (%s) on %s: %s" + % (bit, + bit_str, + computername, + estr)) def test_primarygroupID_cc_add(self): computername = self.computernames[0] -- 2.25.1 From 7f133d2f5ff5e982b79a411b57f5c268c3a7bef1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 14:54:39 +1200 Subject: [PATCH 452/645] CVE-2020-25722 selftest: Replace internal loop in test_uac_bits_set() using @DynamicTestClass This generates a single test per bit which is easier to debug. Elsewhere we use this pattern where we want to be able to put some cases in a knownfail, which is otherwise not possible. Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 (cherry picked from commit 17ae0319db53a7b88e7fb44a9e2fd4bf1d1daa0e) --- .../dsdb/tests/python/user_account_control.py | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 1a396740df0..fd0ae38a3f9 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -105,6 +105,9 @@ class UserAccountControlTests(samba.tests.TestCase): cls.generate_dynamic_test("test_uac_bits_add", bit_str, bit, bit_str) + cls.generate_dynamic_test("test_uac_bits_set", + bit_str, bit, bit_str) + def add_computer_ldap(self, computername, others=None, samdb=None): if samdb is None: @@ -401,7 +404,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE) - def test_uac_bits_set(self): + def _test_uac_bits_set_with_args(self, bit, bit_str): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) @@ -435,25 +438,27 @@ class UserAccountControlTests(samba.tests.TestCase): invalid_bits = set([UF_TEMP_DUPLICATE_ACCOUNT, UF_PARTIAL_SECRETS_ACCOUNT]) - for bit in bits: - m = ldb.Message() - m.dn = res[0].dn - m["userAccountControl"] = ldb.MessageElement(str(bit | UF_PASSWD_NOTREQD), - ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - if (bit in priv_bits): - self.fail("Unexpectedly able to set userAccountControl bit 0x%08X on %s" % (bit, m.dn)) - except LdbError as e: - (enum, estr) = e.args - if bit in invalid_bits: - self.assertEqual(enum, ldb.ERR_OTHER, "was not able to set 0x%08X on %s" % (bit, m.dn)) - # No point going on, try the next bit - continue - elif (bit in priv_bits): - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) - else: - self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) + m = ldb.Message() + m.dn = res[0].dn + m["userAccountControl"] = ldb.MessageElement(str(bit | UF_PASSWD_NOTREQD), + ldb.FLAG_MOD_REPLACE, "userAccountControl") + try: + self.samdb.modify(m) + if (bit in priv_bits): + self.fail("Unexpectedly able to set userAccountControl bit 0x%08X (%s), on %s" + % (bit, bit_str, m.dn)) + except LdbError as e: + (enum, estr) = e.args + if bit in invalid_bits: + self.assertEqual(enum, + ldb.ERR_OTHER, + "was not able to set 0x%08X (%s) on %s" + % (bit, bit_str, m.dn)) + elif (bit in priv_bits): + self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + else: + self.fail("Unable to set userAccountControl bit 0x%08X (%s) on %s: %s" + % (bit, bit_str, m.dn, estr)) def _test_uac_bits_unrelated_modify_with_args(self, account_type): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) -- 2.25.1 From b69fb3a55610a323ce37027687a1350c20b9bd36 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 30 Aug 2021 18:17:47 +1200 Subject: [PATCH 453/645] CVE-2020-25722 selftest: Update user_account_control tests to pass against Windows 2019 This gets us closer to passing against Windows 2019, without making major changes to what was tested. More tests are needed, but it is important to get what was being tested tested again. Account types (eg UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT) are now required on all objects, this can't be omitted any more. Also for UF_NORMAL_ACCOUNT for these accounts without a password set |UF_PASSWD_NOTREQD must be included. Signed-off-by: Andrew Bartlett Reviewed-by: Alexander Bokovoy BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Sep 15 08:49:11 UTC 2021 on sn-devel-184 (cherry picked from commit d12cb47724c2e8d19a28286d4c3ef72271a002fd) --- selftest/knownfail.d/user_account_control | 1 + .../dsdb/tests/python/user_account_control.py | 114 ++++++++++++++++-- 2 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 selftest/knownfail.d/user_account_control diff --git a/selftest/knownfail.d/user_account_control b/selftest/knownfail.d/user_account_control new file mode 100644 index 00000000000..ad3af678708 --- /dev/null +++ b/selftest/knownfail.d/user_account_control @@ -0,0 +1 @@ +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_cc_normal_bare.ad_dc_default diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index fd0ae38a3f9..efb83b2dcff 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -84,7 +84,7 @@ bits = [UF_SCRIPT, UF_ACCOUNTDISABLE, UF_00000004, UF_HOMEDIR_REQUIRED, UF_PARTIAL_SECRETS_ACCOUNT, UF_USE_AES_KEYS, int("0x10000000", 16), int("0x20000000", 16), int("0x40000000", 16), int("0x80000000", 16)] -account_types = set([UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT]) +account_types = set([UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT, UF_INTERDOMAIN_TRUST_ACCOUNT]) @DynamicTestCase @@ -108,6 +108,11 @@ class UserAccountControlTests(samba.tests.TestCase): cls.generate_dynamic_test("test_uac_bits_set", bit_str, bit, bit_str) + cls.generate_dynamic_test("test_uac_bits_add", + "UF_NORMAL_ACCOUNT_UF_PASSWD_NOTREQD", + UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD, + "UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD") + def add_computer_ldap(self, computername, others=None, samdb=None): if samdb is None: @@ -272,7 +277,7 @@ class UserAccountControlTests(samba.tests.TestCase): m = ldb.Message() m.dn = res[0].dn - m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT), + m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") self.samdb.modify(m) @@ -334,9 +339,10 @@ class UserAccountControlTests(samba.tests.TestCase): (enum, estr) = e10.args self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + m = ldb.Message() m.dn = res[0].dn - m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT), + m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") self.samdb.modify(m) @@ -351,6 +357,50 @@ class UserAccountControlTests(samba.tests.TestCase): (enum, estr) = e11.args self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + def test_add_computer_cc_normal_bare(self): + user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) + mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) + + old_sd = self.sd_utils.read_sd_on_dn(self.OU) + self.sd_utils.dacl_add_ace(self.OU, mod) + + computername = self.computernames[0] + sd = ldb.MessageElement((ndr_pack(self.sd_reference_modify)), + ldb.FLAG_MOD_ADD, + "nTSecurityDescriptor") + self.add_computer_ldap(computername, + others={"nTSecurityDescriptor": sd}) + + res = self.admin_samdb.search("%s" % self.base_dn, + expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + scope=SCOPE_SUBTREE, + attrs=["ntSecurityDescriptor"]) + + desc = res[0]["nTSecurityDescriptor"][0] + desc = ndr_unpack(security.descriptor, desc, allow_remaining=True) + + sddl = desc.as_sddl(self.domain_sid) + self.assertEqual(self.sd_reference_modify.as_sddl(self.domain_sid), sddl) + + m = ldb.Message() + m.dn = res[0].dn + m["description"] = ldb.MessageElement( + ("A description"), ldb.FLAG_MOD_REPLACE, + "description") + self.samdb.modify(m) + + m = ldb.Message() + m.dn = res[0].dn + m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT), + ldb.FLAG_MOD_REPLACE, "userAccountControl") + try: + self.samdb.modify(m) + self.fail("Unexpectedly able to set userAccountControl to be an Normal account without |UF_PASSWD_NOTREQD on %s" % m.dn) + except LdbError as e7: + (enum, estr) = e7.args + self.assertEqual(ldb.ERR_UNWILLING_TO_PERFORM, enum) + + def test_admin_mod_uac(self): computername = self.computernames[0] self.add_computer_ldap(computername, samdb=self.admin_samdb) @@ -469,13 +519,23 @@ class UserAccountControlTests(samba.tests.TestCase): self.sd_utils.dacl_add_ace(self.OU, mod) computername = self.computernames[0] - self.add_computer_ldap(computername, others={"userAccountControl": [str(account_type)]}) + if account_type == UF_WORKSTATION_TRUST_ACCOUNT: + self.add_computer_ldap(computername, others={"userAccountControl": [str(account_type)]}) + else: + self.add_computer_ldap(computername) - res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + res = self.admin_samdb.search(self.OU, + expression=f"(cn={computername})", scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) - self.assertEqual(int(res[0]["userAccountControl"][0]), account_type) + self.assertEqual(len(res), 1) + + orig_uac = int(res[0]["userAccountControl"][0]) + if account_type == UF_WORKSTATION_TRUST_ACCOUNT: + self.assertEqual(orig_uac, account_type) + else: + self.assertEqual(orig_uac & UF_NORMAL_ACCOUNT, + account_type) m = ldb.Message() m.dn = res[0].dn @@ -504,7 +564,7 @@ class UserAccountControlTests(samba.tests.TestCase): # Reset this to the initial position, just to be sure m = ldb.Message() m.dn = res[0].dn - m["userAccountControl"] = ldb.MessageElement(str(account_type), + m["userAccountControl"] = ldb.MessageElement(str(orig_uac), ldb.FLAG_MOD_REPLACE, "userAccountControl") self.admin_samdb.modify(m) @@ -513,7 +573,11 @@ class UserAccountControlTests(samba.tests.TestCase): scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) - self.assertEqual(int(res[0]["userAccountControl"][0]), account_type) + if account_type == UF_WORKSTATION_TRUST_ACCOUNT: + self.assertEqual(orig_uac, account_type) + else: + self.assertEqual(orig_uac & UF_NORMAL_ACCOUNT, + account_type) m = ldb.Message() m.dn = res[0].dn @@ -521,6 +585,7 @@ class UserAccountControlTests(samba.tests.TestCase): ldb.FLAG_MOD_REPLACE, "userAccountControl") try: self.admin_samdb.modify(m) + if bit in invalid_bits: self.fail("Should have been unable to set userAccountControl bit 0x%08X on %s" % (bit, m.dn)) @@ -534,6 +599,19 @@ class UserAccountControlTests(samba.tests.TestCase): self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) # No point going on, try the next bit continue + + elif (account_type == UF_NORMAL_ACCOUNT) \ + and (bit in account_types) \ + and (bit != account_type): + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + continue + + elif (account_type == UF_WORKSTATION_TRUST_ACCOUNT) \ + and (bit != UF_NORMAL_ACCOUNT) \ + and (bit != account_type): + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + continue + else: self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) @@ -637,17 +715,27 @@ class UserAccountControlTests(samba.tests.TestCase): self.sd_utils.dacl_add_ace(self.OU, mod) - invalid_bits = set([UF_TEMP_DUPLICATE_ACCOUNT, UF_PARTIAL_SECRETS_ACCOUNT]) + invalid_bits = set([UF_TEMP_DUPLICATE_ACCOUNT]) + # UF_NORMAL_ACCOUNT is invalid alone, needs UF_PASSWD_NOTREQD + unwilling_bits = set([UF_NORMAL_ACCOUNT]) + # These bits are privileged, but authenticated users have that CAR by default, so this is a pain to test priv_to_auth_users_bits = set([UF_PASSWD_NOTREQD, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED, UF_DONT_EXPIRE_PASSWD]) # These bits really are privileged priv_bits = set([UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT, - UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION]) + UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, + UF_PARTIAL_SECRETS_ACCOUNT]) + + if bit not in account_types and ((bit & UF_NORMAL_ACCOUNT) == 0): + bit_add = bit|UF_WORKSTATION_TRUST_ACCOUNT + else: + bit_add = bit try: - self.add_computer_ldap(computername, others={"userAccountControl": [str(bit)]}) + + self.add_computer_ldap(computername, others={"userAccountControl": [str(bit_add)]}) delete_force(self.admin_samdb, "CN=%s,%s" % (computername, self.OU)) if bit in priv_bits: self.fail("Unexpectdly able to set userAccountControl bit 0x%08X (%s) on %s" @@ -664,6 +752,8 @@ class UserAccountControlTests(samba.tests.TestCase): computername)) elif bit in priv_bits: self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + elif bit in unwilling_bits: + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) else: self.fail("Unable to set userAccountControl bit 0x%08X (%s) on %s: %s" % (bit, -- 2.25.1 From 4a9d094f6b9ed33c8b743419306e2d0601258e63 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 16 Sep 2021 16:09:24 +1200 Subject: [PATCH 454/645] CVE-2020-25722 selftest: Use self.assertRaisesLdbError() in user_account_control.py test This changes most of the simple pattern with self.samdb.modify() to use the wrapper. Some other calls still need to be converted, while the complex decision tree tests should remain as-is for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Mon Oct 4 21:55:43 UTC 2021 on sn-devel-184 (cherry picked from commit b45190bdac7bd9dcefd5ed88be4bd9a97a712664) --- .../dsdb/tests/python/user_account_control.py | 100 +++++++----------- 1 file changed, 37 insertions(+), 63 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index efb83b2dcff..c9b50b83e9d 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -245,35 +245,27 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_SERVER_TRUST_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to be a DC on %s" % m.dn) - except LdbError as e5: - (enum, estr) = e5.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl to be a DC on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT | samba.dsdb.UF_PARTIAL_SECRETS_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to be an RODC on %s" % m.dn) - except LdbError as e6: - (enum, estr) = e6.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl to be a RODC on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to be an Workstation on %s" % m.dn) - except LdbError as e7: - (enum, estr) = e7.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl to be a Workstation on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn @@ -285,13 +277,10 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["primaryGroupID"] = ldb.MessageElement(str(security.DOMAIN_RID_ADMINS), ldb.FLAG_MOD_REPLACE, "primaryGroupID") - try: - self.samdb.modify(m) - except LdbError as e8: - (enum, estr) = e8.args - self.assertEqual(ldb.ERR_UNWILLING_TO_PERFORM, enum) - return - self.fail() + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + f"Unexpectedly able to set primaryGroupID on {m.dn}", + self.samdb.modify, m) + def test_mod_computer_cc(self): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) @@ -321,24 +310,17 @@ class UserAccountControlTests(samba.tests.TestCase): m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT | samba.dsdb.UF_PARTIAL_SECRETS_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl on %s" % m.dn) - except LdbError as e9: - (enum, estr) = e9.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl as RODC on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_SERVER_TRUST_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail() - except LdbError as e10: - (enum, estr) = e10.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) - + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl as DC on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn @@ -350,12 +332,10 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to be an Workstation on %s" % m.dn) - except LdbError as e11: - (enum, estr) = e11.args - self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Unexpectedly able to set userAccountControl to be a workstation on {m.dn}", + self.samdb.modify, m) + def test_add_computer_cc_normal_bare(self): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) @@ -393,12 +373,11 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to be an Normal account without |UF_PASSWD_NOTREQD on %s" % m.dn) - except LdbError as e7: - (enum, estr) = e7.args - self.assertEqual(ldb.ERR_UNWILLING_TO_PERFORM, enum) + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + f"Unexpectedly able to set userAccountControl to be an Normal " + "account without |UF_PASSWD_NOTREQD Unexpectedly able to " + "set userAccountControl to be a workstation on {m.dn}", + self.samdb.modify, m) def test_admin_mod_uac(self): @@ -420,12 +399,11 @@ class UserAccountControlTests(samba.tests.TestCase): UF_PARTIAL_SECRETS_ACCOUNT | UF_TRUSTED_FOR_DELEGATION), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.admin_samdb.modify(m) - self.fail("Unexpectedly able to set userAccountControl to UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|UF_TRUSTED_FOR_DELEGATION on %s" % m.dn) - except LdbError as e12: - (enum, estr) = e12.args - self.assertEqual(ldb.ERR_OTHER, enum) + self.assertRaisesLdbError(ldb.ERR_OTHER, + f"Unexpectedly able to set userAccountControl to " + "UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT|" + "UF_TRUSTED_FOR_DELEGATION on {m.dn}", + self.admin_samdb.modify, m) m = ldb.Message() m.dn = res[0].dn @@ -835,14 +813,10 @@ class UserAccountControlTests(samba.tests.TestCase): m["primaryGroupID"] = ldb.MessageElement( [str(security.DOMAIN_RID_USERS)], ldb.FLAG_MOD_REPLACE, "primaryGroupID") - try: - self.admin_samdb.modify(m) - # When creating a new object, you can not ever set the primaryGroupID - self.fail("Unexpectedly able to set primaryGroupID to be other than DCS on %s" % computername) - except LdbError as e15: - (enum, estr) = e15.args - self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + f"Unexpectedly able to set primaryGroupID to be other than DCS on {m.dn}", + self.admin_samdb.modify, m) def test_primarygroupID_priv_user_modify(self): computername = self.computernames[0] -- 2.25.1 From 66dad8ee9f6db6cef77cc32d12f47c4b53e69349 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 21 Oct 2021 16:46:56 +1300 Subject: [PATCH 455/645] CVE-2020-17049 tests/krb5: Check account name and SID in PAC for S4U tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Mon Oct 25 09:23:35 UTC 2021 on sn-devel-184 (cherry picked from commit c174e9ebe715aad6910d53c1f427a0512c09d651) --- python/samba/tests/krb5/kdc_base_test.py | 4 ++++ python/samba/tests/krb5/raw_testcase.py | 26 ++++++++++++++++++++++++ python/samba/tests/krb5/s4u_tests.py | 12 +++++++++++ 3 files changed, 42 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index b24c6376ab0..8ae9c24b0fc 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1337,6 +1337,8 @@ class KDCBaseTest(RawKerberosTest): def get_tgt(self, creds, to_rodc=False, kdc_options=None, expected_flags=None, unexpected_flags=None, + expected_account_name=None, + expected_sid=None, pac_request=True, expect_pac=True, fresh=False): user_name = creds.get_username() cache_key = (user_name, to_rodc, kdc_options, pac_request) @@ -1386,6 +1388,8 @@ class KDCBaseTest(RawKerberosTest): expected_cname=cname, expected_srealm=realm, expected_sname=sname, + expected_account_name=expected_account_name, + expected_sid=expected_sid, expected_salt=salt, expected_flags=expected_flags, unexpected_flags=unexpected_flags, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f352615db1f..fdf078ea788 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1984,6 +1984,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_account_name=None, + expected_sid=None, expected_supported_etypes=None, expected_flags=None, unexpected_flags=None, @@ -2033,6 +2035,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_account_name': expected_account_name, + 'expected_sid': expected_sid, 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, @@ -2078,6 +2082,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_anon=False, expected_srealm=None, expected_sname=None, + expected_account_name=None, + expected_sid=None, expected_supported_etypes=None, expected_flags=None, unexpected_flags=None, @@ -2128,6 +2134,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_anon': expected_anon, 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, + 'expected_account_name': expected_account_name, + 'expected_sid': expected_sid, 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, 'unexpected_flags': unexpected_flags, @@ -2561,6 +2569,9 @@ class RawKerberosTest(TestCaseInTempDir): f'expected: {expected_types} ' f'got: {buffer_types}') + expected_account_name = kdc_exchange_dict['expected_account_name'] + expected_sid = kdc_exchange_dict['expected_sid'] + for pac_buffer in pac.buffers: if pac_buffer.type == krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION: expected_proxy_target = kdc_exchange_dict[ @@ -2584,6 +2595,17 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(account_name, pac_buffer.info.account_name) + elif pac_buffer.type == krb5pac.PAC_TYPE_LOGON_INFO: + logon_info = pac_buffer.info.info.info3.base + + if expected_account_name is not None: + self.assertEqual(expected_account_name, + str(logon_info.account_name)) + + if expected_sid is not None: + expected_rid = int(expected_sid.rsplit('-', 1)[1]) + self.assertEqual(expected_rid, logon_info.rid) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -3548,6 +3570,8 @@ class RawKerberosTest(TestCaseInTempDir): etypes, padata, kdc_options, + expected_account_name=None, + expected_sid=None, expected_flags=None, unexpected_flags=None, expected_supported_etypes=None, @@ -3580,6 +3604,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_cname=expected_cname, expected_srealm=expected_srealm, expected_sname=expected_sname, + expected_account_name=expected_account_name, + expected_sid=expected_sid, expected_supported_etypes=expected_supported_etypes, ticket_decryption_key=ticket_decryption_key, generate_padata_fn=generate_padata_fn, diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index ea629d29706..593ef94c910 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -238,6 +238,10 @@ class S4UKerberosTests(KDCBaseTest): client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[client_name]) + samdb = self.get_samdb() + client_dn = client_creds.get_dn() + sid = self.get_objectSid(samdb, client_dn) + service_name = service_creds.get_username()[:-1] service_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=['host', service_name]) @@ -279,6 +283,8 @@ class S4UKerberosTests(KDCBaseTest): expected_cname=client_cname, expected_srealm=realm, expected_sname=service_sname, + expected_account_name=client_name, + expected_sid=sid, expected_flags=expected_flags, unexpected_flags=unexpected_flags, ticket_decryption_key=service_decryption_key, @@ -438,6 +444,10 @@ class S4UKerberosTests(KDCBaseTest): account_type=self.AccountType.USER, opts=client_opts) + samdb = self.get_samdb() + client_dn = client_creds.get_dn() + sid = self.get_objectSid(samdb, client_dn) + service1_opts = kdc_dict.pop('service1_opts', {}) service2_opts = kdc_dict.pop('service2_opts', {}) @@ -552,6 +562,8 @@ class S4UKerberosTests(KDCBaseTest): expected_cname=client_cname, expected_srealm=service2_realm, expected_sname=service2_sname, + expected_account_name=client_username, + expected_sid=sid, expected_supported_etypes=service2_etypes, ticket_decryption_key=service2_decryption_key, check_error_fn=check_error_fn, -- 2.25.1 From 9a29561e083c8c88a9f4fe33e92bfe87041e1390 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 Aug 2021 22:31:02 +1200 Subject: [PATCH 456/645] CVE-2020-25722 dsdb: Tests for our known set of privileged attributes This, except for where we choose to disagree, does pass against Windows 2019. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14703 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14778 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14775 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 54 ++++ source4/dsdb/tests/python/priv_attrs.py | 388 ++++++++++++++++++++++++ source4/selftest/tests.py | 2 + 3 files changed, 444 insertions(+) create mode 100644 selftest/knownfail.d/priv_attr create mode 100644 source4/dsdb/tests/python/priv_attrs.py diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr new file mode 100644 index 00000000000..31b9cb23b44 --- /dev/null +++ b/selftest/knownfail.d/priv_attr @@ -0,0 +1,54 @@ +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-RODC_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-RODC_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-del-add_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-replace_CC_default_computer diff --git a/source4/dsdb/tests/python/priv_attrs.py b/source4/dsdb/tests/python/priv_attrs.py new file mode 100644 index 00000000000..ec2b13045e5 --- /dev/null +++ b/source4/dsdb/tests/python/priv_attrs.py @@ -0,0 +1,388 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# This tests the restrictions on userAccountControl that apply even if write access is permitted +# +# Copyright Samuel Cabrero 2014 +# Copyright Andrew Bartlett 2014 +# +# Licenced under the GPLv3 +# + +import optparse +import sys +import unittest +import samba +import samba.getopt as options +import samba.tests +import ldb +import base64 + +sys.path.insert(0, "bin/python") +from samba.tests.subunitrun import TestProgram, SubunitOptions +from samba.tests import DynamicTestCase +from samba.subunit.run import SubunitTestRunner +from samba.auth import system_session +from samba.samdb import SamDB +from samba.dcerpc import samr, security, lsa +from samba.credentials import Credentials +from samba.ndr import ndr_unpack, ndr_pack +from samba.tests import delete_force +from samba import gensec, sd_utils +from samba.credentials import DONT_USE_KERBEROS +from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError +from ldb import Message, MessageElement, Dn +from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE +from samba.dsdb import UF_SCRIPT, UF_ACCOUNTDISABLE, UF_00000004, UF_HOMEDIR_REQUIRED, \ + UF_LOCKOUT, UF_PASSWD_NOTREQD, UF_PASSWD_CANT_CHANGE, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED,\ + UF_TEMP_DUPLICATE_ACCOUNT, UF_NORMAL_ACCOUNT, UF_00000400, UF_INTERDOMAIN_TRUST_ACCOUNT, \ + UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT, UF_00004000, \ + UF_00008000, UF_DONT_EXPIRE_PASSWD, UF_MNS_LOGON_ACCOUNT, UF_SMARTCARD_REQUIRED, \ + UF_TRUSTED_FOR_DELEGATION, UF_NOT_DELEGATED, UF_USE_DES_KEY_ONLY, UF_DONT_REQUIRE_PREAUTH, \ + UF_PASSWORD_EXPIRED, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, UF_NO_AUTH_DATA_REQUIRED, \ + UF_PARTIAL_SECRETS_ACCOUNT, UF_USE_AES_KEYS + + +parser = optparse.OptionParser("user_account_control.py [options] ") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) + +# use command line creds if available +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +opts, args = parser.parse_args() + +if len(args) < 1: + parser.print_usage() + sys.exit(1) +host = args[0] + +if "://" not in host: + ldaphost = "ldap://%s" % host +else: + ldaphost = host + start = host.rindex("://") + host = host.lstrip(start + 3) + +lp = sambaopts.get_loadparm() +creds = credopts.get_credentials(lp) +creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL) + + +""" +Check the combinations of: + +rodc kdc +a2d2 +useraccountcontrol (trusted for delegation) +sidHistory + +x + +add +modify(replace) +modify(add) + +x + +sd WP on add +cc default perms +admin created, WP to user + +x + +computer +user +""" + +attrs = {"sidHistory": + {"value": ndr_pack(security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS)), + "priv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, + "msDS-AllowedToDelegateTo": + {"value": f"host/{host}", + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, + "userAccountControl-a2d-user": + {"attr": "userAccountControl", + "value": str(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION|UF_NORMAL_ACCOUNT), + "priv-error": ldb.ERR_UNWILLING_TO_PERFORM, + "unpriv-add-error": ldb.ERR_UNWILLING_TO_PERFORM, + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, + "userAccountControl-a2d-computer": + {"attr": "userAccountControl", + "value": str(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION|UF_WORKSTATION_TRUST_ACCOUNT), + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + "only-1": "computer"}, + "userAccountControl-DC": + {"attr": "userAccountControl", + "value": str(UF_SERVER_TRUST_ACCOUNT), + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + "only-2": "computer"}, + "userAccountControl-RODC": + {"attr": "userAccountControl", + "value": str(UF_PARTIAL_SECRETS_ACCOUNT|UF_WORKSTATION_TRUST_ACCOUNT), + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + "only-1": "computer"}, + "msDS-SecondaryKrbTgtNumber": + {"value": "65536", + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, + "primaryGroupID": + {"value": str(security.DOMAIN_RID_ADMINS), + "priv-error": ldb.ERR_UNWILLING_TO_PERFORM, + "unpriv-add-error": ldb.ERR_UNWILLING_TO_PERFORM, + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS} + } + + + +@DynamicTestCase +class PrivAttrsTests(samba.tests.TestCase): + + def get_creds(self, target_username, target_password): + creds_tmp = Credentials() + creds_tmp.set_username(target_username) + creds_tmp.set_password(target_password) + creds_tmp.set_domain(creds.get_domain()) + creds_tmp.set_realm(creds.get_realm()) + creds_tmp.set_workstation(creds.get_workstation()) + creds_tmp.set_gensec_features(creds_tmp.get_gensec_features() + | gensec.FEATURE_SEAL) + 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): + if not self.strict_checking: + self.assertNotEqual(got, ldb.SUCCESS) + else: + self.assertEqual(got, wanted) + + def setUp(self): + super().setUp() + + strict_checking = samba.tests.env_get_var_value('STRICT_CHECKING', allow_missing=True) + if strict_checking is None: + strict_checking = '1' + self.strict_checking = bool(int(strict_checking)) + + self.admin_creds = creds + self.admin_samdb = SamDB(url=ldaphost, credentials=self.admin_creds, lp=lp) + self.domain_sid = security.dom_sid(self.admin_samdb.get_domain_sid()) + self.base_dn = self.admin_samdb.domain_dn() + + self.unpriv_user = "testuser1" + self.unpriv_user_pw = "samba123@" + self.unpriv_creds = self.get_creds(self.unpriv_user, self.unpriv_user_pw) + + self.admin_sd_utils = sd_utils.SDUtils(self.admin_samdb) + + self.test_ou_name = "OU=test_priv_attrs" + self.test_ou = self.test_ou_name + "," + self.base_dn + + delete_force(self.admin_samdb, self.test_ou, controls=["tree_delete:0"]) + + self.admin_samdb.create_ou(self.test_ou) + + expected_user_dn = f"CN={self.unpriv_user},{self.test_ou_name},{self.base_dn}" + + self.admin_samdb.newuser(self.unpriv_user, self.unpriv_user_pw, userou=self.test_ou_name) + res = self.admin_samdb.search(expected_user_dn, + scope=SCOPE_BASE, + attrs=["objectSid"]) + + self.assertEqual(1, len(res)) + + self.unpriv_user_dn = res[0].dn + self.addCleanup(delete_force, self.admin_samdb, self.unpriv_user_dn, controls=["tree_delete:0"]) + + self.unpriv_user_sid = self.admin_sd_utils.get_object_sid(self.unpriv_user_dn) + + self.unpriv_samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp) + + @classmethod + def setUpDynamicTestCases(cls): + for test_name in attrs.keys(): + for add_or_mod in ["add", "mod-del-add", "mod-replace"]: + for permission in ["admin-add", "CC"]: + for sd in ["default", "WP"]: + for objectclass in ["computer", "user"]: + tname = f"{test_name}_{add_or_mod}_{permission}_{sd}_{objectclass}" + targs = (test_name, + add_or_mod, + permission, + sd, + objectclass) + cls.generate_dynamic_test("test_priv_attr", + tname, + *targs) + + def add_computer_ldap(self, computername, others=None, samdb=None): + dn = "CN=%s,%s" % (computername, self.test_ou) + domainname = ldb.Dn(samdb, samdb.domain_dn()).canonical_str().replace("/", "") + samaccountname = "%s$" % computername + dnshostname = "%s.%s" % (computername, domainname) + msg_dict = { + "dn": dn, + "objectclass": "computer"} + if others is not None: + msg_dict = dict(list(msg_dict.items()) + list(others.items())) + + msg = ldb.Message.from_dict(samdb, msg_dict) + msg["sAMAccountName"] = samaccountname + + print("Adding computer account %s" % computername) + try: + samdb.add(msg) + except ldb.LdbError: + print(msg) + raise + return msg.dn + + def add_user_ldap(self, username, others=None, samdb=None): + dn = "CN=%s,%s" % (username, self.test_ou) + domainname = ldb.Dn(samdb, samdb.domain_dn()).canonical_str().replace("/", "") + samaccountname = "%s$" % username + msg_dict = { + "dn": dn, + "objectclass": "user"} + if others is not None: + msg_dict = dict(list(msg_dict.items()) + list(others.items())) + + msg = ldb.Message.from_dict(samdb, msg_dict) + msg["sAMAccountName"] = samaccountname + + print("Adding user account %s" % username) + try: + samdb.add(msg) + except ldb.LdbError: + print(msg) + raise + return msg.dn + + def add_thing_ldap(self, user, others, samdb, objectclass): + if objectclass == "user": + dn = self.add_user_ldap(user, others, samdb=samdb) + elif objectclass == "computer": + dn = self.add_computer_ldap(user, others, samdb=samdb) + return dn + + def _test_priv_attr_with_args(self, test_name, add_or_mod, permission, sd, objectclass): + user="privattrs" + if "attr" in attrs[test_name]: + attr = attrs[test_name]["attr"] + else: + attr = test_name + if add_or_mod == "add": + others = {attr: attrs[test_name]["value"]} + else: + others = {} + + if permission == "CC": + samdb = self.unpriv_samdb + # Set CC on container to allow user add + mod = "(OA;CI;CC;bf967aba-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid) + self.admin_sd_utils.dacl_add_ace(self.test_ou, mod) + mod = "(OA;CI;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid) + self.admin_sd_utils.dacl_add_ace(self.test_ou, mod) + + else: + samdb = self.admin_samdb + + if sd == "WP": + # Set SD to WP to the target user as part of add + sd = "O:%sG:DUD:(OA;CIID;RPWP;;;%s)(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;%s)" % (self.unpriv_user_sid, self.unpriv_user_sid, self.unpriv_user_sid) + tmp_desc = security.descriptor.from_sddl(sd, self.domain_sid) + others["ntSecurityDescriptor"] = ndr_pack(tmp_desc) + + if add_or_mod == "add": + + # only-1 and only-2 are due to windows behaviour + + if "only-1" in attrs[test_name] and \ + attrs[test_name]["only-1"] != objectclass: + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + self.fail(f"{test_name}: Unexpectedly able to set {attr} on new {objectclass} as ADMIN (should fail LDAP_OBJECT_CLASS_VIOLATION)") + except LdbError as e5: + (enum, estr) = e5.args + self.assertGotLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, enum) + elif permission == "CC": + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + self.fail(f"{test_name}: Unexpectedly able to set {attr} on new {objectclass}") + except LdbError as e5: + (enum, estr) = e5.args + if "unpriv-add-error" in attrs[test_name]: + self.assertGotLdbError(attrs[test_name]["unpriv-add-error"], \ + enum) + else: + self.assertGotLdbError(attrs[test_name]["unpriv-error"], \ + enum) + elif "only-2" in attrs[test_name] and \ + attrs[test_name]["only-2"] != objectclass: + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + self.fail(f"{test_name}: Unexpectedly able to set {attr} on new {objectclass} as ADMIN (should fail LDAP_OBJECT_CLASS_VIOLATION)") + except LdbError as e5: + (enum, estr) = e5.args + self.assertGotLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, enum) + elif "priv-error" in attrs[test_name]: + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + self.fail(f"{test_name}: Unexpectedly able to set {attr} on new {objectclass} as ADMIN") + except LdbError as e5: + (enum, estr) = e5.args + self.assertGotLdbError(attrs[test_name]["priv-error"], enum) + else: + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + except LdbError as e5: + (enum, estr) = e5.args + self.fail(f"Failed to add account {user} as objectclass {objectclass}") + else: + try: + dn = self.add_thing_ldap(user, others, samdb, objectclass) + except LdbError as e5: + (enum, estr) = e5.args + self.fail(f"Failed to add account {user} as objectclass {objectclass}") + + if add_or_mod == "add": + return + + m = ldb.Message() + m.dn = dn + + # Do modify + if add_or_mod == "mod-del-add": + m["0"] = ldb.MessageElement([], + ldb.FLAG_MOD_DELETE, + attr) + m["1"] = ldb.MessageElement(attrs[test_name]["value"], + ldb.FLAG_MOD_ADD, + attr) + else: + m["0"] = ldb.MessageElement(attrs[test_name]["value"], + ldb.FLAG_MOD_REPLACE, + attr) + + try: + self.unpriv_samdb.modify(m) + self.fail(f"{test_name}: Unexpectedly able to set {attr} on {m.dn}") + except LdbError as e5: + (enum, estr) = e5.args + if attr == "userAccountControl" and sd == "default": + # We get a different error if we try and swap between + # being a computer back to being a user when created with "Create child" permissions + if (int(attrs[test_name]["value"]) & UF_NORMAL_ACCOUNT) \ + and objectclass == "computer" and permission == "CC": + self.assertGotLdbError(ldb.ERR_UNWILLING_TO_PERFORM, enum) + return + self.assertGotLdbError(attrs[test_name]["unpriv-error"], enum) + + + + +runner = SubunitTestRunner() +rc = 0 +if not runner.run(unittest.makeSuite(PrivAttrsTests)).wasSuccessful(): + rc = 1 +sys.exit(rc) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index e7ec2f363d2..e4e599c664c 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -981,6 +981,8 @@ plantestsuite("samba4.sam.python(fl2008r2dc)", "fl2008r2dc", [python, os.path.jo plantestsuite("samba4.sam.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) plantestsuite("samba4.asq.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "asq.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) plantestsuite("samba4.user_account_control.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "user_account_control.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) +plantestsuite("samba4.priv_attrs.python(ad_dc_default)", "ad_dc_default", ["STRICT_CHECKING=0", python, os.path.join(DSDB_PYTEST_DIR, "priv_attrs.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) +plantestsuite("samba4.priv_attrs.strict.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "priv_attrs.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) for env in ['ad_dc_default:local', 'schema_dc:local']: planoldpythontestsuite(env, "dsdb_schema_info", -- 2.25.1 From 93b5b2aee522fa8fa19cacbce7522d5255104082 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 12 Aug 2021 11:10:09 +1200 Subject: [PATCH 457/645] CVE-2020-25722 dsdb: Move krbtgt password setup after the point of checking if any passwords are changed This allows the add of an RODC, before setting the password, to avoid this module, which helps isolate testing of security around the msDS-SecondaryKrbTgtNumber attribute. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14703 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 12 +- .../dsdb/samdb/ldb_modules/password_hash.c | 106 +++++++++--------- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr index 31b9cb23b44..ab6db192aae 100644 --- a/selftest/knownfail.d/priv_attr +++ b/selftest/knownfail.d/priv_attr @@ -14,14 +14,10 @@ samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccoun samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_admin-add_default_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_user +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_computer +samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_computer samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_computer diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2111b5547d9..ab6151aa549 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -2472,6 +2472,59 @@ static int setup_password_fields(struct setup_password_fields_io *io) return LDB_SUCCESS; } + if (io->u.is_krbtgt) { + size_t min = 196; + size_t max = 255; + size_t diff = max - min; + size_t len = max; + struct ldb_val *krbtgt_utf16 = NULL; + + if (!io->ac->pwd_reset) { + return dsdb_module_werror(io->ac->module, + LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS, + WERR_DS_ATT_ALREADY_EXISTS, + "Password change on krbtgt not permitted!"); + } + + if (io->n.cleartext_utf16 == NULL) { + return dsdb_module_werror(io->ac->module, + LDB_ERR_UNWILLING_TO_PERFORM, + WERR_DS_INVALID_ATTRIBUTE_SYNTAX, + "Password reset on krbtgt requires UTF16!"); + } + + /* + * Instead of taking the callers value, + * we just generate a new random value here. + * + * Include null termination in the array. + */ + if (diff > 0) { + size_t tmp; + + generate_random_buffer((uint8_t *)&tmp, sizeof(tmp)); + + tmp %= diff; + + len = min + tmp; + } + + krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val); + if (krbtgt_utf16 == NULL) { + return ldb_oom(ldb); + } + + *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16, + (len+1)*2); + if (krbtgt_utf16->data == NULL) { + return ldb_oom(ldb); + } + krbtgt_utf16->length = len * 2; + generate_secret_buffer(krbtgt_utf16->data, + krbtgt_utf16->length); + io->n.cleartext_utf16 = krbtgt_utf16; + } + /* transform the old password (for password changes) */ ret = setup_given_passwords(io, &io->og); if (ret != LDB_SUCCESS) { @@ -3649,59 +3702,6 @@ static int setup_io(struct ph_context *ac, return ldb_operr(ldb); } - if (io->u.is_krbtgt) { - size_t min = 196; - size_t max = 255; - size_t diff = max - min; - size_t len = max; - struct ldb_val *krbtgt_utf16 = NULL; - - if (!ac->pwd_reset) { - return dsdb_module_werror(ac->module, - LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS, - WERR_DS_ATT_ALREADY_EXISTS, - "Password change on krbtgt not permitted!"); - } - - if (io->n.cleartext_utf16 == NULL) { - return dsdb_module_werror(ac->module, - LDB_ERR_UNWILLING_TO_PERFORM, - WERR_DS_INVALID_ATTRIBUTE_SYNTAX, - "Password reset on krbtgt requires UTF16!"); - } - - /* - * Instead of taking the callers value, - * we just generate a new random value here. - * - * Include null termination in the array. - */ - if (diff > 0) { - size_t tmp; - - generate_random_buffer((uint8_t *)&tmp, sizeof(tmp)); - - tmp %= diff; - - len = min + tmp; - } - - krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val); - if (krbtgt_utf16 == NULL) { - return ldb_oom(ldb); - } - - *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16, - (len+1)*2); - if (krbtgt_utf16->data == NULL) { - return ldb_oom(ldb); - } - krbtgt_utf16->length = len * 2; - generate_secret_buffer(krbtgt_utf16->data, - krbtgt_utf16->length); - io->n.cleartext_utf16 = krbtgt_utf16; - } - if (existing_msg != NULL) { NTSTATUS status; -- 2.25.1 From c3425c02fe25538e5def3843d3907305f0c7a68b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 13 Aug 2021 17:42:23 +1200 Subject: [PATCH 458/645] CVE-2020-25722 dsdb: Restrict the setting of privileged attributes during LDAP add/modify The remaining failures in the priv_attrs (not the strict one) test are due to missing objectclass constraints on the administrator which should be addressed, but are not a security issue. A better test for confirming constraints between objectclass and userAccountControl UF_NORMAL_ACCONT/UF_WORKSTATION_TRUST values would be user_account_control.py. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14703 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14778 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14775 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 24 ---- source4/dsdb/samdb/ldb_modules/samldb.c | 148 +++++++++++++++++++++--- 2 files changed, 129 insertions(+), 43 deletions(-) diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr index ab6db192aae..c3a779010d9 100644 --- a/selftest/knownfail.d/priv_attr +++ b/selftest/knownfail.d/priv_attr @@ -1,31 +1,7 @@ -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_user samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_computer samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-AllowedToDelegateTo_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_msDS-SecondaryKrbTgtNumber_add_CC_default_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 4da8564c77a..cb5fda324a4 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1976,6 +1976,29 @@ static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac, return ret; } +static int samldb_get_domain_secdesc(struct samldb_ctx *ac, + struct security_descriptor **domain_sd) +{ + const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; + struct ldb_result *res; + struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); + int ret = dsdb_module_search_dn(ac->module, ac, &res, + domain_dn, + sd_attrs, + DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + if (res->count != 1) { + return ldb_module_operr(ac->module); + } + + return dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module), + ac, res->msgs[0], domain_sd); + +} + /** * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured * @@ -1987,12 +2010,8 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, { int i, ret = 0; bool need_acl_check = false; - struct ldb_result *res; - const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; struct security_token *user_token; struct security_descriptor *domain_sd; - struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); - struct ldb_context *ldb = ldb_module_get_ctx(ac->module); const struct uac_to_guid { uint32_t uac; uint32_t priv_to_change_from; @@ -2078,21 +2097,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } - ret = dsdb_module_search_dn(ac->module, ac, &res, - domain_dn, - sd_attrs, - DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, - ac->req); - if (ret != LDB_SUCCESS) { - return ret; - } - if (res->count != 1) { - return ldb_module_operr(ac->module); - } - - ret = dsdb_get_sd_from_ldb_message(ldb, - ac, res->msgs[0], &domain_sd); - + ret = samldb_get_domain_secdesc(ac, &domain_sd); if (ret != LDB_SUCCESS) { return ret; } @@ -2154,6 +2159,8 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, return ldb_module_operr(ac->module); } if (map[i].guid) { + struct ldb_dn *domain_dn + = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); dsdb_acl_debug(domain_sd, acl_user_token(ac->module), domain_dn, true, @@ -3486,7 +3493,98 @@ static char *refer_if_rodc(struct ldb_context *ldb, struct ldb_request *req, return NULL; } +/* + * Restrict all access to sensitive attributes. + * + * We don't want to even inspect the values, so we can use the same + * routine for ADD and MODIFY. + * + */ + +static int samldb_check_sensitive_attributes(struct samldb_ctx *ac) +{ + struct ldb_message_element *el = NULL; + struct security_token *user_token = NULL; + int ret; + + if (dsdb_module_am_system(ac->module)) { + return LDB_SUCCESS; + } + + user_token = acl_user_token(ac->module); + if (user_token == NULL) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + + el = ldb_msg_find_element(ac->msg, "sidHistory"); + if (el) { + /* + * sidHistory is restricted to the (not implemented + * yet in Samba) DsAddSidHistory call (direct LDB access is + * as SYSTEM so will bypass this). + * + * If you want to modify this, say to merge domains, + * directly modify the sam.ldb as root. + */ + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "sidHistory " + "(entry %s) cannot be created " + "or changed over LDAP!", + ldb_dn_get_linearized(ac->msg->dn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + el = ldb_msg_find_element(ac->msg, "msDS-SecondaryKrbTgtNumber"); + if (el) { + struct security_descriptor *domain_sd; + /* + * msDS-SecondaryKrbTgtNumber allows the creator to + * become an RODC, this is trusted as an RODC + * account + */ + ret = samldb_get_domain_secdesc(ac, &domain_sd); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = acl_check_extended_right(ac, domain_sd, + user_token, + GUID_DRS_DS_INSTALL_REPLICA, + SEC_ADS_CONTROL_ACCESS, + NULL); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "msDS-SecondaryKrbTgtNumber " + "(entry %s) cannot be created " + "or changed without " + "DS-Install-Replica extended right!", + ldb_dn_get_linearized(ac->msg->dn)); + return ret; + } + } + + el = ldb_msg_find_element(ac->msg, "msDS-AllowedToDelegateTo"); + if (el) { + /* + * msDS-AllowedToDelegateTo is incredibly powerful, + * given that it allows a server to become ANY USER on + * the target server only listed by SPN so needs to be + * protected just as the userAccountControl + * UF_TRUSTED_FOR_DELEGATION is. + */ + + bool have_priv = security_token_has_privilege(user_token, + SEC_PRIV_ENABLE_DELEGATION); + if (have_priv == false) { + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "msDS-AllowedToDelegateTo " + "(entry %s) cannot be created " + "or changed without SePrivEnableDelegation!", + ldb_dn_get_linearized(ac->msg->dn)); + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } + return LDB_SUCCESS; +} /* add */ static int samldb_add(struct ldb_module *module, struct ldb_request *req) { @@ -3533,6 +3631,12 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return ldb_operr(ldb); } + ret = samldb_check_sensitive_attributes(ac); + if (ret != LDB_SUCCESS) { + talloc_free(ac); + return ret; + } + el = ldb_msg_find_element(ac->msg, "fSMORoleOwner"); if (el != NULL) { ret = samldb_fsmo_role_owner_check(ac); @@ -3740,6 +3844,12 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) return ldb_operr(ldb); } + ret = samldb_check_sensitive_attributes(ac); + if (ret != LDB_SUCCESS) { + talloc_free(ac); + return ret; + } + if (is_undelete == NULL) { el = ldb_msg_find_element(ac->msg, "primaryGroupID"); if (el != NULL) { -- 2.25.1 From ddc15ca1ea3bde955cc666d01608ce0ea4efe28b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Sep 2021 20:34:54 +1200 Subject: [PATCH 459/645] CVE-2020-25722 selftest: Extend priv_attrs test - work around UF_NORMAL_ACCOUNT rules on Windows 2019 (requires |UF_PASSWD_NOTREQD or a password) - extend to also cover the sensitive UF_TRUSTED_FOR_DELEGATION BUG: https://bugzilla.samba.org/show_bug.cgi?id=14703 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14778 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14775 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 16 ++-------- source4/dsdb/tests/python/priv_attrs.py | 40 +++++++++++++++---------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr index c3a779010d9..4b85a869089 100644 --- a/selftest/knownfail.d/priv_attr +++ b/selftest/knownfail.d/priv_attr @@ -1,7 +1,3 @@ -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer -samba4.priv_attrs.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer @@ -14,13 +10,5 @@ samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_use samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-RODC_add_CC_default_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_admin-add_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-del-add_CC_default_computer -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-replace_CC_default_computer +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-computer_add_CC_WP_user +samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-computer_add_CC_default_user diff --git a/source4/dsdb/tests/python/priv_attrs.py b/source4/dsdb/tests/python/priv_attrs.py index ec2b13045e5..aa35dcc1317 100644 --- a/source4/dsdb/tests/python/priv_attrs.py +++ b/source4/dsdb/tests/python/priv_attrs.py @@ -99,30 +99,47 @@ attrs = {"sidHistory": {"value": ndr_pack(security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS)), "priv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, - "msDS-AllowedToDelegateTo": + + "msDS-AllowedToDelegateTo": {"value": f"host/{host}", "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, - "userAccountControl-a2d-user": + + "userAccountControl-a2d-user": {"attr": "userAccountControl", - "value": str(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION|UF_NORMAL_ACCOUNT), - "priv-error": ldb.ERR_UNWILLING_TO_PERFORM, - "unpriv-add-error": ldb.ERR_UNWILLING_TO_PERFORM, + "value": str(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION|UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, - "userAccountControl-a2d-computer": + + "userAccountControl-a2d-computer": {"attr": "userAccountControl", "value": str(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION|UF_WORKSTATION_TRUST_ACCOUNT), "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, "only-1": "computer"}, - "userAccountControl-DC": + + # This flag makes many legitimate authenticated clients + # send a forwardable ticket-granting-ticket to the server + "userAccountControl-t4d-user": + {"attr": "userAccountControl", + "value": str(UF_TRUSTED_FOR_DELEGATION|UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, + + "userAccountControl-t4d-computer": + {"attr": "userAccountControl", + "value": str(UF_TRUSTED_FOR_DELEGATION|UF_WORKSTATION_TRUST_ACCOUNT), + "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + "only-1": "computer"}, + + "userAccountControl-DC": {"attr": "userAccountControl", "value": str(UF_SERVER_TRUST_ACCOUNT), "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, "only-2": "computer"}, - "userAccountControl-RODC": + + "userAccountControl-RODC": {"attr": "userAccountControl", "value": str(UF_PARTIAL_SECRETS_ACCOUNT|UF_WORKSTATION_TRUST_ACCOUNT), "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, "only-1": "computer"}, + "msDS-SecondaryKrbTgtNumber": {"value": "65536", "unpriv-error": ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS}, @@ -369,13 +386,6 @@ class PrivAttrsTests(samba.tests.TestCase): self.fail(f"{test_name}: Unexpectedly able to set {attr} on {m.dn}") except LdbError as e5: (enum, estr) = e5.args - if attr == "userAccountControl" and sd == "default": - # We get a different error if we try and swap between - # being a computer back to being a user when created with "Create child" permissions - if (int(attrs[test_name]["value"]) & UF_NORMAL_ACCOUNT) \ - and objectclass == "computer" and permission == "CC": - self.assertGotLdbError(ldb.ERR_UNWILLING_TO_PERFORM, enum) - return self.assertGotLdbError(attrs[test_name]["unpriv-error"], enum) -- 2.25.1 From 13c256c999df4afd96bddfe602a8f0c388e302b9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Sep 2021 10:21:03 +1200 Subject: [PATCH 460/645] CVE-2020-25722 selftest: Test combinations of account type and objectclass for creating a user The idea here is to split out the restrictions seen on Windows 2019 at the schema level, as seen when acting as an administrator. These pass against Windows 2019 except for the account type swapping which is not wanted. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- .../user_account_control-uac_mod_lock | 11 ++ .../dsdb/tests/python/user_account_control.py | 165 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 selftest/knownfail.d/user_account_control-uac_mod_lock diff --git a/selftest/knownfail.d/user_account_control-uac_mod_lock b/selftest/knownfail.d/user_account_control-uac_mod_lock new file mode 100644 index 00000000000..a70534506f3 --- /dev/null +++ b/selftest/knownfail.d/user_account_control-uac_mod_lock @@ -0,0 +1,11 @@ +# We do not want user account control account type swapping, so we mark these as knownfail +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_deladd +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index c9b50b83e9d..442fe741220 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -91,6 +91,41 @@ account_types = set([UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_ class UserAccountControlTests(samba.tests.TestCase): @classmethod def setUpDynamicTestCases(cls): + for account_type in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + for objectclass in ["computer", "user"]: + test_name = f"{account_type_str}_{objectclass}" + cls.generate_dynamic_test("test_objectclass_uac_lock", + test_name, + account_type, + objectclass) + + for account_type in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + for account_type2 in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + for how in ["replace", "deladd"]: + account_type2_str = dsdb.user_account_control_flag_bit_to_string(account_type2) + test_name = f"{account_type_str}_{account_type2_str}_{how}" + cls.generate_dynamic_test("test_objectclass_uac_mod_lock", + test_name, + account_type, + account_type2, + how) + for objectclass in ["user", "computer"]: + for how in ["replace", "deladd"]: + test_name = f"{account_type_str}_{objectclass}_{how}" + cls.generate_dynamic_test("test_objectclass_mod_lock", + test_name, + account_type, + objectclass, + how) + for account_type in [UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT]: account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) cls.generate_dynamic_test("test_uac_bits_unrelated_modify", @@ -844,6 +879,136 @@ class UserAccountControlTests(samba.tests.TestCase): "primaryGroupID") self.admin_samdb.modify(m) + def _test_objectclass_uac_lock_with_args(self, + account_type, + objectclass): + name = "oc_uac_lock$" + dn = "CN=%s,%s" % (name, self.OU) + msg_dict = { + "dn": dn, + "objectclass": objectclass, + "samAccountName": name, + "userAccountControl": str(account_type | UF_PASSWD_NOTREQD)} + + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + + print(f"Adding account {name} as {account_type_str} with objectclass {objectclass}") + + if (objectclass == "user" \ + and account_type == UF_NORMAL_ACCOUNT): + self.admin_samdb.add(msg_dict) + elif objectclass == "computer": + self.admin_samdb.add(msg_dict) + else: + self.assertRaisesLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, + "Should have been unable to {account_type_str} on {objectclass}", + self.admin_samdb.add, msg_dict) + + def _test_objectclass_uac_mod_lock_with_args(self, + account_type, + account_type2, + how): + name = "uac_mod_lock$" + dn = "CN=%s,%s" % (name, self.OU) + if account_type == UF_NORMAL_ACCOUNT: + objectclass = "user" + else: + objectclass = "computer" + + msg_dict = { + "dn": dn, + "objectclass": objectclass, + "samAccountName": name, + "userAccountControl": str(account_type | UF_PASSWD_NOTREQD)} + + account_type_str \ + = dsdb.user_account_control_flag_bit_to_string(account_type) + account_type2_str \ + = dsdb.user_account_control_flag_bit_to_string(account_type2) + + print(f"Adding account {name} as {account_type_str} with objectclass {objectclass}") + + self.admin_samdb.add(msg_dict) + + m = ldb.Message() + m.dn = ldb.Dn(self.admin_samdb, dn) + if how == "replace": + m["userAccountControl"] = ldb.MessageElement(str(account_type2 | UF_PASSWD_NOTREQD), + ldb.FLAG_MOD_REPLACE, "userAccountControl") + elif how == "deladd": + m["0userAccountControl"] = ldb.MessageElement([], + ldb.FLAG_MOD_DELETE, "userAccountControl") + m["1userAccountControl"] = ldb.MessageElement(str(account_type2 | UF_PASSWD_NOTREQD), + ldb.FLAG_MOD_ADD, "userAccountControl") + else: + raise ValueError(f"{how} was not a valid argument") + + if (account_type in [UF_SERVER_TRUST_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT]) and \ + (account_type2 in [UF_SERVER_TRUST_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT]): + self.admin_samdb.modify(m) + elif (account_type == account_type2): + self.admin_samdb.modify(m) + else: + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + f"Should have been unable to change {account_type_str} to {account_type2_str}", + self.admin_samdb.modify, m) + + def _test_objectclass_mod_lock_with_args(self, + account_type, + objectclass, + how): + name = "uac_mod_lock$" + dn = "CN=%s,%s" % (name, self.OU) + if objectclass == "computer": + new_objectclass = ["top", + "person", + "organizationalPerson", + "user"] + elif objectclass == "user": + new_objectclass = ["top", + "person", + "organizationalPerson", + "user", + "computer"] + + msg_dict = { + "dn": dn, + "objectclass": objectclass, + "samAccountName": name, + "userAccountControl": str(account_type | UF_PASSWD_NOTREQD)} + + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + + print(f"Adding account {name} as {account_type_str} with objectclass {objectclass}") + + try: + self.admin_samdb.add(msg_dict) + if (objectclass == "user" \ + and account_type != UF_NORMAL_ACCOUNT): + self.fail("Able to create {account_type_str} on {objectclass}") + except LdbError as e: + (enum, estr) = e.args + self.assertEqual(enum, ldb.ERR_OBJECT_CLASS_VIOLATION) + + if objectclass == "user" and account_type != UF_NORMAL_ACCOUNT: + return + + m = ldb.Message() + m.dn = ldb.Dn(self.admin_samdb, dn) + if how == "replace": + m["objectclass"] = ldb.MessageElement(new_objectclass, + ldb.FLAG_MOD_REPLACE, "objectclass") + elif how == "adddel": + m["0objectclass"] = ldb.MessageElement([], + ldb.FLAG_MOD_DELETE, "objectclass") + m["1objectclass"] = ldb.MessageElement(new_objectclass, + ldb.FLAG_MOD_ADD, "objectclass") + + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + "Should have been unable Able to change objectclass of a {objectclass}", + self.admin_samdb.modify, m) runner = SubunitTestRunner() rc = 0 -- 2.25.1 From 2bc6ac6c2956529025c9910bc7dcc738f868f2b1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 20 Sep 2021 12:35:51 +1200 Subject: [PATCH 461/645] CVE-2020-25722 selftest: allow for future failures in BindTests.test_virtual_email_account_style_bind This allows for any failures here to be handled via the knownfail system. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- auth/credentials/tests/bind.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/auth/credentials/tests/bind.py b/auth/credentials/tests/bind.py index 8bee6f96c62..b6b65a56c75 100755 --- a/auth/credentials/tests/bind.py +++ b/auth/credentials/tests/bind.py @@ -90,7 +90,8 @@ class BindTests(samba.tests.TestCase): # this test to detect when the LDAP DN is being double-parsed # but must be in the user@realm style to allow the account to # be created - self.ldb.add_ldif(""" + try: + self.ldb.add_ldif(""" dn: """ + self.virtual_user_dn + """ cn: frednurk@""" + self.realm + """ displayName: Fred Nurk @@ -103,13 +104,21 @@ objectClass: person objectClass: top objectClass: user """) + except LdbError as e: + (num, msg) = e.args + self.fail(f"Failed to create e-mail user: {msg}") + self.addCleanup(delete_force, self.ldb, self.virtual_user_dn) - self.ldb.modify_ldif(""" + try: + self.ldb.modify_ldif(""" dn: """ + self.virtual_user_dn + """ changetype: modify replace: unicodePwd unicodePwd:: """ + base64.b64encode(u"\"P@ssw0rd\"".encode('utf-16-le')).decode('utf8') + """ """) + except LdbError as e: + (num, msg) = e.args + self.fail(f"Failed to set password on e-mail user: {msg}") self.ldb.enable_account('distinguishedName=%s' % self.virtual_user_dn) -- 2.25.1 From 85de96b222a48980c03cf0b4a3957cfb98c0b30e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 20 Sep 2021 14:54:03 +1200 Subject: [PATCH 462/645] CVE-2020-25722 selftest: Catch possible errors in PasswordSettingsTestCase.test_pso_none_applied() This allows future patches to restrict changing the account type without triggering an error. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- .../dsdb/tests/python/password_settings.py | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/source4/dsdb/tests/python/password_settings.py b/source4/dsdb/tests/python/password_settings.py index fcb671690c3..e1c49d7bffb 100644 --- a/source4/dsdb/tests/python/password_settings.py +++ b/source4/dsdb/tests/python/password_settings.py @@ -594,19 +594,27 @@ class PasswordSettingsTestCase(PasswordTestCase): dummy_pso.apply_to(user.dn) self.assertTrue(user.get_resultant_PSO() == dummy_pso.dn) - # now clear the ADS_UF_NORMAL_ACCOUNT flag for the user, which should - # mean a resultant PSO is no longer returned (we're essentially turning - # the user into a DC here, which is a little overkill but tests - # behaviour as per the Windows specification) - self.set_attribute(user.dn, "userAccountControl", - str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT), - operation=FLAG_MOD_REPLACE) + try: + # now clear the ADS_UF_NORMAL_ACCOUNT flag for the user, which should + # mean a resultant PSO is no longer returned (we're essentially turning + # the user into a DC here, which is a little overkill but tests + # behaviour as per the Windows specification) + self.set_attribute(user.dn, "userAccountControl", + str(dsdb.UF_WORKSTATION_TRUST_ACCOUNT), + operation=FLAG_MOD_REPLACE) + except ldb.LdbError as e: + (num, msg) = e.args + self.fail("Failed to change user into a workstation: {msg}") self.assertIsNone(user.get_resultant_PSO()) - # reset it back to a normal user account - self.set_attribute(user.dn, "userAccountControl", - str(dsdb.UF_NORMAL_ACCOUNT), - operation=FLAG_MOD_REPLACE) + try: + # reset it back to a normal user account + self.set_attribute(user.dn, "userAccountControl", + str(dsdb.UF_NORMAL_ACCOUNT), + operation=FLAG_MOD_REPLACE) + except ldb.LdbError as e: + (num, msg) = e.args + self.fail("Failed to change user back into a user: {msg}") self.assertTrue(user.get_resultant_PSO() == dummy_pso.dn) # no PSO should be returned if RID is equal to DOMAIN_USER_RID_KRBTGT -- 2.25.1 From aa39c8271118b936f3eadec0bca3f6b49f4261f9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Sep 2021 13:41:40 +1200 Subject: [PATCH 463/645] CVE-2020-25722 selftest: Catch errors from samdb.modify() in user_account_control tests This will allow these to be listed in a knownfail shortly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- .../dsdb/tests/python/user_account_control.py | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 442fe741220..a22a72f12da 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -306,7 +306,11 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") - self.samdb.modify(m) + try: + self.samdb.modify(m) + except LdbError as e: + (enum, estr) = e.args + self.fail(f"got {estr} setting userAccountControl to UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD") m = ldb.Message() m.dn = res[0].dn @@ -361,7 +365,11 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") - self.samdb.modify(m) + try: + self.samdb.modify(m) + except LdbError as e: + (enum, estr) = e.args + self.fail(f"got {estr} setting userAccountControl to UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD") m = ldb.Message() m.dn = res[0].dn @@ -458,7 +466,11 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(UF_ACCOUNTDISABLE), ldb.FLAG_MOD_REPLACE, "userAccountControl") - self.admin_samdb.modify(m) + try: + self.admin_samdb.modify(m) + except LdbError as e: + (enum, estr) = e.args + self.fail(f"got {estr} setting userAccountControl to UF_ACCOUNTDISABLE (as admin)") res = self.admin_samdb.search("%s" % self.base_dn, expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, @@ -579,7 +591,11 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(orig_uac), ldb.FLAG_MOD_REPLACE, "userAccountControl") - self.admin_samdb.modify(m) + try: + self.admin_samdb.modify(m) + except LdbError as e: + (enum, estr) = e.args + self.fail(f"got {estr} resetting userAccountControl to initial value {orig_uac:#08x}") res = self.admin_samdb.search("%s" % self.base_dn, expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, @@ -898,7 +914,12 @@ class UserAccountControlTests(samba.tests.TestCase): and account_type == UF_NORMAL_ACCOUNT): self.admin_samdb.add(msg_dict) elif objectclass == "computer": - self.admin_samdb.add(msg_dict) + try: + self.admin_samdb.add(msg_dict) + except ldb.LdbError as e: + (num, msg) = e.args + self.fail("Failed to create {objectclass} account " + "with {account_type_string}") else: self.assertRaisesLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, "Should have been unable to {account_type_str} on {objectclass}", -- 2.25.1 From 5fe7265c3dbe34af2b13fe36cecc1cb7fc9d813a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 16 Sep 2021 08:46:42 +1200 Subject: [PATCH 464/645] CVE-2020-25722 dsdb: objectclass computer becomes UF_WORKSTATION_TRUST by default There are a lot of knownfail entries added with this commit. These all need to be addressed and removed in subsequent commits which will restructure the tests to pass within this new reality. This default applies even to users with administrator rights, as changing the default based on permissions would break to many assumptions. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 42 +++++++++++++++++++ source4/dsdb/samdb/ldb_modules/samldb.c | 27 +++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 selftest/knownfail.d/uac_objectclass_restrict diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict new file mode 100644 index 00000000000..a076f9cfedb --- /dev/null +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -0,0 +1,42 @@ +# Knownfail entries due to restricting the creation of computer/user +# accounts (in terms of userAccountControl) that do not match the objectclass +# +# All these tests need to be fixed and the entries here removed + +^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_isCriticalSystemObject\(fl2008r2dc\) +^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_userAccountControl\(fl2008r2dc\) +^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) +^samba4.ldap.python\(ad_dc_default\).__main__.BasicTests.test_all\(ad_dc_default\) +^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_isCriticalSystemObject\(ad_dc_default\) +^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_userAccountControl\(ad_dc_default\) +^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_admin_mod_uac\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x10000000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x20000000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x40000000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x80000000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00000004\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00000400\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00004000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00008000\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_ACCOUNTDISABLE\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_DONT_EXPIRE_PASSWD\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_DONT_REQUIRE_PREAUTH\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_HOMEDIR_REQUIRED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_LOCKOUT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_MNS_LOGON_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NORMAL_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NOT_DELEGATED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NO_AUTH_DATA_REQUIRED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWD_CANT_CHANGE\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWD_NOTREQD\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWORD_EXPIRED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SCRIPT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SMARTCARD_REQUIRED\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_AES_KEYS\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_DES_KEY_ONLY\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index cb5fda324a4..8df86f29883 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1413,19 +1413,33 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) switch(ac->type) { case SAMLDB_TYPE_USER: { + bool is_computer_objectclass; bool uac_generated = false, uac_add_flags = false; - + uint32_t default_user_account_control = UF_NORMAL_ACCOUNT; /* Step 1.2: Default values */ ret = dsdb_user_obj_set_defaults(ldb, ac->msg, ac->req); if (ret != LDB_SUCCESS) return ret; + is_computer_objectclass + = (samdb_find_attribute(ldb, + ac->msg, + "objectclass", + "computer") + != NULL); + + if (is_computer_objectclass) { + default_user_account_control + = UF_WORKSTATION_TRUST_ACCOUNT; + } + + /* On add operations we might need to generate a * "userAccountControl" (if it isn't specified). */ el = ldb_msg_find_element(ac->msg, "userAccountControl"); if ((el == NULL) && (ac->req->operation == LDB_ADD)) { ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg, "userAccountControl", - UF_NORMAL_ACCOUNT); + default_user_account_control); if (ret != LDB_SUCCESS) { return ret; } @@ -1444,11 +1458,14 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) raw_uac = user_account_control; /* * "userAccountControl" = 0 or missing one of - * the types means "UF_NORMAL_ACCOUNT". See - * MS-SAMR 3.1.1.8.10 point 8 + * the types means "UF_NORMAL_ACCOUNT" + * or "UF_WORKSTATION_TRUST_ACCOUNT" (if a computer). + * See MS-SAMR 3.1.1.8.10 point 8 */ if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) { - user_account_control = UF_NORMAL_ACCOUNT | user_account_control; + user_account_control + = default_user_account_control + | user_account_control; uac_generated = true; } -- 2.25.1 From 31097ae2f4acd77fda8238cdb58cd0a608e1cc03 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 15:42:08 +1300 Subject: [PATCH 465/645] CVE-2020-25722 dsdb: Improve privileged and unprivileged tests for objectclass/doller/UAC This helps ensure we cover off all the cases that matter for objectclass/trailing-doller/userAccountControl BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_dollar_lock | 1 + selftest/knownfail.d/uac_objectclass_restrict | 18 +- .../user_account_control-uac_mod_lock | 11 -- .../dsdb/tests/python/user_account_control.py | 172 +++++++++++++----- 4 files changed, 142 insertions(+), 60 deletions(-) create mode 100644 selftest/knownfail.d/uac_dollar_lock delete mode 100644 selftest/knownfail.d/user_account_control-uac_mod_lock diff --git a/selftest/knownfail.d/uac_dollar_lock b/selftest/knownfail.d/uac_dollar_lock new file mode 100644 index 00000000000..8c70c859fa4 --- /dev/null +++ b/selftest/knownfail.d/uac_dollar_lock @@ -0,0 +1 @@ +^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_cc_plain \ No newline at end of file diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index a076f9cfedb..bb0787c1a48 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -13,6 +13,22 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_admin_mod_uac\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_NORMAL_ACCOUNT_computer_cc_plain\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_NORMAL_ACCOUNT_computer_cc_withdollar\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_SERVER_TRUST_ACCOUNT_user_cc_plain\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_SERVER_TRUST_ACCOUNT_user_cc_withdollar\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_deladd_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_replace_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace_wp\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x10000000\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x20000000\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x40000000\(ad_dc_default\) @@ -38,5 +54,3 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SMARTCARD_REQUIRED\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_AES_KEYS\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_DES_KEY_ONLY\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) diff --git a/selftest/knownfail.d/user_account_control-uac_mod_lock b/selftest/knownfail.d/user_account_control-uac_mod_lock deleted file mode 100644 index a70534506f3..00000000000 --- a/selftest/knownfail.d/user_account_control-uac_mod_lock +++ /dev/null @@ -1,11 +0,0 @@ -# We do not want user account control account type swapping, so we mark these as knownfail -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_deladd -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index a22a72f12da..dabbac6373a 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -91,32 +91,43 @@ account_types = set([UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_ class UserAccountControlTests(samba.tests.TestCase): @classmethod def setUpDynamicTestCases(cls): + for priv in [(True, "priv"), (False, "cc")]: + for account_type in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + for objectclass in ["computer", "user"]: + for name in [("oc_uac_lock$", "withdollar"), \ + ("oc_uac_lock", "plain")]: + test_name = f"{account_type_str}_{objectclass}_{priv[1]}_{name[1]}" + cls.generate_dynamic_test("test_objectclass_uac_dollar_lock", + test_name, + account_type, + objectclass, + name[0], + priv[0]) + + for priv in [(True, "priv"), (False, "wp")]: + for account_type in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) + for account_type2 in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT]: + for how in ["replace", "deladd"]: + account_type2_str = dsdb.user_account_control_flag_bit_to_string(account_type2) + test_name = f"{account_type_str}_{account_type2_str}_{how}_{priv[1]}" + cls.generate_dynamic_test("test_objectclass_uac_mod_lock", + test_name, + account_type, + account_type2, + how, + priv[0]) for account_type in [UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT]: account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) - for objectclass in ["computer", "user"]: - test_name = f"{account_type_str}_{objectclass}" - cls.generate_dynamic_test("test_objectclass_uac_lock", - test_name, - account_type, - objectclass) - - for account_type in [UF_NORMAL_ACCOUNT, - UF_WORKSTATION_TRUST_ACCOUNT, - UF_SERVER_TRUST_ACCOUNT]: - account_type_str = dsdb.user_account_control_flag_bit_to_string(account_type) - for account_type2 in [UF_NORMAL_ACCOUNT, - UF_WORKSTATION_TRUST_ACCOUNT, - UF_SERVER_TRUST_ACCOUNT]: - for how in ["replace", "deladd"]: - account_type2_str = dsdb.user_account_control_flag_bit_to_string(account_type2) - test_name = f"{account_type_str}_{account_type2_str}_{how}" - cls.generate_dynamic_test("test_objectclass_uac_mod_lock", - test_name, - account_type, - account_type2, - how) for objectclass in ["user", "computer"]: for how in ["replace", "deladd"]: test_name = f"{account_type_str}_{objectclass}_{how}" @@ -895,10 +906,11 @@ class UserAccountControlTests(samba.tests.TestCase): "primaryGroupID") self.admin_samdb.modify(m) - def _test_objectclass_uac_lock_with_args(self, - account_type, - objectclass): - name = "oc_uac_lock$" + def _test_objectclass_uac_dollar_lock_with_args(self, + account_type, + objectclass, + name, + priv): dn = "CN=%s,%s" % (name, self.OU) msg_dict = { "dn": dn, @@ -910,25 +922,57 @@ class UserAccountControlTests(samba.tests.TestCase): print(f"Adding account {name} as {account_type_str} with objectclass {objectclass}") - if (objectclass == "user" \ - and account_type == UF_NORMAL_ACCOUNT): - self.admin_samdb.add(msg_dict) - elif objectclass == "computer": - try: - self.admin_samdb.add(msg_dict) - except ldb.LdbError as e: - (num, msg) = e.args - self.fail("Failed to create {objectclass} account " - "with {account_type_string}") + if priv: + samdb = self.admin_samdb else: - self.assertRaisesLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, - "Should have been unable to {account_type_str} on {objectclass}", - self.admin_samdb.add, msg_dict) + user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) + mod = "(OA;;CC;;;%s)" % str(user_sid) + + self.sd_utils.dacl_add_ace(self.OU, mod) + samdb = self.samdb + + enum = ldb.SUCCESS + try: + samdb.add(msg_dict) + except ldb.LdbError as e: + (enum, msg) = e.args + + if (account_type == UF_SERVER_TRUST_ACCOUNT + and objectclass != "computer"): + self.assertEqual(enum, ldb.ERR_OBJECT_CLASS_VIOLATION) + return + + if priv == False and account_type == UF_SERVER_TRUST_ACCOUNT: + self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + return + + if (objectclass == "user" + and account_type != UF_NORMAL_ACCOUNT): + self.assertEqual(enum, ldb.ERR_OBJECT_CLASS_VIOLATION) + return + + if (not priv and objectclass == "computer" + and account_type == UF_NORMAL_ACCOUNT): + self.assertEqual(enum, ldb.ERR_OBJECT_CLASS_VIOLATION) + return + + if priv and account_type == UF_NORMAL_ACCOUNT: + self.assertEqual(enum, 0) + return + + if (priv == False and + account_type != UF_NORMAL_ACCOUNT and + name[-1] != '$'): + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + return + + self.assertEqual(enum, 0) def _test_objectclass_uac_mod_lock_with_args(self, account_type, account_type2, - how): + how, + priv): name = "uac_mod_lock$" dn = "CN=%s,%s" % (name, self.OU) if account_type == UF_NORMAL_ACCOUNT: @@ -949,10 +993,25 @@ class UserAccountControlTests(samba.tests.TestCase): print(f"Adding account {name} as {account_type_str} with objectclass {objectclass}") + if priv: + samdb = self.admin_samdb + else: + samdb = self.samdb + + user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) + + # Create the object as admin self.admin_samdb.add(msg_dict) + # We want to test what the underlying rules for non-admins + # regardless of security descriptors are, so set this very, + # dangerously, broadly + mod = "(OA;;WP;;;%s)" % str(user_sid) + + self.sd_utils.dacl_add_ace(dn, mod) + m = ldb.Message() - m.dn = ldb.Dn(self.admin_samdb, dn) + m.dn = ldb.Dn(samdb, dn) if how == "replace": m["userAccountControl"] = ldb.MessageElement(str(account_type2 | UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") @@ -964,17 +1023,36 @@ class UserAccountControlTests(samba.tests.TestCase): else: raise ValueError(f"{how} was not a valid argument") - if (account_type in [UF_SERVER_TRUST_ACCOUNT, - UF_WORKSTATION_TRUST_ACCOUNT]) and \ + if (account_type == account_type2): + samdb.modify(m) + elif (account_type == UF_NORMAL_ACCOUNT) and \ + (account_type2 == UF_SERVER_TRUST_ACCOUNT) and not priv: + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Should have been unable to change {account_type_str} to {account_type2_str}", + samdb.modify, m) + elif (account_type == UF_NORMAL_ACCOUNT) and \ + (account_type2 == UF_SERVER_TRUST_ACCOUNT) and priv: + self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + f"Should have been unable to change {account_type_str} to {account_type2_str}", + samdb.modify, m) + elif (account_type == UF_WORKSTATION_TRUST_ACCOUNT) and \ + (account_type2 == UF_SERVER_TRUST_ACCOUNT) and not priv: + self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + f"Should have been unable to change {account_type_str} to {account_type2_str}", + samdb.modify, m) + elif priv: + samdb.modify(m) + elif (account_type in [UF_SERVER_TRUST_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT]) and \ (account_type2 in [UF_SERVER_TRUST_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT]): - self.admin_samdb.modify(m) + samdb.modify(m) elif (account_type == account_type2): - self.admin_samdb.modify(m) + samdb.modify(m) else: - self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + self.assertRaisesLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, f"Should have been unable to change {account_type_str} to {account_type2_str}", - self.admin_samdb.modify, m) + samdb.modify, m) def _test_objectclass_mod_lock_with_args(self, account_type, -- 2.25.1 From 9cdfa278d05afdb9e2799807658848222bb71cea Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 23:33:32 +1300 Subject: [PATCH 466/645] CVE-2020-25722 dsdb: Add tests for modifying objectClass, userAccountControl and sAMAccountName BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14889 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/uac_mod_lock | 46 ++++++ .../dsdb/tests/python/user_account_control.py | 150 ++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 selftest/knownfail.d/uac_mod_lock diff --git a/selftest/knownfail.d/uac_mod_lock b/selftest/knownfail.d/uac_mod_lock new file mode 100644 index 00000000000..6f45fa50554 --- /dev/null +++ b/selftest/knownfail.d/uac_mod_lock @@ -0,0 +1,46 @@ +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_None_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index dabbac6373a..1633998ada4 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -124,6 +124,46 @@ class UserAccountControlTests(samba.tests.TestCase): account_type2, how, priv[0]) + + for objectclass in ["computer", "user"]: + account_types = [UF_NORMAL_ACCOUNT] + if objectclass == "computer": + account_types.append(UF_WORKSTATION_TRUST_ACCOUNT) + account_types.append(UF_SERVER_TRUST_ACCOUNT) + + for account_type in account_types: + account_type_str = ( + dsdb.user_account_control_flag_bit_to_string( + account_type)) + for account_type2 in [UF_NORMAL_ACCOUNT, + UF_WORKSTATION_TRUST_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT, + UF_PARTIAL_SECRETS_ACCOUNT, + None]: + if account_type2 is None: + account_type2_str = None + else: + account_type2_str = ( + dsdb.user_account_control_flag_bit_to_string( + account_type2)) + + for objectclass2 in ["computer", "user", None]: + for name2 in [("oc_uac_lock", "remove_dollar"), + (None, "keep_dollar")]: + test_name = (f"{priv[1]}_{objectclass}_" + f"{account_type_str}_to_" + f"{objectclass2}_" + f"{account_type2_str}_" + f"{name2[1]}") + cls.generate_dynamic_test("test_mod_lock", + test_name, + objectclass, + objectclass2, + account_type, + account_type2, + name2[0], + priv[0]) + for account_type in [UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT]: @@ -968,6 +1008,116 @@ class UserAccountControlTests(samba.tests.TestCase): self.assertEqual(enum, 0) + def _test_mod_lock_with_args(self, + objectclass, + objectclass2, + account_type, + account_type2, + name2, + priv): + name = "oc_uac_lock$" + + dn = "CN=%s,%s" % (name, self.OU) + msg_dict = { + "dn": dn, + "objectclass": objectclass, + "samAccountName": name, + "userAccountControl": str(account_type | UF_PASSWD_NOTREQD)} + + account_type_str = dsdb.user_account_control_flag_bit_to_string( + account_type) + + print(f"Adding account {name} as {account_type_str} " + f"with objectclass {objectclass}") + + # Create the object as admin + self.admin_samdb.add(msg_dict) + + if priv: + samdb = self.admin_samdb + else: + samdb = self.samdb + + user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) + + # We want to test what the underlying rules for non-admins regardless + # of security descriptors are, so set this very, dangerously, broadly + mod = f"(OA;;WP;;;{user_sid})" + + self.sd_utils.dacl_add_ace(dn, mod) + + msg = "Modifying account" + if name2 is not None: + msg += f" to {name2}" + if account_type2 is not None: + account_type2_str = dsdb.user_account_control_flag_bit_to_string( + account_type2) + msg += f" as {account_type2_str}" + else: + account_type2_str = None + if objectclass2 is not None: + msg += f" with objectClass {objectclass2}" + print(msg) + + msg = ldb.Message(ldb.Dn(samdb, dn)) + if objectclass2 is not None: + msg["objectClass"] = ldb.MessageElement(objectclass2, + ldb.FLAG_MOD_REPLACE, + "objectClass") + if name2 is not None: + msg["sAMAccountName"] = ldb.MessageElement(name2, + ldb.FLAG_MOD_REPLACE, + "sAMAccountName") + if account_type2 is not None: + msg["userAccountControl"] = ldb.MessageElement( + str(account_type2 | UF_PASSWD_NOTREQD), + ldb.FLAG_MOD_REPLACE, + "userAccountControl") + enum = ldb.SUCCESS + try: + samdb.modify(msg) + except ldb.LdbError as e: + enum, _ = e.args + + # Setting userAccountControl to be an RODC is not allowed. + if account_type2 == UF_PARTIAL_SECRETS_ACCOUNT: + self.assertEqual(enum, ldb.ERR_OTHER) + return + + # Unprivileged users cannot change userAccountControl. The exception is + # changing a non-normal account to UF_WORKSTATION_TRUST_ACCOUNT, which + # is allowed. + if (not priv + and account_type2 is not None + and account_type != account_type2 + and (account_type == UF_NORMAL_ACCOUNT + or account_type2 != UF_WORKSTATION_TRUST_ACCOUNT)): + self.assertIn(enum, [ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + ldb.ERR_OBJECT_CLASS_VIOLATION]) + return + + # A non-computer account cannot have UF_SERVER_TRUST_ACCOUNT. + if objectclass == "user" and account_type2 == UF_SERVER_TRUST_ACCOUNT: + self.assertIn(enum, [ldb.ERR_UNWILLING_TO_PERFORM, + ldb.ERR_OBJECT_CLASS_VIOLATION]) + return + + # The objectClass is not allowed to change. + if objectclass2 is not None and objectclass != objectclass2: + self.assertIn(enum, [ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_UNWILLING_TO_PERFORM]) + return + + # Unprivileged users cannot remove the trailing dollar from a computer + # account. + if not priv and objectclass == "computer" and ( + name2 is not None and name2[-1] != "$"): + self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + return + + self.assertEqual(enum, 0) + return + def _test_objectclass_uac_mod_lock_with_args(self, account_type, account_type2, -- 2.25.1 From 127b8b6b4cbb750db561333ce772640ed1e19f27 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 16:07:46 +1300 Subject: [PATCH 467/645] CVE-2020-25722 dsdb: Prohibit mismatch between UF_ account types and objectclass. There are a lot of knownfail entries added with this commit. These all need to be addressed and removed in subsequent commits which will restructure the tests to pass within this new reality. The restriction is not applied to users with administrator rights, as this breaks a lot of tests and provides no security benefit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 6 - selftest/knownfail.d/uac_mod_lock | 6 - selftest/knownfail.d/uac_objectclass_restrict | 35 ++-- source4/dsdb/samdb/ldb_modules/samldb.c | 153 ++++++++++++++---- 4 files changed, 145 insertions(+), 55 deletions(-) diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr index 4b85a869089..e0d6104cec9 100644 --- a/selftest/knownfail.d/priv_attr +++ b/selftest/knownfail.d/priv_attr @@ -6,9 +6,3 @@ samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sid samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_computer samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_admin-add_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-RODC_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-RODC_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-computer_add_CC_default_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-computer_add_CC_WP_user -samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-computer_add_CC_default_user diff --git a/selftest/knownfail.d/uac_mod_lock b/selftest/knownfail.d/uac_mod_lock index 6f45fa50554..a84a236c355 100644 --- a/selftest/knownfail.d/uac_mod_lock +++ b/selftest/knownfail.d/uac_mod_lock @@ -24,16 +24,10 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_SERVER_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_SERVER_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index bb0787c1a48..040c4eb219d 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -10,6 +10,16 @@ ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_isCriticalSystemObject\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_userAccountControl\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_WP_user\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_default_user\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_default_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-del-add_CC_default_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_mod-replace_CC_default_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_add_CC_WP_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_add_CC_default_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-del-add_CC_default_computer\(ad_dc_default\) +^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-replace_CC_default_computer\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_admin_mod_uac\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\) @@ -17,18 +27,6 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_NORMAL_ACCOUNT_computer_cc_plain\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_NORMAL_ACCOUNT_computer_cc_withdollar\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_SERVER_TRUST_ACCOUNT_user_cc_plain\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_SERVER_TRUST_ACCOUNT_user_cc_withdollar\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_deladd_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_WORKSTATION_TRUST_ACCOUNT_replace_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_SERVER_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_deladd_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_UF_NORMAL_ACCOUNT_replace_wp\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x10000000\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x20000000\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x40000000\(ad_dc_default\) @@ -54,3 +52,16 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SMARTCARD_REQUIRED\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_AES_KEYS\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_DES_KEY_ONLY\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_deladd_priv\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_deladd_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_replace_priv\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_replace_wp\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT_UF_PASSWD_NOTREQD\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_TRUSTED_FOR_DELEGATION\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION\(ad_dc_default\) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 8df86f29883..15459abcbca 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1365,7 +1365,8 @@ static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, struct dom_sid *sid, uint32_t req_uac, uint32_t user_account_control, - uint32_t user_account_control_old); + uint32_t user_account_control_old, + bool is_computer_objectclass); /* * "Objectclass" trigger (MS-SAMR 3.1.1.8.1) @@ -1484,21 +1485,12 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) ret = samldb_check_user_account_control_rules(ac, NULL, raw_uac, user_account_control, - 0); + 0, + is_computer_objectclass); if (ret != LDB_SUCCESS) { return ret; } - /* Workstation and (read-only) DC objects do need objectclass "computer" */ - if ((samdb_find_attribute(ldb, ac->msg, - "objectclass", "computer") == NULL) && - (user_account_control & - (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) { - ldb_set_errstring(ldb, - "samldb: Requested account type does need objectclass 'computer'!"); - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - /* add "sAMAccountType" attribute */ ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL); if (ret != LDB_SUCCESS) { @@ -1993,6 +1985,106 @@ static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac, return ret; } +/* + * It would be best if these rules apply, always, but for now they + * apply only to non-admins + */ +static int samldb_check_user_account_control_objectclass_invariants( + struct samldb_ctx *ac, + uint32_t user_account_control, + uint32_t user_account_control_old, + bool is_computer_objectclass) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + + uint32_t old_ufa = user_account_control_old & UF_ACCOUNT_TYPE_MASK; + uint32_t new_ufa = user_account_control & UF_ACCOUNT_TYPE_MASK; + + uint32_t old_rodc = user_account_control_old & UF_PARTIAL_SECRETS_ACCOUNT; + uint32_t new_rodc = user_account_control & UF_PARTIAL_SECRETS_ACCOUNT; + + bool is_admin; + struct security_token *user_token + = acl_user_token(ac->module); + if (user_token == NULL) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + + is_admin + = security_token_has_builtin_administrators(user_token); + + + /* + * We want to allow changes to (eg) disable an account + * that was created wrong, only checking the + * objectclass if the account type changes. + */ + if (old_ufa == new_ufa && old_rodc == new_rodc) { + return LDB_SUCCESS; + } + + switch (new_ufa) { + case UF_NORMAL_ACCOUNT: + if (is_computer_objectclass && !is_admin) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_NORMAL_ACCOUNT " + "requires objectclass 'user' not 'computer'!", + W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + break; + + case UF_INTERDOMAIN_TRUST_ACCOUNT: + if (is_computer_objectclass) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_INTERDOMAIN_TRUST_ACCOUNT " + "requires objectclass 'user' not 'computer'!", + W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + break; + + case UF_WORKSTATION_TRUST_ACCOUNT: + if (!is_computer_objectclass) { + /* + * Modify of a user account account into a + * workstation without objectclass computer + * as an admin is still permitted, but not + * to make an RODC + */ + if (is_admin + && ac->req->operation == LDB_MODIFY + && new_rodc == 0) { + break; + } + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_WORKSTATION_TRUST_ACCOUNT " + "requires objectclass 'computer'!", + W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + break; + + case UF_SERVER_TRUST_ACCOUNT: + if (!is_computer_objectclass) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_SERVER_TRUST_ACCOUNT " + "requires objectclass 'computer'!", + W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + break; + + default: + ldb_asprintf_errstring(ldb, + "%08X: samldb: invalid userAccountControl[0x%08X]", + W_ERROR_V(WERR_INVALID_PARAMETER), + user_account_control); + return LDB_ERR_OTHER; + } + return LDB_SUCCESS; +} + static int samldb_get_domain_secdesc(struct samldb_ctx *ac, struct security_descriptor **domain_sd) { @@ -2191,7 +2283,8 @@ static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, struct dom_sid *sid, uint32_t req_uac, uint32_t user_account_control, - uint32_t user_account_control_old) + uint32_t user_account_control_old, + bool is_computer_objectclass) { int ret; struct dsdb_control_password_user_account_control *uac = NULL; @@ -2200,6 +2293,14 @@ static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, if (ret != LDB_SUCCESS) { return ret; } + ret = samldb_check_user_account_control_objectclass_invariants(ac, + user_account_control, + user_account_control_old, + is_computer_objectclass); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old); if (ret != LDB_SUCCESS) { return ret; @@ -2261,7 +2362,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) "objectSid", NULL }; - bool is_computer = false; + bool is_computer_objectclass = false; bool old_is_critical = false; bool new_is_critical = false; @@ -2316,7 +2417,10 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) "lockoutTime", 0); old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0], "isCriticalSystemObject", 0); - /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */ + /* + * When we do not have objectclass "computer" we cannot + * switch to a workstation or (RO)DC + */ el = ldb_msg_find_element(res->msgs[0], "objectClass"); if (el == NULL) { return ldb_operr(ldb); @@ -2324,7 +2428,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) computer_val = data_blob_string_const("computer"); val = ldb_msg_find_val(el, &computer_val); if (val != NULL) { - is_computer = true; + is_computer_objectclass = true; } old_ufa = old_uac & UF_ACCOUNT_TYPE_MASK; @@ -2349,7 +2453,8 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) ret = samldb_check_user_account_control_rules(ac, sid, raw_uac, new_uac, - old_uac); + old_uac, + is_computer_objectclass); if (ret != LDB_SUCCESS) { return ret; } @@ -2371,25 +2476,11 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) case UF_WORKSTATION_TRUST_ACCOUNT: new_is_critical = false; if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) { - if (!is_computer) { - ldb_asprintf_errstring(ldb, - "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT " - "requires objectclass 'computer'!", - W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } new_is_critical = true; } break; case UF_SERVER_TRUST_ACCOUNT: - if (!is_computer) { - ldb_asprintf_errstring(ldb, - "%08X: samldb: UF_SERVER_TRUST_ACCOUNT " - "requires objectclass 'computer'!", - W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); - return LDB_ERR_UNWILLING_TO_PERFORM; - } new_is_critical = true; break; -- 2.25.1 From 18ac29d150eece96cccae3625d6ba4accff04eff Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 28 Oct 2021 14:47:30 +1300 Subject: [PATCH 468/645] CVE-2020-25722 selftest/priv_attrs: Mention that these knownfails are OK (for now) BUG: https://bugzilla.samba.org/show_bug.cgi?id=14775 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/priv_attr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/selftest/knownfail.d/priv_attr b/selftest/knownfail.d/priv_attr index e0d6104cec9..5d3713eafe3 100644 --- a/selftest/knownfail.d/priv_attr +++ b/selftest/knownfail.d/priv_attr @@ -1,3 +1,8 @@ +# These priv_attrs tests would be good to fix, but are not fatal as +# the testsuite is run twice, once with and once without STRICT_CHECKING=0 +# +# These knownfails show that we can improve our error matching against Windows. +# samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_computer samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_WP_user samba4.priv_attrs.strict.python\(.*\).__main__.PrivAttrsTests.test_priv_attr_sidHistory_add_CC_default_computer -- 2.25.1 From e04e9eb407366864a72912ec78a8c62215eaa473 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 16:18:51 +1300 Subject: [PATCH 469/645] CVE-2020-25722 selftest: Adapt selftest to restriction on swapping account types This makes many of our tests pass again. We do not pass against Windows 2019 on all as this does not have this restriction at this time. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 29 +--------- .../dsdb/tests/python/user_account_control.py | 54 +++++++++++++------ 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 040c4eb219d..32d8a99f950 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -27,31 +27,7 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x10000000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x20000000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x40000000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_0x80000000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00000004\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00000400\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00004000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_00008000\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_ACCOUNTDISABLE\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_DONT_EXPIRE_PASSWD\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_DONT_REQUIRE_PREAUTH\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_HOMEDIR_REQUIRED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_LOCKOUT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_MNS_LOGON_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NORMAL_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NOT_DELEGATED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_NO_AUTH_DATA_REQUIRED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWD_CANT_CHANGE\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWD_NOTREQD\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_PASSWORD_EXPIRED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SCRIPT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SMARTCARD_REQUIRED\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_AES_KEYS\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_USE_DES_KEY_ONLY\(ad_dc_default\) +^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SERVER_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) @@ -62,6 +38,3 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT_UF_PASSWD_NOTREQD\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_TRUSTED_FOR_DELEGATION\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 1633998ada4..7a7cfd40b72 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -219,6 +219,23 @@ class UserAccountControlTests(samba.tests.TestCase): print("Adding computer account %s" % computername) samdb.add(msg) + def add_user_ldap(self, username, others=None, samdb=None): + if samdb is None: + samdb = self.samdb + dn = "CN=%s,%s" % (username, self.OU) + samaccountname = "%s" % username + msg_dict = { + "dn": dn, + "objectclass": "user"} + if others is not None: + msg_dict = dict(list(msg_dict.items()) + list(others.items())) + + msg = ldb.Message.from_dict(self.samdb, msg_dict) + msg["sAMAccountName"] = samaccountname + + print("Adding user account %s" % username) + samdb.add(msg) + def get_creds(self, target_username, target_password): creds_tmp = Credentials() creds_tmp.set_username(target_username) @@ -532,17 +549,21 @@ class UserAccountControlTests(samba.tests.TestCase): def _test_uac_bits_set_with_args(self, bit, bit_str): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) - mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) + # Allow the creation of any children and write to any + # attributes (this is not a test of ACLs, this is a test of + # non-ACL userAccountControl rules + mod = f"(OA;CI;WP;;;{user_sid})(OA;;CC;;;{user_sid})" old_sd = self.sd_utils.read_sd_on_dn(self.OU) self.sd_utils.dacl_add_ace(self.OU, mod) + # We want to start with UF_NORMAL_ACCOUNT, so we make a user computername = self.computernames[0] - self.add_computer_ldap(computername) + self.add_user_ldap(computername) res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + expression="(&(objectClass=user)(cn=%s))" % computername, scope=SCOPE_SUBTREE, attrs=[]) @@ -588,7 +609,11 @@ class UserAccountControlTests(samba.tests.TestCase): def _test_uac_bits_unrelated_modify_with_args(self, account_type): user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) - mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid) + + # Allow the creation of any children and write to any + # attributes (this is not a test of ACLs, this is a test of + # non-ACL userAccountControl rules + mod = f"(OA;CI;WP;;;{user_sid})(OA;;CC;;;{user_sid})" old_sd = self.sd_utils.read_sd_on_dn(self.OU) @@ -596,22 +621,19 @@ class UserAccountControlTests(samba.tests.TestCase): computername = self.computernames[0] if account_type == UF_WORKSTATION_TRUST_ACCOUNT: - self.add_computer_ldap(computername, others={"userAccountControl": [str(account_type)]}) - else: self.add_computer_ldap(computername) + else: + self.add_user_ldap(computername) res = self.admin_samdb.search(self.OU, - expression=f"(cn={computername})", + expression=f"(&(objectclass=user)(cn={computername}))", scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) self.assertEqual(len(res), 1) orig_uac = int(res[0]["userAccountControl"][0]) - if account_type == UF_WORKSTATION_TRUST_ACCOUNT: - self.assertEqual(orig_uac, account_type) - else: - self.assertEqual(orig_uac & UF_NORMAL_ACCOUNT, - account_type) + self.assertEqual(orig_uac & account_type, + account_type) m = ldb.Message() m.dn = res[0].dn @@ -649,7 +671,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.fail(f"got {estr} resetting userAccountControl to initial value {orig_uac:#08x}") res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + expression="(&(objectClass=user)(cn=%s))" % computername, scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) @@ -696,7 +718,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + expression="(&(objectClass=user)(cn=%s))" % computername, scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) @@ -726,7 +748,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.fail("Unable to set userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + expression="(&(objectClass=user)(cn=%s))" % computername, scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) @@ -767,7 +789,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.fail("Unexpectedly unable to remove userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) res = self.admin_samdb.search("%s" % self.base_dn, - expression="(&(objectClass=computer)(samAccountName=%s$))" % computername, + expression="(&(objectClass=user)(cn=%s))" % computername, scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) -- 2.25.1 From 3d5c7ae74e6e4986534582b519b9a8911305847b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Sep 2021 11:28:05 +1200 Subject: [PATCH 470/645] CVE-2020-25722 dsdb: samldb_objectclass_trigger() is only called on ADD, so remove indentation This makes the code less indented and simpler to understand. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- source4/dsdb/samdb/ldb_modules/samldb.c | 187 ++++++++++++------------ 1 file changed, 93 insertions(+), 94 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 15459abcbca..e7962cdde42 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1371,9 +1371,9 @@ static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, /* * "Objectclass" trigger (MS-SAMR 3.1.1.8.1) * - * Has to be invoked on "add" and "modify" operations on "user", "computer" and + * Has to be invoked on "add" operations on "user", "computer" and * "group" objects. - * ac->msg contains the "add"/"modify" message + * ac->msg contains the "add" * ac->type contains the object type (main objectclass) */ static int samldb_objectclass_trigger(struct samldb_ctx *ac) @@ -1414,6 +1414,8 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) switch(ac->type) { case SAMLDB_TYPE_USER: { + uint32_t raw_uac; + uint32_t user_account_control; bool is_computer_objectclass; bool uac_generated = false, uac_add_flags = false; uint32_t default_user_account_control = UF_NORMAL_ACCOUNT; @@ -1437,7 +1439,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) /* On add operations we might need to generate a * "userAccountControl" (if it isn't specified). */ el = ldb_msg_find_element(ac->msg, "userAccountControl"); - if ((el == NULL) && (ac->req->operation == LDB_ADD)) { + if (el == NULL) { ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg, "userAccountControl", default_user_account_control); @@ -1449,114 +1451,111 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) } el = ldb_msg_find_element(ac->msg, "userAccountControl"); - if (el != NULL) { - uint32_t raw_uac; - uint32_t user_account_control; - /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */ - user_account_control = ldb_msg_find_attr_as_uint(ac->msg, - "userAccountControl", - 0); - raw_uac = user_account_control; - /* - * "userAccountControl" = 0 or missing one of - * the types means "UF_NORMAL_ACCOUNT" - * or "UF_WORKSTATION_TRUST_ACCOUNT" (if a computer). - * See MS-SAMR 3.1.1.8.10 point 8 - */ - if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) { - user_account_control - = default_user_account_control - | user_account_control; - uac_generated = true; - } + SMB_ASSERT(el != NULL); - /* - * As per MS-SAMR 3.1.1.8.10 these flags have not to be set - */ - if ((user_account_control & UF_LOCKOUT) != 0) { - user_account_control &= ~UF_LOCKOUT; - uac_generated = true; - } - if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) { - user_account_control &= ~UF_PASSWORD_EXPIRED; - uac_generated = true; - } + /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */ + user_account_control = ldb_msg_find_attr_as_uint(ac->msg, + "userAccountControl", + 0); + raw_uac = user_account_control; + /* + * "userAccountControl" = 0 or missing one of + * the types means "UF_NORMAL_ACCOUNT" + * or "UF_WORKSTATION_TRUST_ACCOUNT" (if a computer). + * See MS-SAMR 3.1.1.8.10 point 8 + */ + if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) { + user_account_control + = default_user_account_control + | user_account_control; + uac_generated = true; + } + + /* + * As per MS-SAMR 3.1.1.8.10 these flags have not to be set + */ + if ((user_account_control & UF_LOCKOUT) != 0) { + user_account_control &= ~UF_LOCKOUT; + uac_generated = true; + } + if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) { + user_account_control &= ~UF_PASSWORD_EXPIRED; + uac_generated = true; + } - ret = samldb_check_user_account_control_rules(ac, NULL, - raw_uac, - user_account_control, - 0, - is_computer_objectclass); + ret = samldb_check_user_account_control_rules(ac, NULL, + raw_uac, + user_account_control, + 0, + is_computer_objectclass); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* add "sAMAccountType" attribute */ + ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* "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"); if (ret != LDB_SUCCESS) { return ret; } - - /* add "sAMAccountType" attribute */ - ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL); + 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"); if (ret != LDB_SUCCESS) { return ret; } + el2 = ldb_msg_find_element(ac->msg, + "isCriticalSystemObject"); + el2->flags = LDB_FLAG_MOD_REPLACE; + } - /* "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"); - 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"); - 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 */ - if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) { - uint32_t rid; + /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ + if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) { + uint32_t rid; - ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid); + ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid); + if (ret != LDB_SUCCESS) { + return ret; + } + /* + * Older AD deployments don't know about the + * RODC group + */ + if (rid == DOMAIN_RID_READONLY_DCS) { + ret = samldb_prim_group_tester(ac, rid); if (ret != LDB_SUCCESS) { return ret; } - /* - * Older AD deployments don't know about the - * RODC group - */ - if (rid == DOMAIN_RID_READONLY_DCS) { - ret = samldb_prim_group_tester(ac, rid); - if (ret != LDB_SUCCESS) { - return ret; - } - } } + } - /* Step 1.5: Add additional flags when needed */ - /* Obviously this is done when the "userAccountControl" - * has been generated here (tested against Windows - * Server) */ - if (uac_generated) { - if (uac_add_flags) { - user_account_control |= UF_ACCOUNTDISABLE; - user_account_control |= UF_PASSWD_NOTREQD; - } - - ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg, - "userAccountControl", - user_account_control); - if (ret != LDB_SUCCESS) { - return ret; - } + /* Step 1.5: Add additional flags when needed */ + /* Obviously this is done when the "userAccountControl" + * has been generated here (tested against Windows + * Server) */ + if (uac_generated) { + if (uac_add_flags) { + user_account_control |= UF_ACCOUNTDISABLE; + user_account_control |= UF_PASSWD_NOTREQD; } + ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg, + "userAccountControl", + user_account_control); + if (ret != LDB_SUCCESS) { + return ret; + } } break; } -- 2.25.1 From 5961cd04b5d14eea9472f2d5238c495d59420413 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Sep 2021 11:29:02 +1200 Subject: [PATCH 471/645] CVE-2020-25722 dsdb: Add restrictions on computer accounts without a trailing $ BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_dollar_lock | 1 - selftest/knownfail.d/uac_mod_lock | 12 -- source4/dsdb/samdb/ldb_modules/samldb.c | 171 +++++++++++++++++++++--- 3 files changed, 154 insertions(+), 30 deletions(-) delete mode 100644 selftest/knownfail.d/uac_dollar_lock diff --git a/selftest/knownfail.d/uac_dollar_lock b/selftest/knownfail.d/uac_dollar_lock deleted file mode 100644 index 8c70c859fa4..00000000000 --- a/selftest/knownfail.d/uac_dollar_lock +++ /dev/null @@ -1 +0,0 @@ -^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_objectclass_uac_dollar_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_cc_plain \ No newline at end of file diff --git a/selftest/knownfail.d/uac_mod_lock b/selftest/knownfail.d/uac_mod_lock index a84a236c355..068a47c6e61 100644 --- a/selftest/knownfail.d/uac_mod_lock +++ b/selftest/knownfail.d/uac_mod_lock @@ -20,21 +20,9 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_None_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_SERVER_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_None_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_SERVER_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_None_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index e7962cdde42..aeef663d2f0 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -68,6 +68,13 @@ struct samldb_ctx { /* used for add operations */ enum samldb_add_type type; + /* + * should we apply the need_trailing_dollar restriction to + * samAccountName + */ + + bool need_trailing_dollar; + /* the resulting message */ struct ldb_message *msg; @@ -232,12 +239,86 @@ static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr, static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac) { - int ret = samldb_unique_attr_check(ac, "samAccountName", NULL, - ldb_get_default_basedn( - ldb_module_get_ctx(ac->module))); - if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) { + int ret = 0; + bool is_admin; + struct security_token *user_token = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + struct ldb_message_element *el = dsdb_get_single_valued_attr(ac->msg, "samAccountName", + ac->req->operation); + if (el == NULL || el->num_values == 0) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: 'samAccountName' can't be deleted/empty!", + W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); + if (ac->req->operation == LDB_ADD) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + } + + ret = samldb_unique_attr_check(ac, "samAccountName", NULL, + ldb_get_default_basedn( + ldb_module_get_ctx(ac->module))); + + /* + * Error code munging to try and match what must be some quite + * strange code-paths in Windows + */ + if (ret == LDB_ERR_CONSTRAINT_VIOLATION + && ac->req->operation == LDB_MODIFY) { + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } else if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) { ret = LDB_ERR_CONSTRAINT_VIOLATION; } + + if (ret != LDB_SUCCESS) { + return ret; + } + + if (!ac->need_trailing_dollar) { + return LDB_SUCCESS; + } + + /* This does not permit a single $ */ + if (el->values[0].length < 2) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: 'samAccountName' " + "can't just be one character!", + W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + user_token = acl_user_token(ac->module); + if (user_token == NULL) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + + is_admin + = security_token_has_builtin_administrators(user_token); + + if (is_admin) { + /* + * Administrators are allowed to select strange names. + * This is poor practice but not prevented. + */ + return false; + } + + if (el->values[0].data[el->values[0].length - 1] != '$') { + ldb_asprintf_errstring(ldb, + "%08X: samldb: 'samAccountName' " + "must have a trailing $!", + W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (el->values[0].data[el->values[0].length - 2] == '$') { + ldb_asprintf_errstring(ldb, + "%08X: samldb: 'samAccountName' " + "must not have a double trailing $!", + W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + return ret; } @@ -554,17 +635,31 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) } /* sAMAccountName handling */ -static int samldb_generate_sAMAccountName(struct ldb_context *ldb, +static int samldb_generate_sAMAccountName(struct samldb_ctx *ac, struct ldb_message *msg) { + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); char *name; - /* Format: $000000-000000000000 */ + /* + * This is currently a Samba-only behaviour, to add a trailing + * $ even for the generated accounts. + */ + + if (ac->need_trailing_dollar) { + /* Format: $000000-00000000000$ */ + name = talloc_asprintf(msg, "$%.6X-%.6X%.5X$", + (unsigned int)generate_random(), + (unsigned int)generate_random(), + (unsigned int)generate_random()); + } else { + /* Format: $000000-000000000000 */ - name = talloc_asprintf(msg, "$%.6X-%.6X%.6X", - (unsigned int)generate_random(), - (unsigned int)generate_random(), - (unsigned int)generate_random()); + name = talloc_asprintf(msg, "$%.6X-%.6X%.6X", + (unsigned int)generate_random(), + (unsigned int)generate_random(), + (unsigned int)generate_random()); + } if (name == NULL) { return ldb_oom(ldb); } @@ -573,11 +668,10 @@ static int samldb_generate_sAMAccountName(struct ldb_context *ldb, static int samldb_check_sAMAccountName(struct samldb_ctx *ac) { - struct ldb_context *ldb = ldb_module_get_ctx(ac->module); int ret; if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) { - ret = samldb_generate_sAMAccountName(ldb, ac->msg); + ret = samldb_generate_sAMAccountName(ac, ac->msg); if (ret != LDB_SUCCESS) { return ret; } @@ -1492,6 +1586,20 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) return ret; } + /* + * Require, for non-admin modifications, a trailing $ + * for either objectclass=computer or a trust account + * type in userAccountControl + */ + if ((user_account_control + & UF_TRUST_ACCOUNT_MASK) != 0) { + ac->need_trailing_dollar = true; + } + + if (is_computer_objectclass) { + ac->need_trailing_dollar = true; + } + /* add "sAMAccountType" attribute */ ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL); if (ret != LDB_SUCCESS) { @@ -4005,12 +4113,41 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) el = ldb_msg_find_element(ac->msg, "sAMAccountName"); if (el != NULL) { + uint32_t user_account_control; + struct ldb_result *res = NULL; + const char * const attrs[] = { "userAccountControl", + "objectclass", + NULL }; + ret = dsdb_module_search_dn(ac->module, + ac, + &res, + ac->msg->dn, + attrs, + DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + + user_account_control + = ldb_msg_find_attr_as_uint(res->msgs[0], + "userAccountControl", + 0); + + if ((user_account_control + & UF_TRUST_ACCOUNT_MASK) != 0) { + ac->need_trailing_dollar = true; + + } else if (samdb_find_attribute(ldb, + res->msgs[0], + "objectclass", + "computer") + != NULL) { + ac->need_trailing_dollar = true; + } + ret = samldb_sam_accountname_valid_check(ac); - /* - * Other errors are checked for elsewhere, we just - * want to prevent duplicates - */ - if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + if (ret != LDB_SUCCESS) { return ret; } } -- 2.25.1 From 9926c7bb8d4428b192c26a72f83af589fdf0881a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 11:57:22 +1300 Subject: [PATCH 472/645] CVE-2020-25722 selftest: Adapt sam.py test_isCriticalSystemObject to new UF_WORKSTATION_TRUST_ACCOUNT default Objects with objectclass computer now have UF_WORKSTATION_TRUST_ACCOUNT by default and so this test must adapt. The changes to this test passes against Windows 2019 except for the new behaviour around the UF_WORKSTATION_TRUST_ACCOUNT default. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- .../knownfail.d/sam-isCriticalSystemObject | 1 + selftest/knownfail.d/uac_objectclass_restrict | 2 -- source4/dsdb/tests/python/sam.py | 36 ++++++++++++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 selftest/knownfail.d/sam-isCriticalSystemObject diff --git a/selftest/knownfail.d/sam-isCriticalSystemObject b/selftest/knownfail.d/sam-isCriticalSystemObject new file mode 100644 index 00000000000..a6351a81907 --- /dev/null +++ b/selftest/knownfail.d/sam-isCriticalSystemObject @@ -0,0 +1 @@ +^samba4.sam.python\(.*\).__main__.SamTests.test_isCriticalSystemObject_user \ No newline at end of file diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 32d8a99f950..d093c631bd3 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -3,11 +3,9 @@ # # All these tests need to be fixed and the entries here removed -^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_isCriticalSystemObject\(fl2008r2dc\) ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_userAccountControl\(fl2008r2dc\) ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) ^samba4.ldap.python\(ad_dc_default\).__main__.BasicTests.test_all\(ad_dc_default\) -^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_isCriticalSystemObject\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_userAccountControl\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_WP_user\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 8220cf8b44f..67e2f7b23c3 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -2926,6 +2926,39 @@ class SamTests(samba.tests.TestCase): delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_isCriticalSystemObject_user(self): + """Test the isCriticalSystemObject behaviour""" + print("Testing isCriticalSystemObject behaviour\n") + + # Add tests (of a user) + + ldb.add({ + "dn": "cn=ldaptestuser,cn=users," + self.base_dn, + "objectclass": "user"}) + + res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, + scope=SCOPE_BASE, + attrs=["isCriticalSystemObject"]) + self.assertTrue(len(res1) == 1) + self.assertTrue("isCriticalSystemObject" not in res1[0]) + + # Modification tests + m = Message() + + m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT), + FLAG_MOD_REPLACE, "userAccountControl") + ldb.modify(m) + + res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, + scope=SCOPE_BASE, + attrs=["isCriticalSystemObject"]) + self.assertTrue(len(res1) == 1) + self.assertTrue("isCriticalSystemObject" in res1[0]) + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") + + delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_isCriticalSystemObject(self): """Test the isCriticalSystemObject behaviour""" print("Testing isCriticalSystemObject behaviour\n") @@ -2940,7 +2973,8 @@ class SamTests(samba.tests.TestCase): scope=SCOPE_BASE, attrs=["isCriticalSystemObject"]) self.assertTrue(len(res1) == 1) - self.assertTrue("isCriticalSystemObject" not in res1[0]) + self.assertTrue("isCriticalSystemObject" in res1[0]) + self.assertEqual(str(res1[0]["isCriticalSystemObject"][0]), "FALSE") delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) -- 2.25.1 From 6b70f6627c567b3d8abb344317da5746af9418e6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 13:02:42 +1300 Subject: [PATCH 473/645] CVE-2020-25722 samdb: Fill in isCriticalSystemObject on any account type change BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/sam-isCriticalSystemObject | 1 - source4/dsdb/samdb/ldb_modules/samldb.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) delete mode 100644 selftest/knownfail.d/sam-isCriticalSystemObject diff --git a/selftest/knownfail.d/sam-isCriticalSystemObject b/selftest/knownfail.d/sam-isCriticalSystemObject deleted file mode 100644 index a6351a81907..00000000000 --- a/selftest/knownfail.d/sam-isCriticalSystemObject +++ /dev/null @@ -1 +0,0 @@ -^samba4.sam.python\(.*\).__main__.SamTests.test_isCriticalSystemObject_user \ No newline at end of file diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index aeef663d2f0..5352af1099f 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -2621,8 +2621,14 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) el->flags = LDB_FLAG_MOD_REPLACE; } - /* "isCriticalSystemObject" might be set/changed */ - if (old_is_critical != new_is_critical) { + /* + * "isCriticalSystemObject" might be set/changed + * + * Even a change from UF_NORMAL_ACCOUNT (implicitly FALSE) to + * UF_WORKSTATION_TRUST_ACCOUNT (actually FALSE) triggers + * 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"); if (ret != LDB_SUCCESS) { -- 2.25.1 From 7d75c7c5e14e79feb53ca924dd62013d1d0d82e5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 14:03:05 +1300 Subject: [PATCH 474/645] CVE-2020-25722 selftest: Split test_userAccountControl into unit tests The parts that create and delete a single object can be safely split out into an individual test. At this point the parts that fail against Windows 2019 are: error: __main__.SamTests.test_userAccountControl_computer_add_normal [ _ldb.LdbError: (53, 'LDAP error 53 LDAP_UNWILLING_TO_PERFORM - <0000052D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n> <>') error: __main__.SamTests.test_userAccountControl_computer_modify [ _ldb.LdbError: (53, 'LDAP error 53 LDAP_UNWILLING_TO_PERFORM - <0000052D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n> <>') error: __main__.SamTests.test_userAccountControl_user_add_0_uac [ _ldb.LdbError: (53, 'LDAP error 53 LDAP_UNWILLING_TO_PERFORM - <0000052D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n> <>') error: __main__.SamTests.test_userAccountControl_user_add_normal [ _ldb.LdbError: (53, 'LDAP error 53 LDAP_UNWILLING_TO_PERFORM - <0000052D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n> <>') error: __main__.SamTests.test_userAccountControl_user_modify [ _ldb.LdbError: (53, 'LDAP error 53 LDAP_UNWILLING_TO_PERFORM - <0000052D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n> <>') BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 6 ++++-- source4/dsdb/tests/python/sam.py | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index d093c631bd3..ac7befffb1b 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -3,10 +3,12 @@ # # All these tests need to be fixed and the entries here removed -^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_userAccountControl\(fl2008r2dc\) +^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_add_0_uac +^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_add_trust +^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_modify +^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_user_modify ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) ^samba4.ldap.python\(ad_dc_default\).__main__.BasicTests.test_all\(ad_dc_default\) -^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_userAccountControl\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_WP_user\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_default_user\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 67e2f7b23c3..077a1a86e90 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -1885,7 +1885,7 @@ class SamTests(samba.tests.TestCase): delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) - def test_userAccountControl(self): + def test_userAccountControl_user_add_0_uac(self): """Test the userAccountControl behaviour""" print("Testing userAccountControl behaviour\n") @@ -1913,12 +1913,15 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_normal(self): + """Test the userAccountControl behaviour""" ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, "objectclass": "user", "userAccountControl": str(UF_NORMAL_ACCOUNT)}) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_normal_pwnotreq(self): ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, "objectclass": "user", @@ -1933,6 +1936,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_normal_pwnotreq_lockout_expired(self): ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, "objectclass": "user", @@ -1952,6 +1956,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_temp_dup(self): try: ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1963,6 +1968,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OTHER) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_server(self): try: ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1974,6 +1980,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_workstation(self): try: ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1984,6 +1991,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_rodc(self): try: ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1994,6 +2002,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + def test_userAccountControl_user_add_trust(self): try: ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -2007,6 +2016,7 @@ class SamTests(samba.tests.TestCase): # Modify operation + def test_userAccountControl_user_modify(self): ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, "objectclass": "user"}) @@ -2177,6 +2187,7 @@ class SamTests(samba.tests.TestCase): (num, _) = e69.args self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + def test_userAccountControl_computer_add_0_uac(self): # With a computer object # Add operation @@ -2201,12 +2212,14 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_normal(self): ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, "objectclass": "computer", "userAccountControl": str(UF_NORMAL_ACCOUNT)}) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_normal_pwnotreqd(self): ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, "objectclass": "computer", @@ -2221,6 +2234,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_normal_pwnotreqd_lockout_expired(self): ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, "objectclass": "computer", @@ -2240,6 +2254,7 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_temp_dup(self): try: ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, @@ -2251,6 +2266,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OTHER) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_server(self): ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, "objectclass": "computer", @@ -2263,6 +2279,7 @@ class SamTests(samba.tests.TestCase): ATYPE_WORKSTATION_TRUST) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_workstation(self): try: ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, @@ -2273,6 +2290,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_add_trust(self): try: ldb.add({ "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, @@ -2284,6 +2302,7 @@ class SamTests(samba.tests.TestCase): self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_userAccountControl_computer_modify(self): # Modify operation ldb.add({ -- 2.25.1 From 33e10d3254168b62e211be00188649ae1a42f947 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 15:06:14 +1300 Subject: [PATCH 475/645] CVE-2020-25722 selftest: Adjust sam.py test_userAccountControl_computer_add_trust to new reality We now enforce that a trust account must be a user. These can not be added over LDAP anyway, and our C code in the RPC server gets this right in any case. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 1 - source4/dsdb/tests/python/sam.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index ac7befffb1b..0fc2f4d47a2 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -4,7 +4,6 @@ # All these tests need to be fixed and the entries here removed ^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_add_0_uac -^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_add_trust ^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_modify ^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_user_modify ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 077a1a86e90..ae83a136785 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -2299,7 +2299,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e72: (num, _) = e72.args - self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) def test_userAccountControl_computer_modify(self): -- 2.25.1 From 60c745521998e32a32988e6f78eb738a3c99d7ff Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 15:14:28 +1300 Subject: [PATCH 476/645] CVE-2020-25722 selftest: New objects of objectclass=computer are workstations by default now BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 1 - source4/dsdb/tests/python/sam.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 0fc2f4d47a2..295818d6a1b 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -3,7 +3,6 @@ # # All these tests need to be fixed and the entries here removed -^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_add_0_uac ^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_modify ^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_user_modify ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index ae83a136785..7ac2319dd49 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -2207,7 +2207,7 @@ class SamTests(samba.tests.TestCase): attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) self.assertEqual(int(res1[0]["sAMAccountType"][0]), - ATYPE_NORMAL_ACCOUNT) + ATYPE_WORKSTATION_TRUST) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) @@ -2315,7 +2315,7 @@ class SamTests(samba.tests.TestCase): attrs=["sAMAccountType", "userAccountControl"]) self.assertTrue(len(res1) == 1) self.assertEqual(int(res1[0]["sAMAccountType"][0]), - ATYPE_NORMAL_ACCOUNT) + ATYPE_WORKSTATION_TRUST) self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0) # As computer you can switch from a normal account to a workstation -- 2.25.1 From 10ffa04d315a1c16ca84417ce40ef181ea715246 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 15:19:19 +1300 Subject: [PATCH 477/645] CVE-2020-25722 selftest: Adapt sam.py test to userAccountControl/objectclass restrictions BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 2 -- source4/dsdb/tests/python/sam.py | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 295818d6a1b..0971c13c2f0 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -3,8 +3,6 @@ # # All these tests need to be fixed and the entries here removed -^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_computer_modify -^samba4.sam.python\(.*\).__main__.SamTests.test_userAccountControl_user_modify ^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) ^samba4.ldap.python\(ad_dc_default\).__main__.BasicTests.test_all\(ad_dc_default\) ^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 7ac2319dd49..e50e25adbe3 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -2135,7 +2135,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e67: (num, _) = e67.args - self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) @@ -2154,7 +2154,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e68: (num, _) = e68.args - self.assertEqual(num, ERR_UNWILLING_TO_PERFORM) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["sAMAccountType"]) @@ -2502,7 +2502,7 @@ class SamTests(samba.tests.TestCase): self.fail() except LdbError as e76: (num, _) = e76.args - self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # "primaryGroupID" does not change if account type remains the same -- 2.25.1 From feb2ddc59336e369741167671abfc82f2d763b70 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Oct 2021 15:42:46 +1300 Subject: [PATCH 478/645] CVE-2020-25722 selftest: adapt ldap.py/sam.py test_all tests to new default computer behaviour Objects of objectclass computer are computers by default now and this changes the sAMAccountType and primaryGroupID as well as userAccountControl BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 3 --- source4/dsdb/tests/python/ldap.py | 13 +++++++------ source4/dsdb/tests/python/sam.py | 4 +++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 0971c13c2f0..7328ca17d80 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -3,9 +3,6 @@ # # All these tests need to be fixed and the entries here removed -^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_users_groups\(fl2008r2dc\) -^samba4.ldap.python\(ad_dc_default\).__main__.BasicTests.test_all\(ad_dc_default\) -^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_users_groups\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_WP_user\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-DC_add_CC_default_user\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-a2d-user_add_CC_WP_computer\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py index a90bf367b1b..bd30faeb1d9 100755 --- a/source4/dsdb/tests/python/ldap.py +++ b/source4/dsdb/tests/python/ldap.py @@ -48,6 +48,7 @@ from samba.dsdb import (UF_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE, SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE, SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE) +from samba.dcerpc.security import DOMAIN_RID_DOMAIN_MEMBERS from samba.ndr import ndr_pack, ndr_unpack from samba.dcerpc import security, lsa @@ -2018,9 +2019,9 @@ delete: description self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) self.assertEqual(str(res[0]["objectCategory"][0]), ("CN=Computer,%s" % ldb.get_schema_basedn())) - self.assertEqual(int(res[0]["primaryGroupID"][0]), 513) - self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) - self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) + self.assertEqual(int(res[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) @@ -2499,9 +2500,9 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) self.assertEqual(str(res[0]["objectCategory"]), ("CN=Computer,%s" % ldb.get_schema_basedn())) - self.assertEqual(int(res[0]["primaryGroupID"][0]), 513) - self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT) - self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) + self.assertEqual(int(res[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS) + self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST) + self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE) self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) self.assertEqual(len(res[0]["memberOf"]), 1) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index e50e25adbe3..faa882e1287 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -291,7 +291,9 @@ class SamTests(samba.tests.TestCase): ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, - "objectclass": "computer"}) + "objectclass": "computer", + "userAccountControl": str(UF_NORMAL_ACCOUNT | + UF_PASSWD_NOTREQD)}) res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["primaryGroupID"]) -- 2.25.1 From 19ea32947ffeb584beba390c83189e97d8666663 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 22:40:06 +1300 Subject: [PATCH 479/645] CVE-2020-25722 selftest: Allow self.assertRaisesLdbError() to take a list of errors to match with BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- python/samba/tests/__init__.py | 30 ++++++++++++------- selftest/knownfail.d/uac_objectclass_restrict | 2 -- .../dsdb/tests/python/user_account_control.py | 5 ++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index f4745519617..14924528b0f 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -21,6 +21,7 @@ from __future__ import print_function import os import tempfile import warnings +import collections import ldb import samba from samba import param @@ -304,23 +305,32 @@ class TestCase(unittest.TestCase): f(*args, **kwargs) except ldb.LdbError as e: (num, msg) = e.args - if num != errcode: + if isinstance(errcode, collections.abc.Container): + found = num in errcode + else: + found = num == errcode + if not found: lut = {v: k for k, v in vars(ldb).items() if k.startswith('ERR_') and isinstance(v, int)} - self.fail("%s, expected " - "LdbError %s, (%d) " - "got %s (%d) " - "%s" % (message, - lut.get(errcode), errcode, - lut.get(num), num, - msg)) + if isinstance(errcode, collections.abc.Container): + errcode_name = ' '.join(lut.get(x) for x in errcode) + else: + errcode_name = lut.get(errcode) + self.fail(f"{message}, expected " + f"LdbError {errcode_name}, {errcode} " + f"got {lut.get(num)} ({num}) " + f"{msg}") else: lut = {v: k for k, v in vars(ldb).items() if k.startswith('ERR_') and isinstance(v, int)} + if isinstance(errcode, collections.abc.Container): + errcode_name = ' '.join(lut.get(x) for x in errcode) + else: + errcode_name = lut.get(errcode) self.fail("%s, expected " - "LdbError %s, (%d) " + "LdbError %s, (%s) " "but we got success" % (message, - lut.get(errcode), + errcode_name, errcode)) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 7328ca17d80..ac6f4857bf4 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -20,8 +20,6 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_SERVER_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_set_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_deladd_priv\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index 7a7cfd40b72..ed68a683e69 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -594,6 +594,9 @@ class UserAccountControlTests(samba.tests.TestCase): if (bit in priv_bits): self.fail("Unexpectedly able to set userAccountControl bit 0x%08X (%s), on %s" % (bit, bit_str, m.dn)) + if (bit in account_types and bit != UF_NORMAL_ACCOUNT): + self.fail("Unexpectedly able to set userAccountControl bit 0x%08X (%s), on %s" + % (bit, bit_str, m.dn)) except LdbError as e: (enum, estr) = e.args if bit in invalid_bits: @@ -601,6 +604,8 @@ class UserAccountControlTests(samba.tests.TestCase): ldb.ERR_OTHER, "was not able to set 0x%08X (%s) on %s" % (bit, bit_str, m.dn)) + elif (bit in account_types): + self.assertIn(enum, [ldb.ERR_OBJECT_CLASS_VIOLATION, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS]) elif (bit in priv_bits): self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum) else: -- 2.25.1 From 6dc03ebc06201e04a04a1aee8edc3be7415d5983 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 22:54:52 +1300 Subject: [PATCH 480/645] CVE-2020-25722 selftest/user_account_control: Allow a broader set of possible errors This favors a test that confirms we got an error over getting exactly the right error, at least for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 4 ---- selftest/knownfail.d/user_account_control | 1 - source4/dsdb/tests/python/user_account_control.py | 12 ++++++++---- 3 files changed, 8 insertions(+), 9 deletions(-) delete mode 100644 selftest/knownfail.d/user_account_control diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index ac6f4857bf4..1d72442f8a8 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -22,10 +22,6 @@ ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_deladd_priv\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_deladd_wp\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_replace_priv\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_uac_mod_lock_UF_NORMAL_ACCOUNT_UF_SERVER_TRUST_ACCOUNT_replace_wp\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT_UF_PASSWD_NOTREQD\(ad_dc_default\) diff --git a/selftest/knownfail.d/user_account_control b/selftest/knownfail.d/user_account_control deleted file mode 100644 index ad3af678708..00000000000 --- a/selftest/knownfail.d/user_account_control +++ /dev/null @@ -1 +0,0 @@ -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_cc_normal_bare.ad_dc_default diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index ed68a683e69..f99f370679b 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -484,7 +484,8 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT), ldb.FLAG_MOD_REPLACE, "userAccountControl") - self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + self.assertRaisesLdbError([ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_UNWILLING_TO_PERFORM], f"Unexpectedly able to set userAccountControl to be an Normal " "account without |UF_PASSWD_NOTREQD Unexpectedly able to " "set userAccountControl to be a workstation on {m.dn}", @@ -1204,12 +1205,14 @@ class UserAccountControlTests(samba.tests.TestCase): samdb.modify(m) elif (account_type == UF_NORMAL_ACCOUNT) and \ (account_type2 == UF_SERVER_TRUST_ACCOUNT) and not priv: - self.assertRaisesLdbError(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + self.assertRaisesLdbError([ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS], f"Should have been unable to change {account_type_str} to {account_type2_str}", samdb.modify, m) elif (account_type == UF_NORMAL_ACCOUNT) and \ (account_type2 == UF_SERVER_TRUST_ACCOUNT) and priv: - self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + self.assertRaisesLdbError([ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_UNWILLING_TO_PERFORM], f"Should have been unable to change {account_type_str} to {account_type2_str}", samdb.modify, m) elif (account_type == UF_WORKSTATION_TRUST_ACCOUNT) and \ @@ -1282,7 +1285,8 @@ class UserAccountControlTests(samba.tests.TestCase): m["1objectclass"] = ldb.MessageElement(new_objectclass, ldb.FLAG_MOD_ADD, "objectclass") - self.assertRaisesLdbError(ldb.ERR_UNWILLING_TO_PERFORM, + self.assertRaisesLdbError([ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_UNWILLING_TO_PERFORM], "Should have been unable Able to change objectclass of a {objectclass}", self.admin_samdb.modify, m) -- 2.25.1 From 501c1ee8acd0145fabcc8ee7380c99ccf9f491de Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Oct 2021 23:41:23 +1300 Subject: [PATCH 481/645] CVE-2020-25722 selftest/user_account_control: more work to cope with UAC/objectclass defaults and lock This new restriction breaks a large number of assumptions in the tests, like that you can remove some UF_ flags, because it turns out doing so will make the 'computer' a 'user' again, and this will fail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- selftest/knownfail.d/uac_objectclass_restrict | 6 --- .../dsdb/tests/python/user_account_control.py | 46 ++++++++++++------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index 1d72442f8a8..c4d4507c833 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -14,14 +14,8 @@ ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-del-add_CC_default_computer\(ad_dc_default\) ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-replace_CC_default_computer\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_admin_mod_uac\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_NORMAL_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_unrelated_modify_UF_WORKSTATION_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_INTERDOMAIN_TRUST_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_uac_bits_add_UF_NORMAL_ACCOUNT_UF_PASSWD_NOTREQD\(ad_dc_default\) diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py index f99f370679b..6a0ef73b29a 100755 --- a/source4/dsdb/tests/python/user_account_control.py +++ b/source4/dsdb/tests/python/user_account_control.py @@ -433,11 +433,10 @@ class UserAccountControlTests(samba.tests.TestCase): m.dn = res[0].dn m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD), ldb.FLAG_MOD_REPLACE, "userAccountControl") - try: - self.samdb.modify(m) - except LdbError as e: - (enum, estr) = e.args - self.fail(f"got {estr} setting userAccountControl to UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD") + + self.assertRaisesLdbError(ldb.ERR_OBJECT_CLASS_VIOLATION, + f"Unexpectedly able to set userAccountControl as to UF_NORMAL_ACCOUNT|UF_PASSWD_NOTREQD on {m.dn}", + self.samdb.modify, m) m = ldb.Message() m.dn = res[0].dn @@ -501,7 +500,7 @@ class UserAccountControlTests(samba.tests.TestCase): scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) - self.assertEqual(int(res[0]["userAccountControl"][0]), (UF_NORMAL_ACCOUNT | + self.assertEqual(int(res[0]["userAccountControl"][0]), (UF_WORKSTATION_TRUST_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)) @@ -681,11 +680,9 @@ class UserAccountControlTests(samba.tests.TestCase): scope=SCOPE_SUBTREE, attrs=["userAccountControl"]) - if account_type == UF_WORKSTATION_TRUST_ACCOUNT: - self.assertEqual(orig_uac, account_type) - else: - self.assertEqual(orig_uac & UF_NORMAL_ACCOUNT, - account_type) + self.assertEqual(len(res), 1) + reset_uac = int(res[0]["userAccountControl"][0]) + self.assertEqual(orig_uac, reset_uac) m = ldb.Message() m.dn = res[0].dn @@ -704,14 +701,16 @@ class UserAccountControlTests(samba.tests.TestCase): # No point going on, try the next bit continue elif bit in super_priv_bits: - self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + self.assertIn(enum, (ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, + ldb.ERR_OBJECT_CLASS_VIOLATION)) # No point going on, try the next bit continue elif (account_type == UF_NORMAL_ACCOUNT) \ and (bit in account_types) \ and (bit != account_type): - self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + self.assertIn(enum, (ldb.ERR_UNWILLING_TO_PERFORM, + ldb.ERR_OBJECT_CLASS_VIOLATION)) continue elif (account_type == UF_WORKSTATION_TRUST_ACCOUNT) \ @@ -789,7 +788,10 @@ class UserAccountControlTests(samba.tests.TestCase): except LdbError as e3: (enum, estr) = e3.args - if bit in priv_to_remove_bits: + if account_type == UF_WORKSTATION_TRUST_ACCOUNT: + # Because removing any bit would change the account back to a user, which is locked by objectclass + self.assertIn(enum, (ldb.ERR_OBJECT_CLASS_VIOLATION, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS)) + elif bit in priv_to_remove_bits: self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) else: self.fail("Unexpectedly unable to remove userAccountControl bit 0x%08X on %s: %s" % (bit, m.dn, estr)) @@ -808,7 +810,7 @@ class UserAccountControlTests(samba.tests.TestCase): self.assertEqual(int(res[0]["userAccountControl"][0]), bit | UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD, "bit 0X%08x should not have been removed" % bit) - else: + elif account_type != UF_WORKSTATION_TRUST_ACCOUNT: self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD, "bit 0X%08x should have been removed" % bit) @@ -859,9 +861,19 @@ class UserAccountControlTests(samba.tests.TestCase): bit_str, computername)) elif bit in priv_bits: - self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + if bit == UF_INTERDOMAIN_TRUST_ACCOUNT: + self.assertIn(enum, (ldb.ERR_OBJECT_CLASS_VIOLATION, + ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS)) + else: + self.assertEqual(enum, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) elif bit in unwilling_bits: - self.assertEqual(enum, ldb.ERR_UNWILLING_TO_PERFORM) + # This can fail early as user in a computer is not permitted as non-admin + self.assertIn(enum, (ldb.ERR_UNWILLING_TO_PERFORM, + ldb.ERR_OBJECT_CLASS_VIOLATION)) + elif bit & UF_NORMAL_ACCOUNT: + # This can fail early as user in a computer is not permitted as non-admin + self.assertIn(enum, (ldb.ERR_UNWILLING_TO_PERFORM, + ldb.ERR_OBJECT_CLASS_VIOLATION)) else: self.fail("Unable to set userAccountControl bit 0x%08X (%s) on %s: %s" % (bit, -- 2.25.1 From 5ecbe0ec32976f4c09e04b95743cbf14bd3e608e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 27 Sep 2021 11:20:19 +1300 Subject: [PATCH 482/645] CVE-2020-25721 krb5pac: Add new buffers for samAccountName and objectSID These appear when PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID is set. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- librpc/idl/krb5pac.idl | 18 ++++++++++++++++-- librpc/ndr/ndr_krb5pac.c | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index 515150ab9cd..ed488dee425 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -86,15 +86,29 @@ interface krb5pac } PAC_CONSTRAINED_DELEGATION; typedef [bitmap32bit] bitmap { - PAC_UPN_DNS_FLAG_CONSTRUCTED = 0x00000001 + PAC_UPN_DNS_FLAG_CONSTRUCTED = 0x00000001, + PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID = 0x00000002 } PAC_UPN_DNS_FLAGS; + typedef struct { + [value(2*strlen_m(samaccountname))] uint16 samaccountname_size; + [relative_short,subcontext(0),subcontext_size(samaccountname_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *samaccountname; + [value(ndr_size_dom_sid(objectsid, ndr->flags))] uint16 objectsid_size; + [relative_short,subcontext(0),subcontext_size(objectsid_size)] dom_sid *objectsid; + } PAC_UPN_DNS_INFO_SAM_NAME_AND_SID; + + typedef [nodiscriminant] union { + [case(PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_SAM_NAME_AND_SID sam_name_and_sid; + [default]; + } PAC_UPN_DNS_INFO_EX; + typedef struct { [value(2*strlen_m(upn_name))] uint16 upn_name_size; [relative_short,subcontext(0),subcontext_size(upn_name_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *upn_name; [value(2*strlen_m(dns_domain_name))] uint16 dns_domain_name_size; [relative_short,subcontext(0),subcontext_size(dns_domain_name_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *dns_domain_name; PAC_UPN_DNS_FLAGS flags; + [switch_is(flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_EX ex; } PAC_UPN_DNS_INFO; typedef [public] struct { @@ -142,7 +156,7 @@ interface krb5pac typedef [public,nopush,nopull] struct { PAC_TYPE type; - [value(_ndr_size_PAC_INFO(info, type, 0))] uint32 _ndr_size; + [value(_ndr_size_PAC_INFO(info, type, LIBNDR_FLAG_ALIGN8))] uint32 _ndr_size; /* * We need to have two subcontexts to get the padding right, * the outer subcontext uses NDR_ROUND(_ndr_size, 8), while diff --git a/librpc/ndr/ndr_krb5pac.c b/librpc/ndr/ndr_krb5pac.c index a9ae2c4a789..57b28df9e52 100644 --- a/librpc/ndr/ndr_krb5pac.c +++ b/librpc/ndr/ndr_krb5pac.c @@ -41,7 +41,7 @@ enum ndr_err_code ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); NDR_CHECK(ndr_push_PAC_TYPE(ndr, NDR_SCALARS, r->type)); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,0))); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,LIBNDR_FLAG_ALIGN8))); { uint32_t _flags_save_PAC_INFO = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8); @@ -59,7 +59,7 @@ enum ndr_err_code ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const { struct ndr_push *_ndr_info_pad; struct ndr_push *_ndr_info; - size_t _ndr_size = _ndr_size_PAC_INFO(r->info, r->type, 0); + size_t _ndr_size = _ndr_size_PAC_INFO(r->info, r->type, LIBNDR_FLAG_ALIGN8); NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info_pad, 0, NDR_ROUND(_ndr_size, 8))); NDR_CHECK(ndr_push_subcontext_start(_ndr_info_pad, &_ndr_info, 0, _ndr_size)); NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->info, r->type)); -- 2.25.1 From 594deba07cd922c187692694e51c8a2e038fe0c7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 15:48:35 +1300 Subject: [PATCH 483/645] CVE-2020-25718 tests/krb5: Allow tests accounts to replicate to RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/rodc_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/samba/tests/krb5/rodc_tests.py b/python/samba/tests/krb5/rodc_tests.py index 302ae865cf1..0e252d90262 100755 --- a/python/samba/tests/krb5/rodc_tests.py +++ b/python/samba/tests/krb5/rodc_tests.py @@ -41,11 +41,13 @@ class RodcKerberosTests(KDCBaseTest): user_creds = self.get_cached_creds( account_type=self.AccountType.USER, opts={ + 'allowed_replication': True, 'revealed_to_rodc': True }) target_creds = self.get_cached_creds( account_type=self.AccountType.COMPUTER, opts={ + 'allowed_replication': True, 'revealed_to_rodc': True }) -- 2.25.1 From 4ae3f4830b92811dac50d539568b0ff89ac2333f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 14:59:01 +1300 Subject: [PATCH 484/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Modify get_service_ticket() to use _generic_kdc_exchange() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 54 ++++++++++++------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 8ae9c24b0fc..c129883e7cd 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1275,7 +1275,7 @@ class KDCBaseTest(RawKerberosTest): expected_flags=None, unexpected_flags=None, fresh=False): user_name = tgt.cname['name-string'][0] - target_name = target_creds.get_username() + target_name = target_creds.get_username()[:-1] cache_key = (user_name, target_name, service, to_rodc, kdc_options) if not fresh: @@ -1288,40 +1288,40 @@ class KDCBaseTest(RawKerberosTest): if kdc_options is None: kdc_options = '0' - kdc_options = krb5_asn1.KDCOptions(kdc_options) - - key = tgt.session_key - ticket = tgt.ticket + kdc_options = str(krb5_asn1.KDCOptions(kdc_options)) - cname = tgt.cname - realm = tgt.crealm - - target_name = target_creds.get_username()[:-1] sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[service, target_name]) + srealm = target_creds.get_realm() - rep, enc_part = self.tgs_req(cname, sname, realm, ticket, key, etype, - to_rodc=to_rodc, - service_creds=target_creds, - kdc_options=kdc_options, - expected_flags=expected_flags, - unexpected_flags=unexpected_flags) + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) - service_ticket = rep['ticket'] + decryption_key = self.TicketDecryptionKey_from_creds(target_creds) - ticket_etype = service_ticket['enc-part']['etype'] - target_key = self.TicketDecryptionKey_from_creds(target_creds, - etype=ticket_etype) + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=tgt.crealm, + expected_cname=tgt.cname, + expected_srealm=srealm, + expected_sname=sname, + expected_supported_etypes=target_creds.tgs_supported_enctypes, + expected_flags=expected_flags, + unexpected_flags=unexpected_flags, + ticket_decryption_key=decryption_key, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=kdc_options, + to_rodc=to_rodc) - session_key = self.EncryptionKey_import(enc_part['key']) + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=srealm, + sname=sname, + etypes=etype) + self.check_tgs_reply(rep) - service_ticket_creds = KerberosTicketCreds(service_ticket, - session_key, - crealm=realm, - cname=cname, - srealm=realm, - sname=sname, - decryption_key=target_key) + service_ticket_creds = kdc_exchange_dict['rep_ticket_creds'] if to_rodc: krbtgt_creds = self.get_rodc_krbtgt_creds() -- 2.25.1 From 10ba30562f4941c2bec8bbe1d0511d4a3ac8aec0 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 15:00:38 +1300 Subject: [PATCH 485/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Add pac_request parameter to get_service_ticket() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index c129883e7cd..813af767dbd 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1273,10 +1273,11 @@ class KDCBaseTest(RawKerberosTest): def get_service_ticket(self, tgt, target_creds, service='host', to_rodc=False, kdc_options=None, expected_flags=None, unexpected_flags=None, - fresh=False): + pac_request=True, expect_pac=True, fresh=False): user_name = tgt.cname['name-string'][0] target_name = target_creds.get_username()[:-1] - cache_key = (user_name, target_name, service, to_rodc, kdc_options) + cache_key = (user_name, target_name, service, to_rodc, kdc_options, + pac_request) if not fresh: ticket = self.tkt_cache.get(cache_key) @@ -1312,6 +1313,8 @@ class KDCBaseTest(RawKerberosTest): tgt=tgt, authenticator_subkey=authenticator_subkey, kdc_options=kdc_options, + pac_request=pac_request, + expect_pac=expect_pac, to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, @@ -1329,6 +1332,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, expect_ticket_checksum=self.tkt_sig_support) self.tkt_cache[cache_key] = service_ticket_creds -- 2.25.1 From 6df49215719fff06e1ba822fed6883de68298291 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:40:09 +1300 Subject: [PATCH 486/645] CVE-2020-25722 tests/krb5: Allow creating server accounts BUG: https://bugzilla.samba.org/show_bug.cgi?id=14776 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 813af767dbd..a0da89041c4 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -38,12 +38,14 @@ from samba.dsdb import ( DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, DS_GUID_COMPUTERS_CONTAINER, + DS_GUID_DOMAIN_CONTROLLERS_CONTAINER, DS_GUID_USERS_CONTAINER, UF_WORKSTATION_TRUST_ACCOUNT, UF_NO_AUTH_DATA_REQUIRED, UF_NORMAL_ACCOUNT, UF_NOT_DELEGATED, UF_PARTIAL_SECRETS_ACCOUNT, + UF_SERVER_TRUST_ACCOUNT, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION ) from samba.join import DCJoinContext @@ -94,6 +96,7 @@ class KDCBaseTest(RawKerberosTest): class AccountType(Enum): USER = auto() COMPUTER = auto() + SERVER = auto() @classmethod def setUpClass(cls): @@ -245,6 +248,8 @@ class KDCBaseTest(RawKerberosTest): if ou is None: if account_type is account_type.COMPUTER: guid = DS_GUID_COMPUTERS_CONTAINER + elif account_type is account_type.SERVER: + guid = DS_GUID_DOMAIN_CONTROLLERS_CONTAINER else: guid = DS_GUID_USERS_CONTAINER @@ -265,6 +270,8 @@ class KDCBaseTest(RawKerberosTest): account_name += '$' if account_type is self.AccountType.COMPUTER: account_control |= UF_WORKSTATION_TRUST_ACCOUNT + elif account_type is self.AccountType.SERVER: + account_control |= UF_SERVER_TRUST_ACCOUNT else: self.fail() -- 2.25.1 From 48a27ed8a97d4339bbfc5d4e47d26b2b8ba413fb Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 30 Sep 2021 16:53:22 +1300 Subject: [PATCH 487/645] CVE-2020-25719 tests/krb5: Add is_tgt() helper method BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index fdf078ea788..055209fd09d 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3086,8 +3086,7 @@ class RawKerberosTest(TestCaseInTempDir): def verify_ticket(self, ticket, krbtgt_key, expect_pac=True, expect_ticket_checksum=True): # Check if the ticket is a TGT. - sname = ticket.ticket['sname'] - is_tgt = self.is_tgs(sname) + is_tgt = self.is_tgt(ticket) # Decrypt the ticket. @@ -3506,6 +3505,10 @@ class RawKerberosTest(TestCaseInTempDir): name = principal['name-string'][0] return name in ('krbtgt', b'krbtgt') + def is_tgt(self, ticket): + sname = ticket.ticket['sname'] + return self.is_tgs(sname) + def get_empty_pac(self): return self.AuthorizationData_create(AD_WIN2K_PAC, bytes(1)) -- 2.25.1 From 1bab23c5d68a5be16d6a20204f849877347db361 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 19 Oct 2021 15:02:10 +1300 Subject: [PATCH 488/645] CVE-2020-25719 tests/krb5: Add method to get unique username for test accounts BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index a0da89041c4..e85574c51cb 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -711,8 +711,7 @@ class KDCBaseTest(RawKerberosTest): rodc_dn = self.get_server_dn(rodc_samdb) - user_name = self.account_base + str(self.account_id) - type(self).account_id += 1 + user_name = self.get_new_username() if name_prefix is not None: user_name = name_prefix + user_name if name_suffix is not None: @@ -821,6 +820,12 @@ class KDCBaseTest(RawKerberosTest): return creds + def get_new_username(self): + user_name = self.account_base + str(self.account_id) + type(self).account_id += 1 + + return user_name + def get_client_creds(self, allow_missing_password=False, allow_missing_keys=True): -- 2.25.1 From b77545ad944d398bb82feec9409c8666bac7c8db Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 20 Oct 2021 15:48:20 +1300 Subject: [PATCH 489/645] MS CVE-2020-17049 tests/krb5: Allow tests to pass if ticket signature checksum type is wrong BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 055209fd09d..62e1b9867dd 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2375,6 +2375,13 @@ class RawKerberosTest(TestCaseInTempDir): krbtgt_creds = self.get_krbtgt_creds() krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + krbtgt_keys = [krbtgt_key] + if not self.strict_checking: + krbtgt_key_rc4 = self.TicketDecryptionKey_from_creds( + krbtgt_creds, + etype=kcrypto.Enctype.RC4) + krbtgt_keys.append(krbtgt_key_rc4) + expect_pac = kdc_exchange_dict['expect_pac'] ticket_session_key = None @@ -2522,7 +2529,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(ticket_decryption_key) if ticket_decryption_key is not None: - self.verify_ticket(ticket_creds, krbtgt_key, expect_pac=expect_pac, + self.verify_ticket(ticket_creds, krbtgt_keys, expect_pac=expect_pac, expect_ticket_checksum=expect_ticket_checksum or self.tkt_sig_support) @@ -3083,7 +3090,7 @@ class RawKerberosTest(TestCaseInTempDir): ticket_blob) self.assertEqual(expected_checksum, checksum) - def verify_ticket(self, ticket, krbtgt_key, expect_pac=True, + def verify_ticket(self, ticket, krbtgt_keys, expect_pac=True, expect_ticket_checksum=True): # Check if the ticket is a TGT. is_tgt = self.is_tgt(ticket) @@ -3171,6 +3178,16 @@ class RawKerberosTest(TestCaseInTempDir): kdc_checksum, kdc_ctype = checksums[ krb5pac.PAC_TYPE_KDC_CHECKSUM] + + if isinstance(krbtgt_keys, collections.abc.Container): + if self.strict_checking: + krbtgt_key = krbtgt_keys[0] + else: + krbtgt_key = next(key for key in krbtgt_keys + if key.ctype == kdc_ctype) + else: + krbtgt_key = krbtgt_keys + krbtgt_key.verify_rodc_checksum(KU_NON_KERB_CKSUM_SALT, server_checksum, kdc_ctype, -- 2.25.1 From d26236f1a1c17d4b996fee922f8a47b6e8eae33d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 21 Oct 2021 16:46:23 +1300 Subject: [PATCH 490/645] CVE-2020-25721 tests/krb5: Check PAC buffer types when STRICT_CHECKING=0 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 62e1b9867dd..8e55790272a 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1102,13 +1102,14 @@ class RawKerberosTest(TestCaseInTempDir): f"unexpected in {v}") def assertSequenceElementsEqual(self, expected, got, *, - require_strict=None): - if self.strict_checking: + require_strict=None, + require_ordered=True): + if self.strict_checking and require_ordered: self.assertEqual(expected, got) else: fail_msg = f'expected: {expected} got: {got}' - if require_strict is not None: + if not self.strict_checking and require_strict is not None: fail_msg += f' (ignoring: {require_strict})' expected = (x for x in expected if x not in require_strict) got = (x for x in got if x not in require_strict) @@ -2569,12 +2570,16 @@ class RawKerberosTest(TestCaseInTempDir): if not self.is_tgs(expected_sname): expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM) - if self.strict_checking: - buffer_types = [pac_buffer.type - for pac_buffer in pac.buffers] - self.assertCountEqual(expected_types, buffer_types, - f'expected: {expected_types} ' - f'got: {buffer_types}') + require_strict = {krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO} + if not self.tkt_sig_support: + require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + + buffer_types = [pac_buffer.type + for pac_buffer in pac.buffers] + self.assertSequenceElementsEqual( + expected_types, buffer_types, + require_ordered=False, + require_strict=require_strict) expected_account_name = kdc_exchange_dict['expected_account_name'] expected_sid = kdc_exchange_dict['expected_sid'] -- 2.25.1 From 44b1469fede2b414f7f9f687c4c482168f9672b3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 22 Oct 2021 11:37:31 +1300 Subject: [PATCH 491/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Refactor create_ccache_with_user() to take credentials of target service This allows us to use get_tgt() and get_service_ticket() to obtain tickets, which simplifies the logic. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 43 ++++++------------------ python/samba/tests/krb5/test_ccache.py | 2 +- python/samba/tests/krb5/test_ldap.py | 7 ++-- python/samba/tests/krb5/test_rpc.py | 7 ++-- python/samba/tests/krb5/test_smb.py | 7 ++-- 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e85574c51cb..e77a940f411 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1283,11 +1283,13 @@ class KDCBaseTest(RawKerberosTest): return rep, enc_part def get_service_ticket(self, tgt, target_creds, service='host', + target_name=None, to_rodc=False, kdc_options=None, expected_flags=None, unexpected_flags=None, pac_request=True, expect_pac=True, fresh=False): user_name = tgt.cname['name-string'][0] - target_name = target_creds.get_username()[:-1] + 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) @@ -1669,51 +1671,28 @@ class KDCBaseTest(RawKerberosTest): return cachefile - def create_ccache_with_user(self, user_credentials, mach_name, - service="host"): + def create_ccache_with_user(self, user_credentials, mach_credentials, + service="host", target_name=None): # Obtain a service ticket authorising the user and place it into a # newly created credentials cache file. user_name = user_credentials.get_username() realm = user_credentials.get_realm() - # Do the initial AS-REQ, should get a pre-authentication required - # response - 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_HST, - names=["krbtgt", realm]) - - rep = self.as_req(cname, sname, realm, etype) - self.check_pre_authentication(rep) - # Do the next AS-REQ - padata = self.get_enc_timestamp_pa_data(user_credentials, rep) - key = self.get_as_rep_key(user_credentials, rep) - rep = self.as_req(cname, sname, realm, etype, padata=[padata]) - self.check_as_reply(rep) + tgt = self.get_tgt(user_credentials) # Request a ticket to the host service on the machine account - ticket = rep['ticket'] - enc_part = self.get_as_rep_enc_data(key, rep) - key = self.EncryptionKey_import(enc_part['key']) - cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=[user_name]) - sname = self.PrincipalName_create(name_type=NT_SRV_HST, - names=[service, mach_name]) - - (rep, enc_part) = self.tgs_req( - cname, sname, realm, ticket, key, etype) - self.check_tgs_reply(rep) - key = self.EncryptionKey_import(enc_part['key']) - - # Check the contents of the pac, and the ticket - ticket = rep['ticket'] + ticket = self.get_service_ticket(tgt, mach_credentials, + service=service, + target_name=target_name) # Write the ticket into a credentials cache file that can be ingested # by the main credentials code. - cachefile = self.create_ccache(cname, ticket, enc_part) + cachefile = self.create_ccache(cname, ticket.ticket, + ticket.encpart_private) # Create a credentials object to reference the credentials cache. creds = Credentials() diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index 6a2b78398ac..040ae5cc9a1 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -67,7 +67,7 @@ class CcacheTests(KDCBaseTest): # ticket, to ensure that the krbtgt ticket doesn't also need to be # stored. (creds, cachefile) = self.create_ccache_with_user(user_credentials, - mach_name) + mach_credentials) # Authenticate in-process to the machine account using the user's # cached credentials. diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 95b2d24221a..7d9ffebe298 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -53,13 +53,16 @@ class LdapTests(KDCBaseTest): # Create the user account. (user_credentials, _) = self.create_account(samdb, user_name) + mach_credentials = self.get_dc_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 # ticket, to ensure that the krbtgt ticket doesn't also need to be # stored. (creds, cachefile) = self.create_ccache_with_user(user_credentials, - mach_name, - service) + mach_credentials, + service, + mach_name) # Authenticate in-process to the machine account using the user's # cached credentials. diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index 40ac6df7a35..ef8dd4dcbf5 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -50,13 +50,16 @@ class RpcTests(KDCBaseTest): # Create the user account. (user_credentials, _) = self.create_account(samdb, user_name) + mach_credentials = self.get_dc_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 # ticket, to ensure that the krbtgt ticket doesn't also need to be # stored. (creds, cachefile) = self.create_ccache_with_user(user_credentials, - mach_name, - service) + mach_credentials, + service, + mach_name) # Authenticate in-process to the machine account using the user's # cached credentials. diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index eebc9a9d4fe..1e70ed322bf 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -55,13 +55,16 @@ class SmbTests(KDCBaseTest): # Create the user account. (user_credentials, _) = self.create_account(samdb, user_name) + mach_credentials = self.get_dc_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 # ticket, to ensure that the krbtgt ticket doesn't also need to be # stored. (creds, cachefile) = self.create_ccache_with_user(user_credentials, - mach_name, - service) + mach_credentials, + service, + mach_name) # Set the Kerberos 5 credentials cache environment variable. This is # required because the codepath that gets run (gse_krb5) looks for it -- 2.25.1 From cf46135b8d4c09da978649ca1d1b8c5eca46b115 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 22 Oct 2021 11:37:37 +1300 Subject: [PATCH 492/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Allow create_ccache_with_user() to return a ticket without a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index e77a940f411..aed4c427ab0 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1672,7 +1672,7 @@ class KDCBaseTest(RawKerberosTest): return cachefile def create_ccache_with_user(self, user_credentials, mach_credentials, - service="host", target_name=None): + service="host", target_name=None, pac=True): # Obtain a service ticket authorising the user and place it into a # newly created credentials cache file. @@ -1689,6 +1689,9 @@ class KDCBaseTest(RawKerberosTest): service=service, target_name=target_name) + if not pac: + ticket = self.modified_ticket(ticket, exclude_pac=True) + # Write the ticket into a credentials cache file that can be ingested # by the main credentials code. cachefile = self.create_ccache(cname, ticket.ticket, -- 2.25.1 From 8bb4b96b4c74cf3276cdc4819c511c87d9ba7734 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 21 Oct 2021 15:45:00 +1300 Subject: [PATCH 493/645] CVE-2020-25722 tests/krb5: Add KDC tests for 3-part SPNs BUG: https://bugzilla.samba.org/show_bug.cgi?id=14776 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 1 + python/samba/tests/krb5/spn_tests.py | 212 +++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 6 + selftest/knownfail_mit_kdc | 6 + source4/selftest/tests.py | 10 ++ 6 files changed, 236 insertions(+) create mode 100755 python/samba/tests/krb5/spn_tests.py diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index aed4c427ab0..cc23484ba2c 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -97,6 +97,7 @@ class KDCBaseTest(RawKerberosTest): USER = auto() COMPUTER = auto() SERVER = auto() + RODC = auto() @classmethod def setUpClass(cls): diff --git a/python/samba/tests/krb5/spn_tests.py b/python/samba/tests/krb5/spn_tests.py new file mode 100755 index 00000000000..62d2ea081bc --- /dev/null +++ b/python/samba/tests/krb5/spn_tests.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2020 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 samba.tests import DynamicTestCase + +import ldb + +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.raw_testcase import KerberosCredentials +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_S_PRINCIPAL_UNKNOWN, + NT_PRINCIPAL, +) + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +global_asn1_print = False +global_hexdump = False + + +@DynamicTestCase +class SpnTests(KDCBaseTest): + test_account_types = { + 'computer': KDCBaseTest.AccountType.COMPUTER, + 'server': KDCBaseTest.AccountType.SERVER, + 'rodc': KDCBaseTest.AccountType.RODC + } + test_spns = { + '2_part': 'ldap/{{account}}', + '3_part_our_domain': 'ldap/{{account}}/{netbios_domain_name}', + '3_part_our_realm': 'ldap/{{account}}/{dns_domain_name}', + '3_part_not_our_realm': 'ldap/{{account}}/test', + '3_part_instance': 'ldap/{{account}}:test/{dns_domain_name}' + } + + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls._mock_rodc_creds = None + + @classmethod + def setUpDynamicTestCases(cls): + for account_type_name, account_type in cls.test_account_types.items(): + for spn_name, spn in cls.test_spns.items(): + tname = f'{spn_name}_spn_{account_type_name}' + targs = (account_type, spn) + cls.generate_dynamic_test('test_spn', tname, *targs) + + def _test_spn_with_args(self, account_type, spn): + target_creds = self._get_creds(account_type) + spn = self._format_spn(spn, target_creds) + + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=spn.split('/')) + + client_creds = self.get_client_creds() + tgt = self.get_tgt(client_creds) + + samdb = self.get_samdb() + netbios_domain_name = samdb.domain_netbios_name() + dns_domain_name = samdb.domain_dns_name() + + subkey = self.RandomKey(tgt.session_key.etype) + + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5,) + + if account_type is self.AccountType.SERVER: + ticket_etype = AES256_CTS_HMAC_SHA1_96 + else: + ticket_etype = None + decryption_key = self.TicketDecryptionKey_from_creds( + target_creds, etype=ticket_etype) + + if (spn.count('/') > 1 + and (spn.endswith(netbios_domain_name) + or spn.endswith(dns_domain_name)) + and account_type is not self.AccountType.SERVER + and account_type is not self.AccountType.RODC): + expected_error_mode = KDC_ERR_S_PRINCIPAL_UNKNOWN + 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=tgt.crealm, + expected_cname=tgt.cname, + expected_srealm=tgt.srealm, + expected_sname=sname, + ticket_decryption_key=decryption_key, + check_rep_fn=check_rep_fn, + check_error_fn=check_error_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error_mode, + tgt=tgt, + authenticator_subkey=subkey, + kdc_options='0', + expect_edata=False) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=tgt.srealm, + sname=sname, + etypes=etypes) + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + def _format_spns(self, spns, creds=None): + return map(lambda spn: self._format_spn(spn, creds), spns) + + def _format_spn(self, spn, creds=None): + samdb = self.get_samdb() + + spn = spn.format(netbios_domain_name=samdb.domain_netbios_name(), + dns_domain_name=samdb.domain_dns_name()) + + if creds is not None: + account_name = creds.get_username() + spn = spn.format(account=account_name) + + return spn + + def _get_creds(self, account_type): + spns = self._format_spns(self.test_spns.values()) + + if account_type is self.AccountType.RODC: + creds = self._mock_rodc_creds + if creds is None: + creds = self._get_mock_rodc_creds(spns) + type(self)._mock_rodc_creds = creds + else: + creds = self.get_cached_creds( + account_type=account_type, + opts={ + 'spn': spns + }) + + return creds + + def _get_mock_rodc_creds(self, spns): + rodc_ctx = self.get_mock_rodc_ctx() + + for spn in spns: + spn = spn.format(account=rodc_ctx.myname) + if spn not in rodc_ctx.SPNs: + rodc_ctx.SPNs.append(spn) + + samdb = self.get_samdb() + rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) + + msg = ldb.Message(rodc_dn) + msg['servicePrincipalName'] = ldb.MessageElement( + rodc_ctx.SPNs, + ldb.FLAG_MOD_REPLACE, + 'servicePrincipalName') + samdb.modify(msg) + + creds = KerberosCredentials() + creds.guess(self.get_lp()) + creds.set_realm(rodc_ctx.realm.upper()) + creds.set_domain(rodc_ctx.domain_name) + creds.set_password(rodc_ctx.acct_pass) + creds.set_username(rodc_ctx.myname) + creds.set_workstation(rodc_ctx.samname) + creds.set_dn(rodc_dn) + creds.set_spn(rodc_ctx.SPNs) + + res = samdb.search(base=rodc_dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-KeyVersionNumber']) + kvno = int(res[0].get('msDS-KeyVersionNumber', idx=0)) + creds.set_kvno(kvno) + + keys = self.get_keys(samdb, rodc_dn) + self.creds_set_keys(creds, keys) + + return creds + + +if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 4b68a2b798c..7d11b6b4617 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -104,6 +104,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/fast_tests.py', 'python/samba/tests/krb5/rodc_tests.py', 'python/samba/tests/krb5/salt_tests.py', + 'python/samba/tests/krb5/spn_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index b39b11c3c53..45524d70fa2 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -255,3 +255,9 @@ ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_b +# +# SPN tests +# +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 4fc68ffd854..c86f9c2c2ea 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -374,3 +374,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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 +# +# SPN tests +# +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer +^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index e4e599c664c..5c4fc87e910 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1399,6 +1399,16 @@ planpythontestsuite( 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support }) +planpythontestsuite( + "ad_dc", + "samba.tests.krb5.spn_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support + }) for env in [ 'vampire_dc', -- 2.25.1 From c61280e1176ebba2cd457e368d7c7f91e5c279a1 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 13 Oct 2021 16:07:09 +1300 Subject: [PATCH 494/645] CVE-2020-25721 ndrdump: Add tests for PAC with UPN_DNS_INFO BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/blackbox/ndrdump.py | 35 +++ .../tests/krb5pac_upn_dns_info_ex.b64.txt | 1 + .../librpc/tests/krb5pac_upn_dns_info_ex.txt | 220 ++++++++++++++++++ ...5pac_upn_dns_info_ex_not_supported.b64.txt | 1 + .../krb5pac_upn_dns_info_ex_not_supported.txt | 213 +++++++++++++++++ 5 files changed, 470 insertions(+) create mode 100644 source4/librpc/tests/krb5pac_upn_dns_info_ex.b64.txt create mode 100644 source4/librpc/tests/krb5pac_upn_dns_info_ex.txt create mode 100644 source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.b64.txt create mode 100644 source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.txt diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py index b8a025b8dce..4a9e4de102a 100644 --- a/python/samba/tests/blackbox/ndrdump.py +++ b/python/samba/tests/blackbox/ndrdump.py @@ -89,6 +89,41 @@ class NdrDumpTests(BlackboxTestCase): expected.encode('utf-8')) self.assertTrue(actual.endswith(b"dump OK\n")) + def test_ndrdump_upn_dns_info_ex(self): + with open(self.data_path( + 'krb5pac_upn_dns_info_ex.txt')) as f: + expected = f.read() + data_path = self.data_path( + 'krb5pac_upn_dns_info_ex.b64.txt') + + try: + actual = self.check_output( + 'ndrdump --debug-stdout -d0 krb5pac PAC_DATA struct ' + '--validate --base64-input ' + data_path) + except BlackboxProcessError as e: + self.fail(e) + + self.assertEqual(actual, expected.encode('utf-8')) + + def test_ndrdump_upn_dns_info_ex_not_supported(self): + with open(self.data_path( + 'krb5pac_upn_dns_info_ex_not_supported.txt')) as f: + expected = f.read() + data_path = self.data_path( + 'krb5pac_upn_dns_info_ex_not_supported.b64.txt') + + try: + # This PAC has been edited to remove the + # PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID bit, so that we can + # simulate older versions of Samba parsing this structure. + actual = self.check_output( + 'ndrdump --debug-stdout -d0 krb5pac PAC_DATA struct ' + '--validate --base64-input ' + data_path) + except BlackboxProcessError as e: + self.fail(e) + + self.assertEqual(actual, expected.encode('utf-8')) + def test_ndrdump_with_binary_struct_number(self): expected = '''pull returned Success GUID : 33323130-3534-3736-3839-616263646566 diff --git a/source4/librpc/tests/krb5pac_upn_dns_info_ex.b64.txt b/source4/librpc/tests/krb5pac_upn_dns_info_ex.b64.txt new file mode 100644 index 00000000000..02b570624bc --- /dev/null +++ b/source4/librpc/tests/krb5pac_upn_dns_info_ex.b64.txt @@ -0,0 +1 @@ +BgAAAAAAAAABAAAA0AEAAGgAAAAAAAAACgAAABwAAAA4AgAAAAAAAAwAAACoAAAAWAIAAAAAAAAGAAAAFAAAAAADAAAAAAAABwAAABAAAAAYAwAAAAAAABAAAAAQAAAAKAMAAAAAAAABEAgAzMzMzMABAAAAAAAAAAACAAAAAAAAAAAA/////////3//////////f7pMcCzXv9cBugzaVqDA1wG6zMkh2ODXARIAEgAEAAIAAAAAAAgAAgAAAAAADAACAAAAAAAQAAIAAAAAABQAAgAAAAAAGAACAAAAAACOBAAAAQIAAAEAAAAcAAIAIAAAAAAAAAAAAAAAAAAAAAAAAAAOABAAIAACABYAGAAkAAIAKAACAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAALAACAAAAAAAAAAAAAAAAAAkAAAAAAAAACQAAAHQAcwB0AHQAawB0AHUAcwByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECAAAHAAAACAAAAAAAAAAHAAAATABPAEMAQQBMAEQAQwAAAAwAAAAAAAAACwAAAFMAQQBNAEIAQQBEAE8ATQBBAEkATgAAAAQAAAABBAAAAAAABRUAAAC2fvX0wDGiOufKt1QBAAAAMAACAAcAAAABAAAAAQEAAAAAABIBAAAAAAAAAIC3ISzXv9cBEgB0AHMAdAB0AGsAdAB1AHMAcgAAAAAANgAYACIAUAADAAAAEgB4ABwAigAAAAAAdABzAHQAdABrAHQAdQBzAHIAQABzAGEAbQBiAGEALgBlAHgAYQBtAHAAbABlAC4AYwBvAG0AAABTAEEATQBCAEEALgBFAFgAQQBNAFAATABFAC4AQwBPAE0AAAAAAAAAdABzAHQAdABrAHQAdQBzAHIAAQUAAAAAAAUVAAAAtn719MAxojrnyrdUjgQAAAAAdv///ys5aox2KdqNY8CVVxkQbs4AAAAAEAAAAFrUeP0b8Pbct0VlVhAAAAB4SC+IGKoLP+0030o= diff --git a/source4/librpc/tests/krb5pac_upn_dns_info_ex.txt b/source4/librpc/tests/krb5pac_upn_dns_info_ex.txt new file mode 100644 index 00000000000..9747d1b6d3a --- /dev/null +++ b/source4/librpc/tests/krb5pac_upn_dns_info_ex.txt @@ -0,0 +1,220 @@ +pull returned Success + PAC_DATA: struct PAC_DATA + num_buffers : 0x00000006 (6) + version : 0x00000000 (0) + buffers: ARRAY(6) + buffers: struct PAC_BUFFER + type : PAC_TYPE_LOGON_INFO (1) + _ndr_size : 0x000001d0 (464) + info : * + info : union PAC_INFO(case 1) + logon_info: struct PAC_LOGON_INFO_CTR + info : * + info: struct PAC_LOGON_INFO + info3: struct netr_SamInfo3 + base: struct netr_SamBaseInfo + logon_time : NTTIME(0) + logoff_time : Thu Sep 14 02:48:05 AM 30828 UTC + kickoff_time : Thu Sep 14 02:48:05 AM 30828 UTC + last_password_change : Wed Oct 13 02:08:12 AM 2021 UTC + allow_password_change : Thu Oct 14 02:08:12 AM 2021 UTC + force_password_change : Wed Nov 24 02:08:12 AM 2021 UTC + account_name: struct lsa_String + length : 0x0012 (18) + size : 0x0012 (18) + string : * + string : 'tsttktusr' + full_name: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + logon_script: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + profile_path: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + home_directory: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + home_drive: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + logon_count : 0x0000 (0) + bad_password_count : 0x0000 (0) + rid : 0x0000048e (1166) + primary_gid : 0x00000201 (513) + groups: struct samr_RidWithAttributeArray + count : 0x00000001 (1) + rids : * + rids: ARRAY(1) + rids: struct samr_RidWithAttribute + rid : 0x00000201 (513) + attributes : 0x00000007 (7) + 1: SE_GROUP_MANDATORY + 1: SE_GROUP_ENABLED_BY_DEFAULT + 1: SE_GROUP_ENABLED + 0: SE_GROUP_OWNER + 0: SE_GROUP_USE_FOR_DENY_ONLY + 0: SE_GROUP_INTEGRITY + 0: SE_GROUP_INTEGRITY_ENABLED + 0: SE_GROUP_RESOURCE + 0x00: SE_GROUP_LOGON_ID (0) + user_flags : 0x00000020 (32) + 0: NETLOGON_GUEST + 0: NETLOGON_NOENCRYPTION + 0: NETLOGON_CACHED_ACCOUNT + 0: NETLOGON_USED_LM_PASSWORD + 1: NETLOGON_EXTRA_SIDS + 0: NETLOGON_SUBAUTH_SESSION_KEY + 0: NETLOGON_SERVER_TRUST_ACCOUNT + 0: NETLOGON_NTLMV2_ENABLED + 0: NETLOGON_RESOURCE_GROUPS + 0: NETLOGON_PROFILE_PATH_RETURNED + 0: NETLOGON_GRACE_LOGON + key: struct netr_UserSessionKey + key: ARRAY(16): + logon_server: struct lsa_StringLarge + length : 0x000e (14) + size : 0x0010 (16) + string : * + string : 'LOCALDC' + logon_domain: struct lsa_StringLarge + length : 0x0016 (22) + size : 0x0018 (24) + string : * + string : 'SAMBADOMAIN' + domain_sid : * + domain_sid : S-1-5-21-4109729462-983708096-1421331175 + LMSessKey: struct netr_LMSessionKey + key: ARRAY(8): + acct_flags : 0x00000010 (16) + 0: ACB_DISABLED + 0: ACB_HOMDIRREQ + 0: ACB_PWNOTREQ + 0: ACB_TEMPDUP + 1: ACB_NORMAL + 0: ACB_MNS + 0: ACB_DOMTRUST + 0: ACB_WSTRUST + 0: ACB_SVRTRUST + 0: ACB_PWNOEXP + 0: ACB_AUTOLOCK + 0: ACB_ENC_TXT_PWD_ALLOWED + 0: ACB_SMARTCARD_REQUIRED + 0: ACB_TRUSTED_FOR_DELEGATION + 0: ACB_NOT_DELEGATED + 0: ACB_USE_DES_KEY_ONLY + 0: ACB_DONT_REQUIRE_PREAUTH + 0: ACB_PW_EXPIRED + 0: ACB_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION + 0: ACB_NO_AUTH_DATA_REQD + 0: ACB_PARTIAL_SECRETS_ACCOUNT + 0: ACB_USE_AES_KEYS + sub_auth_status : 0x00000000 (0) + last_successful_logon : NTTIME(0) + last_failed_logon : NTTIME(0) + failed_logon_count : 0x00000000 (0) + reserved : 0x00000000 (0) + sidcount : 0x00000001 (1) + sids : * + sids: ARRAY(1) + sids: struct netr_SidAttr + sid : * + sid : S-1-18-1 + attributes : 0x00000007 (7) + 1: SE_GROUP_MANDATORY + 1: SE_GROUP_ENABLED_BY_DEFAULT + 1: SE_GROUP_ENABLED + 0: SE_GROUP_OWNER + 0: SE_GROUP_USE_FOR_DENY_ONLY + 0: SE_GROUP_INTEGRITY + 0: SE_GROUP_INTEGRITY_ENABLED + 0: SE_GROUP_RESOURCE + 0x00: SE_GROUP_LOGON_ID (0) + resource_groups: struct PAC_DOMAIN_GROUP_MEMBERSHIP + domain_sid : NULL + groups: struct samr_RidWithAttributeArray + count : 0x00000000 (0) + rids : NULL + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_LOGON_NAME (10) + _ndr_size : 0x0000001c (28) + info : * + info : union PAC_INFO(case 10) + logon_name: struct PAC_LOGON_NAME + logon_time : Wed Oct 13 02:08:11 AM 2021 UTC + size : 0x0012 (18) + account_name : 'tsttktusr' + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_UPN_DNS_INFO (12) + _ndr_size : 0x000000a8 (168) + info : * + info : union PAC_INFO(case 12) + upn_dns_info: struct PAC_UPN_DNS_INFO + upn_name_size : 0x0036 (54) + upn_name : * + upn_name : 'tsttktusr@samba.example.com' + dns_domain_name_size : 0x0022 (34) + dns_domain_name : * + dns_domain_name : 'SAMBA.EXAMPLE.COM' + flags : 0x00000003 (3) + 1: PAC_UPN_DNS_FLAG_CONSTRUCTED + 1: PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID + ex : union PAC_UPN_DNS_INFO_EX(case 2) + sam_name_and_sid: struct PAC_UPN_DNS_INFO_SAM_NAME_AND_SID + samaccountname_size : 0x0012 (18) + samaccountname : * + samaccountname : 'tsttktusr' + objectsid_size : 0x001c (28) + objectsid : * + objectsid : S-1-5-21-4109729462-983708096-1421331175-1166 + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_SRV_CHECKSUM (6) + _ndr_size : 0x00000014 (20) + info : * + info : union PAC_INFO(case 6) + srv_cksum: struct PAC_SIGNATURE_DATA + type : 0xffffff76 (4294967158) + signature : DATA_BLOB length=16 +[0000] 2B 39 6A 8C 76 29 DA 8D 63 C0 95 57 19 10 6E CE +9j.v).. c..W..n. + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_KDC_CHECKSUM (7) + _ndr_size : 0x00000010 (16) + info : * + info : union PAC_INFO(case 7) + kdc_cksum: struct PAC_SIGNATURE_DATA + type : 0x00000010 (16) + signature : DATA_BLOB length=12 +[0000] 5A D4 78 FD 1B F0 F6 DC B7 45 65 56 Z.x..... .EeV + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_TICKET_CHECKSUM (16) + _ndr_size : 0x00000010 (16) + info : * + info : union PAC_INFO(case 16) + ticket_checksum: struct PAC_SIGNATURE_DATA + type : 0x00000010 (16) + signature : DATA_BLOB length=12 +[0000] 78 48 2F 88 18 AA 0B 3F ED 34 DF 4A xH/....? .4.J + _pad : 0x00000000 (0) +push returned Success +pull returned Success +WARNING! orig bytes:824 validated pushed bytes:832 +WARNING! orig pulled bytes:824 validated pulled bytes:832 +WARNING! orig and validated differ at byte 0x2C (44) +WARNING! orig byte[0x2C] = 0xA8 validated byte[0x2C] = 0xB0 +dump OK diff --git a/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.b64.txt b/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.b64.txt new file mode 100644 index 00000000000..cd99b9d0b0a --- /dev/null +++ b/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.b64.txt @@ -0,0 +1 @@ +BgAAAAAAAAABAAAA0AEAAGgAAAAAAAAACgAAABwAAAA4AgAAAAAAAAwAAACoAAAAWAIAAAAAAAAGAAAAFAAAAAADAAAAAAAABwAAABAAAAAYAwAAAAAAABAAAAAQAAAAKAMAAAAAAAABEAgAzMzMzMABAAAAAAAAAAACAAAAAAAAAAAA/////////3//////////f7pMcCzXv9cBugzaVqDA1wG6zMkh2ODXARIAEgAEAAIAAAAAAAgAAgAAAAAADAACAAAAAAAQAAIAAAAAABQAAgAAAAAAGAACAAAAAACOBAAAAQIAAAEAAAAcAAIAIAAAAAAAAAAAAAAAAAAAAAAAAAAOABAAIAACABYAGAAkAAIAKAACAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAALAACAAAAAAAAAAAAAAAAAAkAAAAAAAAACQAAAHQAcwB0AHQAawB0AHUAcwByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAECAAAHAAAACAAAAAAAAAAHAAAATABPAEMAQQBMAEQAQwAAAAwAAAAAAAAACwAAAFMAQQBNAEIAQQBEAE8ATQBBAEkATgAAAAQAAAABBAAAAAAABRUAAAC2fvX0wDGiOufKt1QBAAAAMAACAAcAAAABAAAAAQEAAAAAABIBAAAAAAAAAIC3ISzXv9cBEgB0AHMAdAB0AGsAdAB1AHMAcgAAAAAANgAYACIAUAABAAAAEgB4ABwAigAAAAAAdABzAHQAdABrAHQAdQBzAHIAQABzAGEAbQBiAGEALgBlAHgAYQBtAHAAbABlAC4AYwBvAG0AAABTAEEATQBCAEEALgBFAFgAQQBNAFAATABFAC4AQwBPAE0AAAAAAAAAdABzAHQAdABrAHQAdQBzAHIAAQUAAAAAAAUVAAAAtn719MAxojrnyrdUjgQAAAAAdv///ys5aox2KdqNY8CVVxkQbs4AAAAAEAAAAFrUeP0b8Pbct0VlVhAAAAB4SC+IGKoLP+0030o= diff --git a/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.txt b/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.txt new file mode 100644 index 00000000000..d29832ede49 --- /dev/null +++ b/source4/librpc/tests/krb5pac_upn_dns_info_ex_not_supported.txt @@ -0,0 +1,213 @@ +pull returned Success + PAC_DATA: struct PAC_DATA + num_buffers : 0x00000006 (6) + version : 0x00000000 (0) + buffers: ARRAY(6) + buffers: struct PAC_BUFFER + type : PAC_TYPE_LOGON_INFO (1) + _ndr_size : 0x000001d0 (464) + info : * + info : union PAC_INFO(case 1) + logon_info: struct PAC_LOGON_INFO_CTR + info : * + info: struct PAC_LOGON_INFO + info3: struct netr_SamInfo3 + base: struct netr_SamBaseInfo + logon_time : NTTIME(0) + logoff_time : Thu Sep 14 02:48:05 AM 30828 UTC + kickoff_time : Thu Sep 14 02:48:05 AM 30828 UTC + last_password_change : Wed Oct 13 02:08:12 AM 2021 UTC + allow_password_change : Thu Oct 14 02:08:12 AM 2021 UTC + force_password_change : Wed Nov 24 02:08:12 AM 2021 UTC + account_name: struct lsa_String + length : 0x0012 (18) + size : 0x0012 (18) + string : * + string : 'tsttktusr' + full_name: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + logon_script: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + profile_path: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + home_directory: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + home_drive: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + logon_count : 0x0000 (0) + bad_password_count : 0x0000 (0) + rid : 0x0000048e (1166) + primary_gid : 0x00000201 (513) + groups: struct samr_RidWithAttributeArray + count : 0x00000001 (1) + rids : * + rids: ARRAY(1) + rids: struct samr_RidWithAttribute + rid : 0x00000201 (513) + attributes : 0x00000007 (7) + 1: SE_GROUP_MANDATORY + 1: SE_GROUP_ENABLED_BY_DEFAULT + 1: SE_GROUP_ENABLED + 0: SE_GROUP_OWNER + 0: SE_GROUP_USE_FOR_DENY_ONLY + 0: SE_GROUP_INTEGRITY + 0: SE_GROUP_INTEGRITY_ENABLED + 0: SE_GROUP_RESOURCE + 0x00: SE_GROUP_LOGON_ID (0) + user_flags : 0x00000020 (32) + 0: NETLOGON_GUEST + 0: NETLOGON_NOENCRYPTION + 0: NETLOGON_CACHED_ACCOUNT + 0: NETLOGON_USED_LM_PASSWORD + 1: NETLOGON_EXTRA_SIDS + 0: NETLOGON_SUBAUTH_SESSION_KEY + 0: NETLOGON_SERVER_TRUST_ACCOUNT + 0: NETLOGON_NTLMV2_ENABLED + 0: NETLOGON_RESOURCE_GROUPS + 0: NETLOGON_PROFILE_PATH_RETURNED + 0: NETLOGON_GRACE_LOGON + key: struct netr_UserSessionKey + key: ARRAY(16): + logon_server: struct lsa_StringLarge + length : 0x000e (14) + size : 0x0010 (16) + string : * + string : 'LOCALDC' + logon_domain: struct lsa_StringLarge + length : 0x0016 (22) + size : 0x0018 (24) + string : * + string : 'SAMBADOMAIN' + domain_sid : * + domain_sid : S-1-5-21-4109729462-983708096-1421331175 + LMSessKey: struct netr_LMSessionKey + key: ARRAY(8): + acct_flags : 0x00000010 (16) + 0: ACB_DISABLED + 0: ACB_HOMDIRREQ + 0: ACB_PWNOTREQ + 0: ACB_TEMPDUP + 1: ACB_NORMAL + 0: ACB_MNS + 0: ACB_DOMTRUST + 0: ACB_WSTRUST + 0: ACB_SVRTRUST + 0: ACB_PWNOEXP + 0: ACB_AUTOLOCK + 0: ACB_ENC_TXT_PWD_ALLOWED + 0: ACB_SMARTCARD_REQUIRED + 0: ACB_TRUSTED_FOR_DELEGATION + 0: ACB_NOT_DELEGATED + 0: ACB_USE_DES_KEY_ONLY + 0: ACB_DONT_REQUIRE_PREAUTH + 0: ACB_PW_EXPIRED + 0: ACB_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION + 0: ACB_NO_AUTH_DATA_REQD + 0: ACB_PARTIAL_SECRETS_ACCOUNT + 0: ACB_USE_AES_KEYS + sub_auth_status : 0x00000000 (0) + last_successful_logon : NTTIME(0) + last_failed_logon : NTTIME(0) + failed_logon_count : 0x00000000 (0) + reserved : 0x00000000 (0) + sidcount : 0x00000001 (1) + sids : * + sids: ARRAY(1) + sids: struct netr_SidAttr + sid : * + sid : S-1-18-1 + attributes : 0x00000007 (7) + 1: SE_GROUP_MANDATORY + 1: SE_GROUP_ENABLED_BY_DEFAULT + 1: SE_GROUP_ENABLED + 0: SE_GROUP_OWNER + 0: SE_GROUP_USE_FOR_DENY_ONLY + 0: SE_GROUP_INTEGRITY + 0: SE_GROUP_INTEGRITY_ENABLED + 0: SE_GROUP_RESOURCE + 0x00: SE_GROUP_LOGON_ID (0) + resource_groups: struct PAC_DOMAIN_GROUP_MEMBERSHIP + domain_sid : NULL + groups: struct samr_RidWithAttributeArray + count : 0x00000000 (0) + rids : NULL + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_LOGON_NAME (10) + _ndr_size : 0x0000001c (28) + info : * + info : union PAC_INFO(case 10) + logon_name: struct PAC_LOGON_NAME + logon_time : Wed Oct 13 02:08:11 AM 2021 UTC + size : 0x0012 (18) + account_name : 'tsttktusr' + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_UPN_DNS_INFO (12) + _ndr_size : 0x000000a8 (168) + info : * + info : union PAC_INFO(case 12) + upn_dns_info: struct PAC_UPN_DNS_INFO + upn_name_size : 0x0036 (54) + upn_name : * + upn_name : 'tsttktusr@samba.example.com' + dns_domain_name_size : 0x0022 (34) + dns_domain_name : * + dns_domain_name : 'SAMBA.EXAMPLE.COM' + flags : 0x00000001 (1) + 1: PAC_UPN_DNS_FLAG_CONSTRUCTED + 0: PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID + ex : union PAC_UPN_DNS_INFO_EX(case 0) + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_SRV_CHECKSUM (6) + _ndr_size : 0x00000014 (20) + info : * + info : union PAC_INFO(case 6) + srv_cksum: struct PAC_SIGNATURE_DATA + type : 0xffffff76 (4294967158) + signature : DATA_BLOB length=16 +[0000] 2B 39 6A 8C 76 29 DA 8D 63 C0 95 57 19 10 6E CE +9j.v).. c..W..n. + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_KDC_CHECKSUM (7) + _ndr_size : 0x00000010 (16) + info : * + info : union PAC_INFO(case 7) + kdc_cksum: struct PAC_SIGNATURE_DATA + type : 0x00000010 (16) + signature : DATA_BLOB length=12 +[0000] 5A D4 78 FD 1B F0 F6 DC B7 45 65 56 Z.x..... .EeV + _pad : 0x00000000 (0) + buffers: struct PAC_BUFFER + type : PAC_TYPE_TICKET_CHECKSUM (16) + _ndr_size : 0x00000010 (16) + info : * + info : union PAC_INFO(case 16) + ticket_checksum: struct PAC_SIGNATURE_DATA + type : 0x00000010 (16) + signature : DATA_BLOB length=12 +[0000] 78 48 2F 88 18 AA 0B 3F ED 34 DF 4A xH/....? .4.J + _pad : 0x00000000 (0) +push returned Success +pull returned Success +WARNING! orig bytes:824 validated pushed bytes:768 +WARNING! orig pulled bytes:824 validated pulled bytes:768 +WARNING! orig and validated differ at byte 0x2C (44) +WARNING! orig byte[0x2C] = 0xA8 validated byte[0x2C] = 0x70 +dump OK -- 2.25.1 From 543ffef8611256040b0210307b4e53563601951d Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 15:02:39 +1300 Subject: [PATCH 495/645] CVE-2020-25719 tests/krb5: Add tests for requiring and issuing a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 124 ++++++++++++++++++++--- selftest/knownfail_heimdal_kdc | 9 ++ selftest/knownfail_mit_kdc | 6 ++ 3 files changed, 123 insertions(+), 16 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index f36704f998c..fbeb5fe61fb 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -31,6 +31,7 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_ERROR, KRB_TGS_REP, KDC_ERR_BADMATCH, + KDC_ERR_BADOPTION, NT_PRINCIPAL, NT_SRV_INST, ) @@ -214,7 +215,8 @@ class KdcTgsTests(KDCBaseTest): "rep = {%s},%s" % (rep, pac_data)) def _make_tgs_request(self, client_creds, service_creds, tgt, - expect_pac=True): + pac_request=None, expect_pac=True, + expect_error=False): client_account = client_creds.get_username() cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[client_account]) @@ -241,6 +243,15 @@ class KdcTgsTests(KDCBaseTest): authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + if expect_error: + expected_error_mode = KDC_ERR_BADOPTION + 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, @@ -248,12 +259,14 @@ class KdcTgsTests(KDCBaseTest): expected_sname=expected_sname, expected_supported_etypes=expected_supported_etypes, ticket_decryption_key=target_decryption_key, - check_rep_fn=self.generic_check_kdc_rep, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, - expected_error_mode=0, + expected_error_mode=expected_error_mode, tgt=tgt, authenticator_subkey=authenticator_subkey, kdc_options=kdc_options, + pac_request=pac_request, expect_pac=expect_pac) rep = self._generic_kdc_exchange(kdc_exchange_dict, @@ -261,25 +274,43 @@ class KdcTgsTests(KDCBaseTest): realm=realm, sname=sname, etypes=etypes) - self.check_reply(rep, KRB_TGS_REP) + 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() + + tgt = self.get_tgt(client_creds) + + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt) - return kdc_exchange_dict['rep_ticket_creds'] + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) def test_request_no_pac(self): client_creds = self.get_client_creds() service_creds = self.get_service_creds() - tgt = self.get_tgt(client_creds, pac_request=False, - expect_pac=False) + tgt = self.get_tgt(client_creds, pac_request=False) - pac = self.get_ticket_pac(tgt, expect_pac=False) - self.assertIsNone(pac) + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) ticket = self._make_tgs_request(client_creds, service_creds, tgt, - expect_pac=False) + pac_request=False) - pac = self.get_ticket_pac(ticket, expect_pac=False) - self.assertIsNone(pac) + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) def test_client_no_auth_data_required(self): client_creds = self.get_cached_creds( @@ -297,6 +328,23 @@ class KdcTgsTests(KDCBaseTest): pac = self.get_ticket_pac(ticket) self.assertIsNotNone(pac) + def test_no_pac_client_no_auth_data_required(self): + client_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts={'no_auth_data_required': True}) + service_creds = self.get_service_creds() + + tgt = self.get_tgt(client_creds, pac_request=False) + + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt, + pac_request=False) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + def test_service_no_auth_data_required(self): client_creds = self.get_client_creds() service_creds = self.get_cached_creds( @@ -314,8 +362,42 @@ class KdcTgsTests(KDCBaseTest): pac = self.get_ticket_pac(ticket, expect_pac=False) self.assertIsNone(pac) - def test_remove_pac(self): + def test_no_pac_service_no_auth_data_required(self): client_creds = self.get_client_creds() + service_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={'no_auth_data_required': True}) + + tgt = self.get_tgt(client_creds, pac_request=False) + + pac = self.get_ticket_pac(tgt) + self.assertIsNotNone(pac) + + ticket = self._make_tgs_request(client_creds, service_creds, tgt, + pac_request=False, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_remove_pac_service_no_auth_data_required(self): + client_creds = self.get_client_creds() + service_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={'no_auth_data_required': True}) + + tgt = self.modified_ticket(self.get_tgt(client_creds), + exclude_pac=True) + + pac = self.get_ticket_pac(tgt, expect_pac=False) + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False, expect_error=True) + + def test_remove_pac_client_no_auth_data_required(self): + client_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts={'no_auth_data_required': True}) service_creds = self.get_service_creds() tgt = self.modified_ticket(self.get_tgt(client_creds), @@ -324,12 +406,22 @@ class KdcTgsTests(KDCBaseTest): pac = self.get_ticket_pac(tgt, expect_pac=False) self.assertIsNone(pac) - ticket = self._make_tgs_request(client_creds, service_creds, tgt, - expect_pac=False) + self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False, expect_error=True) - pac = self.get_ticket_pac(ticket, expect_pac=False) + def test_remove_pac(self): + client_creds = self.get_client_creds() + service_creds = self.get_service_creds() + + tgt = self.modified_ticket(self.get_tgt(client_creds), + exclude_pac=True) + + pac = self.get_ticket_pac(tgt, expect_pac=False) self.assertIsNone(pac) + self._make_tgs_request(client_creds, service_creds, tgt, + expect_pac=False, expect_error=True) + if __name__ == "__main__": global_asn1_print = False diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 45524d70fa2..410ba83123c 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -261,3 +261,12 @@ ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer +# +# KDC TGS PAC tests +# +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_client_no_auth_data_required +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required +^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_request_no_pac diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index c86f9c2c2ea..8612d05b3da 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -276,7 +276,13 @@ 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_ldap_service_ticket\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_get_ticket_for_host_service_of_machine_account\(ad_dc\) # +# KDC TGS PAC tests +# +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_client_no_auth_data_required\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required\(ad_dc\) # -- 2.25.1 From 5ab0e635a72a092652dfafb6aeb7ec63afc59e60 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 19 Oct 2021 14:39:36 +1300 Subject: [PATCH 496/645] CVE-2020-25719 tests/krb5: Add a test for making an S4U2Self request without a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/s4u_tests.py | 37 ++++++++++++++++++++++++++-- selftest/knownfail_heimdal_kdc | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 593ef94c910..a80a7b3427e 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -256,6 +256,17 @@ class S4UKerberosTests(KDCBaseTest): if unexpected_flags is not None: unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags) + expected_error_mode = kdc_dict.pop('expected_error_mode', 0) + expected_status = kdc_dict.pop('expected_status', None) + if expected_error_mode: + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + + self.assertIsNone(expected_status) + kdc_options = kdc_dict.pop('kdc_options', '0') kdc_options = krb5_asn1.KDCOptions(kdc_options) @@ -290,9 +301,11 @@ class S4UKerberosTests(KDCBaseTest): ticket_decryption_key=service_decryption_key, expect_ticket_checksum=True, generate_padata_fn=generate_s4u2self_padata, - check_rep_fn=self.generic_check_kdc_rep, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, check_kdc_private_fn=self.generic_check_kdc_private, - expected_error_mode=0, + expected_error_mode=expected_error_mode, + expected_status=expected_status, tgt=service_tgt, authenticator_subkey=authenticator_subkey, kdc_options=str(kdc_options), @@ -321,6 +334,26 @@ class S4UKerberosTests(KDCBaseTest): 'expected_flags': 'forwardable' }) + # Test performing an S4U2Self operation with a forwardable ticket that does + # not contain a PAC. The request should fail. + def test_s4u2self_no_pac(self): + def forwardable_no_pac(ticket): + ticket = self.set_ticket_forwardable(ticket, flag=True) + return self.remove_ticket_pac(ticket) + + self._run_s4u2self_test( + { + 'expected_error_mode': (KDC_ERR_GENERIC, + KDC_ERR_BADOPTION), + 'expected_status': ntstatus.NT_STATUS_INVALID_PARAMETER, + 'client_opts': { + 'not_delegated': False + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': forwardable_no_pac, + 'expected_flags': 'forwardable' + }) + # Test performing an S4U2Self operation without requesting a forwardable # ticket. The resulting ticket should not have the 'forwardable' flag set. def test_s4u2self_without_forwardable(self): diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 410ba83123c..f141efa86e5 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -243,6 +243,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_pac ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed # # The lack of KRB5SignedPath means we no longer return -- 2.25.1 From 24fbd093ad16d884c04e4931cb96244cd648fdea Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 19 Oct 2021 20:02:45 +1300 Subject: [PATCH 497/645] CVE-2020-25719 tests/krb5: Add principal aliasing test BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/alias_tests.py | 201 +++++++++++++++++++ python/samba/tests/krb5/rfc4120_constants.py | 1 + python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 7 + selftest/knownfail_mit_kdc | 7 + source4/selftest/tests.py | 10 + 6 files changed, 227 insertions(+) create mode 100755 python/samba/tests/krb5/alias_tests.py diff --git a/python/samba/tests/krb5/alias_tests.py b/python/samba/tests/krb5/alias_tests.py new file mode 100755 index 00000000000..60213845a44 --- /dev/null +++ b/python/samba/tests/krb5/alias_tests.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 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 sys +import os + +import ldb + +from samba.tests import delete_force +import samba.tests.krb5.kcrypto as kcrypto +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, + NT_PRINCIPAL, +) + +sys.path.insert(0, 'bin/python') +os.environ['PYTHONUNBUFFERED'] = '1' + +global_asn1_print = False +global_hexdump = False + + +class AliasTests(KDCBaseTest): + def test_dc_alias_rename(self): + self._run_dc_alias(action='rename') + + def test_dc_alias_delete(self): + self._run_dc_alias(action='delete') + + def _run_dc_alias(self, action=None): + target_creds = self.get_dc_creds() + target_name = target_creds.get_username()[:-1] + + self._run_alias(target_name, lambda: target_creds, action=action) + + def test_create_alias_rename(self): + self._run_create_alias(action='rename') + + def test_create_alias_delete(self): + self._run_create_alias(action='delete') + + def _run_create_alias(self, action=None): + target_name = self.get_new_username() + + def create_target(): + samdb = self.get_samdb() + + realm = samdb.domain_dns_name().lower() + + hostname = f'{target_name}.{realm}' + spn = f'ldap/{hostname}' + + details = { + 'dNSHostName': hostname + } + + creds, fn = self.create_account( + samdb, + target_name, + account_type=self.AccountType.COMPUTER, + spn=spn, + additional_details=details) + + return creds + + self._run_alias(target_name, create_target, action=action) + + def _run_alias(self, target_name, target_creds_fn, action=None): + samdb = self.get_samdb() + + mach_name = self.get_new_username() + + # Create a machine account. + mach_creds, mach_dn = self.create_account( + samdb, mach_name, account_type=self.AccountType.COMPUTER) + self.addCleanup(delete_force, samdb, mach_dn) + + mach_sid = self.get_objectSid(samdb, mach_dn) + realm = mach_creds.get_realm() + + # The account salt doesn't change when the account is renamed. + old_salt = mach_creds.get_salt() + mach_creds.set_forced_salt(old_salt) + + # Rename the account to alias with the target account. + msg = ldb.Message(ldb.Dn(samdb, mach_dn)) + msg['sAMAccountName'] = ldb.MessageElement(target_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + mach_creds.set_username(target_name) + + # Get a TGT for the machine account. + tgt = self.get_tgt(mach_creds, kdc_options='0', fresh=True) + + # Check the PAC. + pac_data = self.get_pac_data(tgt.ticket_private['authorization-data']) + + upn = f'{target_name}@{realm.lower()}' + + self.assertEqual(target_name, str(pac_data.account_name)) + self.assertEqual(mach_sid, pac_data.account_sid) + self.assertEqual(target_name, pac_data.logon_name) + self.assertEqual(upn, pac_data.upn) + self.assertEqual(realm, pac_data.domain_name) + + # Rename or delete the machine account. + if action == 'rename': + mach_name2 = self.get_new_username() + + msg = ldb.Message(ldb.Dn(samdb, mach_dn)) + msg['sAMAccountName'] = ldb.MessageElement(mach_name2, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + elif action == 'delete': + samdb.delete(mach_dn) + else: + self.fail(action) + + # Get the credentials for the target account. + target_creds = target_creds_fn() + + # Look up the DNS host name of the target account. + target_dn = target_creds.get_dn() + res = samdb.search(target_dn, + scope=ldb.SCOPE_BASE, + attrs=['dNSHostName']) + target_hostname = str(res[0].get('dNSHostName', idx=0)) + + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['ldap', target_hostname]) + target_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[target_name]) + + target_decryption_key = self.TicketDecryptionKey_from_creds( + target_creds) + + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): + padata = self.PA_S4U2Self_create(name=target_cname, + realm=realm, + tgt_session_key=tgt.session_key, + ctype=None) + return [padata], req_body + + expected_error_mode = KDC_ERR_CLIENT_NAME_MISMATCH + + # Make a request using S4U2Self. The request should fail. + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=realm, + expected_cname=target_cname, + expected_srealm=realm, + expected_sname=sname, + ticket_decryption_key=target_decryption_key, + generate_padata_fn=generate_s4u2self_padata, + expected_error_mode=expected_error_mode, + check_error_fn=self.generic_check_kdc_error, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=tgt, + authenticator_subkey=authenticator_subkey, + kdc_options='0', + expect_pac=True) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=realm, + sname=sname, + etypes=etypes) + self.check_error_rep(rep, expected_error_mode) + + +if __name__ == '__main__': + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 39bb2db8e32..b643185f767 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -81,6 +81,7 @@ KDC_ERR_SKEW = 37 KDC_ERR_MODIFIED = 41 KDC_ERR_INAPP_CKSUM = 50 KDC_ERR_GENERIC = 60 +KDC_ERR_CLIENT_NAME_MISMATCH = 75 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 # Extended error types diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 7d11b6b4617..5cae7429985 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -105,6 +105,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/rodc_tests.py', 'python/samba/tests/krb5/salt_tests.py', 'python/samba/tests/krb5/spn_tests.py', + 'python/samba/tests/krb5/alias_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index f141efa86e5..5e0d958ee59 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -271,3 +271,10 @@ ^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_request_no_pac +# +# 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 diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 8612d05b3da..4441be9d203 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -386,3 +386,10 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer +# +# 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 diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 5c4fc87e910..893dfd2076b 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1409,6 +1409,16 @@ planpythontestsuite( 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support }) +planpythontestsuite( + "ad_dc", + "samba.tests.krb5.alias_tests", + environ={ + 'ADMIN_USERNAME': '$USERNAME', + 'ADMIN_PASSWORD': '$PASSWORD', + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support + }) for env in [ 'vampire_dc', -- 2.25.1 From 3e665bbc5b922746254d5240e03e2cf9a86d0655 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 21 Oct 2021 11:45:23 +1300 Subject: [PATCH 498/645] CVE-2020-25718 tests/krb5: Add tests for RODC-printed and invalid TGTs BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 6 +- python/samba/tests/krb5/kdc_tgs_tests.py | 808 +++++++++++++++++++ python/samba/tests/krb5/rfc4120_constants.py | 1 + selftest/knownfail_heimdal_kdc | 64 ++ selftest/knownfail_mit_kdc | 67 ++ 5 files changed, 944 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index cc23484ba2c..4fe7485c492 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -657,7 +657,8 @@ class KDCBaseTest(RawKerberosTest): 'delegation_to_spn': None, 'delegation_from_dn': None, 'trusted_to_auth_for_delegation': False, - 'fast_support': False + 'fast_support': False, + 'id': None } account_opts = { @@ -698,7 +699,8 @@ class KDCBaseTest(RawKerberosTest): delegation_to_spn, delegation_from_dn, trusted_to_auth_for_delegation, - fast_support): + fast_support, + id): if account_type is self.AccountType.USER: self.assertIsNone(spn) self.assertIsNone(delegation_to_spn) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index fbeb5fe61fb..74f1032163e 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -20,6 +20,13 @@ import sys import os +import ldb + + +from samba import dsdb + +from samba.dcerpc import krb5pac + sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" @@ -32,6 +39,10 @@ from samba.tests.krb5.rfc4120_constants import ( KRB_TGS_REP, KDC_ERR_BADMATCH, KDC_ERR_BADOPTION, + KDC_ERR_CLIENT_NAME_MISMATCH, + KDC_ERR_POLICY, + KDC_ERR_S_PRINCIPAL_UNKNOWN, + KDC_ERR_TGT_REVOKED, NT_PRINCIPAL, NT_SRV_INST, ) @@ -422,6 +433,803 @@ class KdcTgsTests(KDCBaseTest): self._make_tgs_request(client_creds, service_creds, tgt, expect_pac=False, expect_error=True) + # Test making a TGS request. + def test_tgs_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + self._run_tgs(tgt, expected_error=0) + + def test_renew_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True) + self._renew_tgt(tgt, expected_error=0) + + def test_validate_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True) + self._validate_tgt(tgt, expected_error=0) + + def test_s4u2self_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + self._s4u2self(tgt, creds, expected_error=0) + + def test_user2user_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + self._user2user(tgt, creds, expected_error=0) + + # Test making a request without a PAC. + 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) + + 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) + + 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) + + 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_BADOPTION) + + 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) + + # 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) + + 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) + + 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) + + 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) + + 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) + + # 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) + + 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) + + 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) + + 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) + + 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) + + # Test with an RODC-issued ticket where the client is revealed to the RODC. + def test_tgs_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._run_tgs(tgt, expected_error=0) + + def test_renew_rodc_revealed(self): + 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) + + 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) + + def test_s4u2self_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._s4u2self(tgt, creds, expected_error=0) + + def test_user2user_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=0) + + # Test with an RODC-issued ticket where the SID in the PAC is changed to + # that of another account. + def test_tgs_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._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_renew_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, renewable=True, from_rodc=True, + new_rid=existing_rid) + self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_validate_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, invalid=True, from_rodc=True, + new_rid=existing_rid) + self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_s4u2self_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._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_user2user_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._user2user(tgt, creds, + expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + # Test with an RODC-issued ticket where the SID in the PAC is changed to a + # non-existent one. + def test_tgs_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._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_renew_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, renewable=True, from_rodc=True, + new_rid=nonexistent_rid) + self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_validate_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, invalid=True, from_rodc=True, + new_rid=nonexistent_rid) + self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + 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) + + def test_user2user_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._user2user(tgt, creds, + expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + # Test with an RODC-issued ticket where the client is not revealed to the + # RODC. + def test_tgs_rodc_not_revealed(self): + creds = self._get_creds(replication_allowed=True) + tgt = self._get_tgt(creds, from_rodc=True) + # TODO: error code + self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_not_revealed(self): + creds = self._get_creds(replication_allowed=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_not_revealed(self): + creds = self._get_creds(replication_allowed=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_not_revealed(self): + creds = self._get_creds(replication_allowed=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_not_revealed(self): + creds = self._get_creds(replication_allowed=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the RODC account does not have the + # PARTIAL_SECRETS bit set. + def test_tgs_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._run_tgs(tgt, expected_error=KDC_ERR_POLICY) + + def test_renew_rodc_no_partial_secrets(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._remove_rodc_partial_secrets() + self._renew_tgt(tgt, expected_error=KDC_ERR_POLICY) + + def test_validate_rodc_no_partial_secrets(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._remove_rodc_partial_secrets() + self._validate_tgt(tgt, expected_error=KDC_ERR_POLICY) + + def test_s4u2self_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._s4u2self(tgt, creds, expected_error=KDC_ERR_POLICY) + + def test_user2user_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._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + + # Test with an RODC-issued ticket where the RODC account does not have an + # msDS-KrbTgtLink. + def test_tgs_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._run_tgs(tgt, expected_error=KDC_ERR_POLICY) + + def test_renew_rodc_no_krbtgt_link(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._remove_rodc_krbtgt_link() + self._renew_tgt(tgt, expected_error=KDC_ERR_POLICY) + + def test_validate_rodc_no_krbtgt_link(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._remove_rodc_krbtgt_link() + self._validate_tgt(tgt, expected_error=KDC_ERR_POLICY) + + def test_s4u2self_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._s4u2self(tgt, creds, expected_error=KDC_ERR_POLICY) + + def test_user2user_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._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + + # Test with an RODC-issued ticket where the client is not allowed to + # replicate to the RODC. + def test_tgs_rodc_not_allowed(self): + creds = self._get_creds(revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_not_allowed(self): + creds = self._get_creds(revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_not_allowed(self): + creds = self._get_creds(revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_not_allowed(self): + creds = self._get_creds(revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_not_allowed(self): + creds = self._get_creds(revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the client is denied from + # replicating to the RODC. + def test_tgs_rodc_denied(self): + creds = self._get_creds(replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_denied(self): + creds = self._get_creds(replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_denied(self): + creds = self._get_creds(replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_denied(self): + creds = self._get_creds(replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_denied(self): + creds = self._get_creds(replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # 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): + creds = self._get_creds(replication_allowed=True, + replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True) + self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_allowed_denied(self): + creds = self._get_creds(replication_allowed=True, + replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_allowed_denied(self): + creds = self._get_creds(replication_allowed=True, + replication_denied=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) + self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_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._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_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._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test user-to-user with incorrect service principal names. + def test_user2user_matching_sname_host(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + user_name = self._get_mach_creds().get_username() + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', user_name]) + + self._user2user(tgt, creds, sname=sname, + expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN) + + def test_user2user_matching_sname_no_host(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + user_name = self._get_mach_creds().get_username() + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + + self._user2user(tgt, creds, sname=sname, + expected_error=KDC_ERR_BADMATCH) + + def test_user2user_wrong_sname(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + other_creds = self.get_service_creds() + user_name = other_creds.get_username() + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + + self._user2user(tgt, creds, sname=sname, + expected_error=(KDC_ERR_BADMATCH, + KDC_ERR_BADOPTION)) + + def test_user2user_non_existent_sname(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', 'non_existent_user']) + + self._user2user(tgt, creds, sname=sname, + expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN) + + def test_user2user_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._user2user(service_ticket, creds, expected_error=KDC_ERR_POLICY) + + def _get_tgt(self, + client_creds, + renewable=False, + invalid=False, + from_rodc=False, + new_rid=None, + remove_pac=False): + self.assertFalse(renewable and invalid) + + if remove_pac: + self.assertIsNone(new_rid) + + tgt = self.get_tgt(client_creds) + + if from_rodc: + krbtgt_creds = self.get_mock_rodc_krbtgt_creds() + else: + krbtgt_creds = self.get_krbtgt_creds() + + if new_rid is not None: + def change_sid_fn(pac): + for pac_buffer in pac.buffers: + if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_INFO: + logon_info = pac_buffer.info.info + + logon_info.info3.base.rid = new_rid + + return pac + + modify_pac_fn = change_sid_fn + else: + modify_pac_fn = None + + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + if remove_pac: + checksum_keys = None + else: + checksum_keys = { + krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key + } + + if renewable: + def set_renewable(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 + + modify_fn = set_renewable + elif invalid: + def set_invalid(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 + + modify_fn = set_invalid + else: + modify_fn = None + + return self.modified_ticket( + tgt, + new_ticket_key=krbtgt_key, + modify_fn=modify_fn, + modify_pac_fn=modify_pac_fn, + exclude_pac=remove_pac, + update_pac_checksums=not remove_pac, + checksum_keys=checksum_keys) + + def _remove_rodc_partial_secrets(self): + samdb = self.get_samdb() + + rodc_ctx = self.get_mock_rodc_ctx() + rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) + + def add_rodc_partial_secrets(): + msg = ldb.Message() + msg.dn = rodc_dn + msg['userAccountControl'] = ldb.MessageElement( + str(rodc_ctx.userAccountControl), + ldb.FLAG_MOD_REPLACE, + 'userAccountControl') + samdb.modify(msg) + + self.addCleanup(add_rodc_partial_secrets) + + uac = rodc_ctx.userAccountControl & ~dsdb.UF_PARTIAL_SECRETS_ACCOUNT + + msg = ldb.Message() + msg.dn = rodc_dn + msg['userAccountControl'] = ldb.MessageElement( + str(uac), + ldb.FLAG_MOD_REPLACE, + 'userAccountControl') + samdb.modify(msg) + + def _remove_rodc_krbtgt_link(self): + samdb = self.get_samdb() + + rodc_ctx = self.get_mock_rodc_ctx() + rodc_dn = ldb.Dn(samdb, rodc_ctx.acct_dn) + + def add_rodc_krbtgt_link(): + msg = ldb.Message() + msg.dn = rodc_dn + msg['msDS-KrbTgtLink'] = ldb.MessageElement( + rodc_ctx.new_krbtgt_dn, + ldb.FLAG_MOD_ADD, + 'msDS-KrbTgtLink') + samdb.modify(msg) + + self.addCleanup(add_rodc_krbtgt_link) + + msg = ldb.Message() + msg.dn = rodc_dn + msg['msDS-KrbTgtLink'] = ldb.MessageElement( + [], + ldb.FLAG_MOD_DELETE, + 'msDS-KrbTgtLink') + samdb.modify(msg) + + def _get_creds(self, + replication_allowed=False, + replication_denied=False, + revealed_to_rodc=False): + return self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={ + 'allowed_replication_mock': replication_allowed, + 'denied_replication_mock': replication_denied, + 'revealed_to_mock_rodc': revealed_to_rodc, + 'id': 0 + }) + + def _get_existing_rid(self, + replication_allowed=False, + replication_denied=False, + revealed_to_rodc=False): + other_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={ + 'allowed_replication_mock': replication_allowed, + 'denied_replication_mock': replication_denied, + 'revealed_to_mock_rodc': revealed_to_rodc, + 'id': 1 + }) + + samdb = self.get_samdb() + + other_dn = other_creds.get_dn() + other_sid = self.get_objectSid(samdb, other_dn) + + other_rid = int(other_sid.rsplit('-', 1)[1]) + + return other_rid + + def _get_mach_creds(self): + return self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={ + 'allowed_replication_mock': True, + 'denied_replication_mock': False, + 'revealed_to_mock_rodc': True, + 'id': 2 + }) + + def _get_non_existent_rid(self): + return (1 << 30) - 1 + + def _run_tgs(self, tgt, expected_error): + target_creds = self.get_service_creds() + self._tgs_req(tgt, expected_error, target_creds) + + def _renew_tgt(self, tgt, expected_error): + krbtgt_creds = self.get_krbtgt_creds() + kdc_options = str(krb5_asn1.KDCOptions('renew')) + self._tgs_req(tgt, expected_error, krbtgt_creds, + kdc_options=kdc_options) + + def _validate_tgt(self, tgt, expected_error): + krbtgt_creds = self.get_krbtgt_creds() + kdc_options = str(krb5_asn1.KDCOptions('validate')) + self._tgs_req(tgt, expected_error, krbtgt_creds, + kdc_options=kdc_options) + + def _s4u2self(self, tgt, tgt_creds, expected_error): + user_creds = self._get_mach_creds() + + user_name = user_creds.get_username() + user_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + user_realm = user_creds.get_realm() + + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): + padata = self.PA_S4U2Self_create( + name=user_cname, + realm=user_realm, + tgt_session_key=tgt.session_key, + ctype=None) + + return [padata], req_body + + self._tgs_req(tgt, expected_error, tgt_creds, + expected_cname=user_cname, + generate_padata_fn=generate_s4u2self_padata, + expect_claims=False) + + def _user2user(self, tgt, tgt_creds, expected_error, sname=None): + user_creds = self._get_mach_creds() + user_tgt = self.get_tgt(user_creds) + + kdc_options = str(krb5_asn1.KDCOptions('enc-tkt-in-skey')) + self._tgs_req(user_tgt, expected_error, tgt_creds, + kdc_options=kdc_options, + additional_ticket=tgt, + sname=sname) + + def _tgs_req(self, tgt, expected_error, target_creds, + kdc_options='0', + expected_cname=None, + additional_ticket=None, + generate_padata_fn=None, + sname=None, + expect_claims=True): + srealm = target_creds.get_realm() + + if sname is None: + target_name = target_creds.get_username() + if target_name == 'krbtgt': + sname = self.PrincipalName_create(name_type=NT_SRV_INST, + names=[target_name, srealm]) + else: + if target_name[-1] == '$': + target_name = target_name[:-1] + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', target_name]) + + if additional_ticket is not None: + additional_tickets = [additional_ticket.ticket] + decryption_key = additional_ticket.session_key + else: + additional_tickets = None + decryption_key = self.TicketDecryptionKey_from_creds( + target_creds) + + subkey = self.RandomKey(tgt.session_key.etype) + + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + if expected_error: + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: + check_error_fn = None + check_rep_fn = self.generic_check_kdc_rep + + if expected_cname is None: + expected_cname = tgt.cname + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=tgt.crealm, + expected_cname=expected_cname, + expected_srealm=srealm, + expected_sname=sname, + ticket_decryption_key=decryption_key, + generate_padata_fn=generate_padata_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, + tgt=tgt, + authenticator_subkey=subkey, + kdc_options=kdc_options, + expect_edata=False, + expect_claims=expect_claims) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=srealm, + sname=sname, + etypes=etypes, + additional_tickets=additional_tickets) + if __name__ == "__main__": global_asn1_print = False diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index b643185f767..490cd255ec3 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -72,6 +72,7 @@ KDC_ERR_POLICY = 12 KDC_ERR_BADOPTION = 13 KDC_ERR_ETYPE_NOSUPP = 14 KDC_ERR_SUMTYPE_NOSUPP = 15 +KDC_ERR_TGT_REVOKED = 20 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 KDC_ERR_BAD_INTEGRITY = 31 diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 5e0d958ee59..27c2dfe3be3 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -278,3 +278,67 @@ ^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 TGT tests +# +^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 +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_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_no_pac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_krbtgt_link +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed +^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_no_pac +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_allowed +^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_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_matching_sname_host +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_matching_sname_no_host +^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_non_existent_sname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_allowed +^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_user2user_rodc_revealed +^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_validate_no_pac +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_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 a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 4441be9d203..84f74e5523e 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -393,3 +393,70 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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 TGT tests +# +^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 +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_revealed +^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_no_pac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_krbtgt_link +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed +^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_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_no_pac +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_allowed +^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_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_matching_sname_no_host +^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_req +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_allowed +^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_user2user_rodc_revealed +^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_validate_no_pac +^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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_partial_secrets +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed +^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 -- 2.25.1 From e7c7108c9f7d9c58476c441b91810e19cf811536 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 28 Oct 2021 16:20:07 +1300 Subject: [PATCH 499/645] CVE-2020-25719 tests/krb5: Add tests for including authdata without a PAC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 32 +++++++++++++++++++++++- python/samba/tests/krb5/raw_testcase.py | 14 +++++++---- selftest/knownfail_heimdal_kdc | 5 ++++ selftest/knownfail_mit_kdc | 5 ++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 74f1032163e..5de79c30e1b 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -485,6 +485,34 @@ class KdcTgsTests(KDCBaseTest): tgt = self._get_tgt(creds, remove_pac=True) self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION) + # 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) + + 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) + + 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) + + 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_BADOPTION) + + 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) + # Test changing the SID in the PAC to that of another account. def test_tgs_sid_mismatch_existing(self): creds = self._get_creds() @@ -928,7 +956,8 @@ class KdcTgsTests(KDCBaseTest): invalid=False, from_rodc=False, new_rid=None, - remove_pac=False): + remove_pac=False, + allow_empty_authdata=False): self.assertFalse(renewable and invalid) if remove_pac: @@ -1011,6 +1040,7 @@ class KdcTgsTests(KDCBaseTest): modify_fn=modify_fn, modify_pac_fn=modify_pac_fn, exclude_pac=remove_pac, + allow_empty_authdata=allow_empty_authdata, update_pac_checksums=not remove_pac, checksum_keys=checksum_keys) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8e55790272a..b5ac393ea67 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3224,6 +3224,7 @@ class RawKerberosTest(TestCaseInTempDir): modify_fn=None, modify_pac_fn=None, exclude_pac=False, + allow_empty_authdata=False, update_pac_checksums=True, checksum_keys=None, include_checksums=None): @@ -3332,8 +3333,10 @@ class RawKerberosTest(TestCaseInTempDir): # Replace the PAC in the authorization data and re-add it to the # ticket enc-part. - auth_data, _ = self.replace_pac(auth_data, new_pac, - expect_pac=expect_pac) + auth_data, _ = self.replace_pac( + auth_data, new_pac, + expect_pac=expect_pac, + allow_empty_authdata=allow_empty_authdata) enc_part['authorization-data'] = auth_data # Re-encrypt the ticket enc-part with the new key. @@ -3454,7 +3457,8 @@ class RawKerberosTest(TestCaseInTempDir): kdc_checksum_buffer.info.signature = kdc_checksum - def replace_pac(self, auth_data, new_pac, expect_pac=True): + def replace_pac(self, auth_data, new_pac, expect_pac=True, + allow_empty_authdata=False): if new_pac is not None: self.assertElementEqual(new_pac, 'ad-type', AD_WIN2K_PAC) self.assertElementPresent(new_pac, 'ad-data') @@ -3483,7 +3487,7 @@ class RawKerberosTest(TestCaseInTempDir): if expect_pac: self.assertIsNotNone(old_pac, 'Expected PAC') - if relevant_elems: + if relevant_elems or allow_empty_authdata: ad_relevant = self.der_encode( relevant_elems, asn1Spec=krb5_asn1.AD_IF_RELEVANT()) @@ -3494,7 +3498,7 @@ class RawKerberosTest(TestCaseInTempDir): else: authdata_elem = None - if authdata_elem is not None: + if authdata_elem is not None or allow_empty_authdata: new_auth_data.append(authdata_elem) if expect_pac: diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 27c2dfe3be3..572fbb0e0cd 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -281,6 +281,7 @@ # # KDC TGT tests # +^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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_denied @@ -292,6 +293,7 @@ ^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_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied @@ -303,6 +305,7 @@ ^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_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied @@ -314,6 +317,7 @@ ^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_matching_sname_host ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_matching_sname_no_host ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac @@ -331,6 +335,7 @@ ^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_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_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_denied diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 84f74e5523e..127fcdc425d 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -396,6 +396,7 @@ 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_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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_denied @@ -408,6 +409,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_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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied @@ -421,6 +423,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_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_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied @@ -433,6 +436,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_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_matching_sname_no_host ^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_req @@ -448,6 +452,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_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_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_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_denied -- 2.25.1 From 7d5681f10767880b98fd206d20df3e24fc62ee21 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 21 Oct 2021 16:46:56 +1300 Subject: [PATCH 500/645] CVE-2020-25721 tests/krb5: Add tests for extended PAC_UPN_DNS_INFO PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 3 +- python/samba/tests/krb5/kdc_tgs_tests.py | 51 +++++++++++++++++++++++- python/samba/tests/krb5/raw_testcase.py | 41 +++++++++++++++++++ python/samba/tests/krb5/s4u_tests.py | 2 + selftest/knownfail_heimdal_kdc | 4 ++ selftest/knownfail_mit_kdc | 4 ++ 6 files changed, 103 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 4fe7485c492..9be6cbab30b 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1358,7 +1358,7 @@ class KDCBaseTest(RawKerberosTest): def get_tgt(self, creds, to_rodc=False, kdc_options=None, expected_flags=None, unexpected_flags=None, - expected_account_name=None, + expected_account_name=None, expected_upn_name=None, expected_sid=None, pac_request=True, expect_pac=True, fresh=False): user_name = creds.get_username() @@ -1410,6 +1410,7 @@ class KDCBaseTest(RawKerberosTest): expected_srealm=realm, expected_sname=sname, expected_account_name=expected_account_name, + expected_upn_name=expected_upn_name, expected_sid=expected_sid, expected_salt=salt, expected_flags=expected_flags, diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 5de79c30e1b..5313dbc6045 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -227,7 +227,10 @@ class KdcTgsTests(KDCBaseTest): def _make_tgs_request(self, client_creds, service_creds, tgt, pac_request=None, expect_pac=True, - expect_error=False): + 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]) @@ -268,6 +271,9 @@ class KdcTgsTests(KDCBaseTest): 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, @@ -433,6 +439,49 @@ class KdcTgsTests(KDCBaseTest): self._make_tgs_request(client_creds, service_creds, tgt, expect_pac=False, expect_error=True) + def test_upn_dns_info_ex_user(self): + client_creds = self.get_client_creds() + self._run_upn_dns_info_ex_test(client_creds) + + def test_upn_dns_info_ex_mac(self): + mach_creds = self.get_mach_creds() + self._run_upn_dns_info_ex_test(mach_creds) + + def test_upn_dns_info_ex_upn_user(self): + client_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts={'upn': 'upn_dns_info_test_upn0@bar'}) + self._run_upn_dns_info_ex_test(client_creds) + + def test_upn_dns_info_ex_upn_mac(self): + mach_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': 'upn_dns_info_test_upn1@bar'}) + self._run_upn_dns_info_ex_test(mach_creds) + + def _run_upn_dns_info_ex_test(self, client_creds): + service_creds = self.get_service_creds() + + samdb = self.get_samdb() + dn = client_creds.get_dn() + + account_name = client_creds.get_username() + upn_name = client_creds.get_upn() + if upn_name is None: + realm = client_creds.get_realm().lower() + upn_name = f'{account_name}@{realm}' + sid = self.get_objectSid(samdb, dn) + + tgt = self.get_tgt(client_creds, + expected_account_name=account_name, + expected_upn_name=upn_name, + expected_sid=sid) + + self._make_tgs_request(client_creds, service_creds, tgt, + expected_account_name=account_name, + expected_upn_name=upn_name, + expected_sid=sid) + # Test making a TGS request. def test_tgs_req(self): creds = self._get_creds() diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index b5ac393ea67..18ee8738eaa 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1986,6 +1986,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, expected_account_name=None, + expected_upn_name=None, expected_sid=None, expected_supported_etypes=None, expected_flags=None, @@ -2019,6 +2020,7 @@ class RawKerberosTest(TestCaseInTempDir): expect_edata=None, expect_pac=True, expect_claims=True, + expect_upn_dns_info_ex=None, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2037,6 +2039,7 @@ class RawKerberosTest(TestCaseInTempDir): '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, 'expected_flags': expected_flags, @@ -2070,6 +2073,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_edata': expect_edata, 'expect_pac': expect_pac, 'expect_claims': expect_claims, + 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, 'to_rodc': to_rodc } if callback_dict is None: @@ -2084,6 +2088,7 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, expected_account_name=None, + expected_upn_name=None, expected_sid=None, expected_supported_etypes=None, expected_flags=None, @@ -2116,6 +2121,7 @@ class RawKerberosTest(TestCaseInTempDir): expect_edata=None, expect_pac=True, expect_claims=True, + expect_upn_dns_info_ex=None, expected_proxy_target=None, expected_transited_services=None, to_rodc=False): @@ -2136,6 +2142,7 @@ class RawKerberosTest(TestCaseInTempDir): '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, 'expected_flags': expected_flags, @@ -2168,6 +2175,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_edata': expect_edata, 'expect_pac': expect_pac, 'expect_claims': expect_claims, + 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, 'expected_proxy_target': expected_proxy_target, 'expected_transited_services': expected_transited_services, 'to_rodc': to_rodc @@ -2584,6 +2592,12 @@ class RawKerberosTest(TestCaseInTempDir): expected_account_name = kdc_exchange_dict['expected_account_name'] expected_sid = kdc_exchange_dict['expected_sid'] + expect_upn_dns_info_ex = kdc_exchange_dict['expect_upn_dns_info_ex'] + if expect_upn_dns_info_ex is None and ( + expected_account_name is not None + or expected_sid is not None): + expect_upn_dns_info_ex = True + for pac_buffer in pac.buffers: if pac_buffer.type == krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION: expected_proxy_target = kdc_exchange_dict[ @@ -2618,6 +2632,31 @@ class RawKerberosTest(TestCaseInTempDir): expected_rid = int(expected_sid.rsplit('-', 1)[1]) self.assertEqual(expected_rid, logon_info.rid) + elif pac_buffer.type == krb5pac.PAC_TYPE_UPN_DNS_INFO: + upn_dns_info = pac_buffer.info + upn_dns_info_ex = upn_dns_info.ex + + expected_realm = kdc_exchange_dict['expected_crealm'] + self.assertEqual(expected_realm, + upn_dns_info.dns_domain_name) + + expected_upn_name = kdc_exchange_dict['expected_upn_name'] + if expected_upn_name is not None: + self.assertEqual(expected_upn_name, + upn_dns_info.upn_name) + + if expect_upn_dns_info_ex: + self.assertIsNotNone(upn_dns_info_ex) + + if upn_dns_info_ex is not None: + if expected_account_name is not None: + self.assertEqual(expected_account_name, + upn_dns_info_ex.samaccountname) + + if expected_sid is not None: + self.assertEqual(expected_sid, + str(upn_dns_info_ex.objectsid)) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -3600,6 +3639,7 @@ class RawKerberosTest(TestCaseInTempDir): padata, kdc_options, expected_account_name=None, + expected_upn_name=None, expected_sid=None, expected_flags=None, unexpected_flags=None, @@ -3634,6 +3674,7 @@ class RawKerberosTest(TestCaseInTempDir): 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=ticket_decryption_key, diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index a80a7b3427e..5005affd6b3 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -309,6 +309,7 @@ class S4UKerberosTests(KDCBaseTest): tgt=service_tgt, authenticator_subkey=authenticator_subkey, kdc_options=str(kdc_options), + expect_upn_dns_info_ex=False, expect_claims=False) self._generic_kdc_exchange(kdc_exchange_dict, @@ -610,6 +611,7 @@ class S4UKerberosTests(KDCBaseTest): kdc_options=kdc_options, pac_options=pac_options, expect_edata=expect_edata, + expect_upn_dns_info_ex=False, expected_proxy_target=expected_proxy_target, expected_transited_services=expected_transited_services, expect_pac=expect_pac) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 572fbb0e0cd..46866823590 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -317,6 +317,10 @@ ^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_upn_dns_info_ex_mac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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_matching_sname_host ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_matching_sname_no_host diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 127fcdc425d..d2acc5559ed 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -436,6 +436,10 @@ 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_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_upn_dns_info_ex_mac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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_matching_sname_no_host ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac -- 2.25.1 From 378a7815ed426557e532be71f09d4814cecbe628 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Aug 2021 17:11:24 +0200 Subject: [PATCH 501/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Add tests for connecting to services anonymously and without a PAC At the end of the patchset we assume NT_STATUS_NO_IMPERSONATION_TOKEN if no PAC is available. For now we want to look for ACCESS_DENIED as this allows the test to pass (showing that gensec:require_pac = true is a useful partial mitigation). This will also help others doing backports that do not take the full patch set. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/test_ccache.py | 31 +++++++++--- python/samba/tests/krb5/test_ldap.py | 70 ++++++++++++++++++++++---- python/samba/tests/krb5/test_rpc.py | 46 ++++++++++++++--- python/samba/tests/krb5/test_smb.py | 31 +++++++++--- source4/selftest/tests.py | 17 ++++--- 5 files changed, 158 insertions(+), 37 deletions(-) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index 040ae5cc9a1..cb5061b92d9 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -21,10 +21,11 @@ import sys import os from ldb import SCOPE_SUBTREE -from samba import gensec +from samba import NTSTATUSError, gensec from samba.auth import AuthContext from samba.dcerpc import security from samba.ndr import ndr_unpack +from samba.ntstatus import NT_STATUS_ACCESS_DENIED from samba.tests.krb5.kdc_base_test import KDCBaseTest @@ -41,11 +42,18 @@ class CcacheTests(KDCBaseTest): """ def test_ccache(self): + self._run_ccache_test("ccacheusr") + + def test_ccache_no_pac(self): + self._run_ccache_test("ccacheusr_nopac", include_pac=False, + expect_anon=True, allow_error=True) + + def _run_ccache_test(self, user_name, include_pac=True, + expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the # user are stored. - user_name = "ccacheusr" mach_name = "ccachemac" service = "host" @@ -67,7 +75,10 @@ class CcacheTests(KDCBaseTest): # ticket, to ensure that the krbtgt ticket doesn't also need to be # stored. (creds, cachefile) = self.create_ccache_with_user(user_credentials, - mach_credentials) + mach_credentials, + pac=include_pac) + # Remove the cached credentials file. + self.addCleanup(os.remove, cachefile.name) # Authenticate in-process to the machine account using the user's # cached credentials. @@ -117,7 +128,16 @@ class CcacheTests(KDCBaseTest): sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) # Retrieve the SIDs from the security token. - session = gensec_server.session_info() + try: + session = gensec_server.session_info() + except NTSTATUSError as e: + if not allow_error: + self.fail() + + enum, _ = e.args + self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + return + token = session.security_token token_sids = token.sids self.assertGreater(len(token_sids), 0) @@ -125,9 +145,6 @@ class CcacheTests(KDCBaseTest): # Ensure that they match. self.assertEqual(sid, token_sids[0]) - # Remove the cached credentials file. - os.remove(cachefile.name) - if __name__ == "__main__": global_asn1_print = False diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 7d9ffebe298..31e50487338 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -20,10 +20,11 @@ import sys import os -from ldb import SCOPE_BASE, SCOPE_SUBTREE +from ldb import LdbError, ERR_OPERATIONS_ERROR, SCOPE_BASE, SCOPE_SUBTREE from samba.dcerpc import security from samba.ndr import ndr_unpack from samba.samdb import SamDB +from samba import credentials from samba.tests.krb5.kdc_base_test import KDCBaseTest @@ -40,13 +41,20 @@ class LdapTests(KDCBaseTest): """ def test_ldap(self): + self._run_ldap_test("ldapusr") + + def test_ldap_no_pac(self): + self._run_ldap_test("ldapusr_nopac", include_pac=False, + expect_anon=True, allow_error=True) + + def _run_ldap_test(self, user_name, include_pac=True, + expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the # user are stored. samdb = self.get_samdb() - user_name = "ldapusr" mach_name = samdb.host_dns_name() service = "ldap" @@ -62,7 +70,10 @@ class LdapTests(KDCBaseTest): (creds, cachefile) = self.create_ccache_with_user(user_credentials, mach_credentials, service, - mach_name) + mach_name, + pac=include_pac) + # Remove the cached credentials file. + self.addCleanup(os.remove, cachefile.name) # Authenticate in-process to the machine account using the user's # cached credentials. @@ -74,22 +85,61 @@ class LdapTests(KDCBaseTest): self.assertEqual(1, len(ldb_res)) sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + # Connect to the machine account and retrieve the user SID. + try: + ldb_as_user = SamDB(url="ldap://%s" % mach_name, + credentials=creds, + lp=self.get_lp()) + except LdbError as e: + if not allow_error: + self.fail() + + enum, estr = e.args + self.assertEqual(ERR_OPERATIONS_ERROR, enum) + self.assertIn('NT_STATUS_ACCESS_DENIED', estr) + return + + ldb_res = ldb_as_user.search('', + scope=SCOPE_BASE, + attrs=["tokenGroups"]) + self.assertEqual(1, len(ldb_res)) + + token_groups = ldb_res[0]["tokenGroups"] + token_sid = ndr_unpack(security.dom_sid, token_groups[0]) + + if expect_anon: + # Ensure we got an anonymous token. + self.assertEqual(security.SID_NT_ANONYMOUS, str(token_sid)) + token_sid = ndr_unpack(security.dom_sid, token_groups[1]) + self.assertEqual(security.SID_NT_NETWORK, str(token_sid)) + if len(token_groups) >= 3: + token_sid = ndr_unpack(security.dom_sid, token_groups[2]) + self.assertEqual(security.SID_NT_THIS_ORGANISATION, + str(token_sid)) + else: + # Ensure that they match. + self.assertEqual(sid, token_sid) + + def test_ldap_anonymous(self): + samdb = self.get_samdb() + mach_name = samdb.host_dns_name() + + anon_creds = credentials.Credentials() + anon_creds.set_anonymous() + # Connect to the machine account and retrieve the user SID. ldb_as_user = SamDB(url="ldap://%s" % mach_name, - credentials=creds, + credentials=anon_creds, lp=self.get_lp()) ldb_res = ldb_as_user.search('', scope=SCOPE_BASE, attrs=["tokenGroups"]) self.assertEqual(1, len(ldb_res)) + # Ensure we got an anonymous token. token_sid = ndr_unpack(security.dom_sid, ldb_res[0]["tokenGroups"][0]) - - # Ensure that they match. - self.assertEqual(sid, token_sid) - - # Remove the cached credentials file. - os.remove(cachefile.name) + self.assertEqual(security.SID_NT_ANONYMOUS, str(token_sid)) + self.assertEqual(len(ldb_res[0]["tokenGroups"]), 1) if __name__ == "__main__": diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index ef8dd4dcbf5..54ad7cf0e48 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -20,7 +20,9 @@ import sys import os +from samba import NTSTATUSError, credentials from samba.dcerpc import lsa +from samba.ntstatus import NT_STATUS_ACCESS_DENIED from samba.tests.krb5.kdc_base_test import KDCBaseTest @@ -37,13 +39,20 @@ class RpcTests(KDCBaseTest): """ def test_rpc(self): + self._run_rpc_test("rpcusr") + + def test_rpc_no_pac(self): + self._run_rpc_test("rpcusr_nopac", include_pac=False, + expect_anon=True, allow_error=True) + + def _run_rpc_test(self, user_name, include_pac=True, + expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the # user are stored. samdb = self.get_samdb() - user_name = "rpcusr" mach_name = samdb.host_dns_name() service = "cifs" @@ -59,20 +68,45 @@ class RpcTests(KDCBaseTest): (creds, cachefile) = self.create_ccache_with_user(user_credentials, mach_credentials, service, - mach_name) + mach_name, + pac=include_pac) + # Remove the cached credentials file. + self.addCleanup(os.remove, cachefile.name) # Authenticate in-process to the machine account using the user's # cached credentials. binding_str = "ncacn_np:%s[\\pipe\\lsarpc]" % mach_name - conn = lsa.lsarpc(binding_str, self.get_lp(), creds) + try: + conn = lsa.lsarpc(binding_str, self.get_lp(), creds) + except NTSTATUSError as e: + if not allow_error: + self.fail() + + enum, _ = e.args + self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + return (account_name, _) = conn.GetUserName(None, None, None) - self.assertEqual(user_name, account_name.string) + if expect_anon: + self.assertNotEqual(user_name, account_name.string) + else: + self.assertEqual(user_name, account_name.string) - # Remove the cached credentials file. - os.remove(cachefile.name) + def test_rpc_anonymous(self): + samdb = self.get_samdb() + mach_name = samdb.host_dns_name() + + anon_creds = credentials.Credentials() + anon_creds.set_anonymous() + + binding_str = "ncacn_np:%s[\\pipe\\lsarpc]" % mach_name + conn = lsa.lsarpc(binding_str, self.get_lp(), anon_creds) + + (account_name, _) = conn.GetUserName(None, None, None) + + self.assertEqual('ANONYMOUS LOGON', account_name.string) if __name__ == "__main__": diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 1e70ed322bf..79ff16ac879 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -21,8 +21,10 @@ import sys import os from ldb import SCOPE_SUBTREE +from samba import NTSTATUSError from samba.dcerpc import security from samba.ndr import ndr_unpack +from samba.ntstatus import NT_STATUS_ACCESS_DENIED from samba.samba3 import libsmb_samba_internal as libsmb from samba.samba3 import param as s3param @@ -41,13 +43,20 @@ class SmbTests(KDCBaseTest): """ def test_smb(self): + self._run_smb_test("smbusr") + + def test_smb_no_pac(self): + self._run_smb_test("smbusr_nopac", include_pac=False, + expect_error=True) + + def _run_smb_test(self, user_name, include_pac=True, + expect_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the # user are stored. samdb = self.get_samdb() - user_name = "smbusr" mach_name = samdb.host_dns_name() service = "cifs" share = "tmp" @@ -64,7 +73,10 @@ class SmbTests(KDCBaseTest): (creds, cachefile) = self.create_ccache_with_user(user_credentials, mach_credentials, service, - mach_name) + mach_name, + pac=include_pac) + # Remove the cached credentials file. + self.addCleanup(os.remove, cachefile.name) # Set the Kerberos 5 credentials cache environment variable. This is # required because the codepath that gets run (gse_krb5) looks for it @@ -95,16 +107,23 @@ class SmbTests(KDCBaseTest): self.addCleanup(s3_lp.set, "client max protocol", max_protocol) s3_lp.set("client max protocol", "NT1") - conn = libsmb.Conn(mach_name, share, lp=s3_lp, creds=creds) + try: + conn = libsmb.Conn(mach_name, share, lp=s3_lp, creds=creds) + except NTSTATUSError as e: + if not expect_error: + self.fail() + + enum, _ = e.args + self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + return + else: + self.assertFalse(expect_error) (uid, gid, gids, sids, guest) = conn.posix_whoami() # Ensure that they match. self.assertEqual(sid, sids[0]) - # Remove the cached credentials file. - os.remove(cachefile.name) - if __name__ == "__main__": global_asn1_print = False diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 893dfd2076b..cb546127201 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -783,14 +783,15 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support }) -planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_rpc", - environ={ - 'ADMIN_USERNAME': '$USERNAME', - 'ADMIN_PASSWORD': '$PASSWORD', - 'STRICT_CHECKING': '0', - 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support - }) +for env in ['ad_dc_default', 'ad_member']: + planoldpythontestsuite(env, "samba.tests.krb5.test_rpc", + environ={ + 'ADMIN_USERNAME': '$DC_USERNAME', + 'ADMIN_PASSWORD': '$DC_PASSWORD', + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support + }) planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", environ={ 'ADMIN_USERNAME': '$USERNAME', -- 2.25.1 From 698e724a2da6797cb1b1818cbd463c17723a1c94 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Oct 2021 16:20:36 +0200 Subject: [PATCH 502/645] CVE-2020-25719 CVE-2020-25717: selftest: remove "gensec:require_pac" settings BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 [jsutton@samba.org Added knownfail entries] Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/no-pac | 4 ++++ selftest/selftest.pl | 2 -- selftest/target/Samba4.pm | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 selftest/knownfail.d/no-pac diff --git a/selftest/knownfail.d/no-pac b/selftest/knownfail.d/no-pac new file mode 100644 index 00000000000..9723d581c2a --- /dev/null +++ b/selftest/knownfail.d/no-pac @@ -0,0 +1,4 @@ +^samba.tests.krb5.test_ccache.samba.tests.krb5.test_ccache.CcacheTests.test_ccache_no_pac +^samba.tests.krb5.test_ldap.samba.tests.krb5.test_ldap.LdapTests.test_ldap_no_pac +^samba.tests.krb5.test_rpc.samba.tests.krb5.test_rpc.RpcTests.test_rpc_no_pac +^samba.tests.krb5.test_smb.samba.tests.krb5.test_smb.SmbTests.test_smb_no_pac diff --git a/selftest/selftest.pl b/selftest/selftest.pl index b166b28e0cb..80eb181a898 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -632,8 +632,6 @@ sub write_clientconf($$$) client min protocol = CORE log level = 1 torture:basedir = $clientdir -#We don't want to pass our self-tests if the PAC code is wrong - gensec:require_pac = true #We don't want to run 'speed' tests for very long torture:timelimit = 1 winbind separator = / diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index aaadd946e03..6d6a44190ec 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -707,8 +707,6 @@ sub provision_raw_step1($$) notify:inotify = false ldb:nosync = true ldap server require strong auth = yes -#We don't want to pass our self-tests if the PAC code is wrong - gensec:require_pac = true log file = $ctx->{logdir}/log.\%m log level = $ctx->{server_loglevel} lanman auth = Yes -- 2.25.1 From f88356eaf191aeda5c7d11d3b6bb2837cbe0dcfd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 10:27:41 +1300 Subject: [PATCH 503/645] CVE-2020-25719 CVE-2020-25717 tests/krb5: Adapt tests for connecting without a PAC to new error codes BUG: https://bugzilla.samba.org/show_bug.cgi?id=14799 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/test_ccache.py | 5 +++-- python/samba/tests/krb5/test_ldap.py | 2 +- python/samba/tests/krb5/test_rpc.py | 4 ++-- python/samba/tests/krb5/test_smb.py | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index cb5061b92d9..d21ec84796e 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -25,7 +25,7 @@ from samba import NTSTATUSError, gensec from samba.auth import AuthContext from samba.dcerpc import security from samba.ndr import ndr_unpack -from samba.ntstatus import NT_STATUS_ACCESS_DENIED +from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN from samba.tests.krb5.kdc_base_test import KDCBaseTest @@ -84,6 +84,7 @@ class CcacheTests(KDCBaseTest): # cached credentials. lp = self.get_lp() + lp.set('server role', 'active directory domain controller') settings = {} settings["lp_ctx"] = lp @@ -135,7 +136,7 @@ class CcacheTests(KDCBaseTest): self.fail() enum, _ = e.args - self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum) return token = session.security_token diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 31e50487338..0205bdf6fb7 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -96,7 +96,7 @@ class LdapTests(KDCBaseTest): enum, estr = e.args self.assertEqual(ERR_OPERATIONS_ERROR, enum) - self.assertIn('NT_STATUS_ACCESS_DENIED', estr) + self.assertIn('NT_STATUS_NO_IMPERSONATION_TOKEN', estr) return ldb_res = ldb_as_user.search('', diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index 54ad7cf0e48..0f2170a8ded 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -22,7 +22,7 @@ import os from samba import NTSTATUSError, credentials from samba.dcerpc import lsa -from samba.ntstatus import NT_STATUS_ACCESS_DENIED +from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN from samba.tests.krb5.kdc_base_test import KDCBaseTest @@ -84,7 +84,7 @@ class RpcTests(KDCBaseTest): self.fail() enum, _ = e.args - self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum) return (account_name, _) = conn.GetUserName(None, None, None) diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 79ff16ac879..7408e5dbece 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -24,7 +24,7 @@ from ldb import SCOPE_SUBTREE from samba import NTSTATUSError from samba.dcerpc import security from samba.ndr import ndr_unpack -from samba.ntstatus import NT_STATUS_ACCESS_DENIED +from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN from samba.samba3 import libsmb_samba_internal as libsmb from samba.samba3 import param as s3param @@ -114,7 +114,7 @@ class SmbTests(KDCBaseTest): self.fail() enum, _ = e.args - self.assertEqual(NT_STATUS_ACCESS_DENIED, enum) + self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum) return else: self.assertFalse(expect_error) -- 2.25.1 From 0abc25364bc62ad8f19578eb1d83995d216e040d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Oct 2021 17:29:34 +0200 Subject: [PATCH 504/645] CVE-2020-25717: s3:winbindd: make sure we default to r->out.authoritative = true We need to make sure that temporary failures don't trigger a fallback to the local SAM that silently ignores the domain name part for users. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/winbindd/winbindd_dual_srv.c | 7 +++++++ source3/winbindd/winbindd_irpc.c | 7 +++++++ source3/winbindd/winbindd_pam.c | 15 +++++++++++---- source3/winbindd/winbindd_pam_auth_crap.c | 9 ++++++++- source3/winbindd/winbindd_util.c | 7 +++++++ 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index fc30cb998fa..2ef62f8ae22 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -934,6 +934,13 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p, union netr_Validation *validation = NULL; bool interactive = false; + /* + * Make sure we start with authoritative=true, + * it will only set to false if we don't know the + * domain. + */ + r->out.authoritative = true; + domain = wb_child_domain(); if (domain == NULL) { return NT_STATUS_REQUEST_NOT_ACCEPTED; diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c index fda29c7e702..12f4554f9b6 100644 --- a/source3/winbindd/winbindd_irpc.c +++ b/source3/winbindd/winbindd_irpc.c @@ -141,6 +141,13 @@ static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg, const char *target_domain_name = NULL; const char *account_name = NULL; + /* + * Make sure we start with authoritative=true, + * it will only set to false if we don't know the + * domain. + */ + req->out.authoritative = true; + switch (req->in.logon_level) { case NetlogonInteractiveInformation: case NetlogonServiceInformation: diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 94416498be7..90d83083b87 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1798,7 +1798,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon( { fstring name_namespace, name_domain, name_user; NTSTATUS result; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags = 0; uint16_t validation_level = 0; union netr_Validation *validation = NULL; @@ -2452,6 +2452,13 @@ done: result = NT_STATUS_NO_LOGON_SERVERS; } + /* + * Here we don't alter + * state->response->data.auth.authoritative based + * on the servers response + * as we don't want a fallback to the local sam + * for interactive PAM logons + */ set_auth_errors(state->response, result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", @@ -2666,7 +2673,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, const char *name_domain = NULL; const char *workstation; uint64_t logon_id = 0; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags = 0; uint16_t validation_level; union netr_Validation *validation = NULL; @@ -2739,7 +2746,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, &validation_level, &validation); if (!NT_STATUS_IS_OK(result)) { - state->response->data.auth.authoritative = authoritative; goto done; } @@ -2771,7 +2777,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, "from firewalled domain [%s]\n", info3->base.account_name.string, info3->base.logon_domain.string); - state->response->data.auth.authoritative = true; result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; goto done; } @@ -2793,6 +2798,8 @@ done: } set_auth_errors(state->response, result); + state->response->data.auth.authoritative = authoritative; + /* * Log the winbind pam authentication, the logon_id will tie this to * any of the logons invoked from this request. diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index b7912db43df..40cab81b5ea 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -24,6 +24,7 @@ struct winbindd_pam_auth_crap_state { struct winbindd_response *response; + bool authoritative; uint32_t flags; }; @@ -45,7 +46,7 @@ struct tevent_req *winbindd_pam_auth_crap_send( if (req == NULL) { return NULL; } - + state->authoritative = true; state->flags = request->flags; if (state->flags & WBFLAG_PAM_AUTH_PAC) { @@ -124,6 +125,11 @@ struct tevent_req *winbindd_pam_auth_crap_send( domain = find_auth_domain(request->flags, auth_domain); if (domain == NULL) { + /* + * We don't know the domain so + * we're not authoritative + */ + state->authoritative = false; tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); return tevent_req_post(req, ev); } @@ -184,6 +190,7 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req, if (tevent_req_is_nterror(req, &status)) { set_auth_errors(response, status); + response->data.auth.authoritative = state->authoritative; return status; } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index bec706f87de..ef197310fa0 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -2092,6 +2092,13 @@ void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) { + /* + * Make sure we start with authoritative=true, + * it will only set to false if we don't know the + * domain. + */ + resp->data.auth.authoritative = true; + resp->data.auth.nt_status = NT_STATUS_V(result); fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); -- 2.25.1 From 9fa9187e53515466b1af29162807ccece3fde125 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Oct 2021 17:29:34 +0200 Subject: [PATCH 505/645] CVE-2020-25717: s4:auth/ntlm: make sure auth_check_password() defaults to r->out.authoritative = true We need to make sure that temporary failures don't trigger a fallback to the local SAM that silently ignores the domain name part for users. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source4/auth/ntlm/auth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c index 1aa2e3b065f..e0c4436343c 100644 --- a/source4/auth/ntlm/auth.c +++ b/source4/auth/ntlm/auth.c @@ -169,6 +169,11 @@ _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx, /*TODO: create a new event context here! */ ev = auth_ctx->event_ctx; + /* + * We are authoritative by default + */ + *pauthoritative = 1; + subreq = auth_check_password_send(mem_ctx, ev, auth_ctx, -- 2.25.1 From a14ab252a6e95f26c923582e45eeb0f0a205f8e6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 506/645] CVE-2020-25717: s4:torture: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source4/torture/rpc/samlogon.c | 4 ++-- source4/torture/rpc/schannel.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index 76933b8869e..703e25fe3c5 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -1407,7 +1407,7 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, union netr_LogonLevel logon; union netr_Validation validation; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags = 0; ZERO_STRUCT(logon); @@ -1520,7 +1520,7 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, union netr_LogonLevel logon; union netr_Validation validation; - uint8_t authoritative = 0; + uint8_t authoritative = 1; struct dcerpc_binding_handle *b = p->binding_handle; ZERO_STRUCT(a); diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index fff0b1aacbd..6dc58c86076 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -50,7 +50,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx, struct netr_NetworkInfo ninfo; union netr_LogonLevel logon; union netr_Validation validation; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t _flags = 0; DATA_BLOB names_blob, chal, lm_resp, nt_resp; int i; -- 2.25.1 From 59084c4e4d8fb91a7ecde4ac68962fc670c1d3a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 507/645] CVE-2020-25717: s4:smb_server: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source4/smb_server/smb/sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index 13f13934412..5e817eecd4b 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -102,7 +102,7 @@ static void sesssetup_old_send(struct tevent_req *subreq) struct auth_session_info *session_info; struct smbsrv_session *smb_sess; NTSTATUS status; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags; status = auth_check_password_recv(subreq, req, &user_info_dc, @@ -243,7 +243,7 @@ static void sesssetup_nt1_send(struct tevent_req *subreq) struct auth_user_info_dc *user_info_dc = NULL; struct auth_session_info *session_info; struct smbsrv_session *smb_sess; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags; NTSTATUS status; -- 2.25.1 From 1e4b11b2cb3d7e91a96d01b1eb0ae21880d21e7c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 508/645] CVE-2020-25717: s4:auth_simple: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source4/auth/ntlm/auth_simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c index 8df160cefc3..8301aec519c 100644 --- a/source4/auth/ntlm/auth_simple.c +++ b/source4/auth/ntlm/auth_simple.c @@ -150,7 +150,7 @@ static void authenticate_ldap_simple_bind_done(struct tevent_req *subreq) const struct tsocket_address *local_address = user_info->local_host; const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE; struct auth_user_info_dc *user_info_dc = NULL; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags = 0; NTSTATUS nt_status; -- 2.25.1 From 144feb8cd64e41fd2b3e6443d8337497e59bee40 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 509/645] CVE-2020-25717: s3:ntlm_auth: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/utils/ntlm_auth.c | 4 ++-- source3/utils/ntlm_auth_diagnostics.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 7f8d2688978..1d22a48c57c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1926,7 +1926,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod TALLOC_FREE(mem_ctx); } else { - uint8_t authoritative = 0; + uint8_t authoritative = 1; if (!domain) { domain = smb_xstrdup(get_winbind_domain()); @@ -2442,7 +2442,7 @@ static bool check_auth_crap(void) char *hex_lm_key; char *hex_user_session_key; char *error_string; - uint8_t authoritative = 0; + uint8_t authoritative = 1; setbuf(stdout, NULL); diff --git a/source3/utils/ntlm_auth_diagnostics.c b/source3/utils/ntlm_auth_diagnostics.c index 41591a8de33..fc0fc19bacb 100644 --- a/source3/utils/ntlm_auth_diagnostics.c +++ b/source3/utils/ntlm_auth_diagnostics.c @@ -54,7 +54,7 @@ static bool test_lm_ntlm_broken(enum ntlm_break break_which) DATA_BLOB lm_response = data_blob(NULL, 24); DATA_BLOB nt_response = data_blob(NULL, 24); DATA_BLOB session_key = data_blob(NULL, 16); - uint8_t authoritative = 0; + uint8_t authoritative = 1; uchar lm_key[8]; uchar user_session_key[16]; uchar lm_hash[16]; @@ -177,7 +177,7 @@ static bool test_ntlm_in_lm(void) NTSTATUS nt_status; uint32_t flags = 0; DATA_BLOB nt_response = data_blob(NULL, 24); - uint8_t authoritative = 0; + uint8_t authoritative = 1; uchar lm_key[8]; uchar lm_hash[16]; uchar user_session_key[16]; @@ -245,7 +245,7 @@ static bool test_ntlm_in_both(void) uint32_t flags = 0; DATA_BLOB nt_response = data_blob(NULL, 24); DATA_BLOB session_key = data_blob(NULL, 16); - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint8_t lm_key[8]; uint8_t lm_hash[16]; uint8_t user_session_key[16]; @@ -322,7 +322,7 @@ static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which) DATA_BLOB lmv2_response = data_blob_null; DATA_BLOB ntlmv2_session_key = data_blob_null; DATA_BLOB names_blob = NTLMv2_generate_names_blob(NULL, get_winbind_netbios_name(), get_winbind_domain()); - uint8_t authoritative = 0; + uint8_t authoritative = 1; uchar user_session_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; @@ -452,7 +452,7 @@ static bool test_plaintext(enum ntlm_break break_which) char *password; smb_ucs2_t *nt_response_ucs2; size_t converted_size; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uchar user_session_key[16]; uchar lm_key[16]; static const uchar zeros[8] = { 0, }; -- 2.25.1 From 7aa8687162d6b72b58ab9b1930139a1d95db1e53 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 510/645] CVE-2020-25717: s3:torture: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/torture/pdbtest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c index 5d74aa9ab78..b300504c4cb 100644 --- a/source3/torture/pdbtest.c +++ b/source3/torture/pdbtest.c @@ -277,7 +277,7 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry) struct netr_SamInfo6 *info6_wbc = NULL; NTSTATUS status; bool ok; - uint8_t authoritative = 0; + uint8_t authoritative = 1; int rc; rc = SMBOWFencrypt(pdb_get_nt_passwd(pdb_entry), challenge_8, -- 2.25.1 From 18113fc323a540d55a098429e4dda087d96ac962 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 511/645] CVE-2020-25717: s3:rpcclient: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/rpcclient/cmd_netlogon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index d5c1b91f2be..4ea63e40b8d 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -496,7 +496,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, uint32_t logon_param = 0; const char *workstation = NULL; struct netr_SamInfo3 *info3 = NULL; - uint8_t authoritative = 0; + uint8_t authoritative = 1; uint32_t flags = 0; uint16_t validation_level; union netr_Validation *validation = NULL; -- 2.25.1 From 7c43de94e7deae8a2cc290ed75d9e63da79d8ab5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 512/645] CVE-2020-25717: s3:auth: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 2 +- source3/auth/auth_samba4.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 8af74481034..8044e6d8af0 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -416,7 +416,7 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context, { NTSTATUS nt_status; void *server_info; - uint8_t authoritative = 0; + uint8_t authoritative = 1; struct tevent_context *ev = NULL; struct tevent_req *subreq = NULL; bool ok; diff --git a/source3/auth/auth_samba4.c b/source3/auth/auth_samba4.c index 418e2cfa56d..d964160414f 100644 --- a/source3/auth/auth_samba4.c +++ b/source3/auth/auth_samba4.c @@ -119,7 +119,7 @@ static NTSTATUS check_samba4_security( NTSTATUS nt_status; struct auth_user_info_dc *user_info_dc; struct auth4_context *auth4_context; - uint8_t authoritative = 0; + uint8_t authoritative = 1; struct auth_serversupplied_info *server_info = NULL; nt_status = make_auth4_context_s4(auth_context, mem_ctx, &auth4_context); -- 2.25.1 From 95433feb122b68f0edc355c60f5de6c49e02f5b0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Oct 2021 17:42:41 +0200 Subject: [PATCH 513/645] CVE-2020-25717: auth/ntlmssp: start with authoritative = 1 This is not strictly needed, but makes it easier to audit that we don't miss important places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- auth/ntlmssp/ntlmssp_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c index 001238278d7..939aa0ef4aa 100644 --- a/auth/ntlmssp/ntlmssp_server.c +++ b/auth/ntlmssp/ntlmssp_server.c @@ -799,7 +799,7 @@ static void ntlmssp_server_auth_done(struct tevent_req *subreq) struct gensec_security *gensec_security = state->gensec_security; struct gensec_ntlmssp_context *gensec_ntlmssp = state->gensec_ntlmssp; struct auth4_context *auth_context = gensec_security->auth_context; - uint8_t authoritative = 0; + uint8_t authoritative = 1; NTSTATUS status; status = auth_context->check_ntlm_password_recv(subreq, -- 2.25.1 From 043497192db3aee024cf3154c01795fd6ba1ac40 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 28 Sep 2021 10:43:40 +0200 Subject: [PATCH 514/645] CVE-2020-25717: loadparm: Add new parameter "min domain uid" BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Samuel Cabrero Signed-off-by: Stefan Metzmacher [abartlet@samba.org Backported from master/4.15 due to conflicts with other new parameters] --- docs-xml/smbdotconf/security/mindomainuid.xml | 17 +++++++++++++++++ docs-xml/smbdotconf/winbind/idmapconfig.xml | 4 ++++ lib/param/loadparm.c | 4 ++++ source3/param/loadparm.c | 2 ++ 4 files changed, 27 insertions(+) create mode 100644 docs-xml/smbdotconf/security/mindomainuid.xml diff --git a/docs-xml/smbdotconf/security/mindomainuid.xml b/docs-xml/smbdotconf/security/mindomainuid.xml new file mode 100644 index 00000000000..46ae795d730 --- /dev/null +++ b/docs-xml/smbdotconf/security/mindomainuid.xml @@ -0,0 +1,17 @@ + + + + The integer parameter specifies the minimum uid allowed when mapping a + local account to a domain account. + + + + Note that this option interacts with the configured idmap ranges! + + + +1000 + diff --git a/docs-xml/smbdotconf/winbind/idmapconfig.xml b/docs-xml/smbdotconf/winbind/idmapconfig.xml index 1374040fb29..f70f11df757 100644 --- a/docs-xml/smbdotconf/winbind/idmapconfig.xml +++ b/docs-xml/smbdotconf/winbind/idmapconfig.xml @@ -80,6 +80,9 @@ authoritative for a unix ID to SID mapping, so it must be set for each individually configured domain and for the default configuration. The configured ranges must be mutually disjoint. + + + Note that the low value interacts with the option! @@ -115,4 +118,5 @@ +min domain uid diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 8bca0ee632a..3e53e8c235a 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -3048,6 +3048,10 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter( lp_ctx, "ldap max search request size", "256000"); + lpcfg_do_global_parameter(lp_ctx, + "min domain uid", + "1000"); + for (i = 0; parm_table[i].label; i++) { if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) { lp_ctx->flags[i] |= FLAG_DEFAULT; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 64e7afb5d86..813268b72c8 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -959,6 +959,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) Globals.ldap_max_authenticated_request_size = 16777216; Globals.ldap_max_search_request_size = 256000; + Globals.min_domain_uid = 1000; + /* Now put back the settings that were set with lp_set_cmdline() */ apply_lp_set_cmdline(); } -- 2.25.1 From 337938c270ef344b82c66ff37632b8f9e79d8d97 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 5 Oct 2021 16:56:06 +0200 Subject: [PATCH 515/645] CVE-2020-25717: selftest: Add a test for the new 'min domain uid' parameter BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Samuel Cabrero Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett [abartlet@samba.org Fixed knowfail per instruction from metze] --- .../samba/tests/krb5/test_min_domain_uid.py | 121 ++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail.d/min_domain_uid | 1 + source4/selftest/tests.py | 7 + 4 files changed, 130 insertions(+) create mode 100755 python/samba/tests/krb5/test_min_domain_uid.py create mode 100644 selftest/knownfail.d/min_domain_uid diff --git a/python/samba/tests/krb5/test_min_domain_uid.py b/python/samba/tests/krb5/test_min_domain_uid.py new file mode 100755 index 00000000000..77414b239f0 --- /dev/null +++ b/python/samba/tests/krb5/test_min_domain_uid.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Samuel Cabrero 2021 +# +# 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 sys +import os +import pwd +import ctypes + +from samba.tests import env_get_var_value +from samba.samba3 import libsmb_samba_internal as libsmb +from samba.samba3 import param as s3param +from samba import NTSTATUSError, ntstatus + +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.credentials import MUST_USE_KERBEROS, DONT_USE_KERBEROS + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +class SmbMinDomainUid(KDCBaseTest): + """Test for SMB authorization without NSS winbind. In such setup domain + accounts are mapped to local accounts using the 'username map' option. + """ + + def setUp(self): + super(KDCBaseTest, self).setUp() + + # Create a user account, along with a Kerberos credentials cache file + # where the service ticket authenticating the user are stored. + self.samdb = self.get_samdb() + + self.mach_name = env_get_var_value('SERVER') + self.user_name = "root" + self.service = "cifs" + self.share = "tmp" + + # Create the user account. + (self.user_creds, _) = self.create_account(self.samdb, self.user_name) + + # Build the global inject file path + server_conf = env_get_var_value('SMB_CONF_PATH') + server_conf_dir = os.path.dirname(server_conf) + self.global_inject = os.path.join(server_conf_dir, "global_inject.conf") + + def _test_min_uid(self, creds): + # Assert unix root uid is less than 'idmap config ADDOMAIN' minimum + s3_lp = s3param.get_context() + s3_lp.load(self.get_lp().configfile) + + domain_range = s3_lp.get("idmap config * : range").split('-') + domain_range_low = int(domain_range[0]) + unix_root_pw = pwd.getpwnam(self.user_name) + self.assertLess(unix_root_pw.pw_uid, domain_range_low) + self.assertLess(unix_root_pw.pw_gid, domain_range_low) + + conn = libsmb.Conn(self.mach_name, self.share, lp=s3_lp, creds=creds) + # Disconnect + conn = None + + # Restrict access to local root account uid + with open(self.global_inject, 'w') as f: + f.write("min domain uid = %s\n" % (unix_root_pw.pw_uid + 1)) + + with self.assertRaises(NTSTATUSError) as cm: + conn = libsmb.Conn(self.mach_name, + self.share, + lp=s3_lp, + creds=creds) + code = ctypes.c_uint32(cm.exception.args[0]).value + self.assertEqual(code, ntstatus.NT_STATUS_INVALID_TOKEN) + + # check that the local root account uid is now allowed + with open(self.global_inject, 'w') as f: + f.write("min domain uid = %s\n" % unix_root_pw.pw_uid) + + conn = libsmb.Conn(self.mach_name, self.share, lp=s3_lp, creds=creds) + # Disconnect + conn = None + + with open(self.global_inject, 'w') as f: + f.truncate() + + def test_min_domain_uid_krb5(self): + krb5_state = self.user_creds.get_kerberos_state() + self.user_creds.set_kerberos_state(MUST_USE_KERBEROS) + ret = self._test_min_uid(self.user_creds) + self.user_creds.set_kerberos_state(krb5_state) + return ret + + def test_min_domain_uid_ntlmssp(self): + krb5_state = self.user_creds.get_kerberos_state() + self.user_creds.set_kerberos_state(DONT_USE_KERBEROS) + ret = self._test_min_uid(self.user_creds) + self.user_creds.set_kerberos_state(krb5_state) + return ret + + def tearDown(self): + # Ensure no leftovers in global inject file + with open(self.global_inject, 'w') as f: + f.truncate() + + super(KDCBaseTest, self).tearDown() + +if __name__ == "__main__": + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 5cae7429985..048bd1c3099 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -106,6 +106,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/salt_tests.py', 'python/samba/tests/krb5/spn_tests.py', 'python/samba/tests/krb5/alias_tests.py', + 'python/samba/tests/krb5/test_min_domain_uid.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail.d/min_domain_uid b/selftest/knownfail.d/min_domain_uid new file mode 100644 index 00000000000..00bf75cd8af --- /dev/null +++ b/selftest/knownfail.d/min_domain_uid @@ -0,0 +1 @@ +^samba.tests.krb5.test_min_domain_uid.samba.*.SmbMinDomainUid.test_min_domain_uid_.*\(ad_member_no_nss_wb:local\) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index cb546127201..50c838f6098 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -800,6 +800,13 @@ planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", 'FAST_SUPPORT': have_fast_support, 'TKT_SIG_SUPPORT': tkt_sig_support }) +planoldpythontestsuite("ad_member_no_nss_wb:local", + "samba.tests.krb5.test_min_domain_uid", + environ={ + 'ADMIN_USERNAME': '$DC_USERNAME', + 'ADMIN_PASSWORD': '$DC_PASSWORD', + 'STRICT_CHECKING': '0' + }) for env in ["ad_dc", smbv1_disabled_testenv]: planoldpythontestsuite(env, "samba.tests.smb", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.25.1 From 46884e3c844825b28bdb6056c7080aacc4214fff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Oct 2021 19:57:18 +0200 Subject: [PATCH 516/645] CVE-2020-25717: s3:auth: let auth3_generate_session_info_pac() forward the low level errors Mapping everything to ACCESS_DENIED makes it hard to debug problems, which may happen because of our more restrictive behaviour in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 8044e6d8af0..86585ad690c 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -166,7 +166,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", nt_errstr(status))); - status = NT_STATUS_ACCESS_DENIED; + status = nt_status_squash(status); goto done; } -- 2.25.1 From 0ba7d50aed7059f001978eb44d1376047e1c1f8b Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 28 Sep 2021 10:45:11 +0200 Subject: [PATCH 517/645] CVE-2020-25717: s3:auth: Check minimum domain uid BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Samuel Cabrero Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett [abartlet@samba.org Removed knownfail on advice from metze] --- selftest/knownfail.d/min_domain_uid | 1 - source3/auth/auth_util.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/min_domain_uid diff --git a/selftest/knownfail.d/min_domain_uid b/selftest/knownfail.d/min_domain_uid deleted file mode 100644 index 00bf75cd8af..00000000000 --- a/selftest/knownfail.d/min_domain_uid +++ /dev/null @@ -1 +0,0 @@ -^samba.tests.krb5.test_min_domain_uid.samba.*.SmbMinDomainUid.test_min_domain_uid_.*\(ad_member_no_nss_wb:local\) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 39713df539f..a6b3262ff6b 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -2098,6 +2098,22 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, } } goto out; + } else if ((lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) && + !is_myname(domain) && pwd->pw_uid < lp_min_domain_uid()) { + /* + * !is_myname(domain) because when smbd starts tries to setup + * the guest user info, calling this function with nobody + * username. Nobody is usually uid 65535 but it can be changed + * to a regular user with 'guest account' parameter + */ + nt_status = NT_STATUS_INVALID_TOKEN; + DBG_NOTICE("Username '%s%s%s' is invalid on this system, " + "it does not meet 'min domain uid' " + "restriction (%u < %u): %s\n", + nt_domain, lp_winbind_separator(), nt_username, + pwd->pw_uid, lp_min_domain_uid(), + nt_errstr(nt_status)); + goto out; } result = make_server_info(tmp_ctx); -- 2.25.1 From 8b92d89382ad10c7715ddf59416c7ad1a79494c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Oct 2021 17:40:30 +0200 Subject: [PATCH 518/645] CVE-2020-25717: s3:auth: we should not try to autocreate the guest account We should avoid autocreation of users as much as possible. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/user_krb5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c index 8998f9c8f8a..074e8c7eb71 100644 --- a/source3/auth/user_krb5.c +++ b/source3/auth/user_krb5.c @@ -155,7 +155,7 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, if (!fuser) { return NT_STATUS_NO_MEMORY; } - pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); + pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false); } /* extra sanity check that the guest account is valid */ -- 2.25.1 From 331e2b729b69d6b5e7893b50a5e8a49888ae1ab5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Oct 2021 18:08:20 +0200 Subject: [PATCH 519/645] CVE-2020-25717: s3:auth: no longer let check_account() autocreate local users So far we autocreated local user accounts based on just the account_name (just ignoring any domain part). This only happens via a possible 'add user script', which is not typically defined on domain members and on NT4 DCs local users already exist in the local passdb anyway. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index a6b3262ff6b..6bdd45aee89 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1893,7 +1893,7 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain, return NT_STATUS_NO_MEMORY; } - passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true ); + passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false); if (!passwd) { DEBUG(3, ("Failed to find authenticated user %s via " "getpwnam(), denying access.\n", dom_user)); -- 2.25.1 From f4b3a5ca04d5b80cfef289bf26aeb2d3ad7da747 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 8 Oct 2021 12:33:16 +0200 Subject: [PATCH 520/645] CVE-2020-25717: s3:auth: remove fallbacks in smb_getpwnam() So far we tried getpwnam("DOMAIN\account") first and always did a fallback to getpwnam("account") completely ignoring the domain part, this just causes problems as we mix "DOMAIN1\account", "DOMAIN2\account", and "account"! As we require a running winbindd for domain member setups we should no longer do a fallback to just "account" for users served by winbindd! For users of the local SAM don't use this code path, as check_sam_security() doesn't call check_account(). The only case where smb_getpwnam("account") happens is when map_username() via ("username map [script]") mapped "DOMAIN\account" to something without '\', but that is explicitly desired by the admin. Note: use 'git show -w' BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Ralph Boehme Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ktest | 26 +++++++++++++ source3/auth/auth_util.c | 77 +++++++++++++++++++++----------------- 2 files changed, 68 insertions(+), 35 deletions(-) create mode 100644 selftest/knownfail.d/ktest diff --git a/selftest/knownfail.d/ktest b/selftest/knownfail.d/ktest new file mode 100644 index 00000000000..809612ba0b9 --- /dev/null +++ b/selftest/knownfail.d/ktest @@ -0,0 +1,26 @@ +^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2...lsa.LookupSidsReply.ktest +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5...rpcclient.ktest:local +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5...rpcclient.ktest:local +^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,connect...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,connect...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,packet...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,packet...lsa.LookupSidsReply.ktest +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,packet...rpcclient.ktest:local +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,packet...rpcclient.ktest:local +^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,sign...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,sign...lsa.LookupSidsReply.ktest +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,sign...rpcclient.ktest:local +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,sign...rpcclient.ktest:local +^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,seal...lsa.LookupSidsReply.ktest +^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,seal...lsa.LookupSidsReply.ktest +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,seal...rpcclient.ktest:local +^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,seal...rpcclient.ktest:local +^samba3.blackbox.smbclient_krb5.old.ccache..smbclient.ktest:local +^samba3.blackbox.smbclient_krb5.new.ccache..smbclient.ktest:local +^samba3.blackbox.smbclient_large_file..krb5.smbclient.large.posix.write.read.ktest:local +^samba3.blackbox.smbclient_large_file..krb5.cmp.of.read.and.written.files.ktest:local +^samba3.blackbox.smbclient_krb5.old.ccache.--client-protection=encrypt.smbclient.ktest:local +^samba3.blackbox.smbclient_krb5.new.ccache.--client-protection=encrypt.smbclient.ktest:local +^samba3.blackbox.smbclient_large_file.--client-protection=encrypt.krb5.smbclient.large.posix.write.read.ktest:local +^samba3.blackbox.smbclient_large_file.--client-protection=encrypt.krb5.cmp.of.read.and.written.files.ktest:local diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 6bdd45aee89..9f23a2d1a6a 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1928,7 +1928,7 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, { struct passwd *pw = NULL; char *p = NULL; - char *username = NULL; + const char *username = NULL; /* we only save a copy of the username it has been mangled by winbindd use default domain */ @@ -1947,48 +1947,55 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, /* code for a DOMAIN\user string */ if ( p ) { - pw = Get_Pwnam_alloc( mem_ctx, domuser ); - if ( pw ) { - /* make sure we get the case of the username correct */ - /* work around 'winbind use default domain = yes' */ - - if ( lp_winbind_use_default_domain() && - !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { - char *domain; - - /* split the domain and username into 2 strings */ - *p = '\0'; - domain = username; - - *p_save_username = talloc_asprintf(mem_ctx, - "%s%c%s", - domain, - *lp_winbind_separator(), - pw->pw_name); - if (!*p_save_username) { - TALLOC_FREE(pw); - return NULL; - } - } else { - *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); - } + const char *domain = NULL; - /* whew -- done! */ - return pw; + /* split the domain and username into 2 strings */ + *p = '\0'; + domain = username; + p++; + username = p; + + if (strequal(domain, get_global_sam_name())) { + /* + * This typically don't happen + * as check_sam_Security() + * don't call make_server_info_info3() + * and thus check_account(). + * + * But we better keep this. + */ + goto username_only; } - /* setup for lookup of just the username */ - /* remember that p and username are overlapping memory */ - - p++; - username = talloc_strdup(mem_ctx, p); - if (!username) { + pw = Get_Pwnam_alloc( mem_ctx, domuser ); + if (pw == NULL) { return NULL; } + /* make sure we get the case of the username correct */ + /* work around 'winbind use default domain = yes' */ + + if ( lp_winbind_use_default_domain() && + !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { + *p_save_username = talloc_asprintf(mem_ctx, + "%s%c%s", + domain, + *lp_winbind_separator(), + pw->pw_name); + if (!*p_save_username) { + TALLOC_FREE(pw); + return NULL; + } + } else { + *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); + } + + /* whew -- done! */ + return pw; + } /* just lookup a plain username */ - +username_only: pw = Get_Pwnam_alloc(mem_ctx, username); /* Create local user if requested but only if winbindd -- 2.25.1 From 7d850dee06447806db1d423b35184f7857a58535 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Sep 2021 13:13:52 +0200 Subject: [PATCH 521/645] CVE-2020-25717: s3:lib: add lp_allow_trusted_domains() logic to is_allowed_domain() is_allowed_domain() is a central place we already use to trigger NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, so we can add additional logic there. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/lib/util_names.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source3/lib/util_names.c b/source3/lib/util_names.c index efef88f4f7b..2dff6346267 100644 --- a/source3/lib/util_names.c +++ b/source3/lib/util_names.c @@ -203,5 +203,18 @@ bool is_allowed_domain(const char *domain_name) } } - return true; + if (lp_allow_trusted_domains()) { + return true; + } + + if (strequal(lp_workgroup(), domain_name)) { + return true; + } + + if (is_myname(domain_name)) { + return true; + } + + DBG_NOTICE("Not trusted domain '%s'\n", domain_name); + return false; } -- 2.25.1 From 683fe4aa0725d8f77ad8bccc47688d00af8a6cbc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Oct 2021 18:03:55 +0200 Subject: [PATCH 522/645] CVE-2020-25717: s3:auth: don't let create_local_token depend on !winbind_ping() We always require a running winbindd on a domain member, so we should better fail a request instead of silently alter the behaviour, which results in a different unix token, just because winbindd might be restarted. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_util.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 9f23a2d1a6a..b59cac88825 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -571,13 +571,11 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, } /* - * If winbind is not around, we can not make much use of the SIDs the - * domain controller provided us with. Likewise if the user name was - * mapped to some local unix user. + * If the user name was mapped to some local unix user, + * we can not make much use of the SIDs the + * domain controller provided us with. */ - - if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || - (server_info->nss_token)) { + if (server_info->nss_token) { char *found_username = NULL; status = create_token_from_username(session_info, server_info->unix_name, -- 2.25.1 From 116707f8536e2641ba5055731cdb657c01c0a031 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 11 Nov 2020 18:50:45 +0200 Subject: [PATCH 523/645] CVE-2020-25717: Add FreeIPA domain controller role As we want to reduce use of 'classic domain controller' role but FreeIPA relies on it internally, add a separate role to mark FreeIPA domain controller role. It means that role won't result in ROLE_STANDALONE. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Alexander Bokovoy Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- docs-xml/smbdotconf/security/serverrole.xml | 7 ++++ lib/param/loadparm_server_role.c | 2 ++ lib/param/param_table.c | 1 + lib/param/util.c | 1 + libcli/netlogon/netlogon.c | 2 +- libds/common/roles.h | 1 + source3/auth/auth.c | 3 ++ source3/auth/auth_sam.c | 14 ++++---- source3/include/smb_macros.h | 2 +- source3/lib/netapi/joindomain.c | 1 + source3/param/loadparm.c | 4 ++- source3/passdb/lookup_sid.c | 2 +- source3/passdb/machine_account_secrets.c | 7 ++-- source3/registry/reg_backend_prod_options.c | 1 + source3/rpc_server/dssetup/srv_dssetup_nt.c | 1 + source3/smbd/server.c | 2 +- source3/winbindd/winbindd_misc.c | 2 +- source3/winbindd/winbindd_util.c | 40 ++++++++++++++++----- source4/auth/ntlm/auth.c | 1 + source4/kdc/kdc-heimdal.c | 1 + source4/rpc_server/samr/dcesrv_samr.c | 2 ++ 21 files changed, 72 insertions(+), 25 deletions(-) diff --git a/docs-xml/smbdotconf/security/serverrole.xml b/docs-xml/smbdotconf/security/serverrole.xml index 9511c61c96d..b8b83a127b5 100644 --- a/docs-xml/smbdotconf/security/serverrole.xml +++ b/docs-xml/smbdotconf/security/serverrole.xml @@ -78,6 +78,13 @@ url="http://wiki.samba.org/index.php/Samba4/HOWTO">Samba4 HOWTO + SERVER ROLE = IPA DOMAIN CONTROLLER + + This mode of operation runs Samba in a hybrid mode for IPA + domain controller, providing forest trust to Active Directory. + This role requires special configuration performed by IPA installers + and should not be used manually by any administrator. + security diff --git a/lib/param/loadparm_server_role.c b/lib/param/loadparm_server_role.c index 7a6bc770723..a78d1ab9cf3 100644 --- a/lib/param/loadparm_server_role.c +++ b/lib/param/loadparm_server_role.c @@ -42,6 +42,7 @@ static const struct srv_role_tab { { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" }, { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" }, { ROLE_ACTIVE_DIRECTORY_DC, "ROLE_ACTIVE_DIRECTORY_DC" }, + { ROLE_IPA_DC, "ROLE_IPA_DC"}, { 0, NULL } }; @@ -140,6 +141,7 @@ bool lp_is_security_and_server_role_valid(int server_role, int security) case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: case ROLE_ACTIVE_DIRECTORY_DC: + case ROLE_IPA_DC: if (security == SEC_USER) { valid = true; } diff --git a/lib/param/param_table.c b/lib/param/param_table.c index 47b85de1f87..780252017d2 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -111,6 +111,7 @@ static const struct enum_list enum_server_role[] = { {ROLE_ACTIVE_DIRECTORY_DC, "active directory domain controller"}, {ROLE_ACTIVE_DIRECTORY_DC, "domain controller"}, {ROLE_ACTIVE_DIRECTORY_DC, "dc"}, + {ROLE_IPA_DC, "IPA primary domain controller"}, {-1, NULL} }; diff --git a/lib/param/util.c b/lib/param/util.c index cd8e74b9d8f..9a0fc102de8 100644 --- a/lib/param/util.c +++ b/lib/param/util.c @@ -255,6 +255,7 @@ const char *lpcfg_sam_name(struct loadparm_context *lp_ctx) case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: case ROLE_ACTIVE_DIRECTORY_DC: + case ROLE_IPA_DC: return lpcfg_workgroup(lp_ctx); default: return lpcfg_netbios_name(lp_ctx); diff --git a/libcli/netlogon/netlogon.c b/libcli/netlogon/netlogon.c index 239503e85b6..59af460dc4e 100644 --- a/libcli/netlogon/netlogon.c +++ b/libcli/netlogon/netlogon.c @@ -93,7 +93,7 @@ NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, if (ndr->offset < ndr->data_size) { TALLOC_FREE(ndr); /* - * We need to handle a bug in FreeIPA (at least <= 4.1.2). + * We need to handle a bug in IPA (at least <= 4.1.2). * * They include the ip address information without setting * NETLOGON_NT_VERSION_5EX_WITH_IP, while using diff --git a/libds/common/roles.h b/libds/common/roles.h index 4772c8d7d3f..03ba1915b21 100644 --- a/libds/common/roles.h +++ b/libds/common/roles.h @@ -33,6 +33,7 @@ enum server_role { /* not in samr.idl */ ROLE_ACTIVE_DIRECTORY_DC = 4, + ROLE_IPA_DC = 5, /* To determine the role automatically, this is not a valid role */ ROLE_AUTO = 100 diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 12f7917b38d..4944c0fee1a 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -542,6 +542,7 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx, break; case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: + case ROLE_IPA_DC: role = "'DC'"; methods = "anonymous sam winbind sam_ignoredomain"; break; @@ -573,6 +574,7 @@ NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx, switch (lp_server_role()) { case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: + case ROLE_IPA_DC: methods = "sam_netlogon3 winbind"; break; @@ -594,6 +596,7 @@ NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx, case ROLE_DOMAIN_MEMBER: case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: + case ROLE_IPA_DC: methods = "sam"; break; case ROLE_ACTIVE_DIRECTORY_DC: diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index e8e0d543f8c..a2ce1013975 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -143,12 +143,13 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context, break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: if (!is_local_name && !is_my_domain) { /* If we are running on a DC that has PASSDB module with domain * information, check if DNS forest name is matching the domain - * name. This is the case of FreeIPA domain controller when - * trusted AD DCs attempt to authenticate FreeIPA users using - * the forest root domain (which is the only domain in FreeIPA). + * name. This is the case of IPA domain controller when + * trusted AD DCs attempt to authenticate IPA users using + * the forest root domain (which is the only domain in IPA). */ struct pdb_domain_info *dom_info = NULL; @@ -234,6 +235,7 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context, switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: break; default: DBG_ERR("Invalid server role\n"); @@ -252,9 +254,9 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context, if (!is_my_domain) { /* If we are running on a DC that has PASSDB module with domain * information, check if DNS forest name is matching the domain - * name. This is the case of FreeIPA domain controller when - * trusted AD DCs attempt to authenticate FreeIPA users using - * the forest root domain (which is the only domain in FreeIPA). + * name. This is the case of IPA domain controller when + * trusted AD DCs attempt to authenticate IPA users using + * the forest root domain (which is the only domain in IPA). */ struct pdb_domain_info *dom_info = NULL; dom_info = pdb_get_domain_info(mem_ctx); diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 266c17427e8..105c92fbd24 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -205,7 +205,7 @@ copy an IP address from one buffer to another Check to see if we are a DC for this domain *****************************************************************************/ -#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) +#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_server_role() == ROLE_IPA_DC) #define IS_AD_DC (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) /* diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c index f2d36fc00db..d1710c4b938 100644 --- a/source3/lib/netapi/joindomain.c +++ b/source3/lib/netapi/joindomain.c @@ -375,6 +375,7 @@ WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx, case ROLE_DOMAIN_MEMBER: case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: *r->out.name_type = NetSetupDomainName; break; case ROLE_STANDALONE: diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 813268b72c8..cd1c307c4cc 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -4404,6 +4404,7 @@ int lp_default_server_announce(void) default_server_announce |= SV_TYPE_DOMAIN_MEMBER; break; case ROLE_DOMAIN_PDC: + case ROLE_IPA_DC: default_server_announce |= SV_TYPE_DOMAIN_CTRL; break; case ROLE_DOMAIN_BDC: @@ -4429,7 +4430,8 @@ int lp_default_server_announce(void) bool lp_domain_master(void) { if (Globals._domain_master == Auto) - return (lp_server_role() == ROLE_DOMAIN_PDC); + return (lp_server_role() == ROLE_DOMAIN_PDC || + lp_server_role() == ROLE_IPA_DC); return (bool)Globals._domain_master; } diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index eb8ddae4283..7c3e3b44980 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -121,7 +121,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* If we are running on a DC that has PASSDB module with domain * information, check if DNS forest name is matching the domain - * name. This is the case of FreeIPA domain controller when + * name. This is the case of IPA domain controller when * trusted AD DC looks up users found in a Global Catalog of * the forest root domain. */ if (!check_global_sam && (IS_DC)) { diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index f426d9da25e..96131c558d2 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -198,7 +198,8 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) dyn_guid = (struct GUID *)secrets_fetch(key, &size); if (!dyn_guid) { - if (lp_server_role() == ROLE_DOMAIN_PDC) { + if (lp_server_role() == ROLE_DOMAIN_PDC || + lp_server_role() == ROLE_IPA_DC) { new_guid = GUID_random(); if (!secrets_store_domain_guid(domain, &new_guid)) return False; @@ -314,9 +315,7 @@ static const char *trust_keystr(const char *domain) enum netr_SchannelType get_default_sec_channel(void) { - if (lp_server_role() == ROLE_DOMAIN_BDC || - lp_server_role() == ROLE_DOMAIN_PDC || - lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) { + if (IS_DC) { return SEC_CHAN_BDC; } else { return SEC_CHAN_WKSTA; diff --git a/source3/registry/reg_backend_prod_options.c b/source3/registry/reg_backend_prod_options.c index 655c587ac40..7bd3f324c37 100644 --- a/source3/registry/reg_backend_prod_options.c +++ b/source3/registry/reg_backend_prod_options.c @@ -40,6 +40,7 @@ static int prod_options_fetch_values(const char *key, struct regval_ctr *regvals switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: value_ascii = "LanmanNT"; break; case ROLE_STANDALONE: diff --git a/source3/rpc_server/dssetup/srv_dssetup_nt.c b/source3/rpc_server/dssetup/srv_dssetup_nt.c index 7e3efa8504e..aa896e15ac4 100644 --- a/source3/rpc_server/dssetup/srv_dssetup_nt.c +++ b/source3/rpc_server/dssetup/srv_dssetup_nt.c @@ -62,6 +62,7 @@ static WERROR fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, basic->domain = get_global_sam_name(); break; case ROLE_DOMAIN_PDC: + case ROLE_IPA_DC: basic->role = DS_ROLE_PRIMARY_DC; basic->domain = get_global_sam_name(); break; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 10ae5a42dac..864a9589353 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1963,7 +1963,7 @@ extern void build_options(bool screen); exit_daemon("smbd can not open secrets.tdb", EACCES); } - if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { + if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC || lp_server_role() == ROLE_IPA_DC) { struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers()); if (!open_schannel_session_store(NULL, lp_ctx)) { exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES); diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index d27ed76e81e..0e31fc6b65c 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -75,7 +75,7 @@ static char *get_trust_type_string(TALLOC_CTX *mem_ctx, case SEC_CHAN_BDC: { int role = lp_server_role(); - if (role == ROLE_DOMAIN_PDC) { + if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) { s = talloc_strdup(mem_ctx, "PDC"); if (s == NULL) { return NULL; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index ef197310fa0..1ae4a8d3ca3 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1251,15 +1251,37 @@ bool init_domain_list(void) secure_channel_type = SEC_CHAN_LOCAL; } - status = add_trusted_domain(get_global_sam_name(), - NULL, - get_global_sam_sid(), - LSA_TRUST_TYPE_DOWNLEVEL, - trust_flags, - 0, /* trust_attribs */ - secure_channel_type, - NULL, - &domain); + if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) { + /* This is IPA DC that presents itself as + * an Active Directory domain controller to trusted AD + * forests but in fact is a classic domain controller. + */ + trust_flags = NETR_TRUST_FLAG_PRIMARY; + trust_flags |= NETR_TRUST_FLAG_IN_FOREST; + trust_flags |= NETR_TRUST_FLAG_NATIVE; + trust_flags |= NETR_TRUST_FLAG_OUTBOUND; + trust_flags |= NETR_TRUST_FLAG_TREEROOT; + status = add_trusted_domain(pdb_domain_info->name, + pdb_domain_info->dns_domain, + &pdb_domain_info->sid, + LSA_TRUST_TYPE_UPLEVEL, + trust_flags, + LSA_TRUST_ATTRIBUTE_WITHIN_FOREST, + secure_channel_type, + NULL, + &domain); + TALLOC_FREE(pdb_domain_info); + } else { + status = add_trusted_domain(get_global_sam_name(), + NULL, + get_global_sam_sid(), + LSA_TRUST_TYPE_DOWNLEVEL, + trust_flags, + 0, /* trust_attribs */ + secure_channel_type, + NULL, + &domain); + } if (!NT_STATUS_IS_OK(status)) { DBG_ERR("Failed to add local SAM to " "domain to winbindd's internal list\n"); diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c index e0c4436343c..6302a60232d 100644 --- a/source4/auth/ntlm/auth.c +++ b/source4/auth/ntlm/auth.c @@ -736,6 +736,7 @@ const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context * case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: case ROLE_ACTIVE_DIRECTORY_DC: + case ROLE_IPA_DC: auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL); break; } diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c index ee4e1387def..28dadcb1fd5 100644 --- a/source4/kdc/kdc-heimdal.c +++ b/source4/kdc/kdc-heimdal.c @@ -276,6 +276,7 @@ static NTSTATUS kdc_task_init(struct task_server *task) return NT_STATUS_INVALID_DOMAIN_ROLE; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: task_server_terminate( task, "Cannot start KDC as a 'classic Samba' DC", false); return NT_STATUS_INVALID_DOMAIN_ROLE; diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 70f914bf14c..7345cac6bd6 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -573,6 +573,7 @@ static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: case ROLE_AUTO: return NT_STATUS_INTERNAL_ERROR; case ROLE_DOMAIN_MEMBER: @@ -721,6 +722,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state, break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: case ROLE_AUTO: return NT_STATUS_INTERNAL_ERROR; case ROLE_DOMAIN_MEMBER: -- 2.25.1 From 81881dc73e504447e81f6462dfed9a948784e31c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 5 Oct 2021 18:11:57 +0200 Subject: [PATCH 524/645] CVE-2020-25719 CVE-2020-25717: auth/gensec: always require a PAC in domain mode (DC or member) AD domains always provide a PAC unless UF_NO_AUTH_DATA_REQUIRED is set on the service account, which can only be explicitly configured, but that's an invalid configuration! We still try to support standalone servers in an MIT realm, as legacy setup. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett [jsutton@samba.org Removed knownfail entries] --- auth/gensec/gensec_util.c | 27 +++++++++++++++++++++++---- selftest/knownfail.d/no-pac | 4 ---- 2 files changed, 23 insertions(+), 8 deletions(-) delete mode 100644 selftest/knownfail.d/no-pac diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c index e185acc0c20..694661b53b5 100644 --- a/auth/gensec/gensec_util.c +++ b/auth/gensec/gensec_util.c @@ -25,6 +25,8 @@ #include "auth/gensec/gensec_internal.h" #include "auth/common_auth.h" #include "../lib/util/asn1.h" +#include "param/param.h" +#include "libds/common/roles.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -46,10 +48,27 @@ NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx, session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS; if (!pac_blob) { - if (gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) { - DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access\n", - principal_string)); - return NT_STATUS_ACCESS_DENIED; + enum server_role server_role = + lpcfg_server_role(gensec_security->settings->lp_ctx); + + /* + * For any domain setup (DC or member) we require having + * a PAC, as the service ticket comes from an AD DC, + * which will always provide a PAC, unless + * UF_NO_AUTH_DATA_REQUIRED is configured for our + * account, but that's just an invalid configuration, + * the admin configured for us! + * + * As a legacy case, we still allow kerberos tickets from an MIT + * realm, but only in standalone mode. In that mode we'll only + * ever accept a kerberos authentication with a keytab file + * being explicitly configured via the 'keytab method' option. + */ + if (server_role != ROLE_STANDALONE) { + DBG_WARNING("Unable to find PAC in ticket from %s, " + "failing to allow access\n", + principal_string); + return NT_STATUS_NO_IMPERSONATION_TOKEN; } DBG_NOTICE("Unable to find PAC for %s, resorting to local " "user lookup\n", principal_string); diff --git a/selftest/knownfail.d/no-pac b/selftest/knownfail.d/no-pac deleted file mode 100644 index 9723d581c2a..00000000000 --- a/selftest/knownfail.d/no-pac +++ /dev/null @@ -1,4 +0,0 @@ -^samba.tests.krb5.test_ccache.samba.tests.krb5.test_ccache.CcacheTests.test_ccache_no_pac -^samba.tests.krb5.test_ldap.samba.tests.krb5.test_ldap.LdapTests.test_ldap_no_pac -^samba.tests.krb5.test_rpc.samba.tests.krb5.test_rpc.RpcTests.test_rpc_no_pac -^samba.tests.krb5.test_smb.samba.tests.krb5.test_smb.SmbTests.test_smb_no_pac -- 2.25.1 From c3849123e9b183103781e6243f46a4575a071140 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 11 Oct 2021 23:17:19 +0200 Subject: [PATCH 525/645] CVE-2020-25719 CVE-2020-25717: s4:auth: remove unused auth_generate_session_info_principal() We'll require a PAC at the main gensec layer already. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source4/auth/auth.h | 8 ------ source4/auth/ntlm/auth.c | 49 ++++-------------------------------- source4/auth/ntlm/auth_sam.c | 12 --------- 3 files changed, 5 insertions(+), 64 deletions(-) diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 3f9fb1ae3cb..6b7db99cbe2 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -69,14 +69,6 @@ struct auth_operations { TALLOC_CTX *mem_ctx, struct auth_user_info_dc **interim_info, bool *authoritative); - - /* Lookup a 'session info interim' return based only on the principal or DN */ - NTSTATUS (*get_user_info_dc_principal)(TALLOC_CTX *mem_ctx, - struct auth4_context *auth_context, - const char *principal, - struct ldb_dn *user_dn, - struct auth_user_info_dc **interim_info); - uint32_t flags; }; struct auth_method_context { diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c index 6302a60232d..98283b0e241 100644 --- a/source4/auth/ntlm/auth.c +++ b/source4/auth/ntlm/auth.c @@ -86,48 +86,6 @@ _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t cha return NT_STATUS_OK; } -/**************************************************************************** -Used in the gensec_gssapi and gensec_krb5 server-side code, where the -PAC isn't available, and for tokenGroups in the DSDB stack. - - Supply either a principal or a DN -****************************************************************************/ -static NTSTATUS auth_generate_session_info_principal(struct auth4_context *auth_ctx, - TALLOC_CTX *mem_ctx, - const char *principal, - struct ldb_dn *user_dn, - uint32_t session_info_flags, - struct auth_session_info **session_info) -{ - NTSTATUS nt_status; - struct auth_method_context *method; - struct auth_user_info_dc *user_info_dc; - - for (method = auth_ctx->methods; method; method = method->next) { - if (!method->ops->get_user_info_dc_principal) { - continue; - } - - nt_status = method->ops->get_user_info_dc_principal(mem_ctx, auth_ctx, principal, user_dn, &user_info_dc); - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { - continue; - } - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - nt_status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx, - user_info_dc, - user_info_dc->info->account_name, - session_info_flags, session_info); - talloc_free(user_info_dc); - - return nt_status; - } - - return NT_STATUS_NOT_IMPLEMENTED; -} - /** * Check a user's Plaintext, LM or NTLM password. * (sync version) @@ -626,8 +584,11 @@ static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx, TALLOC_CTX *tmp_ctx; if (!pac_blob) { - return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name, - NULL, session_info_flags, session_info); + /* + * This should already be catched at the main + * gensec layer, but better check twice + */ + return NT_STATUS_INTERNAL_ERROR; } tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context"); diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index e4ebeae7523..e80b1e82fec 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -937,22 +937,11 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx, return NT_STATUS_OK; } -/* Wrapper for the auth subsystem pointer */ -static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx, - struct auth4_context *auth_context, - const char *principal, - struct ldb_dn *user_dn, - struct auth_user_info_dc **user_info_dc) -{ - return authsam_get_user_info_dc_principal(mem_ctx, auth_context->lp_ctx, auth_context->sam_ctx, - principal, user_dn, user_info_dc); -} static const struct auth_operations sam_ignoredomain_ops = { .name = "sam_ignoredomain", .want_check = authsam_ignoredomain_want_check, .check_password_send = authsam_check_password_send, .check_password_recv = authsam_check_password_recv, - .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper, }; static const struct auth_operations sam_ops = { @@ -960,7 +949,6 @@ static const struct auth_operations sam_ops = { .want_check = authsam_want_check, .check_password_send = authsam_check_password_send, .check_password_recv = authsam_check_password_recv, - .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper, }; _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *); -- 2.25.1 From b45f1a4fa026731be701b8518989a1de74000941 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Sep 2021 12:27:28 +0200 Subject: [PATCH 526/645] CVE-2020-25717: s3:ntlm_auth: fix memory leaks in ntlm_auth_generate_session_info_pac() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/utils/ntlm_auth.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 1d22a48c57c..e6efdfcec5c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -817,23 +817,27 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c if (!p) { DEBUG(3, ("[%s] Doesn't look like a valid principal\n", princ_name)); - return NT_STATUS_LOGON_FAILURE; + status = NT_STATUS_LOGON_FAILURE; + goto done; } user = talloc_strndup(mem_ctx, princ_name, p - princ_name); if (!user) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } realm = talloc_strdup(talloc_tos(), p + 1); if (!realm) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } if (!strequal(realm, lp_realm())) { DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); if (!lp_allow_trusted_domains()) { - return NT_STATUS_LOGON_FAILURE; + status = NT_STATUS_LOGON_FAILURE; + goto done; } } @@ -841,7 +845,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c domain = talloc_strdup(mem_ctx, logon_info->info3.base.logon_domain.string); if (!domain) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } DEBUG(10, ("Domain is [%s] (using PAC)\n", domain)); } else { @@ -871,7 +876,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c domain = talloc_strdup(mem_ctx, realm); } if (!domain) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto done; } DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain)); } -- 2.25.1 From 411dd8cbe94d06ae35c39c507451a000e8635cd8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Sep 2021 12:44:01 +0200 Subject: [PATCH 527/645] CVE-2020-25717: s3:ntlm_auth: let ntlm_auth_generate_session_info_pac() base the name on the PAC LOGON_INFO only BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/utils/ntlm_auth.c | 91 ++++++++++++--------------------------- 1 file changed, 28 insertions(+), 63 deletions(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index e6efdfcec5c..5541c58350b 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -789,10 +789,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c struct PAC_LOGON_INFO *logon_info = NULL; char *unixuser; NTSTATUS status; - char *domain = NULL; - char *realm = NULL; - char *user = NULL; - char *p; + const char *domain = ""; + const char *user = ""; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { @@ -809,79 +807,46 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c if (!NT_STATUS_IS_OK(status)) { goto done; } - } - - DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); - - p = strchr_m(princ_name, '@'); - if (!p) { - DEBUG(3, ("[%s] Doesn't look like a valid principal\n", - princ_name)); - status = NT_STATUS_LOGON_FAILURE; + } else { + status = NT_STATUS_ACCESS_DENIED; + DBG_WARNING("Kerberos ticket for[%s] has no PAC: %s\n", + princ_name, nt_errstr(status)); goto done; } - user = talloc_strndup(mem_ctx, princ_name, p - princ_name); - if (!user) { - status = NT_STATUS_NO_MEMORY; - goto done; + if (logon_info->info3.base.account_name.string != NULL) { + user = logon_info->info3.base.account_name.string; + } else { + user = ""; + } + if (logon_info->info3.base.logon_domain.string != NULL) { + domain = logon_info->info3.base.logon_domain.string; + } else { + domain = ""; } - realm = talloc_strdup(talloc_tos(), p + 1); - if (!realm) { - status = NT_STATUS_NO_MEMORY; + if (strlen(user) == 0 || strlen(domain) == 0) { + status = NT_STATUS_ACCESS_DENIED; + DBG_WARNING("Kerberos ticket for[%s] has invalid " + "account_name[%s]/logon_domain[%s]: %s\n", + princ_name, + logon_info->info3.base.account_name.string, + logon_info->info3.base.logon_domain.string, + nt_errstr(status)); goto done; } - if (!strequal(realm, lp_realm())) { - DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); + DBG_NOTICE("Kerberos ticket principal name is [%s] " + "account_name[%s]/logon_domain[%s]\n", + princ_name, user, domain); + + if (!strequal(domain, lp_workgroup())) { if (!lp_allow_trusted_domains()) { status = NT_STATUS_LOGON_FAILURE; goto done; } } - if (logon_info && logon_info->info3.base.logon_domain.string) { - domain = talloc_strdup(mem_ctx, - logon_info->info3.base.logon_domain.string); - if (!domain) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - DEBUG(10, ("Domain is [%s] (using PAC)\n", domain)); - } else { - - /* If we have winbind running, we can (and must) shorten the - username by using the short netbios name. Otherwise we will - have inconsistent user names. With Kerberos, we get the - fully qualified realm, with ntlmssp we get the short - name. And even w2k3 does use ntlmssp if you for example - connect to an ip address. */ - - wbcErr wbc_status; - struct wbcDomainInfo *info = NULL; - - DEBUG(10, ("Mapping [%s] to short name using winbindd\n", - realm)); - - wbc_status = wbcDomainInfo(realm, &info); - - if (WBC_ERROR_IS_OK(wbc_status)) { - domain = talloc_strdup(mem_ctx, - info->short_name); - wbcFreeMemory(info); - } else { - DEBUG(3, ("Could not find short name: %s\n", - wbcErrorString(wbc_status))); - domain = talloc_strdup(mem_ctx, realm); - } - if (!domain) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain)); - } - unixuser = talloc_asprintf(tmp_ctx, "%s%c%s", domain, winbind_separator(), user); if (!unixuser) { status = NT_STATUS_NO_MEMORY; -- 2.25.1 From c28b87b90ef9a27d7e74fb2abd38dde26b876eee Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Oct 2021 19:42:20 +0200 Subject: [PATCH 528/645] CVE-2020-25717: s3:auth: let auth3_generate_session_info_pac() delegate everything to make_server_info_wbcAuthUserInfo() This consolidates the code paths used for NTLMSSP and Kerberos! I checked what we were already doing for NTLMSSP, which is this: a) source3/auth/auth_winbind.c calls wbcAuthenticateUserEx() b) as a domain member we require a valid response from winbindd, otherwise we'll return NT_STATUS_NO_LOGON_SERVERS c) we call make_server_info_wbcAuthUserInfo(), which internally calls make_server_info_info3() d) auth_check_ntlm_password() calls smb_pam_accountcheck(unix_username, rhost), where rhost is only an ipv4 or ipv6 address (without reverse dns lookup) e) from auth3_check_password_send/auth3_check_password_recv() server_returned_info will be passed to auth3_generate_session_info(), triggered by gensec_session_info(), which means we'll call into create_local_token() in order to transform auth_serversupplied_info into auth_session_info. For Kerberos gensec_session_info() will call auth3_generate_session_info_pac() via the gensec_generate_session_info_pac() helper function. The current logic is this: a) gensec_generate_session_info_pac() is the function that evaluates the 'gensec:require_pac', which defaulted to 'no' before. b) auth3_generate_session_info_pac() called wbcAuthenticateUserEx() in order to pass the PAC blob to winbindd, but only to prime its cache, e.g. netsamlogon cache and others. Most failures were just ignored. c) If the PAC blob is available, it extracted the PAC_LOGON_INFO from it. d) Then we called the horrible get_user_from_kerberos_info() function: - It uses a first part of the tickets principal name (before the @) as username and combines that with the 'logon_info->base.logon_domain' if the logon_info (PAC) is present. - As a fallback without a PAC it's tries to ask winbindd for a mapping from realm to netbios domain name. - Finally is falls back to using the realm as netbios domain name With this information is builds 'userdomain+winbind_separator+useraccount' and calls map_username() followed by smb_getpwnam() with create=true, Note this is similar to the make_server_info_info3() => check_account() => smb_getpwnam() logic under 3. - It also calls smb_pam_accountcheck(), but may pass the reverse DNS lookup name instead of the ip address as rhost. - It does some MAP_TO_GUEST_ON_BAD_UID logic and auto creates the guest account. e) We called create_info3_from_pac_logon_info() f) make_session_info_krb5() calls gets called and triggers this: - If get_user_from_kerberos_info() mapped to guest, it calls make_server_info_guest() - If create_info3_from_pac_logon_info() created a info3 from logon_info, it calls make_server_info_info3() - Without a PAC it tries pdb_getsampwnam()/make_server_info_sam() with a fallback to make_server_info_pw() From there it calls create_local_token() I tried to change auth3_generate_session_info_pac() to behave similar to auth_winbind.c together with auth3_generate_session_info() as a domain member, as we now rely on a PAC: a) As domain member we require a PAC and always call wbcAuthenticateUserEx() and require a valid response! b) we call make_server_info_wbcAuthUserInfo(), which internally calls make_server_info_info3(). Note make_server_info_info3() handles MAP_TO_GUEST_ON_BAD_UID and make_server_info_guest() internally. c) Similar to auth_check_ntlm_password() we now call smb_pam_accountcheck(unix_username, rhost), where rhost is only an ipv4 or ipv6 address (without reverse dns lookup) d) From there it calls create_local_token() As standalone server (in an MIT realm) we continue with the already existing code logic, which works without a PAC: a) we keep smb_getpwnam() with create=true logic as it also requires an explicit 'add user script' option. b) In the following commits we assert that there's actually no PAC in this mode, which means we can remove unused and confusing code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14646 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 137 ++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 28 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 86585ad690c..450c358beeb 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -46,6 +46,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, uint32_t session_info_flags, struct auth_session_info **session_info) { + enum server_role server_role = lp_server_role(); TALLOC_CTX *tmp_ctx; struct PAC_LOGON_INFO *logon_info = NULL; struct netr_SamInfo3 *info3_copy = NULL; @@ -54,39 +55,59 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, char *ntuser; char *ntdomain; char *username; - char *rhost; + const char *rhost; struct passwd *pw; NTSTATUS status; - int rc; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } - if (pac_blob) { -#ifdef HAVE_KRB5 + if (tsocket_address_is_inet(remote_address, "ip")) { + rhost = tsocket_address_inet_addr_string( + remote_address, tmp_ctx); + if (rhost == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + } else { + rhost = "127.0.0.1"; + } + + if (server_role != ROLE_STANDALONE) { struct wbcAuthUserParams params = { 0 }; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; + struct auth_serversupplied_info *server_info = NULL; + char *original_user_name = NULL; + char *p = NULL; wbcErr wbc_err; + if (pac_blob == NULL) { + /* + * This should already be catched at the main + * gensec layer, but better check twice + */ + status = NT_STATUS_INTERNAL_ERROR; + goto done; + } + /* * Let winbind decode the PAC. * This will also store the user * data in the netsamlogon cache. * - * We need to do this *before* we - * call get_user_from_kerberos_info() - * as that does a user lookup that - * expects info in the netsamlogon cache. - * - * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=11259 + * This used to be a cache prime + * optimization, but now we delegate + * all logic to winbindd, as we require + * winbindd as domain member anyway. */ params.level = WBC_AUTH_USER_LEVEL_PAC; params.password.pac.data = pac_blob->data; params.password.pac.length = pac_blob->length; + /* we are contacting the privileged pipe */ become_root(); wbc_err = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); @@ -99,18 +120,90 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, */ switch (wbc_err) { - case WBC_ERR_WINBIND_NOT_AVAILABLE: case WBC_ERR_SUCCESS: break; + case WBC_ERR_WINBIND_NOT_AVAILABLE: + status = NT_STATUS_NO_LOGON_SERVERS; + DBG_ERR("winbindd not running - " + "but required as domain member: %s\n", + nt_errstr(status)); + goto done; case WBC_ERR_AUTH_ERROR: status = NT_STATUS(err->nt_status); wbcFreeMemory(err); goto done; + case WBC_ERR_NO_MEMORY: + status = NT_STATUS_NO_MEMORY; + goto done; default: status = NT_STATUS_LOGON_FAILURE; goto done; } + status = make_server_info_wbcAuthUserInfo(tmp_ctx, + info->account_name, + info->domain_name, + info, &server_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("make_server_info_wbcAuthUserInfo failed: %s\n", + nt_errstr(status))); + goto done; + } + + /* We skip doing this step if the caller asked us not to */ + if (!(server_info->guest)) { + const char *unix_username = server_info->unix_name; + + /* We might not be root if we are an RPC call */ + become_root(); + status = smb_pam_accountcheck(unix_username, rhost); + unbecome_root(); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("check_ntlm_password: PAM Account for user [%s] " + "FAILED with error %s\n", + unix_username, nt_errstr(status))); + goto done; + } + + DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] " + "succeeded\n", unix_username)); + } + + DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); + + p = strchr_m(princ_name, '@'); + if (!p) { + DEBUG(3, ("[%s] Doesn't look like a valid principal\n", + princ_name)); + status = NT_STATUS_LOGON_FAILURE; + goto done; + } + + original_user_name = talloc_strndup(tmp_ctx, princ_name, p - princ_name); + if (original_user_name == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + status = create_local_token(mem_ctx, + server_info, + NULL, + original_user_name, + session_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("create_local_token failed: %s\n", + nt_errstr(status))); + goto done; + } + + goto session_info_ready; + } + + /* This is the standalone legacy code path */ + + if (pac_blob != NULL) { +#ifdef HAVE_KRB5 status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, NULL, NULL, 0, &logon_info); #else @@ -121,22 +214,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, } } - rc = get_remote_hostname(remote_address, - &rhost, - tmp_ctx); - if (rc < 0) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - if (strequal(rhost, "UNKNOWN")) { - rhost = tsocket_address_inet_addr_string(remote_address, - tmp_ctx); - if (rhost == NULL) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - } - status = get_user_from_kerberos_info(tmp_ctx, rhost, princ_name, logon_info, &is_mapped, &is_guest, @@ -170,6 +247,8 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, goto done; } +session_info_ready: + /* setup the string used by %U */ set_current_user_info((*session_info)->unix_info->sanitized_username, (*session_info)->unix_info->unix_name, @@ -179,7 +258,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, lp_load_with_shares(get_dyn_CONFIGFILE()); DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n", - ntuser, ntdomain, rhost)); + (*session_info)->info->account_name, + (*session_info)->info->domain_name, + rhost)); status = NT_STATUS_OK; -- 2.25.1 From ba7bf09c277dc78689104f46d2b2edd0c5b32128 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 5 Oct 2021 18:12:49 +0200 Subject: [PATCH 529/645] CVE-2020-25717: s3:auth: let auth3_generate_session_info_pac() reject a PAC in standalone mode We should be strict in standalone mode, that we only support MIT realms without a PAC in order to keep the code sane. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 450c358beeb..7d00cfa95c7 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -48,8 +48,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, { enum server_role server_role = lp_server_role(); TALLOC_CTX *tmp_ctx; - struct PAC_LOGON_INFO *logon_info = NULL; - struct netr_SamInfo3 *info3_copy = NULL; bool is_mapped; bool is_guest; char *ntuser; @@ -203,19 +201,20 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, /* This is the standalone legacy code path */ if (pac_blob != NULL) { -#ifdef HAVE_KRB5 - status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, - NULL, NULL, 0, &logon_info); -#else - status = NT_STATUS_ACCESS_DENIED; -#endif + /* + * In standalone mode we don't expect a PAC! + * we only support MIT realms + */ + status = NT_STATUS_BAD_TOKEN_TYPE; + DBG_WARNING("Unexpected PAC for [%s] in standalone mode - %s\n", + princ_name, nt_errstr(status)); if (!NT_STATUS_IS_OK(status)) { goto done; } } status = get_user_from_kerberos_info(tmp_ctx, rhost, - princ_name, logon_info, + princ_name, NULL, &is_mapped, &is_guest, &ntuser, &ntdomain, &username, &pw); @@ -226,19 +225,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, goto done; } - /* Get the info3 from the PAC data if we have it */ - if (logon_info) { - status = create_info3_from_pac_logon_info(tmp_ctx, - logon_info, - &info3_copy); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - } - status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, - info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + NULL, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", -- 2.25.1 From 8f9748b36bba184f00bb7e527514428c5bf2ef8c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Oct 2021 17:59:59 +0200 Subject: [PATCH 530/645] CVE-2020-25717: s3:auth: simplify get_user_from_kerberos_info() by removing the unused logon_info argument This code is only every called in standalone mode on a MIT realm, it means we never have a PAC and we also don't have winbindd arround. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 2 +- source3/auth/proto.h | 1 - source3/auth/user_krb5.c | 57 +++++++------------------------------ 3 files changed, 11 insertions(+), 49 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 7d00cfa95c7..8649dd87efc 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -214,7 +214,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, } status = get_user_from_kerberos_info(tmp_ctx, rhost, - princ_name, NULL, + princ_name, &is_mapped, &is_guest, &ntuser, &ntdomain, &username, &pw); diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 097b17fee44..46fae447347 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -423,7 +423,6 @@ struct PAC_LOGON_INFO; NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, const char *cli_name, const char *princ_name, - struct PAC_LOGON_INFO *logon_info, bool *is_mapped, bool *mapped_to_guest, char **ntuser, diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c index 074e8c7eb71..7b69ca6c222 100644 --- a/source3/auth/user_krb5.c +++ b/source3/auth/user_krb5.c @@ -31,7 +31,6 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, const char *cli_name, const char *princ_name, - struct PAC_LOGON_INFO *logon_info, bool *is_mapped, bool *mapped_to_guest, char **ntuser, @@ -40,8 +39,8 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, struct passwd **_pw) { NTSTATUS status; - char *domain = NULL; - char *realm = NULL; + const char *domain = NULL; + const char *realm = NULL; char *user = NULL; char *p; char *fuser = NULL; @@ -62,55 +61,16 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - realm = talloc_strdup(talloc_tos(), p + 1); - if (!realm) { - return NT_STATUS_NO_MEMORY; - } + realm = p + 1; if (!strequal(realm, lp_realm())) { DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); if (!lp_allow_trusted_domains()) { return NT_STATUS_LOGON_FAILURE; } - } - - if (logon_info && logon_info->info3.base.logon_domain.string) { - domain = talloc_strdup(mem_ctx, - logon_info->info3.base.logon_domain.string); - if (!domain) { - return NT_STATUS_NO_MEMORY; - } - DEBUG(10, ("Domain is [%s] (using PAC)\n", domain)); + domain = realm; } else { - - /* If we have winbind running, we can (and must) shorten the - username by using the short netbios name. Otherwise we will - have inconsistent user names. With Kerberos, we get the - fully qualified realm, with ntlmssp we get the short - name. And even w2k3 does use ntlmssp if you for example - connect to an ip address. */ - - wbcErr wbc_status; - struct wbcDomainInfo *info = NULL; - - DEBUG(10, ("Mapping [%s] to short name using winbindd\n", - realm)); - - wbc_status = wbcDomainInfo(realm, &info); - - if (WBC_ERROR_IS_OK(wbc_status)) { - domain = talloc_strdup(mem_ctx, - info->short_name); - wbcFreeMemory(info); - } else { - DEBUG(3, ("Could not find short name: %s\n", - wbcErrorString(wbc_status))); - domain = talloc_strdup(mem_ctx, realm); - } - if (!domain) { - return NT_STATUS_NO_MEMORY; - } - DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain)); + domain = lp_workgroup(); } fuser = talloc_asprintf(mem_ctx, @@ -175,7 +135,11 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } *ntuser = user; - *ntdomain = domain; + *ntdomain = talloc_strdup(mem_ctx, domain); + if (*ntdomain == NULL) { + return NT_STATUS_NO_MEMORY; + } + *_pw = pw; return NT_STATUS_OK; @@ -282,7 +246,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, const char *cli_name, const char *princ_name, - struct PAC_LOGON_INFO *logon_info, bool *is_mapped, bool *mapped_to_guest, char **ntuser, -- 2.25.1 From 4d0464f983a9e18c1de3378afe68f23b87c44049 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Oct 2021 18:03:04 +0200 Subject: [PATCH 531/645] CVE-2020-25717: s3:auth: simplify make_session_info_krb5() by removing unused arguments This is only ever be called in standalone mode with an MIT realm, so we don't have a PAC/info3 structure. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- source3/auth/auth_generic.c | 2 +- source3/auth/proto.h | 2 -- source3/auth/user_krb5.c | 20 +------------------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 8649dd87efc..b429c5f9f04 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -227,7 +227,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, - NULL, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + is_guest, is_mapped, session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 46fae447347..fb7f663512b 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -434,9 +434,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, - DATA_BLOB *session_key, struct auth_session_info **session_info); /* The following definitions come from auth/auth_samba4.c */ diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c index 7b69ca6c222..b8f37cbeee0 100644 --- a/source3/auth/user_krb5.c +++ b/source3/auth/user_krb5.c @@ -150,9 +150,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, - DATA_BLOB *session_key, struct auth_session_info **session_info) { NTSTATUS status; @@ -166,20 +164,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, return status; } - } else if (info3) { - /* pass the unmapped username here since map_username() - will be called again in make_server_info_info3() */ - - status = make_server_info_info3(mem_ctx, - ntuser, ntdomain, - &server_info, - info3); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("make_server_info_info3 failed: %s!\n", - nt_errstr(status))); - return status; - } - } else { /* * We didn't get a PAC, we have to make up the user @@ -231,7 +215,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, server_info->nss_token |= username_was_mapped; - status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info); + status = create_local_token(mem_ctx, server_info, NULL, ntuser, session_info); talloc_free(server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("failed to create local token: %s\n", @@ -261,9 +245,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, - DATA_BLOB *session_key, struct auth_session_info **session_info) { return NT_STATUS_NOT_IMPLEMENTED; -- 2.25.1 From 81760e4bad2f1f74b6971b28947e9c9e292d3495 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 14:07:41 +1300 Subject: [PATCH 532/645] CVE-2020-25722 Add test for SPN deletion followed by addition BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org Removed transaction hooks, these do nothing over remote LDAP] --- selftest/knownfail.d/acl-spn | 1 + source4/dsdb/tests/python/acl.py | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 selftest/knownfail.d/acl-spn diff --git a/selftest/knownfail.d/acl-spn b/selftest/knownfail.d/acl-spn new file mode 100644 index 00000000000..e68add920a6 --- /dev/null +++ b/selftest/knownfail.d/acl-spn @@ -0,0 +1 @@ +^samba4.ldap.acl.python.*AclSPNTests.test_delete_add_spn diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index 815422c2677..9c3a7be0ab6 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -2190,6 +2190,54 @@ class AclSPNTests(AclTests): def test_spn_rodc(self): self.dc_spn_test(self.rodcctx) + def test_delete_add_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}' + + allowed_spn = f'{spn_base}.{self.dcctx.dnsdomain}' + not_allowed_spn = f'{spn_base}/{self.dcctx.get_domain_name()}' + + # Ensure we are able to add an allowed SPN. + msg = Message(Dn(self.ldb_user1, self.computerdn)) + msg['servicePrincipalName'] = MessageElement(allowed_spn, + FLAG_MOD_ADD, + 'servicePrincipalName') + self.ldb_user1.modify(msg) + + # Ensure we are not able to add a disallowed SPN. + msg = Message(Dn(self.ldb_user1, self.computerdn)) + msg['servicePrincipalName'] = MessageElement(not_allowed_spn, + FLAG_MOD_ADD, + 'servicePrincipalName') + try: + self.ldb_user1.modify(msg) + except LdbError as e: + num, _ = e.args + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail(f'able to add disallowed SPN {not_allowed_spn}') + + # Ensure that deleting an existing SPN followed by adding a disallowed + # SPN fails. + msg = Message(Dn(self.ldb_user1, self.computerdn)) + msg['0'] = MessageElement([], + FLAG_MOD_DELETE, + 'servicePrincipalName') + msg['1'] = MessageElement(not_allowed_spn, + FLAG_MOD_ADD, + 'servicePrincipalName') + try: + self.ldb_user1.modify(msg) + except LdbError as e: + num, _ = e.args + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail(f'able to add disallowed SPN {not_allowed_spn}') + + # tests SEC_ADS_LIST vs. SEC_ADS_LIST_OBJECT @DynamicTestCase class AclVisibiltyTests(AclTests): -- 2.25.1 From 6346726aeaa587a0edad9dc789f88923c0dd00b6 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 8 Oct 2021 15:49:31 +1300 Subject: [PATCH 533/645] CVE-2020-25722 s4:dsdb:tests: Add missing self.fail() calls Without these calls the tests could pass if an expected error did not occur. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14832 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett [abartlet@samba.org Included in backport as changing ACLs while ACL tests are not checking for unexpected success would be bad] --- source4/dsdb/tests/python/acl.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index 9c3a7be0ab6..abe91942f4f 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -1647,6 +1647,8 @@ userPassword: thatsAcomplPASS1 except LdbError as e31: (num, _) = e31.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + pass # Not self.fail() as we normally want success. def test_reset_password3(self): """Grant WP and see what happens (unicodePwd)""" @@ -1708,6 +1710,8 @@ userPassword: thatsAcomplPASS1 except LdbError as e34: (num, _) = e34.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + pass # Not self.fail() as we normally want success class AclExtendedTests(AclTests): @@ -2024,6 +2028,8 @@ class AclSPNTests(AclTests): except LdbError as e39: (num, _) = e39.args self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail() mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1) self.sd_utils.dacl_add_ace(ctx.acct_dn, mod) @@ -2062,29 +2068,39 @@ class AclSPNTests(AclTests): except LdbError as e40: (num, _) = e40.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/DomainDnsZones.%s" % (ctx.myname, ctx.dnsdomain, ctx.dnsdomain)) except LdbError as e41: (num, _) = e41.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "nosuchservice/%s/%s" % ("abcd", "abcd")) except LdbError as e42: (num, _) = e42.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" % (ctx.myname, ctx.dnsdomain, netbiosdomain)) except LdbError as e43: (num, _) = e43.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, ctx.acct_dn, "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s" % (ctx.ntds_guid, ctx.dnsdomain)) except LdbError as e44: (num, _) = e44.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() def test_computer_spn(self): # with WP, any value can be set @@ -2130,6 +2146,8 @@ class AclSPNTests(AclTests): except LdbError as e45: (num, _) = e45.args self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail() mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1) self.sd_utils.dacl_add_ace(self.computerdn, mod) @@ -2148,41 +2166,55 @@ class AclSPNTests(AclTests): except LdbError as e46: (num, _) = e46.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, netbiosdomain)) except LdbError as e47: (num, _) = e47.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, self.dcctx.dnsdomain)) except LdbError as e48: (num, _) = e48.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain)) except LdbError as e49: (num, _) = e49.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "GC/%s.%s/%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest)) except LdbError as e50: (num, _) = e50.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain)) except LdbError as e51: (num, _) = e51.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() try: self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" % (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain)) except LdbError as e52: (num, _) = e52.args self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() def test_spn_rwdc(self): self.dc_spn_test(self.dcctx) -- 2.25.1 From 1df87f58be1bbaab4a367e5e121e21e8dc58afdc Mon Sep 17 00:00:00 2001 From: Nadezhda Ivanova Date: Mon, 25 Oct 2021 14:54:56 +0300 Subject: [PATCH 534/645] CVE-2020-25722: s4-acl: test Control Access Rights honor the Applies-to attribute Validate Writes and Control Access Rights should only grant access if the object is of the type listed in the Right's appliesTo attribute. Tests to verify this behavior BUG: https://bugzilla.samba.org/show_bug.cgi?id=14832 Signed-off-by: Nadezhda Ivanova Reviewed-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/bug-14832 | 1 + source4/dsdb/tests/python/acl.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 selftest/knownfail.d/bug-14832 diff --git a/selftest/knownfail.d/bug-14832 b/selftest/knownfail.d/bug-14832 new file mode 100644 index 00000000000..059a1778e65 --- /dev/null +++ b/selftest/knownfail.d/bug-14832 @@ -0,0 +1 @@ +^samba4.ldap.acl.python\(.*\).__main__.AclSPNTests.test_user_spn\(.*\) \ No newline at end of file diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index abe91942f4f..53acb99c296 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -1926,6 +1926,8 @@ class AclSPNTests(AclTests): self.computername = "testcomp8" self.test_user = "spn_test_user8" self.computerdn = "CN=%s,CN=computers,%s" % (self.computername, self.base_dn) + self.user_object = "user_with_spn" + self.user_object_dn = "CN=%s,CN=Users,%s" % (self.user_object, self.base_dn) self.dc_dn = "CN=%s,OU=Domain Controllers,%s" % (self.dcname, self.base_dn) self.site = "Default-First-Site-Name" self.rodcctx = DCJoinContext(server=host, creds=creds, lp=lp, @@ -1947,6 +1949,7 @@ class AclSPNTests(AclTests): self.dcctx.cleanup_old_join() delete_force(self.ldb_admin, "cn=%s,cn=computers,%s" % (self.computername, self.base_dn)) delete_force(self.ldb_admin, self.get_user_dn(self.test_user)) + delete_force(self.ldb_admin, self.user_object_dn) del self.ldb_user1 @@ -2222,6 +2225,20 @@ class AclSPNTests(AclTests): def test_spn_rodc(self): self.dc_spn_test(self.rodcctx) + def test_user_spn(self): + #grant SW to a regular user and try to set the spn on a user object + #should get ERR_INSUFFICIENT_ACCESS_RIGHTS, since Validate-SPN only applies to computer + self.ldb_admin.newuser(self.user_object, self.user_pass) + mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1) + self.sd_utils.dacl_add_ace(self.user_object_dn, mod) + try: + self.replace_spn(self.ldb_user1, self.user_object_dn, "nosuchservice/%s/%s" % ("abcd", "abcd")) + except LdbError as e60: + (num, _) = e60.args + self.assertEqual(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail() + def test_delete_add_spn(self): # Grant Validated-SPN property. mod = f'(OA;;SW;{security.GUID_DRS_VALIDATE_SPN};;{self.user_sid1})' -- 2.25.1 From b82ef20fdecadd3a7f23ddae2c0caf24f0d04d2c Mon Sep 17 00:00:00 2001 From: Nadezhda Ivanova Date: Mon, 18 Oct 2021 14:27:59 +0300 Subject: [PATCH 535/645] CVE-2020-25722: s4-acl: Make sure Control Access Rights honor the Applies-to attribute Validate Writes and Control Access Rights only grant access if the object is of the type listed in the Right's appliesTo attribute. For example, even though a Validated-SPN access may be granted to a user object in the SD, it should only pass if the object is of class computer This patch enforces the appliesTo attribute classes for access checks from within the ldb stack. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14832 Signed-off-by: Nadezhda Ivanova Reviewed-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/bug-14832 | 1 - source4/dsdb/common/util.c | 11 +++ source4/dsdb/samdb/ldb_modules/acl.c | 87 +++++++++++++++++++---- source4/dsdb/samdb/ldb_modules/acl_util.c | 40 +++++++++++ source4/dsdb/samdb/ldb_modules/dirsync.c | 13 +++- source4/dsdb/samdb/ldb_modules/samldb.c | 56 ++++++++------- 6 files changed, 168 insertions(+), 40 deletions(-) delete mode 100644 selftest/knownfail.d/bug-14832 diff --git a/selftest/knownfail.d/bug-14832 b/selftest/knownfail.d/bug-14832 deleted file mode 100644 index 059a1778e65..00000000000 --- a/selftest/knownfail.d/bug-14832 +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.acl.python\(.*\).__main__.AclSPNTests.test_user_spn\(.*\) \ No newline at end of file diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index d88688a8ec1..166bc4b252e 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1179,6 +1179,17 @@ struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) return new_dn; } +struct ldb_dn *samdb_extended_rights_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) +{ + struct ldb_dn *new_dn; + + new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx)); + if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Extended-Rights")) { + talloc_free(new_dn); + return NULL; + } + return new_dn; +} /* work out the domain sid for the current open ldb */ diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index b1bbf936006..9cae15881de 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -698,7 +698,12 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, return LDB_SUCCESS; } - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_VALIDATE_SPN, SEC_ADS_SELF_WRITE, sid); @@ -911,7 +916,7 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } -/* ckecks if modifications are allowed on "Member" attribute */ +/* checks if modifications are allowed on "Member" attribute */ static int acl_check_self_membership(TALLOC_CTX *mem_ctx, struct ldb_module *module, struct ldb_request *req, @@ -925,6 +930,16 @@ static int acl_check_self_membership(TALLOC_CTX *mem_ctx, struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_dn *user_dn; struct ldb_message_element *member_el; + const struct ldb_message *msg = NULL; + + if (req->operation == LDB_MODIFY) { + msg = req->op.mod.message; + } else if (req->operation == LDB_ADD) { + msg = req->op.add.message; + } else { + return LDB_ERR_OPERATIONS_ERROR; + } + /* if we have wp, we can do whatever we like */ if (acl_check_access_on_attribute(module, mem_ctx, @@ -935,13 +950,13 @@ static int acl_check_self_membership(TALLOC_CTX *mem_ctx, return LDB_SUCCESS; } /* if we are adding/deleting ourselves, check for self membership */ - ret = dsdb_find_dn_by_sid(ldb, mem_ctx, - &acl_user_token(module)->sids[PRIMARY_USER_SID_INDEX], + ret = dsdb_find_dn_by_sid(ldb, mem_ctx, + &acl_user_token(module)->sids[PRIMARY_USER_SID_INDEX], &user_dn); if (ret != LDB_SUCCESS) { return ret; } - member_el = ldb_msg_find_element(req->op.mod.message, "member"); + member_el = ldb_msg_find_element(msg, "member"); if (!member_el) { return ldb_operr(ldb); } @@ -955,13 +970,18 @@ static int acl_check_self_membership(TALLOC_CTX *mem_ctx, return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } } - ret = acl_check_extended_right(mem_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(mem_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_SELF_MEMBERSHIP, SEC_ADS_SELF_WRITE, sid); if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { dsdb_acl_debug(sd, acl_user_token(module), - req->op.mod.message->dn, + msg->dn, true, 10); } @@ -1021,6 +1041,9 @@ static int acl_check_password_rights( * so we don't have to strict verification of the input. */ ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, sd, acl_user_token(module), GUID_DRS_USER_CHANGE_PASSWORD, @@ -1044,7 +1067,12 @@ static int acl_check_password_rights( * the only caller is samdb_set_password_internal(), * so we don't have to strict verification of the input. */ - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_FORCE_CHANGE_PASSWORD, SEC_ADS_CONTROL_ACCESS, sid); @@ -1097,7 +1125,12 @@ static int acl_check_password_rights( if (rep_attr_cnt > 0) { pav->pwd_reset = true; - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_FORCE_CHANGE_PASSWORD, SEC_ADS_CONTROL_ACCESS, sid); @@ -1107,7 +1140,12 @@ static int acl_check_password_rights( if (add_attr_cnt != del_attr_cnt) { pav->pwd_reset = true; - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_FORCE_CHANGE_PASSWORD, SEC_ADS_CONTROL_ACCESS, sid); @@ -1117,7 +1155,12 @@ static int acl_check_password_rights( if (add_val_cnt == 1 && del_val_cnt == 1) { pav->pwd_reset = false; - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_USER_CHANGE_PASSWORD, SEC_ADS_CONTROL_ACCESS, sid); @@ -1131,7 +1174,12 @@ static int acl_check_password_rights( if (add_val_cnt == 1 && del_val_cnt == 0) { pav->pwd_reset = true; - ret = acl_check_extended_right(tmp_ctx, sd, acl_user_token(module), + ret = acl_check_extended_right(tmp_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_FORCE_CHANGE_PASSWORD, SEC_ADS_CONTROL_ACCESS, sid); @@ -1686,6 +1734,9 @@ static int acl_check_reanimate_tombstone(TALLOC_CTX *mem_ctx, struct ldb_result *acl_res; struct security_descriptor *sd = NULL; struct dom_sid *sid = NULL; + const struct dsdb_schema *schema = NULL; + const struct dsdb_class *objectclass = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(module); static const char *acl_attrs[] = { "nTSecurityDescriptor", "objectClass", @@ -1706,10 +1757,20 @@ static int acl_check_reanimate_tombstone(TALLOC_CTX *mem_ctx, ret = dsdb_get_sd_from_ldb_message(mem_ctx, req, acl_res->msgs[0], &sd); sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid"); + schema = dsdb_get_schema(ldb, req); + if (!schema) { + return LDB_ERR_OPERATIONS_ERROR; + } + objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]); if (ret != LDB_SUCCESS || !sd) { return ldb_operr(ldb_module_get_ctx(module)); } - return acl_check_extended_right(mem_ctx, sd, acl_user_token(module), + return acl_check_extended_right(mem_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), GUID_DRS_REANIMATE_TOMBSTONE, SEC_ADS_CONTROL_ACCESS, sid); } diff --git a/source4/dsdb/samdb/ldb_modules/acl_util.c b/source4/dsdb/samdb/ldb_modules/acl_util.c index b9931795e19..e38b264ca23 100644 --- a/source4/dsdb/samdb/ldb_modules/acl_util.c +++ b/source4/dsdb/samdb/ldb_modules/acl_util.c @@ -197,6 +197,9 @@ fail: /* checks for validated writes */ int acl_check_extended_right(TALLOC_CTX *mem_ctx, + struct ldb_module *module, + struct ldb_request *req, + const struct dsdb_class *objectclass, struct security_descriptor *sd, struct security_token *token, const char *ext_right, @@ -208,6 +211,43 @@ int acl_check_extended_right(TALLOC_CTX *mem_ctx, uint32_t access_granted; struct object_tree *root = NULL; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + static const char *no_attrs[] = { NULL }; + struct ldb_result *extended_rights_res = NULL; + struct ldb_dn *extended_rights_dn = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(module); + int ret = 0; + + /* + * Find the extended right and check if applies to + * the objectclass of the object + */ + extended_rights_dn = samdb_extended_rights_dn(ldb, req); + if (!extended_rights_dn) { + ldb_set_errstring(ldb, + "access_check: CN=Extended-Rights dn could not be generated!"); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Note: we are checking only the structural object class. */ + ret = dsdb_module_search(module, req, &extended_rights_res, + extended_rights_dn, LDB_SCOPE_ONELEVEL, + no_attrs, + DSDB_FLAG_NEXT_MODULE | + DSDB_FLAG_AS_SYSTEM, + req, + "(&(rightsGuid=%s)(appliesTo=%s))", + ext_right, + GUID_string(tmp_ctx, + &(objectclass->schemaIDGUID))); + + if (ret != LDB_SUCCESS) { + return ret; + } else if (extended_rights_res->count == 0 ) { + ldb_debug(ldb, LDB_DEBUG_TRACE, + "acl_check_extended_right: Could not find appliesTo for %s\n", + ext_right); + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } GUID_from_string(ext_right, &right); diff --git a/source4/dsdb/samdb/ldb_modules/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c index 1dfdf3d2447..69f051f734b 100644 --- a/source4/dsdb/samdb/ldb_modules/dirsync.c +++ b/source4/dsdb/samdb/ldb_modules/dirsync.c @@ -1066,7 +1066,9 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req if (!(dirsync_ctl->flags & LDAP_DIRSYNC_OBJECT_SECURITY)) { struct dom_sid *sid; struct security_descriptor *sd = NULL; - const char *acl_attrs[] = { "nTSecurityDescriptor", "objectSid", NULL }; + const char *acl_attrs[] = { "nTSecurityDescriptor", "objectSid", "objectClass", NULL }; + const struct dsdb_schema *schema = NULL; + const struct dsdb_class *objectclass = NULL; /* * If we don't have the flag and if we have the "replicate directory change" granted * then we upgrade ourself to system to not be blocked by the acl @@ -1096,7 +1098,14 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req if (ret != LDB_SUCCESS) { return ret; } - ret = acl_check_extended_right(dsc, sd, acl_user_token(module), GUID_DRS_GET_CHANGES, SEC_ADS_CONTROL_ACCESS, sid); + schema = dsdb_get_schema(ldb, req); + if (!schema) { + return LDB_ERR_OPERATIONS_ERROR; + } + objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]); + ret = acl_check_extended_right(dsc, module, req, objectclass, + sd, acl_user_token(module), + GUID_DRS_GET_CHANGES, SEC_ADS_CONTROL_ACCESS, sid); if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { return ret; diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 5352af1099f..6db7840b0c1 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -2192,12 +2192,15 @@ static int samldb_check_user_account_control_objectclass_invariants( return LDB_SUCCESS; } -static int samldb_get_domain_secdesc(struct samldb_ctx *ac, - struct security_descriptor **domain_sd) +static int samldb_get_domain_secdesc_and_oc(struct samldb_ctx *ac, + struct security_descriptor **domain_sd, + const struct dsdb_class **objectclass) { - const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; + const char * const sd_attrs[] = {"ntSecurityDescriptor", "objectClass", NULL}; struct ldb_result *res; struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); + const struct dsdb_schema *schema = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); int ret = dsdb_module_search_dn(ac->module, ac, &res, domain_dn, sd_attrs, @@ -2210,6 +2213,11 @@ static int samldb_get_domain_secdesc(struct samldb_ctx *ac, return ldb_module_operr(ac->module); } + schema = dsdb_get_schema(ldb, ac->req); + if (!schema) { + return ldb_module_operr(ac->module);; + } + *objectclass = dsdb_get_structural_oc_from_msg(schema, res->msgs[0]); return dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module), ac, res->msgs[0], domain_sd); @@ -2228,6 +2236,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, bool need_acl_check = false; struct security_token *user_token; struct security_descriptor *domain_sd; + const struct dsdb_class *objectclass = NULL; const struct uac_to_guid { uint32_t uac; uint32_t priv_to_change_from; @@ -2313,7 +2322,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } - ret = samldb_get_domain_secdesc(ac, &domain_sd); + ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass); if (ret != LDB_SUCCESS) { return ret; } @@ -2344,7 +2353,11 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } } else if (map[i].guid) { - ret = acl_check_extended_right(ac, domain_sd, + ret = acl_check_extended_right(ac, + ac->module, + ac->req, + objectclass, + domain_sd, user_token, map[i].guid, SEC_ADS_CONTROL_ACCESS, @@ -2684,12 +2697,11 @@ static int samldb_check_pwd_last_set_acl(struct samldb_ctx *ac, { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); int ret = 0; - struct ldb_result *res = NULL; - const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; struct security_token *user_token = NULL; struct security_descriptor *domain_sd = NULL; struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); const char *operation = ""; + const struct dsdb_class *objectclass = NULL; if (dsdb_module_am_system(ac->module)) { return LDB_SUCCESS; @@ -2711,24 +2723,15 @@ static int samldb_check_pwd_last_set_acl(struct samldb_ctx *ac, return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } - ret = dsdb_module_search_dn(ac->module, ac, &res, - domain_dn, - sd_attrs, - DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, - ac->req); - if (ret != LDB_SUCCESS) { - return ret; - } - if (res->count != 1) { - return ldb_module_operr(ac->module); - } - - ret = dsdb_get_sd_from_ldb_message(ldb, ac, res->msgs[0], &domain_sd); + ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass); if (ret != LDB_SUCCESS) { return ret; } - - ret = acl_check_extended_right(ac, domain_sd, + ret = acl_check_extended_right(ac, + ac->module, + ac->req, + objectclass, + domain_sd, user_token, GUID_DRS_UNEXPIRE_PASSWORD, SEC_ADS_CONTROL_ACCESS, @@ -3758,16 +3761,21 @@ static int samldb_check_sensitive_attributes(struct samldb_ctx *ac) el = ldb_msg_find_element(ac->msg, "msDS-SecondaryKrbTgtNumber"); if (el) { struct security_descriptor *domain_sd; + const struct dsdb_class *objectclass = NULL; /* * msDS-SecondaryKrbTgtNumber allows the creator to * become an RODC, this is trusted as an RODC * account */ - ret = samldb_get_domain_secdesc(ac, &domain_sd); + ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass); if (ret != LDB_SUCCESS) { return ret; } - ret = acl_check_extended_right(ac, domain_sd, + ret = acl_check_extended_right(ac, + ac->module, + ac->req, + objectclass, + domain_sd, user_token, GUID_DRS_DS_INSTALL_REPLICA, SEC_ADS_CONTROL_ACCESS, -- 2.25.1 From 9a2660fce85a07673ba0d69eef32c3b6a9f77cbe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 1 Nov 2021 17:19:29 +1300 Subject: [PATCH 536/645] CVE-2020-25722 Check all elements in acl_check_spn() not just the first one Thankfully we are aleady in a loop over all the message elements in acl_modify() so this is an easy and safe change to make. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- selftest/knownfail.d/acl-spn | 1 - source4/dsdb/samdb/ldb_modules/acl.c | 31 +++++++++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) delete mode 100644 selftest/knownfail.d/acl-spn diff --git a/selftest/knownfail.d/acl-spn b/selftest/knownfail.d/acl-spn deleted file mode 100644 index e68add920a6..00000000000 --- a/selftest/knownfail.d/acl-spn +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.acl.python.*AclSPNTests.test_delete_add_spn diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 9cae15881de..d0b3da4d9e8 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -653,9 +653,14 @@ success: return LDB_SUCCESS; } +/* + * Passing in 'el' is critical, we want to check all the values. + * + */ static int acl_check_spn(TALLOC_CTX *mem_ctx, struct ldb_module *module, struct ldb_request *req, + const struct ldb_message_element *el, struct security_descriptor *sd, struct dom_sid *sid, const struct dsdb_attribute *attr, @@ -667,7 +672,6 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_result *acl_res; struct ldb_result *netbios_res; - struct ldb_message_element *el; struct ldb_dn *partitions_dn = samdb_partitions_dn(ldb, tmp_ctx); uint32_t userAccountControl; const char *samAccountName; @@ -717,6 +721,23 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, return ret; } + /* + * If we have "validated write spn", allow delete of any + * existing value (this keeps constrained delete to the same + * rules as unconstrained) + */ + if (req->operation == LDB_MODIFY) { + /* + * If not add or replace (eg delete), + * return success + */ + if ((el->flags + & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) { + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } + } + ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, req->op.mod.message->dn, acl_attrs, @@ -745,13 +766,6 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, netbios_name = ldb_msg_find_attr_as_string(netbios_res->msgs[0], "nETBIOSName", NULL); - el = ldb_msg_find_element(req->op.mod.message, "servicePrincipalName"); - if (!el) { - talloc_free(tmp_ctx); - return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, - "Error finding element for servicePrincipalName."); - } - /* NTDSDSA objectGuid of object we are checking SPN for */ if (userAccountControl & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { ret = dsdb_module_find_ntdsguid_for_computer(module, tmp_ctx, @@ -1510,6 +1524,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) ret = acl_check_spn(tmp_ctx, module, req, + el, sd, sid, attr, -- 2.25.1 From bbd3d2116791c6ec17835453a7530cba6cdb6e48 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 1 Nov 2021 17:21:16 +1300 Subject: [PATCH 537/645] CVE-2020-25722 Check for all errors from acl_check_extended_right() in acl_check_spn() We should not fail open on error. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/dsdb/samdb/ldb_modules/acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index d0b3da4d9e8..712724909e3 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -712,7 +712,7 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, SEC_ADS_SELF_WRITE, sid); - if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { + if (ret != LDB_SUCCESS) { dsdb_acl_debug(sd, acl_user_token(module), req->op.mod.message->dn, true, -- 2.25.1 From 1a3b16a2b06754c763cd5a1e761b256d4a40a435 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Mon, 4 Oct 2021 12:56:42 +1300 Subject: [PATCH 538/645] CVE-2020-25722 pytests: add reverse lookup dict for LDB error codes You can give ldb_err() it a number, an LdbError, or a sequence of numbers, and it will return the corresponding strings. Examples: ldb_err(68) # "LDB_ERR_ENTRY_ALREADY_EXISTS" LDB_ERR_LUT[68] # "LDB_ERR_ENTRY_ALREADY_EXISTS" expected = (ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, ldb.ERR_INVALID_CREDENTIALS) try: foo() except ldb.LdbError as e: self.fail(f"got {ldb_err(e)}, expected one of {ldb_err(expected)}") BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/tests/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index 14924528b0f..388036939cd 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -64,6 +64,22 @@ BINDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), HEXDUMP_FILTER = bytearray([x if ((len(repr(chr(x))) == 3) and (x < 127)) else ord('.') for x in range(256)]) +LDB_ERR_LUT = {v: k for k,v in vars(ldb).items() if k.startswith('ERR_')} + +def ldb_err(v): + if isinstance(v, ldb.LdbError): + v = v.args[0] + + if v in LDB_ERR_LUT: + return LDB_ERR_LUT[v] + + try: + return f"[{', '.join(LDB_ERR_LUT.get(x, x) for x in v)}]" + except TypeError as e: + print(e) + return v + + def DynamicTestCase(cls): cls.setUpDynamicTestCases() return cls -- 2.25.1 From 8be76080994542662884498ff59c0a24c3d588f3 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Sun, 24 Oct 2021 15:18:05 +1300 Subject: [PATCH 539/645] CVE-2020-25722 pytest: assertRaisesLdbError invents a message if you're lazy This makes it easier to convert tests that don't have good messages. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/tests/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index 388036939cd..e04ddcb4ba8 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -317,6 +317,8 @@ class TestCase(unittest.TestCase): def assertRaisesLdbError(self, errcode, message, f, *args, **kwargs): """Assert a function raises a particular LdbError.""" + if message is None: + message = f"{f.__name__}(*{args}, **{kwargs})" try: f(*args, **kwargs) except ldb.LdbError as e: -- 2.25.1 From 7115b31a7f2e3c11fb9eb19a07d3a16fa93e39d2 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 11 Aug 2021 16:56:07 +1200 Subject: [PATCH 540/645] CVE-2020-25722 s4/dsdb/cracknames: always free tmp_ctx in spn_alias BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/cracknames.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index b4bd9d8f9c9..7336778ec53 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -99,10 +99,12 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru service_dn = ldb_dn_new(tmp_ctx, ldb_ctx, "CN=Directory Service,CN=Windows NT,CN=Services"); if ( ! ldb_dn_add_base(service_dn, ldb_get_config_basedn(ldb_ctx))) { + talloc_free(tmp_ctx); return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; } service_dn_str = ldb_dn_alloc_linearized(tmp_ctx, service_dn); if ( ! service_dn_str) { + talloc_free(tmp_ctx); return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; } @@ -111,13 +113,15 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { DEBUG(1, ("ldb_search: dn: %s not found: %s\n", service_dn_str, ldb_errstring(ldb_ctx))); + talloc_free(tmp_ctx); return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; } else if (ret == LDB_ERR_NO_SUCH_OBJECT) { DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str)); + talloc_free(tmp_ctx); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } else if (res->count != 1) { - talloc_free(res); DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str)); + talloc_free(tmp_ctx); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } -- 2.25.1 From 25d0316ae86f4088c75f30fb664b387b5a2558fd Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 10 Aug 2021 23:02:36 +0000 Subject: [PATCH 541/645] CVE-2020-25722 s4/cracknames: lookup_spn_alias doesn't need krb5 context BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/cracknames.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index 7336778ec53..235276bc4c8 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -72,9 +72,9 @@ static WERROR dns_domain_from_principal(TALLOC_CTX *mem_ctx, struct smb_krb5_con info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY; return WERR_OK; -} +} -static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, +static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(struct ldb_context *ldb_ctx, TALLOC_CTX *mem_ctx, const char *alias_from, char **alias_to) @@ -219,8 +219,7 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c dns_name = (const char *)component->data; /* MAP it */ - namestatus = LDB_lookup_spn_alias(smb_krb5_context->krb5_context, - sam_ctx, mem_ctx, + namestatus = LDB_lookup_spn_alias(sam_ctx, mem_ctx, service, &new_service); if (namestatus == DRSUAPI_DS_NAME_STATUS_NOT_FOUND) { -- 2.25.1 From bc50a01d4726b8542c5b410c53c542635d36dd97 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 28 Jul 2021 05:38:50 +0000 Subject: [PATCH 542/645] CVE-2020-25722 samba-tool spn: accept -H for database url Following the convention and making testing easier BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/netcmd/spn.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/python/samba/netcmd/spn.py b/python/samba/netcmd/spn.py index f0069460e3e..46e9c59272a 100644 --- a/python/samba/netcmd/spn.py +++ b/python/samba/netcmd/spn.py @@ -18,7 +18,6 @@ import samba.getopt as options import ldb -from samba import provision from samba.samdb import SamDB from samba.auth import system_session from samba.netcmd.common import _get_user_realm_domain @@ -40,14 +39,20 @@ class cmd_spn_list(Command): "credopts": options.CredentialsOptions, "versionopts": options.VersionOptions, } + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", + type=str, metavar="URL", dest="H"), + ] takes_args = ["user"] - def run(self, user, credopts=None, sambaopts=None, versionopts=None): + def run(self, user, H=None, + credopts=None, + sambaopts=None, + versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) - paths = provision.provision_paths_from_lp(lp, lp.get("realm")) - sam = SamDB(paths.samdb, session_info=system_session(), + sam = SamDB(H, session_info=system_session(), credentials=creds, lp=lp) # TODO once I understand how, use the domain info to naildown # to the correct domain @@ -82,17 +87,20 @@ class cmd_spn_add(Command): "versionopts": options.VersionOptions, } takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", + type=str, metavar="URL", dest="H"), Option("--force", help="Force the addition of the spn" " even it exists already", action="store_true"), - ] + ] takes_args = ["name", "user"] - def run(self, name, user, force=False, credopts=None, sambaopts=None, + def run(self, name, user, H=None, force=False, + credopts=None, + sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) - paths = provision.provision_paths_from_lp(lp, lp.get("realm")) - sam = SamDB(paths.samdb, session_info=system_session(), + sam = SamDB(H, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), @@ -141,15 +149,18 @@ class cmd_spn_delete(Command): "credopts": options.CredentialsOptions, "versionopts": options.VersionOptions, } + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", + type=str, metavar="URL", dest="H"), + ] takes_args = ["name", "user?"] - def run(self, name, user=None, credopts=None, sambaopts=None, + def run(self, name, user=None, H=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) - paths = provision.provision_paths_from_lp(lp, lp.get("realm")) - sam = SamDB(paths.samdb, session_info=system_session(), + sam = SamDB(H, session_info=system_session(), credentials=creds, lp=lp) res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), -- 2.25.1 From 5a3d01aee24cf5677afbe580f90e557911ba4fb0 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 27 Aug 2021 11:36:42 +1200 Subject: [PATCH 543/645] CVE-2020-25722 samba-tool spn add: remove --force option This did not actually *force* the creation of a duplicate SPN, it just ignored the client-side check for the existing copy. Soon we are going to enforce SPN uniqueness on the server side, and this --force will not work. This will make the --force test fail, and if that tests fail, so will others that depend the duplicate values. So we remove those tests. It is wrong-headed to try to make duplicate SPNs in any case, which is probably why there is no sign of anyone ever having used this option. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/netcmd/spn.py | 6 ++---- source4/setup/tests/blackbox_spn.sh | 5 +---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/python/samba/netcmd/spn.py b/python/samba/netcmd/spn.py index 46e9c59272a..2676ff34fac 100644 --- a/python/samba/netcmd/spn.py +++ b/python/samba/netcmd/spn.py @@ -89,12 +89,10 @@ class cmd_spn_add(Command): takes_options = [ Option("-H", "--URL", help="LDB URL for database or target server", type=str, metavar="URL", dest="H"), - Option("--force", help="Force the addition of the spn" - " even it exists already", action="store_true"), ] takes_args = ["name", "user"] - def run(self, name, user, H=None, force=False, + def run(self, name, user, H=None, credopts=None, sambaopts=None, versionopts=None): @@ -105,7 +103,7 @@ class cmd_spn_add(Command): res = sam.search( expression="servicePrincipalName=%s" % ldb.binary_encode(name), scope=ldb.SCOPE_SUBTREE) - if len(res) != 0 and not force: + if len(res) != 0: raise CommandError("Service principal %s already" " affected to another user" % name) diff --git a/source4/setup/tests/blackbox_spn.sh b/source4/setup/tests/blackbox_spn.sh index 429ace9494f..764ded4c88b 100755 --- a/source4/setup/tests/blackbox_spn.sh +++ b/source4/setup/tests/blackbox_spn.sh @@ -22,11 +22,8 @@ testit "addspn" $PYTHON $samba_tool spn add FOO/bar Administrator $CONFIG testit "delspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG testit "readdspn" $PYTHON $samba_tool spn add FOO/bar Administrator $CONFIG testit_expect_failure "failexistingspn" $PYTHON $samba_tool spn add FOO/bar Guest $CONFIG -testit "existingspnforce" $PYTHON $samba_tool spn add --force FOO/bar Guest $CONFIG testit_expect_failure "faildelspnnotgooduser" $PYTHON $samba_tool spn delete FOO/bar krbtgt $CONFIG -testit_expect_failure "faildelspnmoreoneuser" $PYTHON $samba_tool spn delete FOO/bar $CONFIG -testit "deluserspn" $PYTHON $samba_tool spn delete FOO/bar Guest $CONFIG -testit "dellastuserspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG +testit "deluserspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG testit_expect_failure "faildelspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG testit_expect_failure "failaddspn" $PYTHON $samba_tool spn add FOO/bar nonexistinguser $CONFIG -- 2.25.1 From 87f702050b12ed65133903b07edba1dc9582ffc5 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 1 Sep 2021 18:35:02 +1200 Subject: [PATCH 544/645] CVE-2020-25722 tests: blackbox samba-tool spn non-admin test It is soon going to be impossible to add duplicate SPNs (short of going behind DSDB's back on the local filesystem). Our test of adding SPNs on non-admin users doubled as the test for adding a duplicate (using --force). As --force is gone, we add these tests on Guest after the SPN on Administrator is gone. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/setup/tests/blackbox_spn.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/setup/tests/blackbox_spn.sh b/source4/setup/tests/blackbox_spn.sh index 764ded4c88b..8f0258d0db8 100755 --- a/source4/setup/tests/blackbox_spn.sh +++ b/source4/setup/tests/blackbox_spn.sh @@ -24,6 +24,8 @@ testit "readdspn" $PYTHON $samba_tool spn add FOO/bar Administrator $CONFIG testit_expect_failure "failexistingspn" $PYTHON $samba_tool spn add FOO/bar Guest $CONFIG testit_expect_failure "faildelspnnotgooduser" $PYTHON $samba_tool spn delete FOO/bar krbtgt $CONFIG testit "deluserspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG +testit "readd_spn_guest" $PYTHON $samba_tool spn add FOO/bar Guest $CONFIG +testit "deluserspn_guest" $PYTHON $samba_tool spn delete FOO/bar Guest $CONFIG testit_expect_failure "faildelspn" $PYTHON $samba_tool spn delete FOO/bar $CONFIG testit_expect_failure "failaddspn" $PYTHON $samba_tool spn add FOO/bar nonexistinguser $CONFIG -- 2.25.1 From 2a67ea23e48f81780f7c8e94d706bb4f60acc360 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 28 Oct 2021 09:45:36 +1300 Subject: [PATCH 545/645] CVE-2020-25722 s4/provision: add host/ SPNs at the start There are two reasons for this. Firstly, leaving SPNs unclaimed is dangerous, as someone else could grab them first. Secondly, in some circumstances (self join) we try to add a DNS/ SPN a little bit later in provision. Under the rules we are introducing for CVE-2020-25722, this will make our later attempts to add HOST/ fail. This causes a few errors in samba4.blackbox.dbcheck.* tests, which assert that revivified old domains match stored reference versions. Now they don't, because they have servicePrincipalNames. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/cve-2020-25722-provision | 4 ++++ source4/setup/provision_self_join.ldif | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 selftest/knownfail.d/cve-2020-25722-provision diff --git a/selftest/knownfail.d/cve-2020-25722-provision b/selftest/knownfail.d/cve-2020-25722-provision new file mode 100644 index 00000000000..7fd4b4b3763 --- /dev/null +++ b/selftest/knownfail.d/cve-2020-25722-provision @@ -0,0 +1,4 @@ +samba4.blackbox.dbcheck.release-4-0-0 +samba4.blackbox.dbcheck.release-4-0-0.quick +samba4.blackbox.upgradeprovision.release-4-0-0 +samba4.blackbox.functionalprep.check_databases_same diff --git a/source4/setup/provision_self_join.ldif b/source4/setup/provision_self_join.ldif index f77ac5710ec..92bf4d9cf8f 100644 --- a/source4/setup/provision_self_join.ldif +++ b/source4/setup/provision_self_join.ldif @@ -15,11 +15,16 @@ localPolicyFlags: 0 operatingSystem: Samba operatingSystemVersion: ${SAMBA_VERSION_STRING} sAMAccountName: ${NETBIOSNAME}$ -# The "servicePrincipalName" updates are now handled by the "samba_spnupdate" -# script userAccountControl: 532480 clearTextPassword:: ${MACHINEPASS_B64} objectSid: ${DOMAINSID}-${DCRID} +# While some "servicePrincipalName" updates might be handled by the +# "samba_spnupdate" script, we need to get the basics in here before +# we add any others. +servicePrincipalName: HOST/${DNSNAME} +servicePrincipalName: HOST/${NETBIOSNAME} +servicePrincipalName: HOST/${DNSNAME}/${DNSNAME} + dn: CN=RID Set,CN=${NETBIOSNAME},OU=Domain Controllers,${DOMAINDN} objectClass: rIDSet -- 2.25.1 From 79789b1d8f48a87b1f614d54c6e77a5842a1280b Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 28 Oct 2021 13:07:01 +1300 Subject: [PATCH 546/645] CVE-2020-25722 blackbox/upgrades tests: ignore SPN for ldapcmp We need to have the SPNs there before someone else nabs them, which makes the re-provisioned old releases different from the reference versions that we keep for this comparison. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/cve-2020-25722-provision | 4 ---- source4/setup/tests/blackbox_upgradeprovision.sh | 8 ++++---- testprogs/blackbox/dbcheck-oldrelease.sh | 4 ++-- testprogs/blackbox/functionalprep.sh | 2 +- testprogs/blackbox/upgradeprovision-oldrelease.sh | 4 ++-- 5 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 selftest/knownfail.d/cve-2020-25722-provision diff --git a/selftest/knownfail.d/cve-2020-25722-provision b/selftest/knownfail.d/cve-2020-25722-provision deleted file mode 100644 index 7fd4b4b3763..00000000000 --- a/selftest/knownfail.d/cve-2020-25722-provision +++ /dev/null @@ -1,4 +0,0 @@ -samba4.blackbox.dbcheck.release-4-0-0 -samba4.blackbox.dbcheck.release-4-0-0.quick -samba4.blackbox.upgradeprovision.release-4-0-0 -samba4.blackbox.functionalprep.check_databases_same diff --git a/source4/setup/tests/blackbox_upgradeprovision.sh b/source4/setup/tests/blackbox_upgradeprovision.sh index 5222b5ca924..3fe33f9eaff 100755 --- a/source4/setup/tests/blackbox_upgradeprovision.sh +++ b/source4/setup/tests/blackbox_upgradeprovision.sh @@ -42,19 +42,19 @@ upgradeprovision_full() { # really doesn't change anything. ldapcmp() { - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --skip-missing-dn --filter=servicePrincipalName } ldapcmp_full() { - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision_full/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision_full/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --skip-missing-dn --filter=servicePrincipalName } ldapcmp_sd() { - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --sd --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --sd --skip-missing-dn --filter=servicePrincipalName } ldapcmp_full_sd() { - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision_full/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --sd --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX/upgradeprovision_full/private/sam.ldb tdb://$PREFIX/upgradeprovision_reference/private/sam.ldb --two --sd --skip-missing-dn --filter=servicePrincipalName } testit "upgradeprovision" upgradeprovision diff --git a/testprogs/blackbox/dbcheck-oldrelease.sh b/testprogs/blackbox/dbcheck-oldrelease.sh index 41c55178d4e..f33b5a2be3b 100755 --- a/testprogs/blackbox/dbcheck-oldrelease.sh +++ b/testprogs/blackbox/dbcheck-oldrelease.sh @@ -388,13 +388,13 @@ referenceprovision() { ldapcmp() { if [ x$RELEASE = x"release-4-0-0" ]; then - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --two --skip-missing-dn --filter=dnsRecord,displayName,msDS-SupportedEncryptionTypes + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --two --skip-missing-dn --filter=dnsRecord,displayName,msDS-SupportedEncryptionTypes,servicePrincipalName fi } ldapcmp_sd() { if [ x$RELEASE = x"release-4-0-0" ]; then - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --two --sd --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb --two --sd --skip-missing-dn --filter=servicePrincipalName fi } diff --git a/testprogs/blackbox/functionalprep.sh b/testprogs/blackbox/functionalprep.sh index 1d37611ef7a..0b776d9ab13 100755 --- a/testprogs/blackbox/functionalprep.sh +++ b/testprogs/blackbox/functionalprep.sh @@ -61,7 +61,7 @@ provision_2012r2() { ldapcmp_ignore() { # At some point we will need to ignore, but right now, it should be perfect IGNORE_ATTRS=$1 - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/$2/private/sam.ldb tdb://$PREFIX_ABS/$3/private/sam.ldb --two --skip-missing-dn --filter msDS-SupportedEncryptionTypes + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/$2/private/sam.ldb tdb://$PREFIX_ABS/$3/private/sam.ldb --two --skip-missing-dn --filter msDS-SupportedEncryptionTypes,servicePrincipalName } ldapcmp() { diff --git a/testprogs/blackbox/upgradeprovision-oldrelease.sh b/testprogs/blackbox/upgradeprovision-oldrelease.sh index 208baa54a02..557988fc393 100755 --- a/testprogs/blackbox/upgradeprovision-oldrelease.sh +++ b/testprogs/blackbox/upgradeprovision-oldrelease.sh @@ -106,12 +106,12 @@ referenceprovision() { ldapcmp() { if [ x$RELEASE != x"alpha13" ]; then - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_upgrade_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}_upgrade/private/sam.ldb --two --skip-missing-dn --filter=dnsRecord,displayName,msDS-SupportedEncryptionTypes + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_upgrade_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}_upgrade/private/sam.ldb --two --skip-missing-dn --filter=dnsRecord,displayName,msDS-SupportedEncryptionTypes,servicePrincipalName fi } ldapcmp_full() { - $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_upgrade_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}_upgrade_full/private/sam.ldb --two --filter=dNSProperty,dnsRecord,cn,displayName,versionNumber,systemFlags,msDS-HasInstantiatedNCs --skip-missing-dn + $PYTHON $BINDIR/samba-tool ldapcmp tdb://$PREFIX_ABS/${RELEASE}_upgrade_reference/private/sam.ldb tdb://$PREFIX_ABS/${RELEASE}_upgrade_full/private/sam.ldb --two --filter=dNSProperty,dnsRecord,cn,displayName,versionNumber,systemFlags,msDS-HasInstantiatedNCs,servicePrincipalName --skip-missing-dn } ldapcmp_sd() { -- 2.25.1 From 2367fb1209c346dcfd67bfa9b63a30c5481235cc Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Mon, 13 Sep 2021 14:15:09 +1200 Subject: [PATCH 547/645] CVE-2020-25722 pytest: test sAMAccountName/userPrincipalName over ldap Because the sam account name + the dns host name is used as the default user principal name, we need to check for collisions between these. Fixes are coming in upcoming patches. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/tests/ldap_upn_sam_account.py | 510 +++++++++++++++++++++ selftest/knownfail.d/ldap_upn_sam_account | 16 + source4/selftest/tests.py | 9 + 3 files changed, 535 insertions(+) create mode 100644 python/samba/tests/ldap_upn_sam_account.py create mode 100644 selftest/knownfail.d/ldap_upn_sam_account diff --git a/python/samba/tests/ldap_upn_sam_account.py b/python/samba/tests/ldap_upn_sam_account.py new file mode 100644 index 00000000000..cc1cce9b6c3 --- /dev/null +++ b/python/samba/tests/ldap_upn_sam_account.py @@ -0,0 +1,510 @@ +# Unix SMB/CIFS implementation. +# +# Copyright 2021 (C) Catalyst IT 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 samba.samdb import SamDB +from samba.auth import system_session +import ldb +from samba.tests.subunitrun import SubunitOptions, TestProgram +from samba.tests import TestCase, ldb_err +from samba.tests import DynamicTestCase +import samba.getopt as options +import optparse +from samba.colour import c_RED, c_GREEN, c_DARK_YELLOW +import re +import pprint +from samba.dsdb import ( + UF_SERVER_TRUST_ACCOUNT, + UF_TRUSTED_FOR_DELEGATION, +) + + +# bad sAMAccountName characters from [MS-SAMR] +# "3.1.1.6 Attribute Constraints for Originating Updates" +BAD_SAM_CHARS = (''.join(chr(x) for x in range(0, 32)) + + '"/\\[]:|<>+=;?,*') + +# 0x7f is *said* to be bad, but turns out to be fine. +ALLEGED_BAD_SAM_CHARS = chr(127) + +LATIN1_BAD_CHARS = set([chr(x) for x in range(129, 160)] + + list("ªºÿ") + + [chr(x) for x in range(0xc0, 0xc6)] + + [chr(x) for x in range(0xc7, 0xd7)] + + [chr(x) for x in range(0xd8, 0xde)] + + [chr(x) for x in range(0xe0, 0xe6)] + + [chr(x) for x in range(0xe7, 0xf7)] + + [chr(x) for x in range(0xf8, 0xfe)]) + + +LATIN_EXTENDED_A_NO_CLASH = {306, 307, 330, 331, 338, 339, 358, 359, 383} + +#XXX does '\x00' just truncate the string though? +#XXX elsewhere we see "[\\\"|,/:<>+=;?*']" with "'" + + +## UPN limits +# max length 1024 UTF-8 bytes, following "rfc822" +# for o365 sync https://docs.microsoft.com/en-us/microsoft-365/enterprise/prepare-for-directory-synchronization?view=o365-worldwide +# max length is 113 [64 before @] "@" [48 after @] +# invalid chars: '\\%&*+/=?{}|<>();:,[]"' +# allowed chars: A – Z, a - z, 0 – 9, ' . - _ ! # ^ ~ +# "Letters with diacritical marks, such as umlauts, accents, and tildes, are invalid characters." +# +# "@" can't be first +# "The username cannot end with a period (.), an ampersand (&), a space, or an at sign (@)." +# + +# per RFC 822, «"a b" @ example.org» is + + +ok = True +bad = False +report = 'report' +exists = ldb.ERR_ENTRY_ALREADY_EXISTS + + +if sys.stdout.isatty(): + c_doc = c_DARK_YELLOW +else: + c_doc = lambda x: x + + +def get_samdb(): + return SamDB(url=f"ldap://{SERVER}", + lp=LP, + session_info=system_session(), + credentials=CREDS) + + +def format(s): + if type(s) is str: + s = s.format(realm=REALM.upper(), + lrealm=REALM.lower(), + other_realm=(REALM + ".another.example.net")) + return s + + +class LdapUpnSamTestBase(TestCase): + """Make sure we can't add userPrincipalNames or sAMAccountNames that + implicitly collide. + """ + _disabled = False + + @classmethod + def setUpDynamicTestCases(cls): + if getattr(cls, '_disabled', False): + return + for doc, *rows in cls.cases: + name = re.sub(r'\W+', '_', doc) + cls.generate_dynamic_test("test_upn_sam", name, rows, doc) + + def setup_objects(self, rows): + objects = set(r[0] for r in rows) + for name in objects: + if ':' in name: + objtype, name = name.split(':', 1) + else: + objtype = 'user' + getattr(self, f'add_{objtype}')(name) + self.addCleanup(self.remove_object, name) + + def _test_upn_sam_with_args(self, rows, doc): + self.setup_objects(rows) + cdoc = c_doc(doc) + + for i, row in enumerate(rows): + if len(row) == 4: + obj, data, expected, op = row + else: + obj, data, expected = row + op = ldb.FLAG_MOD_REPLACE + + dn, dnsname = self.objects[obj] + sam, upn = None, None + if isinstance(data, dict): + sam = data.get('sam') + upn = data.get('upn') + elif isinstance(data, str): + if '@' in data: + upn = data + else: + sam = data + else: # bytes + if b'@' in data: + upn = data + else: + sam = data + + m = {"dn": dn} + + if upn is not None: + m["userPrincipalName"] = format(upn) + + if sam is not None: + m["sAMAccountName"] = format(sam) + + msg = ldb.Message.from_dict(self.samdb, m, op) + + if expected is bad: + try: + self.samdb.modify(msg) + except ldb.LdbError as e: + print(f"row {i+1} of '{cdoc}' failed as expected with " + f"{ldb_err(e)}\n") + continue + self.fail(f"row {i+1} of '{cdoc}' should have failed:\n" + f"{pprint.pformat(m)} on {obj}") + elif expected is ok: + try: + self.samdb.modify(msg) + except ldb.LdbError as e: + raise AssertionError( + f"row {i+1} of '{cdoc}' failed with {ldb_err(e)}:\n" + f"{pprint.pformat(m)} on {obj}") from None + elif expected is report: + try: + self.samdb.modify(msg) + print(f"row {i+1} of '{cdoc}' SUCCEEDED:\n" + f"{pprint.pformat(m)} on {obj}") + except ldb.LdbError as e: + print(f"row {i+1} of '{cdoc}' FAILED " + f"with {ldb_err(e)}:\n" + f"{pprint.pformat(m)} on {obj}") + + else: + try: + self.samdb.modify(msg) + except ldb.LdbError as e: + if hasattr(expected, '__contains__'): + if e.args[0] in expected: + continue + + if e.args[0] == expected: + continue + + self.fail(f"row {i+1} of '{cdoc}' " + f"should have failed with {ldb_err(expected)} " + f"but instead failed with {ldb_err(e)}:\n" + f"{pprint.pformat(m)} on {obj}") + self.fail(f"row {i+1} of '{cdoc}' " + f"should have failed with {ldb_err(expected)}:\n" + f"{pprint.pformat(m)} on {obj}") + + def add_dc(self, name): + dn = f"CN={name},OU=Domain Controllers,{self.base_dn}" + dnsname = f"{name}.{REALM}".lower() + self.samdb.add({ + "dn": dn, + "objectclass": "computer", + "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | + UF_TRUSTED_FOR_DELEGATION), + "dnsHostName": dnsname, + "carLicense": self.id() + }) + self.objects[name] = (dn, dnsname) + + def add_user(self, name): + dn = f"CN={name},{self.ou}" + self.samdb.add({ + "dn": dn, + "name": name, + "objectclass": "user", + "carLicense": self.id() + }) + self.objects[name] = (dn, None) + + def remove_object(self, name): + dn, dnsname = self.objects.pop(name) + self.samdb.delete(dn) + + def setUp(self): + super().setUp() + self.samdb = get_samdb() + self.base_dn = self.samdb.get_default_basedn() + self.short_id = self.id().rsplit('.', 1)[1][:63] + self.objects = {} + self.ou = f"OU={ self.short_id },{ self.base_dn }" + self.addCleanup(self.samdb.delete, self.ou, ["tree_delete:1"]) + self.samdb.add({"dn": self.ou, "objectclass": "organizationalUnit"}) + + +@DynamicTestCase +class LdapUpnSamTest(LdapUpnSamTestBase): + cases = [ + # The structure is + # ( «documentation/message that becomes test name», + # («short object id», «upn or sam or mapping», «expected»), + # («short object id», «upn or sam or mapping», «expected»), + # ..., + # ) + # + # where the first item is a one line string explaining the + # test, and subsequent items describe database modifications, + # to be applied in series. + # + # First is a short ID, which maps to an object DN. Second is + # either a string or a dictionary. + # + # * If a string, if it contains '@', it is a UPN, otherwise a + # samaccountname. + # + # * If a dictionary, it is a mapping of some of ['sam', 'upn'] + # to strings (in this way, you can add two attributes in one + # mesage, or attempt a samaccountname with '@'). + # + # expected can be «ok», «bad» (mapped to True and False, + # respectively), or a specific LDB error code, if that exact + # exception is wanted. + ("add good UPN", + ('A', 'a@{realm}', ok), + ), + ("add the same upn to different objects", + ('A', 'a@{realm}', ok), + ('B', 'a@{realm}', ldb.ERR_CONSTRAINT_VIOLATION), + ('B', 'a@{lrealm}', ldb.ERR_CONSTRAINT_VIOLATION), # lowercase realm + ), + ("replace UPN with itself", + ('A', 'a@{realm}', ok), + ('A', 'a@{realm}', ok), + ('A', 'a@{lrealm}', ok), + ), + ("replace SAM with itself", + ('A', 'a', ok), + ('A', 'a', ok), + ), + ("replace UPN realm", + ('A', 'a@{realm}', ok), + ('A', 'a@{other_realm}', ok), + ), + ("matching SAM and UPN", + ('A', 'a', ok), + ('A', 'a@{realm}', ok), + ), + ("matching SAM and UPN, other realm", + ('A', 'a', ok), + ('A', 'a@{other_realm}', ok), + ), + ("matching SAM and UPN, single message", + ('A', {'sam': 'a', 'upn': 'a@{realm}'}, ok), + ('A', {'sam': 'a', 'upn': 'a@{other_realm}'}, ok), + ), + ("different objects, different realms", + ('A', 'a@{realm}', ok), + ('B', 'a@{other_realm}', ok), + ), + ("different objects, same UPN, different case", + ('A', 'a@{realm}', ok), + ('B', 'A@{realm}', ldb.ERR_CONSTRAINT_VIOLATION), + ), + ("different objects, SAM after UPN", + ('A', 'a@{realm}', ok), + ('B', 'a', ldb.ERR_CONSTRAINT_VIOLATION), + ), + ("different objects, SAM before UPN", + ('A', 'a', ok), + ('B', 'a@{realm}', exists), + ), + ("different objects, SAM account clash", + ('A', 'a', ok), + ('B', 'a', exists), + ), + ("different objects, SAM account clash, different case", + ('A', 'a', ok), + ('B', 'A', exists), + ), + ("two way clash", + ('A', {'sam': 'x', 'upn': 'y@{realm}'}, ok), + # The sam account raises EXISTS while the UPN raises + # CONSTRAINT_VIOLATION. We don't really care in which order + # they are checked, so either error is ok. + ('B', {'sam': 'y', 'upn': 'x@{realm}'}, + (exists, ldb.ERR_CONSTRAINT_VIOLATION)), + ), + ("two way clash, other realm", + ('A', {'sam': 'x', 'upn': 'y@{other_realm}'}, ok), + ('B', {'sam': 'y', 'upn': 'x@{other_realm}'}, ok), + ), + # UPN versions of bad sam account names + ("UPN clash on other realm", + ('A', 'a@x.x', ok), + ('B', 'a@x.x', ldb.ERR_CONSTRAINT_VIOLATION), + ), + ("UPN same but for trailing spaces", + ('A', 'a@{realm}', ok), + ('B', 'a @{realm}', ok), + ), + # UPN has no at + ("UPN has no at", + ('A', {'upn': 'noat'}, ok), + ('B', {'upn': 'noat'}, ldb.ERR_CONSTRAINT_VIOLATION), + ('C', {'upn': 'NOAT'}, ldb.ERR_CONSTRAINT_VIOLATION), + ), + # UPN has non-ascii at, followed by real at. + ("UPN with non-ascii at vs real at", + ('A', {'upn': 'smallat﹫{realm}'}, ok), + ('B', {'upn': 'smallat@{realm}'}, ok), + ('C', {'upn': 'tagat\U000e0040{realm}'}, ok), + ('D', {'upn': 'tagat@{realm}'}, ok), + ), + ("UPN with unicode at vs real at, real at first", + ('B', {'upn': 'smallat@{realm}'}, ok), + ('A', {'upn': 'smallat﹫{realm}'}, ok), + ('D', {'upn': 'tagat@{realm}'}, ok), + ('C', {'upn': 'tagat\U000e0040{realm}'}, ok), + ), + ("UPN username too long", + # SPN soft limit 20; hard limit 256, overall UPN 1024 + ('A', 'a' * 25 + '@b.c', ok), + ('A', 'a' * 65 + '@b.c', ok), # Azure AD limit is 64 + ('A', 'a' * 257 + '@b.c', ok), # 256 is sam account name limit + ), + ("sam account name 20 long", + # SPN soft limit 20 + ('A', 'a' * 20, ok), + ), + ("UPN has two at signs", + ('A', 'a@{realm}', ok), + ('A', 'a@{realm}@{realm}', ok), + ('A', 'a@a.b', ok), + ('A', 'a@a@a.b', ok), + ), + ("SAM has at signs clashing upn second, non-realm", + ('A', {'sam': 'a@a.b'}, ok), + ('B', 'a@a.b@a.b', ok), # UPN won't clash with SAM, because realm + ), + ("SAM has at signs clashing upn second", + ('A', {'sam': 'a@{realm}'}, ok), + ('B', 'a@{realm}@{realm}', bad), # UPN would clashes with SAM + ), + ("SAM has at signs clashing upn first", + ('B', 'a@{realm}@{realm}', ok), + ('A', {'sam': 'a@{realm}'}, bad), + ), + ("spaces around at", + ('A', 'a name @ {realm}', ok), + ('B', 'a name @ {realm}', ldb.ERR_CONSTRAINT_VIOLATION), + ('B', 'a name @{realm}', ok), # because realm looks different + ('C', 'a name@{realm}', ok), + ('D', 'a name', ldb.ERR_CONSTRAINT_VIOLATION), + ('D', 'a name ', (exists, ldb.ERR_CONSTRAINT_VIOLATION)), # matches B + ), + ("SAM starts with at", + ('A', {'sam': '@{realm}'}, ok), + ('B', {'sam': '@a'}, ok), + ('C', {'sam': '@{realm}'}, exists), + ('C', {'sam': '@a'}, exists), + ('C', {'upn': '@{realm}@{realm}'}, bad), + ('C', {'upn': '@a@{realm}'}, bad), + ), + ("UPN starts with at", + ('A', {'upn': '@{realm}'}, ok), + ('B', {'upn': '@a@{realm}'}, ok), + ('C', {'upn': '@{realm}'}, bad), + ('C', {'sam': '@a'}, bad), + ), + ("SAM ends with at", + ('A', {'sam': '{realm}@'}, ok), + ('B', {'sam': 'a@'}, ok), + ('C', {'sam': '{realm}@'}, exists), + ('C', {'sam': 'a@'}, exists), + ('C', {'upn': 'a@@{realm}'}, bad), + ('C', {'upn': '{realm}@@{realm}'}, bad), + ), + ("UPN ends with at", + ('A', {'upn': '{realm}@'}, ok), + ('B', {'upn': '@a@{realm}@'}, ok), + ('C', {'upn': '{realm}@'}, bad), + ('C', {'sam': '@a@{realm}'}, ok), # not like B, because other realm + ), + ] + + +@DynamicTestCase +class LdapUpnSamSambaOnlyTest(LdapUpnSamTestBase): + # We don't run these ones outside of selftest, where we are + # probably testing against Windows and these are known failures. + _disabled = 'SAMBA_SELFTEST' not in os.environ + cases = [ + ("sam account name too long", + # SPN soft limit 20 + ('A', 'a' * 19, ok), + ('A', 'a' * 20, ok), + ('A', 'a' * 65, ok), + ('A', 'a' * 255, ok), + ('A', 'a' * 256, ok), + ('A', 'a' * 257, ldb.ERR_INVALID_ATTRIBUTE_SYNTAX), + ), + ("UPN username too long", + ('A', 'a' * 254 + '@' + 'b.c' * 257, + ldb.ERR_INVALID_ATTRIBUTE_SYNTAX), # 1024 is alleged UPN limit + ), + ("UPN same but for internal spaces", + ('A', 'a b@x.x', ok), + ('B', 'a b@x.x', ldb.ERR_CONSTRAINT_VIOLATION), + ), + ("SAM contains delete", + # forbidden according to documentation, but works in practice on Windows + ('A', 'a\x7f', ldb.ERR_CONSTRAINT_VIOLATION), + ('A', 'a\x7f'.encode(), ldb.ERR_CONSTRAINT_VIOLATION), + ('A', 'a\x7fb', ldb.ERR_CONSTRAINT_VIOLATION), + ('A', 'a\x7fb'.encode(), ldb.ERR_CONSTRAINT_VIOLATION), + ('A', '\x7fb', ldb.ERR_CONSTRAINT_VIOLATION), + ('A', '\x7fb'.encode(), ldb.ERR_CONSTRAINT_VIOLATION), + ), + # The wide at symbol ('@' U+FF20) does not count as '@' for Samba + # so it will look like a string with no @s. + ("UPN with unicode wide at vs real at", + ('A', {'upn': 'wideat@{realm}'}, ok), + ('B', {'upn': 'wideat@{realm}'}, ok), + ), + ("UPN with real at vs wide at", + ('B', {'upn': 'wideat@{realm}'}, ok), + ('A', {'upn': 'wideat@{realm}'}, ok) + ), + ] + + +def main(): + global LP, CREDS, SERVER, REALM + + parser = optparse.OptionParser( + "python3 ldap_upn_sam_account_name.py [options]") + sambaopts = options.SambaOptions(parser) + parser.add_option_group(sambaopts) + + # use command line creds if available + credopts = options.CredentialsOptions(parser) + parser.add_option_group(credopts) + subunitopts = SubunitOptions(parser) + parser.add_option_group(subunitopts) + + opts, args = parser.parse_args() + if len(args) != 1: + parser.print_usage() + sys.exit(1) + + LP = sambaopts.get_loadparm() + CREDS = credopts.get_credentials(LP) + SERVER = args[0] + REALM = CREDS.get_realm() + + TestProgram(module=__name__, opts=subunitopts) + +main() diff --git a/selftest/knownfail.d/ldap_upn_sam_account b/selftest/knownfail.d/ldap_upn_sam_account new file mode 100644 index 00000000000..c4d494968b2 --- /dev/null +++ b/selftest/knownfail.d/ldap_upn_sam_account @@ -0,0 +1,16 @@ +samba.tests.ldap_upn_sam_account.+LdapUpnSamSambaOnlyTest.test_upn_sam_SAM_contains_delete +samba.tests.ldap_upn_sam_account.+LdapUpnSamSambaOnlyTest.test_upn_sam_UPN_same_but_for_internal_spaces +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_ends_with_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_has_at_signs_clashing_upn_first +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_has_at_signs_clashing_upn_second +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_starts_with_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_clash_on_other_realm +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_ends_with_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_has_no_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_starts_with_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_add_the_same_upn_to_different_objects +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_SAM_after_UPN +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_SAM_before_UPN +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_same_UPN_different_case +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_spaces_around_at +samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_two_way_clash diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 50c838f6098..be4696f4cbc 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -983,6 +983,15 @@ planoldpythontestsuite("ad_dc", extra_args=['-U"$USERNAME%$PASSWORD"'], environ={'TEST_ENV': 'ad_dc'}) +plantestsuite_loadlist("samba.tests.ldap_upn_sam_account", "ad_dc", + [python, + f"{srcdir()}/python/samba/tests/ldap_upn_sam_account.py", + '$SERVER', + '-U"$USERNAME%$PASSWORD"', + '--workgroup=$DOMAIN', + '$LOADLIST', '$LISTOPT']) + + plantestsuite_loadlist("samba4.tokengroups.krb5.python(ad_dc_default)", "ad_dc_default:local", [python, os.path.join(DSDB_PYTEST_DIR, "token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '-k', 'yes', '$LOADLIST', '$LISTOPT']) plantestsuite_loadlist("samba4.tokengroups.ntlm.python(ad_dc_default)", "ad_dc_default:local", [python, os.path.join(DSDB_PYTEST_DIR, "token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '-k', 'no', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.sam.python(fl2008r2dc)", "fl2008r2dc", [python, os.path.join(DSDB_PYTEST_DIR, "sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) -- 2.25.1 From 50f4e7070a0bc3418a6051254559980db15d55a6 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 6 Aug 2021 12:03:18 +1200 Subject: [PATCH 548/645] CVE-2020-25722 pytest: test setting servicePrincipalName over ldap BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- python/samba/tests/ldap_spn.py | 917 +++++++++++++++++++++++++++++++++ selftest/knownfail.d/ldap_spn | 26 + source4/selftest/tests.py | 10 +- 3 files changed, 952 insertions(+), 1 deletion(-) create mode 100644 python/samba/tests/ldap_spn.py create mode 100644 selftest/knownfail.d/ldap_spn diff --git a/python/samba/tests/ldap_spn.py b/python/samba/tests/ldap_spn.py new file mode 100644 index 00000000000..8a398ffaa49 --- /dev/null +++ b/python/samba/tests/ldap_spn.py @@ -0,0 +1,917 @@ +# Unix SMB/CIFS implementation. +# +# Copyright 2021 (C) Catalyst IT 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 sys +import os +import pprint +import re +from samba.samdb import SamDB +from samba.auth import system_session +import ldb +from samba.sd_utils import SDUtils +from samba.credentials import DONT_USE_KERBEROS, Credentials +from samba.gensec import FEATURE_SEAL +from samba.tests.subunitrun import SubunitOptions, TestProgram +from samba.tests import TestCase, ldb_err +from samba.tests import DynamicTestCase +import samba.getopt as options +import optparse +from samba.colour import c_RED, c_GREEN, c_DARK_YELLOW +from samba.dsdb import ( + UF_SERVER_TRUST_ACCOUNT, + UF_TRUSTED_FOR_DELEGATION, +) + + +SPN_GUID = 'f3a64788-5306-11d1-a9c5-0000f80367c1' + +RELEVANT_ATTRS = {'dNSHostName', + 'servicePrincipalName', + 'sAMAccountName', + 'dn'} + +ok = True +bad = False +report = 'report' + +operr = ldb.ERR_OPERATIONS_ERROR +denied = ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS +constraint = ldb.ERR_CONSTRAINT_VIOLATION +exists = ldb.ERR_ENTRY_ALREADY_EXISTS + +add = ldb.FLAG_MOD_ADD +replace = ldb.FLAG_MOD_REPLACE +delete = ldb.FLAG_MOD_DELETE + +try: + breakpoint +except NameError: + # for python <= 3.6 + def breakpoint(): + import pdb + pdb.set_trace() + + +def init(): + # This needs to happen before the class definition, and we put it + # in a function to keep the namespace clean. + global LP, CREDS, SERVER, REALM, COLOUR_TEXT, subunitopts, FILTER + + parser = optparse.OptionParser( + "python3 ldap_spn.py [options]") + sambaopts = options.SambaOptions(parser) + parser.add_option_group(sambaopts) + + # use command line creds if available + credopts = options.CredentialsOptions(parser) + parser.add_option_group(credopts) + subunitopts = SubunitOptions(parser) + parser.add_option_group(subunitopts) + + parser.add_option('--colour', action="store_true", + help="use colour text", + default=sys.stdout.isatty()) + + parser.add_option('--filter', help="only run tests matching this regex") + + opts, args = parser.parse_args() + if len(args) != 1: + parser.print_usage() + sys.exit(1) + + LP = sambaopts.get_loadparm() + CREDS = credopts.get_credentials(LP) + SERVER = args[0] + REALM = CREDS.get_realm() + COLOUR_TEXT = opts.colour + FILTER = opts.filter + + +init() + + +def colour_text(x, state=None): + if not COLOUR_TEXT: + return x + if state == 'error': + return c_RED(x) + if state == 'pass': + return c_GREEN(x) + + return c_DARK_YELLOW(x) + + +def get_samdb(creds=None): + if creds is None: + creds = CREDS + session = system_session() + else: + session = None + + return SamDB(url=f"ldap://{SERVER}", + lp=LP, + session_info=session, + credentials=creds) + + +def add_unpriv_user(samdb, ou, username, + writeable_objects=None, + password="samba123@"): + creds = Credentials() + creds.set_username(username) + creds.set_password(password) + creds.set_domain(CREDS.get_domain()) + creds.set_realm(CREDS.get_realm()) + creds.set_workstation(CREDS.get_workstation()) + creds.set_gensec_features(CREDS.get_gensec_features() | FEATURE_SEAL) + creds.set_kerberos_state(DONT_USE_KERBEROS) + dnstr = f"CN={username},{ou}" + + # like, WTF, samdb.newuser(), this is what you make us do. + short_ou = ou.split(',', 1)[0] + + samdb.newuser(username, password, userou=short_ou) + + if writeable_objects: + sd_utils = SDUtils(samdb) + sid = sd_utils.get_object_sid(dnstr) + for obj in writeable_objects: + mod = f"(OA;CI;WP;{ SPN_GUID };;{ sid })" + sd_utils.dacl_add_ace(obj, mod) + + unpriv_samdb = get_samdb(creds=creds) + return unpriv_samdb + + +class LdapSpnTestBase(TestCase): + _disabled = False + + @classmethod + def setUpDynamicTestCases(cls): + if getattr(cls, '_disabled', False): + return + for doc, *rows in cls.cases: + if FILTER: + if not re.search(FILTER, doc): + continue + name = re.sub(r'\W+', '_', doc) + cls.generate_dynamic_test("test_spn", name, rows, doc) + + def setup_objects(self, rows): + objects = set(r[0] for r in rows) + for name in objects: + if ':' in name: + objtype, name = name.split(':', 1) + else: + objtype = 'dc' + getattr(self, f'add_{objtype}')(name) + + def setup_users(self, rows): + # When you are adding an SPN that aliases (or would be aliased + # by) another SPN on another object, you need to have write + # permission on that other object too. + # + # To test this negatively and positively, we need to have + # users with various combinations of write permission, which + # means fiddling with SDs on the objects. + # + # The syntax is: + # '' : user with no special permissions + # '*' : admin user + # 'A' : user can write to A only + # 'A,C' : user can write to A and C + # 'C,A' : same, but makes another user + self.userdbs = { + '*': self.samdb + } + + permissions = set(r[2] for r in rows) + for p in permissions: + if p == '*': + continue + if p == '': + user = 'nobody' + writeable_objects = None + else: + user = 'writes_' + p.replace(",", '_') + writeable_objects = [self.objects[x][0] for x in p.split(',')] + + self.userdbs[p] = add_unpriv_user(self.samdb, self.ou, user, + writeable_objects) + + def _test_spn_with_args(self, rows, doc): + cdoc = colour_text(doc) + edoc = colour_text(doc, 'error') + pdoc = colour_text(doc, 'pass') + + if COLOUR_TEXT: + sys.stderr.flush() + print('\n', c_DARK_YELLOW('#' * 10), f'starting «{cdoc}»\n') + sys.stdout.flush() + + self.samdb = get_samdb() + self.base_dn = self.samdb.get_default_basedn() + self.short_id = self.id().rsplit('.', 1)[1][:63] + self.objects = {} + self.ou = f"OU={ self.short_id },{ self.base_dn }" + self.addCleanup(self.samdb.delete, self.ou, ["tree_delete:1"]) + self.samdb.create_ou(self.ou) + + self.setup_objects(rows) + self.setup_users(rows) + + for i, row in enumerate(rows): + if len(row) == 5: + obj, data, rights, expected, op = row + else: + obj, data, rights, expected = row + op = ldb.FLAG_MOD_REPLACE + + # We use this DB with possibly restricted rights for this row + samdb = self.userdbs[rights] + + if ':' in obj: + objtype, obj = obj.split(':', 1) + else: + objtype = 'dc' + + dn, dnsname = self.objects[obj] + m = {"dn": dn} + + if isinstance(data, dict): + m.update(data) + else: + m['servicePrincipalName'] = data + + # for python's sake (and our sanity) we try to ensure we + # have consistent canonical case in our attributes + keys = set(m.keys()) + if not keys.issubset(RELEVANT_ATTRS): + raise ValueError(f"unexpected attr {keys - RELEVANT_ATTRS}. " + "Casefold typo?") + + for k in ('dNSHostName', 'servicePrincipalName'): + if isinstance(m.get(k), str): + m[k] = m[k].format(dnsname=f"x.{REALM}") + + msg = ldb.Message.from_dict(samdb, m, op) + + if expected is bad: + try: + samdb.modify(msg) + except ldb.LdbError as e: + print(f"row {i+1} of '{pdoc}' failed as expected with " + f"{ldb_err(e)}\n") + continue + self.fail(f"row {i+1}: " + f"{rights} {pprint.pformat(m)} on {objtype} {obj} " + f"should fail ({edoc})") + + elif expected is ok: + try: + samdb.modify(msg) + except ldb.LdbError as e: + self.fail(f"row {i+1} of {edoc} failed with {ldb_err(e)}:\n" + f"{rights} {pprint.pformat(m)} on {objtype} {obj}") + + elif expected is report: + try: + self.samdb.modify(msg) + print(f"row {i+1} " + f"of '{cdoc}' {colour_text('SUCCEEDED', 'pass')}:\n" + f"{pprint.pformat(m)} on {obj}") + except ldb.LdbError as e: + print(f"row {i+1} " + f"of '{cdoc}' {colour_text('FAILED', 'error')} " + f"with {ldb_err(e)}:\n{pprint.pformat(m)} on {obj}") + + elif expected is breakpoint: + try: + breakpoint() + samdb.modify(msg) + except ldb.LdbError as e: + print(f"row {i+1} of '{pdoc}' FAILED with {ldb_err(e)}\n") + + else: # an ldb error number + try: + samdb.modify(msg) + except ldb.LdbError as e: + if e.args[0] == expected: + continue + self.fail(f"row {i+1} of '{edoc}' " + f"should have failed with {ldb_err(expected)}:\n" + f"not {ldb_err(e)}:\n" + f"{rights} {pprint.pformat(m)} on {objtype} {obj}") + self.fail(f"row {i+1} of '{edoc}' " + f"should have failed with {ldb_err(expected)}:\n" + f"{rights} {pprint.pformat(m)} on {objtype} {obj}") + + def add_dc(self, name): + dn = f"CN={name},OU=Domain Controllers,{self.base_dn}" + dnsname = f"{name}.{REALM}".lower() + self.samdb.add({ + "dn": dn, + "objectclass": "computer", + "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | + UF_TRUSTED_FOR_DELEGATION), + "dnsHostName": dnsname, + "carLicense": self.id() + }) + self.addCleanup(self.remove_object, name) + self.objects[name] = (dn, dnsname) + + def add_user(self, name): + dn = f"CN={name},{self.ou}" + self.samdb.add({ + "dn": dn, + "name": name, + "samAccountName": name, + "objectclass": "user", + "carLicense": self.id() + }) + self.addCleanup(self.remove_object, name) + self.objects[name] = (dn, None) + + def remove_object(self, name): + dn, dnsname = self.objects.pop(name) + self.samdb.delete(dn) + + +@DynamicTestCase +class LdapSpnTest(LdapSpnTestBase): + """Make sure we can't add clashing servicePrincipalNames. + + This would be possible using sPNMappings aliases — for example, if + the mapping maps host/ to cifs/, we should not be able to add + different addresses for each. + """ + + # default sPNMappings: host=alerter, appmgmt, cisvc, clipsrv, + # browser, dhcp, dnscache, replicator, eventlog, eventsystem, + # policyagent, oakley, dmserver, dns, mcsvc, fax, msiserver, ias, + # messenger, netlogon, netman, netdde, netddedsm, nmagent, + # plugplay, protectedstorage, rasman, rpclocator, rpc, rpcss, + # remoteaccess, rsvp, samss, scardsvr, scesrv, seclogon, scm, + # dcom, cifs, spooler, snmp, schedule, tapisrv, trksvr, trkwks, + # ups, time, wins, www, http, w3svc, iisadmin, msdtc + # + # I think in practice this is rarely if ever changed or added to. + + cases = [ + ("add one as admin", + ('A', 'host/{dnsname}', '*', ok), + ), + ("add one as rightful user", + ('A', 'host/{dnsname}', 'A', ok), + ), + ("attempt to add one as nobody", + ('A', 'host/{dnsname}', '', denied), + ), + + ("add and replace as admin", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/x.{dnsname}', '*', ok), + ), + ("replace as rightful user", + ('A', 'host/{dnsname}', 'A', ok), + ('A', 'host/x.{dnsname}', 'A', ok), + ), + ("attempt to replace one as nobody", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/x.{dnsname}', '', denied), + ), + + ("add second as admin", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/x.{dnsname}', '*', ok, add), + ), + ("add second as rightful user", + ('A', 'host/{dnsname}', 'A', ok), + ('A', 'host/x.{dnsname}', 'A', ok, add), + ), + ("attempt to add second as nobody", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/x.{dnsname}', '', denied, add), + ), + + ("add the same one twice, simple duplicate error", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '*', bad, add), + ), + ("simple duplicate attributes, as non-admin", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', 'A', bad, add), + ), + + ("add the same one twice, identical duplicate", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '*', bad, add), + ), + + ("add a conflict, host first, as nobody", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', '', denied), + ), + + ("add a conflict, service first, as nobody", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'host/{dnsname}', '', denied), + ), + + + ("three way conflict, host first, as admin", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', '*', ok), + ('C', 'www/z.{dnsname}', '*', ok), + ), + ("three way conflict, host first, with sufficient rights", + ('A', 'host/z.{dnsname}', 'A', ok), + ('B', 'cifs/z.{dnsname}', 'B,A', ok), + ('C', 'www/z.{dnsname}', 'C,A', ok), + ), + ("three way conflict, host first, adding duplicate", + ('A', 'host/z.{dnsname}', 'A', ok), + ('B', 'cifs/z.{dnsname}', 'B,A', ok), + ('C', 'cifs/z.{dnsname}', 'C,A', bad), + ), + ("three way conflict, host first, adding duplicate, full rights", + ('A', 'host/z.{dnsname}', 'A', ok), + ('B', 'cifs/z.{dnsname}', 'B,A', ok), + ('C', 'cifs/z.{dnsname}', 'C,B,A', bad), + ), + + ("three way conflict, host first, with other write rights", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', 'A,B', ok), + ('C', 'cifs/z.{dnsname}', 'A,B', bad), + + ), + ("three way conflict, host first, as nobody", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', '*', ok), + ('C', 'www/z.{dnsname}', '', denied), + ), + + ("three way conflict, services first, as admin", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'www/{dnsname}', '*', ok), + ('C', 'host/{dnsname}', '*', constraint), + ), + ("three way conflict, services first, with service write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'www/{dnsname}', '*', ok), + ('C', 'host/{dnsname}', 'A,B', bad), + ), + + ("three way conflict, service first, as nobody", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'www/{dnsname}', '*', ok), + ('C', 'host/{dnsname}', '', denied), + ), + ("replace host before specific", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok), + ), + ("replace host after specific, as nobody", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '', denied), + ), + + ("non-conflict host before specific", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok, add), + ), + ("non-conflict host after specific", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '*', ok, add), + ), + ("non-conflict host before specific, non-admin", + ('A', 'host/{dnsname}', 'A', ok), + ('A', 'cifs/{dnsname}', 'A', ok, add), + ), + ("non-conflict host after specific, as nobody", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '', denied, add), + ), + + ("add a conflict, host first on user, as admin", + ('user:C', 'host/{dnsname}', '*', ok), + ('B', 'cifs/{dnsname}', '*', ok), + ), + ("add a conflict, host first on user, host rights", + ('user:C', 'host/{dnsname}', '*', ok), + ('B', 'cifs/{dnsname}', 'C', denied), + ), + ("add a conflict, host first on user, both rights", + ('user:C', 'host/{dnsname}', '*', ok), + ('B', 'cifs/{dnsname}', 'B,C', ok), + ), + ("add a conflict, host first both on user", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}', '*', ok), + ), + ("add a conflict, host first both on user, host rights", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}', 'C', denied), + ), + ("add a conflict, host first both on user, both rights", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}', 'C,D', ok), + ), + ("add a conflict, host first both on user, as nobody", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}', '', denied), + ), + ("add a conflict, host first, with both write rights", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', 'A,B', ok), + ), + + ("add a conflict, host first, second on user, as admin", + ('A', 'host/{dnsname}', '*', ok), + ('user:D', 'cifs/{dnsname}', '*', ok), + ), + ("add a conflict, host first, second on user, with rights", + ('A', 'host/{dnsname}', '*', ok), + ('user:D', 'cifs/{dnsname}', 'A,D', ok), + ), + + ("nonsense SPNs, part 1, as admin", + ('A', 'a-b-c/{dnsname}', '*', ok), + ('A', 'rrrrrrrrrrrrr /{dnsname}', '*', ok), + ), + ("nonsense SPNs, part 1, as user", + ('A', 'a-b-c/{dnsname}', 'A', ok), + ('A', 'rrrrrrrrrrrrr /{dnsname}', 'A', ok), + ), + ("nonsense SPNs, part 1, as nobody", + ('A', 'a-b-c/{dnsname}', '', denied), + ('A', 'rrrrrrrrrrrrr /{dnsname}', '', denied), + ), + + ("add a conflict, using port", + ('A', 'dns/{dnsname}', '*', ok), + ('B', 'dns/{dnsname}:53', '*', ok), + ), + ("add a conflict, using port, port first", + ('user:C', 'dns/{dnsname}:53', '*', ok), + ('user:D', 'dns/{dnsname}', '*', ok), + ), + ("three part spns", + ('A', {'dNSHostName': '{dnsname}'}, '*', ok), + ('A', 'cifs/{dnsname}/DomainDNSZones.{dnsname}', '*', ok), + ('B', 'cifs/{dnsname}/DomainDNSZones.{dnsname}', '*', constraint), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}/DomainDNSZones.{dnsname}', '*', ok), + ('B', 'cifs/y.{dnsname}/DomainDNSZones.{dnsname}', '*', constraint), + ), + ("three part nonsense spns", + ('A', {'dNSHostName': 'bean'}, '*', ok), + ('A', 'cifs/bean/DomainDNSZones.bean', '*', ok), + ('B', 'cifs/bean/DomainDNSZones.bean', '*', constraint), + ('A', {'dNSHostName': 'y.bean'}, '*', ok), + ('B', 'cifs/bean/DomainDNSZones.bean', '*', ok), + ('B', 'cifs/y.bean/DomainDNSZones.bean', '*', constraint), + ('C', 'host/bean/bean', '*', ok), + ), + + ("one part spns (no slashes)", + ('A', '{dnsname}', '*', constraint), + ('B', 'cifs', '*', constraint), + ('B', 'cifs/', '*', ok), + ('B', ' ', '*', constraint), + ('user:C', 'host', '*', constraint), + ), + + ("dodgy spns", + # These tests pass on Windows. An SPN must have one or two + # slashes, with at least one character before the first one, + # UNLESS the first slash is followed by a good enough service + # name (e.g. "/host/x.y" rather than "sdfsd/x.y"). + ('A', '\\/{dnsname}', '*', ok), + ('B', 'cifs/\\\\{dnsname}', '*', ok), + ('B', r'cifs/\\\{dnsname}', '*', ok), + ('B', r'cifs/\\\{dnsname}/', '*', ok), + ('A', r'cīfs/\\\{dnsname}/', '*', constraint), # 'ī' maps to 'i' + # on the next two, full-width solidus (U+FF0F) does not work + # as '/'. + ('A', 'cifs/sfic', '*', constraint, add), + ('A', r'cifs/\\\{dnsname}', '*', constraint, add), + ('B', '\n', '*', constraint), + ('B', '\n/\n', '*', ok), + ('B', '\n/\n/\n', '*', ok), + ('B', '\n/\n/\n/\n', '*', constraint), + ('B', ' /* and so on */ ', '*', ok, add), + ('B', r'¯\_(ツ)_/¯', '*', ok, add), # ¯\_(ツ)_/¯ + # つ is hiragana for katakana ツ, so the next one fails for + # something analogous to casefold reasons. + ('A', r'¯\_(つ)_/¯', '*', constraint), + ('A', r'¯\_(㋡)_/¯', '*', constraint), # circled ツ + ('B', '//', '*', constraint), # all can't be empty, + ('B', ' //', '*', ok), # service can be space + ('B', '/host/{dnsname}', '*', ok), # or empty if others aren't + ('B', '/host/x.y.z', '*', ok), + ('B', '/ /x.y.z', '*', ok), + ('B', ' / / ', '*', ok), + ('user:C', b'host/', '*', ok), + ('user:C', ' /host', '*', ok), # service is ' ' (space) + ('B', ' /host', '*', constraint), # already on C + ('B', ' /HōST', '*', constraint), # ō equiv to O + ('B', ' /ħØşt', '*', constraint), # maps to ' /host' + ('B', ' /H0ST', '*', ok), # 0 is zero + ('B', ' /НoST', '*', ok), # Cyrillic Н (~N) + ('B', ' /host', '*', ok), # two space + ('B', '\u00a0/host', '*', ok), # non-breaking space + ('B', ' 2/HōST/⌷[ ][]¨(', '*', ok), + ('B', ' (//)', '*', ok, add), + ('B', ' ///', '*', constraint), + ('B', r' /\//', '*', constraint), # escape doesn't help + ('B', ' /\\//', '*', constraint), # double escape doesn't help + ('B', r'\//', '*', ok), + ('A', r'\\/\\/', '*', ok), + ('B', '|//|', '*', ok, add), + ('B', r'\/\/\\', '*', ok, add), + + ('A', ':', '*', constraint), + ('A', ':/:', '*', ok), + ('A', ':/:80', '*', ok), # port number syntax is not special + ('A', ':/:( ツ', '*', ok), + ('A', ':/:/:', '*', ok), + ('B', b'cifs/\x11\xaa\xbb\xcc\\example.com', '*', ok), + ('A', b':/\xcc\xcc\xcc\xcc', '*', ok), + ('A', b':/b\x00/b/b/b', '*', ok), # string handlng truncates at \x00 + ('A', b'a@b/a@b/a@b', '*', ok), + ('A', b'a/a@b/a@b', '*', ok), + ), + ("empty part spns (consecutive slashes)", + ('A', 'cifs//{dnsname}', '*', ok), + ('B', 'cifs//{dnsname}', '*', bad), # should clash with line 1 + ('B', 'cifs/zzzy.{dnsname}/', '*', ok), + ('B', '/host/zzzy.{dnsname}', '*', ok), + ), + ("too many spn parts", + ('A', 'cifs/{dnsname}/{dnsname}/{dnsname}', '*', bad), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}/{dnsname}/', '*', bad), + ('B', 'cifs/y.{dnsname}/{dnsname}/toop', '*', bad), + ('B', 'host/{dnsname}/a/b/c', '*', bad), + ), + ("add a conflict, host first, as admin", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', '*', ok), + ), + ("add a conflict, host first, with host write rights", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', 'A', denied), + ), + ("add a conflict, service first, with service write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'host/{dnsname}', 'A', denied), + ), + ("adding dNSHostName after cifs with no old dNSHostName", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}', '*', constraint), + ('B', 'cifs/y.{dnsname}', '*', ok), + ('B', 'host/y.{dnsname}', '*', ok), + ), + ("changing dNSHostName after cifs", + ('A', {'dNSHostName': '{dnsname}'}, '*', ok), + ('A', 'cifs/{dnsname}', '*', ok), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}', '*', ok), + ('B', 'cifs/y.{dnsname}', '*', bad), + ('B', 'host/y.{dnsname}', '*', bad), + ), + ] + + +@DynamicTestCase +class LdapSpnSambaOnlyTest(LdapSpnTestBase): + # We don't run these ones outside of selftest, where we are + # probably testing against Windows and these are known failures. + _disabled = 'SAMBA_SELFTEST' not in os.environ + cases = [ + ("add a conflict, host first, with service write rights", + ('A', 'host/z.{dnsname}', '*', ok), + ('B', 'cifs/z.{dnsname}', 'B', denied), + ), + ("add a conflict, service first, with host write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'host/{dnsname}', 'B', constraint), + ), + ("add a conflict, service first, as admin", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'host/{dnsname}', '*', constraint), + ), + ("add a conflict, service first, with both write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'host/{dnsname}', 'A,B', constraint), + ), + ("add a conflict, host first both on user, service rights", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}', 'D', denied), + ), + + ("changing dNSHostName after host", + ('A', {'dNSHostName': '{dnsname}'}, '*', ok), + ('A', 'host/{dnsname}', '*', ok), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}', 'B', ok), # no clash with A + ('B', 'cifs/y.{dnsname}', 'B', bad), # should clash with A + ('B', 'host/y.{dnsname}', '*', bad), + ), + + ("mystery dnsname clash, host first", + ('user:C', 'host/heeble.example.net', '*', ok), + ('user:D', 'www/heeble.example.net', '*', ok), + ), + ("mystery dnsname clash, www first", + ('user:D', 'www/heeble.example.net', '*', ok), + ('user:C', 'host/heeble.example.net', '*', constraint), + ), + ("replace as admin", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok), + ), + ("replace as non-admin with rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', 'A', ok), + ('A', 'cifs/{dnsname}', 'A', ok), + ), + ("replace vial delete as non-admin with rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', 'A', ok), + ('A', 'host/{dnsname}', 'A', ok, delete), + ('A', 'cifs/{dnsname}', 'A', ok, add), + ), + ("replace as non-admin without rights", + ('B', 'cifs/b', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', 'B', denied), + ('A', 'cifs/{dnsname}', 'B', denied), + ), + ("replace as nobody", + ('B', 'cifs/b', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '', denied), + ('A', 'cifs/{dnsname}', '', denied), + ), + ("accumulate and delete as admin", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', '*', ok, add), + ('A', 'www/{dnsname}', '*', ok, add), + ('A', 'www/...', '*', ok, add), + ('A', 'host/...', '*', ok, add), + ('A', 'www/{dnsname}', '*', ok, delete), + ('A', 'host/{dnsname}', '*', ok, delete), + ('A', 'host/{dnsname}', '*', ok, add), + ('A', 'www/{dnsname}', '*', ok, add), + ('A', 'host/...', '*', ok, delete), + ), + ("accumulate and delete with user rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'host/{dnsname}', 'A', ok, add), + ('A', 'www/{dnsname}', 'A', ok, add), + ('A', 'www/...', 'A', ok, add), + ('A', 'host/...', 'A', ok, add), + ('A', 'www/{dnsname}', 'A', ok, delete), + ('A', 'host/{dnsname}', 'A', ok, delete), + ('A', 'host/{dnsname}', 'A', ok, add), + ('A', 'www/{dnsname}', 'A', ok, add), + ('A', 'host/...', 'A', ok, delete), + ), + ("three way conflict, host first, with partial write rights", + ('A', 'host/z.{dnsname}', 'A', ok), + ('B', 'cifs/z.{dnsname}', 'B', denied), + ('C', 'www/z.{dnsname}', 'C', denied), + ), + ("three way conflict, host first, with partial write rights 2", + ('A', 'host/z.{dnsname}', 'A', ok), + ('B', 'cifs/z.{dnsname}', 'B', bad), + ('C', 'www/z.{dnsname}', 'C,A', ok), + ), + + ("three way conflict sandwich, sufficient rights", + ('B', 'host/{dnsname}', 'B', ok), + ('A', 'cifs/{dnsname}', 'A,B', ok), + # the replaces don't fail even though they appear to affect A + # and B, because they are effectively no-ops, leaving + # everything as it was before. + ('A', 'cifs/{dnsname}', 'A', ok), + ('B', 'host/{dnsname}', 'B', ok), + ('C', 'www/{dnsname}', 'A,B,C', ok), + ('C', 'www/{dnsname}', 'B,C', ok), + # because B already has host/, C doesn't matter + ('B', 'host/{dnsname}', 'A,B', ok), + # removing host (via replace) frees others, needs B only + ('B', 'ldap/{dnsname}', 'B', ok), + ('C', 'www/{dnsname}', 'C', ok), + ('A', 'cifs/{dnsname}', 'A', ok), + + # re-adding host is now impossible while A and C have {dnsname} spns + ('B', 'host/{dnsname}', '*', bad), + ('B', 'host/{dnsname}', 'A,B,C', bad), + # so let's remove those... (not needing B rights) + ('C', 'www/{dnsname}', 'C', ok, delete), + ('A', 'cifs/{dnsname}', 'A', ok, delete), + # and now we can add host/ again + ('B', 'host/{dnsname}', 'B', ok), + ('C', 'www/{dnsname}', 'B,C', ok, add), + ('A', 'cifs/{dnsname}', 'A,B', ok), + ), + ("three way conflict, service first, with all write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'www/{dnsname}', 'A,B,C', ok), + ('C', 'host/{dnsname}', 'A,B,C', bad), + ), + ("three way conflict, service first, just sufficient rights", + ('A', 'cifs/{dnsname}', 'A', ok), + ('B', 'www/{dnsname}', 'B', ok), + ('C', 'host/{dnsname}', 'A,B,C', bad), + ), + + ("three way conflict, service first, with host write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('B', 'www/{dnsname}', '*', ok), + ('C', 'host/{dnsname}', 'C', bad), + ), + ("three way conflict, service first, with both write rights", + ('A', 'cifs/{dnsname}', '*', ok), + ('A', 'cifs/{dnsname}', '*', ok, delete), + ('A', 'www/{dnsname}', 'A,B,C', ok), + ('B', 'host/{dnsname}', 'A,B', bad), + ('A', 'www/{dnsname}', 'A', ok, delete), + ('B', 'host/{dnsname}', 'A,B', ok), + ('C', 'cifs/{dnsname}', 'C', bad), + ('C', 'cifs/{dnsname}', 'B,C', ok), + ), + ("three way conflict, services first, with partial rights", + ('A', 'cifs/{dnsname}', 'A,C', ok), + ('B', 'www/{dnsname}', '*', ok), + ('C', 'host/{dnsname}', 'A,C', bad), + ), + ] + + +@DynamicTestCase +class LdapSpnAmbitiousTest(LdapSpnTestBase): + _disabled = True + cases = [ + ("add a conflict with port, host first both on user", + ('user:C', 'host/{dnsname}', '*', ok), + ('user:D', 'www/{dnsname}:80', '*', bad), + ), + # see https://bugzilla.samba.org/show_bug.cgi?id=8929 + ("add the same one twice, case-insensitive duplicate", + ('A', 'host/{dnsname}', '*', ok), + ('A', 'Host/{dnsname}', '*', bad, add), + ), + ("special SPN", + # should fail because we don't have all the DSA infrastructure + ('A', ("E3514235-4B06-11D1-AB04-00C04FC2DCD2/" + "75b84f00-a81b-4a19-8ef2-8e483cccff11/" + "{dnsname}"), '*', constraint) + ), + ("single part SPNs matching sAMAccountName", + # setting them both together is allegedly a MacOS behaviour, + # but all we get from Windows is a mysterious NO_SUCH_OBJECT. + ('user:A', {'sAMAccountName': 'A', + 'servicePrincipalName': 'A'}, '*', ldb.ERR_NO_SUCH_OBJECT), + ('user:B', {'sAMAccountName': 'B'}, '*', ok), + ('user:B', {'servicePrincipalName': 'B'}, '*', constraint), + ('user:C', {'servicePrincipalName': 'C'}, '*', constraint), + ('user:C', {'sAMAccountName': 'C'}, '*', ok), + ), + ("three part spns with dnsHostName", + ('A', {'dNSHostName': '{dnsname}'}, '*', ok), + ('A', 'cifs/{dnsname}/DomainDNSZones.{dnsname}', '*', ok), + ('A', {'dNSHostName': 'y.{dnsname}'}, '*', ok), + ('B', 'cifs/{dnsname}/DomainDNSZones.{dnsname}', '*', ok), + ('B', 'cifs/y.{dnsname}/DomainDNSZones.{dnsname}', '*', constraint), + ('C', 'host/{y.dnsname}/{y.dnsname}', '*', constraint), + ('A', 'host/y.{dnsname}/{dnsname}', '*', constraint), + ), + ] + + +def main(): + TestProgram(module=__name__, opts=subunitopts) + +main() diff --git a/selftest/knownfail.d/ldap_spn b/selftest/knownfail.d/ldap_spn new file mode 100644 index 00000000000..dc768728658 --- /dev/null +++ b/selftest/knownfail.d/ldap_spn @@ -0,0 +1,26 @@ +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_host_first_both_on_user_service_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_host_first_with_service_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_as_admin +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_with_both_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_with_host_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_changing_dNSHostName_after_host +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_mystery_dnsname_clash_www_first +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_host_first_with_partial_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_host_first_with_partial_write_rights_2 +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_sandwich_sufficient_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_just_sufficient_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_all_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_both_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_host_write_rights +samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_services_first_with_partial_rights +samba.tests.ldap_spn.+LdapSpnTest.test_spn_adding_dNSHostName_after_cifs_with_no_old_dNSHostName +samba.tests.ldap_spn.+LdapSpnTest.test_spn_changing_dNSHostName_after_cifs +samba.tests.ldap_spn.+LdapSpnTest.test_spn_dodgy_spns +samba.tests.ldap_spn.+LdapSpnTest.test_spn_empty_part_spns_consecutive_slashes_ +samba.tests.ldap_spn.+LdapSpnTest.test_spn_one_part_spns_no_slashes_ +samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_part_nonsense_spns +samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_part_spns +samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_host_first_adding_duplicate +samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_host_first_adding_duplicate_full_rights +samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_services_first_as_admin +samba.tests.ldap_spn.+LdapSpnTest.test_spn_too_many_spn_parts diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index be4696f4cbc..67764e43a9a 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -983,7 +983,15 @@ planoldpythontestsuite("ad_dc", extra_args=['-U"$USERNAME%$PASSWORD"'], environ={'TEST_ENV': 'ad_dc'}) -plantestsuite_loadlist("samba.tests.ldap_upn_sam_account", "ad_dc", +plantestsuite_loadlist("samba.tests.ldap_spn", "ad_dc", + [python, + f"{srcdir()}/python/samba/tests/ldap_spn.py", + '$SERVER', + '-U"$USERNAME%$PASSWORD"', + '--workgroup=$DOMAIN', + '$LOADLIST', '$LISTOPT']) + +plantestsuite_loadlist("samba.tests.ldap_upn_sam_account", "ad_dc_ntvfs", [python, f"{srcdir()}/python/samba/tests/ldap_upn_sam_account.py", '$SERVER', -- 2.25.1 From 6af521dcc089823c9ada5ddfa697cd95d12c052b Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 12 Aug 2021 21:53:16 +1200 Subject: [PATCH 549/645] CVE-2020-25722 s4/cracknames: add comment pointing to samldb spn handling These need to stay a little bit in sync. The reverse comment is there. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/cracknames.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index 235276bc4c8..5af62f0b71e 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -79,6 +79,12 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(struct ldb_context *ldb_ct const char *alias_from, char **alias_to) { + /* + * Some of the logic of this function is mirrored in find_spn_alias() + * in source4/dsdb.samdb/ldb_modules/samldb.c. If you change this to + * not return the first matched alias, you will need to rethink that + * function too. + */ unsigned int i; int ret; struct ldb_result *res; -- 2.25.1 From 7f9dcc06af52eec439cd9d3a06803fac7f0b6d3f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 14:12:25 +1300 Subject: [PATCH 550/645] CVE-2020-25722 s4/dsdb/samldb: add samldb_get_single_valued_attr() helper This takes a string of logic out of samldb_unique_attr_check() that we are going to need in other places, and that would be very tedious to repeat. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 6db7840b0c1..40dfab6390b 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -161,6 +161,55 @@ static int samldb_next_step(struct samldb_ctx *ac) } } +static int samldb_get_single_valued_attr(struct ldb_context *ldb, + struct samldb_ctx *ac, + const char *attr, + const char **value) +{ + /* + * The steps we end up going through to get and check a single valued + * attribute. + */ + struct ldb_message_element *el = NULL; + + *value = NULL; + + el = dsdb_get_single_valued_attr(ac->msg, attr, + ac->req->operation); + if (el == NULL) { + /* we are not affected */ + return LDB_SUCCESS; + } + + if (el->num_values > 1) { + ldb_asprintf_errstring( + ldb, + "samldb: %s has %u values, should be single-valued!", + attr, el->num_values); + return LDB_ERR_CONSTRAINT_VIOLATION; + } else if (el->num_values == 0) { + ldb_asprintf_errstring( + ldb, + "samldb: new value for %s " + "not provided for mandatory, single-valued attribute!", + attr); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + + if (el->values[0].length == 0) { + ldb_asprintf_errstring( + ldb, + "samldb: %s is of zero length, should have a value!", + attr); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + *value = (char *)el->values[0].data; + + return LDB_SUCCESS; +} + static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr, const char *attr_conflict, struct ldb_dn *base_dn) -- 2.25.1 From dd9c310bf8be56b3ee370f233a553e2727406d62 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 13:16:30 +1300 Subject: [PATCH 551/645] CVE-2020-25722 s4/dsdb/samldb: unique_attr_check uses samldb_get_single_valued_attr() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 36 +++++++------------------ 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 40dfab6390b..a03fc6eb07c 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -216,37 +216,21 @@ static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr, { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); const char * const no_attrs[] = { NULL }; - struct ldb_result *res; - const char *enc_str; - struct ldb_message_element *el; + struct ldb_result *res = NULL; + const char *str = NULL; + const char *enc_str = NULL; int ret; - el = dsdb_get_single_valued_attr(ac->msg, attr, - ac->req->operation); - if (el == NULL) { - /* we are not affected */ - return LDB_SUCCESS; - } - - if (el->num_values > 1) { - ldb_asprintf_errstring(ldb, - "samldb: %s has %u values, should be single-valued!", - attr, el->num_values); - return LDB_ERR_CONSTRAINT_VIOLATION; - } else if (el->num_values == 0) { - ldb_asprintf_errstring(ldb, - "samldb: new value for %s not provided for mandatory, single-valued attribute!", - attr); - return LDB_ERR_OBJECT_CLASS_VIOLATION; + ret = samldb_get_single_valued_attr(ldb, ac, attr, &str); + if (ret != LDB_SUCCESS) { + return ret; } - if (el->values[0].length == 0) { - ldb_asprintf_errstring(ldb, - "samldb: %s is of zero length, should have a value!", - attr); - return LDB_ERR_OBJECT_CLASS_VIOLATION; + if (str == NULL) { + /* the attribute wasn't found */ + return LDB_SUCCESS; } - enc_str = ldb_binary_encode(ac, el->values[0]); + enc_str = ldb_binary_encode_string(ac, str); if (enc_str == NULL) { return ldb_module_oom(ac->module); } -- 2.25.1 From 323e1e9b47ea947b4494ab22fa34d60fdf40d3be Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 13:17:34 +1300 Subject: [PATCH 552/645] CVE-2020-25722 s4/dsdb/samldb: check for clashes in UPNs/samaccountnames We already know duplicate sAMAccountNames and UserPrincipalNames are bad, but we also have to check against the values these imply in each other. For example, imagine users with SAM account names "Alice" and "Bob" in the realm "example.com". If they do not have explicit UPNs, by the logic of MS-ADTS 5.1.1.1.1 they use the implict UPNs "alice@example.com" and "bob@example.com", respectively. If Bob's UPN gets set to "alice@example.com", it will clash with Alice's implicit one. Therefore we refuse to allow a UPN that implies an existing SAM account name and vice versa. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ldap_upn_sam_account | 15 -- source4/dsdb/samdb/ldb_modules/samldb.c | 206 +++++++++++++++++++++- 2 files changed, 203 insertions(+), 18 deletions(-) diff --git a/selftest/knownfail.d/ldap_upn_sam_account b/selftest/knownfail.d/ldap_upn_sam_account index c4d494968b2..e53d566816e 100644 --- a/selftest/knownfail.d/ldap_upn_sam_account +++ b/selftest/knownfail.d/ldap_upn_sam_account @@ -1,16 +1 @@ samba.tests.ldap_upn_sam_account.+LdapUpnSamSambaOnlyTest.test_upn_sam_SAM_contains_delete -samba.tests.ldap_upn_sam_account.+LdapUpnSamSambaOnlyTest.test_upn_sam_UPN_same_but_for_internal_spaces -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_ends_with_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_has_at_signs_clashing_upn_first -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_has_at_signs_clashing_upn_second -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_SAM_starts_with_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_clash_on_other_realm -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_ends_with_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_has_no_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_UPN_starts_with_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_add_the_same_upn_to_different_objects -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_SAM_after_UPN -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_SAM_before_UPN -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_different_objects_same_UPN_different_case -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_spaces_around_at -samba.tests.ldap_upn_sam_account.+LdapUpnSamTest.test_upn_sam_two_way_clash diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index a03fc6eb07c..0cf00e2b19e 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -235,8 +235,9 @@ static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr, return ldb_module_oom(ac->module); } - /* Make sure that attr (eg) "sAMAccountName" is only used once */ - + /* + * No other object should have the attribute with this value. + */ if (attr_conflict != NULL) { ret = dsdb_module_search(ac->module, ac, &res, base_dn, @@ -270,6 +271,193 @@ static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr, return LDB_SUCCESS; } + + +static inline int samldb_sam_account_upn_clash_sub_search( + struct samldb_ctx *ac, + TALLOC_CTX *mem_ctx, + struct ldb_dn *base_dn, + const char *attr, + const char *value, + const char *err_msg + ) +{ + /* + * A very specific helper function for samldb_sam_account_upn_clash(), + * where we end up doing this same thing several times in a row. + */ + const char * const no_attrs[] = { NULL }; + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + struct ldb_result *res = NULL; + int ret; + char *enc_value = ldb_binary_encode_string(ac, value); + if (enc_value == NULL) { + return ldb_module_oom(ac->module); + } + ret = dsdb_module_search(ac->module, mem_ctx, &res, + base_dn, + LDB_SCOPE_SUBTREE, no_attrs, + DSDB_FLAG_NEXT_MODULE, ac->req, + "(%s=%s)", + attr, enc_value); + talloc_free(enc_value); + + if (ret != LDB_SUCCESS) { + return ret; + } else if (res->count > 1) { + return ldb_operr(ldb); + } else if (res->count == 1) { + if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0){ + ldb_asprintf_errstring(ldb, + "samldb: %s '%s' " + "is already in use %s", + attr, value, err_msg); + /* different errors for different attrs */ + if (strcasecmp("userPrincipalName", attr) == 0) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } + } + return LDB_SUCCESS; +} + +static int samldb_sam_account_upn_clash(struct samldb_ctx *ac) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + int ret; + struct ldb_dn *base_dn = ldb_get_default_basedn(ldb); + TALLOC_CTX *tmp_ctx = NULL; + const char *real_sam = NULL; + const char *real_upn = NULL; + char *implied_sam = NULL; + char *implied_upn = NULL; + const char *realm = NULL; + + ret = samldb_get_single_valued_attr(ldb, ac, + "sAMAccountName", + &real_sam); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samldb_get_single_valued_attr(ldb, ac, + "userPrincipalName", + &real_upn); + if (ret != LDB_SUCCESS) { + return ret; + } + if (real_upn == NULL && real_sam == NULL) { + /* Not changing these things, so we're done */ + return LDB_SUCCESS; + } + + tmp_ctx = talloc_new(ac); + realm = samdb_dn_to_dns_domain(tmp_ctx, base_dn); + if (realm == NULL) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + if (real_upn != NULL) { + /* + * note we take the last @ in the upn because the first (i.e. + * sAMAccountName equivalent) part can contain @. + * + * It is also OK (per Windows) for a UPN to have zero @s. + */ + char *at = NULL; + char *upn_realm = NULL; + implied_sam = talloc_strdup(tmp_ctx, real_upn); + if (implied_sam == NULL) { + talloc_free(tmp_ctx); + return ldb_module_oom(ac->module); + } + + at = strrchr(implied_sam, '@'); + if (at == NULL) { + /* + * there is no @ in this UPN, so we treat the whole + * thing as a sAMAccountName for the purposes of a + * clash. + */ + DBG_INFO("samldb: userPrincipalName '%s' contains " + "no '@' character\n", implied_sam); + } else { + /* + * Now, this upn only implies a sAMAccountName if the + * realm is our realm. So we need to compare the tail + * of the upn to the realm. + */ + *at = '\0'; + upn_realm = at + 1; + if (strcasecmp(upn_realm, realm) != 0) { + /* implied_sam is not the implied + * sAMAccountName after all, because it is + * from a different realm. */ + TALLOC_FREE(implied_sam); + } + } + } + + if (real_sam != NULL) { + implied_upn = talloc_asprintf(tmp_ctx, "%s@%s", + real_sam, realm); + if (implied_upn == NULL) { + talloc_free(tmp_ctx); + return ldb_module_oom(ac->module); + } + } + + /* + * Now we have all of the actual and implied names, in which to search + * for conflicts. + */ + if (real_sam != NULL) { + ret = samldb_sam_account_upn_clash_sub_search( + ac, tmp_ctx, base_dn, "sAMAccountName", + real_sam, ""); + + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + } + if (implied_upn != NULL) { + ret = samldb_sam_account_upn_clash_sub_search( + ac, tmp_ctx, base_dn, "userPrincipalName", implied_upn, + "(implied by sAMAccountName)"); + + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + } + if (real_upn != NULL) { + ret = samldb_sam_account_upn_clash_sub_search( + ac, tmp_ctx, base_dn, "userPrincipalName", + real_upn, ""); + + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + } + if (implied_sam != NULL) { + ret = samldb_sam_account_upn_clash_sub_search( + ac, tmp_ctx, base_dn, "sAMAccountName", implied_sam, + "(implied by userPrincipalName)"); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + } + + talloc_free(tmp_ctx); + return LDB_SUCCESS; +} + + +/* This is run during an add or modify */ static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac) { int ret = 0; @@ -303,7 +491,11 @@ static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac) } else if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) { ret = LDB_ERR_CONSTRAINT_VIOLATION; } + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samldb_sam_account_upn_clash(ac); if (ret != LDB_SUCCESS) { return ret; } @@ -4175,7 +4367,6 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) if (ret != LDB_SUCCESS) { return ret; } - user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", @@ -4199,6 +4390,15 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) } } + el = ldb_msg_find_element(ac->msg, "userPrincipalName"); + if (el != NULL) { + ret = samldb_sam_account_upn_clash(ac); + if (ret != LDB_SUCCESS) { + talloc_free(ac); + return ret; + } + } + el = ldb_msg_find_element(ac->msg, "ldapDisplayName"); if (el != NULL) { ret = samldb_schema_ldapdisplayname_valid_check(ac); -- 2.25.1 From 7eed8aa6566bb049b4ffc09ced7fc40b48cf34c4 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 15:27:25 +1300 Subject: [PATCH 553/645] CVE-2020-25722 s4/dsdb/samldb: check sAMAccountName for illegal characters This only for the real account name, not the account name implicit in a UPN. It doesn't matter if a UPN implies an illegal sAMAccountName, since that is not going to conflict with a real one. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ldap_upn_sam_account | 1 - source4/dsdb/samdb/ldb_modules/samldb.c | 58 +++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/ldap_upn_sam_account diff --git a/selftest/knownfail.d/ldap_upn_sam_account b/selftest/knownfail.d/ldap_upn_sam_account deleted file mode 100644 index e53d566816e..00000000000 --- a/selftest/knownfail.d/ldap_upn_sam_account +++ /dev/null @@ -1 +0,0 @@ -samba.tests.ldap_upn_sam_account.+LdapUpnSamSambaOnlyTest.test_upn_sam_SAM_contains_delete diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 0cf00e2b19e..f420009376c 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -322,6 +322,59 @@ static inline int samldb_sam_account_upn_clash_sub_search( return LDB_SUCCESS; } +static int samaccountname_bad_chars_check(struct samldb_ctx *ac, + const char *name) +{ + /* + * The rules here are based on + * + * https://social.technet.microsoft.com/wiki/contents/articles/11216.active-directory-requirements-for-creating-objects.aspx + * + * Windows considers UTF-8 sequences that map to "similar" characters + * (e.g. 'a', 'ā') to be the same sAMAccountName, and we don't. Names + * that are not valid UTF-8 *are* allowed. + * + * Additionally, Samba collapses multiple spaces, and Windows doesn't. + */ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + size_t i; + + for (i = 0; name[i] != '\0'; i++) { + uint8_t c = name[i]; + char *p = NULL; + if (c < 32 || c == 127) { + ldb_asprintf_errstring( + ldb, + "samldb: sAMAccountName contains invalid " + "0x%.2x character\n", c); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + p = strchr("\"[]:;|=+*?<>/\\,", c); + if (p != NULL) { + ldb_asprintf_errstring( + ldb, + "samldb: sAMAccountName contains invalid " + "'%c' character\n", c); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + } + + if (i == 0) { + ldb_asprintf_errstring( + ldb, + "samldb: sAMAccountName is empty\n"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + if (name[i - 1] == '.') { + ldb_asprintf_errstring( + ldb, + "samldb: sAMAccountName ends with '.'"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + return LDB_SUCCESS; +} + static int samldb_sam_account_upn_clash(struct samldb_ctx *ac) { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); @@ -421,6 +474,11 @@ static int samldb_sam_account_upn_clash(struct samldb_ctx *ac) talloc_free(tmp_ctx); return ret; } + ret = samaccountname_bad_chars_check(ac, real_sam); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } } if (implied_upn != NULL) { ret = samldb_sam_account_upn_clash_sub_search( -- 2.25.1 From fd686da540b447d28555aea7c6a905c0523010bb Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 13:14:32 +1300 Subject: [PATCH 554/645] CVE-2020-25722 s4/dsdb/samldb: check for SPN uniqueness, including aliases Not only should it not be possible to add a servicePrincipalName that is already present in the domain, it should not be possible to add one that is implied by an entry in sPNMappings, unless the user is adding an alias to another SPN and has rights to alter that one. For example, with the default sPNMappings, cifs/ is an alias pointing to host/, meaning if there is no cifs/example.com SPN, the host/example.com one will be used instead. A user can add the cifs/example.com SPN only if they can also change the host/example.com one (because adding the cifs/ effectively changes the host/). The reverse is refused in all cases, unless they happen to be on the same object. That is, if there is a cifs/example.com SPN, there is no way to add host/example.com elsewhere. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ldap_spn | 23 - source4/dsdb/samdb/ldb_modules/samldb.c | 588 +++++++++++++++++++++++- 2 files changed, 585 insertions(+), 26 deletions(-) diff --git a/selftest/knownfail.d/ldap_spn b/selftest/knownfail.d/ldap_spn index dc768728658..b7eb6f30e7a 100644 --- a/selftest/knownfail.d/ldap_spn +++ b/selftest/knownfail.d/ldap_spn @@ -1,26 +1,3 @@ -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_host_first_both_on_user_service_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_host_first_with_service_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_as_admin -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_with_both_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_add_a_conflict_service_first_with_host_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_changing_dNSHostName_after_host -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_mystery_dnsname_clash_www_first -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_host_first_with_partial_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_host_first_with_partial_write_rights_2 -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_sandwich_sufficient_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_just_sufficient_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_all_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_both_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_service_first_with_host_write_rights -samba.tests.ldap_spn.+LdapSpnSambaOnlyTest.test_spn_three_way_conflict_services_first_with_partial_rights -samba.tests.ldap_spn.+LdapSpnTest.test_spn_adding_dNSHostName_after_cifs_with_no_old_dNSHostName -samba.tests.ldap_spn.+LdapSpnTest.test_spn_changing_dNSHostName_after_cifs samba.tests.ldap_spn.+LdapSpnTest.test_spn_dodgy_spns -samba.tests.ldap_spn.+LdapSpnTest.test_spn_empty_part_spns_consecutive_slashes_ samba.tests.ldap_spn.+LdapSpnTest.test_spn_one_part_spns_no_slashes_ -samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_part_nonsense_spns -samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_part_spns -samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_host_first_adding_duplicate -samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_host_first_adding_duplicate_full_rights -samba.tests.ldap_spn.+LdapSpnTest.test_spn_three_way_conflict_services_first_as_admin samba.tests.ldap_spn.+LdapSpnTest.test_spn_too_many_spn_parts diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index f420009376c..f5141936a60 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3383,6 +3383,546 @@ static int samldb_description_check(struct samldb_ctx *ac, bool *modified) return LDB_SUCCESS; } +#define SPN_ALIAS_NONE 0 +#define SPN_ALIAS_LINK 1 +#define SPN_ALIAS_TARGET 2 + +static int find_spn_aliases(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *service_class, + char ***aliases, + size_t *n_aliases, + int *direction) +{ + /* + * If you change the way this works, you should also look at changing + * LDB_lookup_spn_alias() in source4/dsdb/samdb/cracknames.c, which + * does some of the same work. + * + * In particular, note that sPNMappings are resolved on a first come, + * first served basis. For example, if we have + * + * host=ldap,cifs + * foo=ldap + * cifs=host,alerter + * + * then 'ldap', 'cifs', and 'host' will resolve to 'host', and + * 'alerter' will resolve to 'cifs'. + * + * If this resolution method is made more complicated, then the + * cracknames function should also be changed. + */ + size_t i, j; + int ret; + bool ok; + struct ldb_result *res = NULL; + struct ldb_message_element *spnmappings = NULL; + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_dn *service_dn = NULL; + + const char *attrs[] = { + "sPNMappings", + NULL + }; + + *direction = SPN_ALIAS_NONE; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ldb_oom(ldb); + } + + service_dn = ldb_dn_new( + tmp_ctx, ldb, + "CN=Directory Service,CN=Windows NT,CN=Services"); + if (service_dn == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + + ok = ldb_dn_add_base(service_dn, ldb_get_config_basedn(ldb)); + if (! ok) { + talloc_free(tmp_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_search(ldb, tmp_ctx, &res, service_dn, LDB_SCOPE_BASE, + attrs, "(objectClass=nTDSService)"); + + if (ret != LDB_SUCCESS || res->count != 1) { + DBG_WARNING("sPNMappings not found.\n"); + talloc_free(tmp_ctx); + return ret; + } + + spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings"); + if (spnmappings == NULL || spnmappings->num_values == 0) { + DBG_WARNING("no sPNMappings attribute\n"); + talloc_free(tmp_ctx); + return LDB_ERR_NO_SUCH_OBJECT; + } + *n_aliases = 0; + + for (i = 0; i < spnmappings->num_values; i++) { + char *p = NULL; + char *mapping = talloc_strndup( + tmp_ctx, + (char *)spnmappings->values[i].data, + spnmappings->values[i].length); + if (mapping == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + + p = strchr(mapping, '='); + if (p == NULL) { + talloc_free(tmp_ctx); + return LDB_ERR_ALIAS_PROBLEM; + } + p[0] = '\0'; + p++; + + if (strcasecmp(mapping, service_class) == 0) { + /* + * We need to return the reverse aliases for this one. + * + * typically, this means the service_class is "host" + * and the mapping is "host=alerter,appmgmt,cisvc,..", + * so we get "alerter", "appmgmt", etc in the list of + * aliases. + */ + + /* There is one more field than there are commas */ + size_t n = 1; + + for (j = 0; p[j] != '\0'; j++) { + if (p[j] == ',') { + n++; + p[j] = '\0'; + } + } + *aliases = talloc_array(mem_ctx, char*, n); + if (*aliases == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + *n_aliases = n; + talloc_steal(mem_ctx, mapping); + for (j = 0; j < n; j++) { + (*aliases)[j] = p; + p += strlen(p) + 1; + } + talloc_free(tmp_ctx); + *direction = SPN_ALIAS_LINK; + return LDB_SUCCESS; + } + /* + * We need to look along the list to see if service_class is + * there; if so, we return a list of one item (probably "host"). + */ + do { + char *str = p; + p = strchr(p, ','); + if (p != NULL) { + p[0] = '\0'; + p++; + } + if (strcasecmp(str, service_class) == 0) { + *aliases = talloc_array(mem_ctx, char*, 1); + if (*aliases == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + *n_aliases = 1; + (*aliases)[0] = mapping; + talloc_steal(mem_ctx, mapping); + talloc_free(tmp_ctx); + *direction = SPN_ALIAS_TARGET; + return LDB_SUCCESS; + } + } while (p != NULL); + } + DBG_INFO("no sPNMappings alias for '%s'\n", service_class); + talloc_free(tmp_ctx); + *aliases = NULL; + *n_aliases = 0; + return LDB_SUCCESS; +} + + +static int get_spn_dn(struct ldb_context *ldb, + TALLOC_CTX *tmp_ctx, + const char *candidate, + struct ldb_dn **dn) +{ + int ret; + const char *empty_attrs[] = { NULL }; + struct ldb_message *msg = NULL; + struct ldb_dn *base_dn = ldb_get_default_basedn(ldb); + + const char *enc_candidate = NULL; + + *dn = NULL; + + enc_candidate = ldb_binary_encode_string(tmp_ctx, candidate); + if (enc_candidate == NULL) { + return ldb_operr(ldb); + } + + ret = dsdb_search_one(ldb, + tmp_ctx, + &msg, + base_dn, + LDB_SCOPE_SUBTREE, + empty_attrs, + 0, + "(servicePrincipalName=%s)", + enc_candidate); + if (ret != LDB_SUCCESS) { + return ret; + } + *dn = msg->dn; + return LDB_SUCCESS; +} + + +static int check_spn_write_rights(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *spn, + struct ldb_dn *dn) +{ + int ret; + struct ldb_message *msg = NULL; + struct ldb_message_element *del_el = NULL; + struct ldb_message_element *add_el = NULL; + struct ldb_val val = { + .data = discard_const_p(uint8_t, spn), + .length = strlen(spn) + }; + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + return ldb_oom(ldb); + } + msg->dn = dn; + + ret = ldb_msg_add_empty(msg, + "servicePrincipalName", + LDB_FLAG_MOD_DELETE, + &del_el); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + + del_el->values = talloc_array(msg->elements, struct ldb_val, 1); + if (del_el->values == NULL) { + talloc_free(msg); + return ret; + } + + del_el->values[0] = val; + del_el->num_values = 1; + + ret = ldb_msg_add_empty(msg, + "servicePrincipalName", + LDB_FLAG_MOD_ADD, + &add_el); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } + + add_el->values = talloc_array(msg->elements, struct ldb_val, 1); + if (add_el->values == NULL) { + talloc_free(msg); + return ret; + } + + add_el->values[0] = val; + add_el->num_values = 1; + + ret = ldb_modify(ldb, msg); + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { + DBG_ERR("hmm I think we're OK, but not sure\n"); + } else if (ret != LDB_SUCCESS) { + DBG_ERR("SPN write rights check failed with %d\n", ret); + talloc_free(msg); + return ret; + } + talloc_free(msg); + return LDB_SUCCESS; +} + + +static int check_spn_alias_collision(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *spn, + struct ldb_dn *target_dn) +{ + int ret; + char *service_class = NULL; + char *spn_tail = NULL; + char *p = NULL; + char **aliases = NULL; + size_t n_aliases = 0; + size_t i, len; + TALLOC_CTX *tmp_ctx = NULL; + const char *target_dnstr = ldb_dn_get_linearized(target_dn); + int link_direction; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ldb_oom(ldb); + } + + /* + * "dns/example.com/xxx" gives + * service_class = "dns" + * spn_tail = "example.com/xxx" + */ + p = strchr(spn, '/'); + if (p == NULL) { + /* bad SPN */ + talloc_free(tmp_ctx); + return ldb_error(ldb, + LDB_ERR_OPERATIONS_ERROR, + "malformed servicePrincipalName"); + } + len = p - spn; + + service_class = talloc_strndup(tmp_ctx, spn, len); + if (service_class == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + spn_tail = p + 1; + + ret = find_spn_aliases(ldb, + tmp_ctx, + service_class, + &aliases, + &n_aliases, + &link_direction); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + + /* + * we have the list of aliases, and now we need to combined them with + * spn_tail and see if we can find the SPN. + */ + for (i = 0; i < n_aliases; i++) { + struct ldb_dn *colliding_dn = NULL; + const char *colliding_dnstr = NULL; + + char *candidate = talloc_asprintf(tmp_ctx, + "%s/%s", + aliases[i], + spn_tail); + if (candidate == NULL) { + talloc_free(tmp_ctx); + return ldb_oom(ldb); + } + + ret = get_spn_dn(ldb, tmp_ctx, candidate, &colliding_dn); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + DBG_DEBUG("SPN alias '%s' not found (good)\n", + candidate); + talloc_free(candidate); + continue; + } + if (ret != LDB_SUCCESS) { + DBG_ERR("SPN '%s' search error %d\n", candidate, ret); + talloc_free(tmp_ctx); + return ret; + } + + target_dnstr = ldb_dn_get_linearized(target_dn); + /* + * We have found an existing SPN that matches the alias. That + * is OK only if it is on the object we are trying to add to, + * or if the SPN on the other side is a more generic alias for + * this one and we also have rights to modify it. + * + * That is, we can put "host/X" and "cifs/X" on the same + * object, but not on different objects, unless we put the + * host/X on first, and could also change that object when we + * add cifs/X. It is forbidden to add the objects in the other + * order. + * + * The rationale for this is that adding "cifs/X" effectively + * changes "host/X" by diverting traffic. If "host/X" can be + * added after "cifs/X", a sneaky person could get "cifs/X" in + * first, making "host/X" have less effect than intended. + * + * Note: we also can't have "host/X" and "Host/X" on the same + * object, but that is not relevant here. + */ + + ret = ldb_dn_compare(colliding_dn, target_dn); + if (ret != 0) { + colliding_dnstr = ldb_dn_get_linearized(colliding_dn); + DBG_ERR("trying to add SPN '%s' on '%s' when '%s' is " + "on '%s'\n", + spn, + target_dnstr, + candidate, + colliding_dnstr); + + if (link_direction == SPN_ALIAS_LINK) { + /* we don't allow host/X if there is a + * cifs/X */ + talloc_free(tmp_ctx); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + ret = check_spn_write_rights(ldb, + tmp_ctx, + candidate, + colliding_dn); + if (ret != LDB_SUCCESS) { + DBG_ERR("SPN '%s' is on '%s' so '%s' can't be " + "added to '%s'\n", + candidate, + colliding_dnstr, + spn, + target_dnstr); + talloc_free(tmp_ctx); + ldb_asprintf_errstring(ldb, + "samldb: spn[%s] would cause a conflict", + spn); + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else { + DBG_INFO("SPNs '%s' and '%s' alias both on '%s'\n", + candidate, spn, target_dnstr); + } + talloc_free(candidate); + } + + talloc_free(tmp_ctx); + return LDB_SUCCESS; +} + +static int check_spn_direct_collision(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *spn, + struct ldb_dn *target_dn) +{ + int ret; + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_dn *colliding_dn = NULL; + const char *target_dnstr = NULL; + const char *colliding_dnstr = NULL; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ldb_oom(ldb); + } + + ret = get_spn_dn(ldb, tmp_ctx, spn, &colliding_dn); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + DBG_DEBUG("SPN '%s' not found (good)\n", spn); + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } + if (ret != LDB_SUCCESS) { + DBG_ERR("SPN '%s' search error %d\n", spn, ret); + talloc_free(tmp_ctx); + if (ret == LDB_ERR_COMPARE_TRUE) { + /* + * COMPARE_TRUE has special meaning here and we don't + * want to return it by mistake. + */ + ret = LDB_ERR_OPERATIONS_ERROR; + } + return ret; + } + /* + * We have found this exact SPN. This is mostly harmless (depend on + * ADD vs REPLACE) when the spn is being put on the object that + * already has, so we let it through to succeed or fail as some other + * module sees fit. + */ + target_dnstr = ldb_dn_get_linearized(target_dn); + ret = ldb_dn_compare(colliding_dn, target_dn); + if (ret != 0) { + colliding_dnstr = ldb_dn_get_linearized(colliding_dn); + DBG_ERR("SPN '%s' is on '%s' so it can't be " + "added to '%s'\n", + spn, + colliding_dnstr, + target_dnstr); + ldb_asprintf_errstring(ldb, + "samldb: spn[%s] would cause a conflict", + spn); + talloc_free(tmp_ctx); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + DBG_INFO("SPN '%s' is already on '%s'\n", + spn, target_dnstr); + talloc_free(tmp_ctx); + return LDB_ERR_COMPARE_TRUE; +} + + +/* Check that "servicePrincipalName" changes do not introduce a collision + * globally. */ +static int samldb_spn_uniqueness_check(struct samldb_ctx *ac, + struct ldb_message_element *spn_el) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + int ret; + const char *spn = NULL; + size_t i; + TALLOC_CTX *tmp_ctx = talloc_new(ac->msg); + if (tmp_ctx == NULL) { + return ldb_oom(ldb); + } + + for (i = 0; i < spn_el->num_values; i++) { + spn = (char *)spn_el->values[i].data; + + ret = check_spn_direct_collision(ldb, + tmp_ctx, + spn, + ac->msg->dn); + if (ret == LDB_ERR_COMPARE_TRUE) { + DBG_INFO("SPN %s re-added to the same object\n", spn); + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } + if (ret != LDB_SUCCESS) { + DBG_ERR("SPN %s failed direct uniqueness check\n", spn); + talloc_free(tmp_ctx); + return ret; + } + + ret = check_spn_alias_collision(ldb, + tmp_ctx, + spn, + ac->msg->dn); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + /* we have no sPNMappings, hence no aliases */ + break; + } + if (ret != LDB_SUCCESS) { + DBG_ERR("SPN %s failed alias uniqueness check\n", spn); + talloc_free(tmp_ctx); + return ret; + } + DBG_INFO("SPN %s seems to be unique\n", spn); + } + + talloc_free(tmp_ctx); + return LDB_SUCCESS; +} + + + /* This trigger adapts the "servicePrincipalName" attributes if the * "dNSHostName" and/or "sAMAccountName" attribute change(s) */ static int samldb_service_principal_names_change(struct samldb_ctx *ac) @@ -3498,8 +4038,14 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac) return LDB_SUCCESS; } - /* Potential "servicePrincipalName" changes in the same request have to - * be handled before the update (Windows behaviour). */ + /* + * Potential "servicePrincipalName" changes in the same request have + * to be handled before the update (Windows behaviour). + * + * We extract the SPN changes into a new message and run it through + * the stack from this module, so that it subjects them to the SPN + * checks we have here. + */ el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); if (el != NULL) { msg = ldb_msg_new(ac->msg); @@ -3521,7 +4067,7 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac) } while (el != NULL); ret = dsdb_module_modify(ac->module, msg, - DSDB_FLAG_NEXT_MODULE, ac->req); + DSDB_FLAG_OWN_MODULE, ac->req); if (ret != LDB_SUCCESS) { return ret; } @@ -4255,6 +4801,19 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return samldb_fill_object(ac); } + + el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); + if ((el != NULL)) { + /* + * We need to check whether the SPN collides with an existing + * one (anywhere) including via aliases. + */ + ret = samldb_spn_uniqueness_check(ac, el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + if (samdb_find_attribute(ldb, ac->msg, "objectclass", "subnet") != NULL) { ret = samldb_verify_subnet(ac, ac->msg->dn); @@ -4505,12 +5064,35 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req) el2 = ldb_msg_find_element(ac->msg, "sAMAccountName"); if ((el != NULL) || (el2 != NULL)) { modified = true; + /* + * samldb_service_principal_names_change() might add SPN + * changes to the request, so this must come before the SPN + * uniqueness check below. + * + * Note we ALSO have to do the SPN uniqueness check inside + * samldb_service_principal_names_change(), because it does a + * subrequest to do requested SPN modifications *before* its + * automatic ones are added. + */ ret = samldb_service_principal_names_change(ac); if (ret != LDB_SUCCESS) { return ret; } } + el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); + if ((el != NULL)) { + /* + * We need to check whether the SPN collides with an existing + * one (anywhere) including via aliases. + */ + modified = true; + ret = samldb_spn_uniqueness_check(ac, el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + el = ldb_msg_find_element(ac->msg, "fSMORoleOwner"); if (el != NULL) { ret = samldb_fsmo_role_owner_check(ac); -- 2.25.1 From 16dce623ac5fb2f8d7d176cf9d48d9aeb7aff18f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 16:03:18 +1300 Subject: [PATCH 555/645] CVE-2020-25722 s4/dsdb/samldb: reject SPN with too few/many components BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ldap_spn | 2 -- source4/dsdb/samdb/ldb_modules/samldb.c | 41 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail.d/ldap_spn b/selftest/knownfail.d/ldap_spn index b7eb6f30e7a..63f9fe02ef7 100644 --- a/selftest/knownfail.d/ldap_spn +++ b/selftest/knownfail.d/ldap_spn @@ -1,3 +1 @@ samba.tests.ldap_spn.+LdapSpnTest.test_spn_dodgy_spns -samba.tests.ldap_spn.+LdapSpnTest.test_spn_one_part_spns_no_slashes_ -samba.tests.ldap_spn.+LdapSpnTest.test_spn_too_many_spn_parts diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index f5141936a60..006658d2bce 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3868,6 +3868,37 @@ static int check_spn_direct_collision(struct ldb_context *ldb, } +static int count_spn_components(struct ldb_val val) +{ + /* + * a 3 part servicePrincipalName has two slashes, like + * ldap/example.com/DomainDNSZones.example.com. + * + * In krb5_parse_name_flags() we don't count "\/" as a slash (i.e. + * escaped by a backslash), but this is not the behaviour of Windows + * on setting a servicePrincipalName -- slashes are counted regardless + * of backslashes. + * + * Accordingly, here we ignore backslashes. This will reject + * multi-slash SPNs that krb5_parse_name_flags() would accept, and + * allow ones in the form "a\/b" that it won't parse. + */ + size_t i; + int slashes = 0; + for (i = 0; i < val.length; i++) { + char c = val.data[i]; + if (c == '/') { + slashes++; + if (slashes == 3) { + /* at this point we don't care */ + return 4; + } + } + } + return slashes + 1; +} + + /* Check that "servicePrincipalName" changes do not introduce a collision * globally. */ static int samldb_spn_uniqueness_check(struct samldb_ctx *ac, @@ -3883,8 +3914,18 @@ static int samldb_spn_uniqueness_check(struct samldb_ctx *ac, } for (i = 0; i < spn_el->num_values; i++) { + int n_components; spn = (char *)spn_el->values[i].data; + n_components = count_spn_components(spn_el->values[i]); + if (n_components > 3 || n_components < 2) { + ldb_asprintf_errstring(ldb, + "samldb: spn[%s] invalid with %u components", + spn, n_components); + talloc_free(tmp_ctx); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + ret = check_spn_direct_collision(ldb, tmp_ctx, spn, -- 2.25.1 From 2e17444affe01343dfc8ea9b08d627306c0be2ab Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:09:21 +1300 Subject: [PATCH 556/645] CVE-2020-25722 s4/dsdb modules: add dsdb_get_expected_new_values() This function collects a superset of all the new values for the specified attribute that could result from an ldb add or modify message. In most cases -- where there is a single add or modify -- the exact set of added values is returned, and this is done reasonably efficiently using the existing element. Where it gets complicated is when there are multiple elements for the same attribute in a message. Anything added before a replace or delete will be included in these results but may not end up in the database if the message runs its course. Examples: sequence result 1. ADD the element is returned (exact) 2. REPLACE the element is returned (exact) 3. ADD, ADD both elements are concatenated together (exact) 4. ADD, REPLACE both elements are concatenated together (superset) 5. REPLACE, ADD both elements are concatenated together (exact) 6. ADD, DEL, ADD adds are concatenated together (superset) 7. REPLACE, REPLACE both concatenated (superset) 8. DEL, ADD last element is returned (exact) Why this? In the past we have treated dsdb_get_single_valued_attr() as if it returned the complete set of possible database changes, when in fact it only returned the last non-delete. That is, it could have missed values in examples 3-7 above. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/util.c | 121 ++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c index 9519ecfa928..da152e4d754 100644 --- a/source4/dsdb/samdb/ldb_modules/util.c +++ b/source4/dsdb/samdb/ldb_modules/util.c @@ -1441,6 +1441,127 @@ void dsdb_req_chain_debug(struct ldb_request *req, int level) talloc_free(s); } +/* + * Get all the values that *might* be added by an ldb message, as a composite + * ldb element. + * + * This is useful when we need to check all the possible values against some + * criteria. + * + * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES, + * the returned element might contain more values than would actually end up + * in the database if the message was run to its conclusion. + * + * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is + * returned. + * + * The returned element might not be new, and should not be modified or freed + * before the message is finished. + */ + +int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, + const char *attr_name, + struct ldb_message_element **el, + enum ldb_request_type operation) +{ + unsigned int i; + unsigned int el_count = 0; + unsigned int val_count = 0; + struct ldb_val *v = NULL; + struct ldb_message_element *_el = NULL; + *el = NULL; + + if (operation != LDB_ADD && operation != LDB_MODIFY) { + DBG_ERR("inapplicable operation type: %d\n", operation); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* count the adding or replacing elements */ + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + unsigned int tmp; + if ((operation == LDB_MODIFY) && + (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) + == LDB_FLAG_MOD_DELETE)) { + continue; + } + el_count++; + tmp = val_count + msg->elements[i].num_values; + if (unlikely(tmp < val_count)) { + DBG_ERR("too many values for one element!"); + return LDB_ERR_OPERATIONS_ERROR; + } + val_count = tmp; + } + } + if (el_count == 0) { + /* nothing to see here */ + return LDB_SUCCESS; + } + + if (el_count == 1 || val_count == 0) { + /* + * There is one effective element, which we can return as-is, + * OR there are only elements with zero values -- any of which + * will do. + */ + 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) + == LDB_FLAG_MOD_DELETE)) { + continue; + } + *el = &msg->elements[i]; + return LDB_SUCCESS; + } + } + } + + _el = talloc_zero(mem_ctx, struct ldb_message_element); + if (_el == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + _el->name = attr_name; + + if (val_count == 0) { + /* + * Seems unlikely, but sometimes we might be adding zero + * values in multiple separate elements. The talloc zero has + * already set the expected values = NULL, num_values = 0. + */ + *el = _el; + return LDB_SUCCESS; + } + + _el->values = talloc_array(_el, struct ldb_val, val_count); + if (_el->values == NULL) { + talloc_free(_el); + return LDB_ERR_OPERATIONS_ERROR; + } + _el->num_values = val_count; + + v = _el->values; + + for (i = 0; i < val_count; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + if ((operation == LDB_MODIFY) && + (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) + == LDB_FLAG_MOD_DELETE)) { + continue; + } + memcpy(v, + msg->elements[i].values, + msg->elements[i].num_values); + v += msg->elements[i].num_values; + } + } + + *el = _el; + return LDB_SUCCESS; +} + /* * Gets back a single-valued attribute by the rules of the DSDB triggers when * performing a modify operation. -- 2.25.1 From 596ed48c3d8367c6e12dd896c77a1da762ece8df Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:10:44 +1300 Subject: [PATCH 557/645] CVE-2020-25722 s4/dsdb/samldb: samldb_get_single_valued_attr() check all values using dsdb_get_expected_new_values(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 006658d2bce..4bd40a5ef1f 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -171,11 +171,19 @@ static int samldb_get_single_valued_attr(struct ldb_context *ldb, * attribute. */ struct ldb_message_element *el = NULL; + int ret; *value = NULL; - el = dsdb_get_single_valued_attr(ac->msg, attr, - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + attr, + &el, + ac->req->operation); + + if (ret != LDB_SUCCESS) { + return ret; + } if (el == NULL) { /* we are not affected */ return LDB_SUCCESS; -- 2.25.1 From d6ee10cc9202839324cb5bbd3691d0b853a64b48 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 22 Oct 2021 14:52:49 +1300 Subject: [PATCH 558/645] CVE-2020-25722 s4/dsdb/samldb: samldb_sam_accountname_valid_check() check all values Using dsdb_get_expected_new_values(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 4bd40a5ef1f..5d3e0f9771c 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -530,8 +530,17 @@ static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac) bool is_admin; struct security_token *user_token = NULL; struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - struct ldb_message_element *el = dsdb_get_single_valued_attr(ac->msg, "samAccountName", - ac->req->operation); + struct ldb_message_element *el = NULL; + + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "samAccountName", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL || el->num_values == 0) { ldb_asprintf_errstring(ldb, "%08X: samldb: 'samAccountName' can't be deleted/empty!", -- 2.25.1 From cd497960f57b2d369f04c391ab6e9d93c53f1574 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:12:49 +1300 Subject: [PATCH 559/645] CVE-2020-25722 s4/dsdb/samldb: samldb_schema_add_handle_linkid() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 5d3e0f9771c..39533266aeb 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -739,8 +739,15 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac) schema = dsdb_get_schema(ldb, ac); schema_dn = ldb_get_schema_basedn(ldb); - el = dsdb_get_single_valued_attr(ac->msg, "linkID", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "linkID", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL) { return LDB_SUCCESS; } -- 2.25.1 From 1615513f828cfb6b955431abdc68a6836006dd64 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:13:35 +1300 Subject: [PATCH 560/645] CVE-2020-25722 s4/dsdb/samldb: samldb_schema_add_handle_mapiid() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 39533266aeb..5b2c2fc29aa 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -907,8 +907,15 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) schema = dsdb_get_schema(ldb, ac); schema_dn = ldb_get_schema_basedn(ldb); - el = dsdb_get_single_valued_attr(ac->msg, "mAPIID", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "mAPIID", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL) { return LDB_SUCCESS; } -- 2.25.1 From 49f4921aebe4838db6dcdbe5a62c94ff1bb5ef6a Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:14:05 +1300 Subject: [PATCH 561/645] CVE-2020-25722 s4/dsdb/samldb: samldb_prim_group_change() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 5b2c2fc29aa..ba56cf8826e 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -2121,8 +2121,15 @@ static int samldb_prim_group_change(struct samldb_ctx *ac) int ret; const char * const noattrs[] = { NULL }; - el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "primaryGroupID", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL) { /* we are not affected */ return LDB_SUCCESS; -- 2.25.1 From ebe7b80253459906b3c08c28cfc2015cafa42e25 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:15:00 +1300 Subject: [PATCH 562/645] CVE-2020-25722 s4/dsdb/samldb: samldb_user_account_control_change() checks all values There is another call to dsdb_get_expected_new_values() in this function that we change in the next commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index ba56cf8826e..b84ef4c26d5 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -2807,8 +2807,15 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) bool old_is_critical = false; bool new_is_critical = false; - el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "userAccountControl", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL || el->num_values == 0) { ldb_asprintf_errstring(ldb, "%08X: samldb: 'userAccountControl' can't be deleted!", -- 2.25.1 From ca33724844f72ece07b1c9c5b011c00b690c0b6b Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:15:43 +1300 Subject: [PATCH 563/645] CVE-2020-25722 s4/dsdb/samldb _user_account_control_change() always add final value dsdb_get_single_valued_attr() was finding the last non-delete element for userAccountControl and changing its value to the computed value. Unfortunately, the last non-delete element might not be the last element, and a subsequent delete might remove it. Instead we just add a replace on the end. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index b84ef4c26d5..1410e5bc5e6 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3008,9 +3008,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) return ldb_module_oom(ac->module); } - /* Overwrite "userAccountControl" correctly */ - el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl", - ac->req->operation); + ret = ldb_msg_add_empty(ac->msg, + "userAccountControl", + LDB_FLAG_MOD_REPLACE, + &el); + el->values = talloc(ac->msg, struct ldb_val); + el->num_values = 1; el->values[0].data = (uint8_t *) tempstr; el->values[0].length = strlen(tempstr); } else { -- 2.25.1 From 969b743f51a5719a3c6e7e109e50bb366d5f2fe5 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:16:34 +1300 Subject: [PATCH 564/645] CVE-2020-25722 s4/dsdb/samldb: samldb_pwd_last_set_change() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 1410e5bc5e6..8e93df221f5 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3102,8 +3102,15 @@ static int samldb_pwd_last_set_change(struct samldb_ctx *ac) NULL }; - el = dsdb_get_single_valued_attr(ac->msg, "pwdLastSet", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "pwdLastSet", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL || el->num_values == 0) { ldb_asprintf_errstring(ldb, "%08X: samldb: 'pwdLastSet' can't be deleted!", -- 2.25.1 From e5332ea0d5590bcb6ff72d4d850334ae396be52c Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:17:31 +1300 Subject: [PATCH 565/645] CVE-2020-25722 s4/dsdb/samldb: samldb_lockout_time() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 8e93df221f5..48eb88f728b 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3164,8 +3164,15 @@ static int samldb_lockout_time(struct samldb_ctx *ac) struct ldb_message *tmp_msg; int ret; - el = dsdb_get_single_valued_attr(ac->msg, "lockoutTime", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "lockoutTime", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL || el->num_values == 0) { ldb_asprintf_errstring(ldb, "%08X: samldb: 'lockoutTime' can't be deleted!", -- 2.25.1 From a969e1670eb38f80184aa7c6459c1b530748f3a6 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:17:50 +1300 Subject: [PATCH 566/645] CVE-2020-25722 s4/dsdb/samldb: samldb_group_type_change() checks all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 48eb88f728b..391437d759d 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -3221,8 +3221,15 @@ static int samldb_group_type_change(struct samldb_ctx *ac) struct ldb_result *res; const char * const attrs[] = { "groupType", NULL }; - el = dsdb_get_single_valued_attr(ac->msg, "groupType", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "groupType", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + if (el == NULL) { /* we are not affected */ return LDB_SUCCESS; -- 2.25.1 From 5a937e2eac1bcb2bf9f6c5ccade2c6ad41d066fc Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:18:10 +1300 Subject: [PATCH 567/645] CVE-2020-25722 s4/dsdb/samldb: samldb_service_principal_names_change checks values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 391437d759d..80ca1e3afc0 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -4047,10 +4047,22 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac) unsigned int i, j; int ret; - el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName", - ac->req->operation); - el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName", - ac->req->operation); + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "dNSHostName", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "sAMAccountName", + &el2, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } if ((el == NULL) && (el2 == NULL)) { /* we are not affected */ return LDB_SUCCESS; -- 2.25.1 From 6e58867c6a0be1a5ffe6fcb3aea0b4718e39e1bb Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:18:21 +1300 Subject: [PATCH 568/645] CVE-2020-25722 s4/dsdb/samldb: samldb_fsmo_role_owner_check checks values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 80ca1e3afc0..d75277b3853 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -4302,9 +4302,15 @@ static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac) struct ldb_dn *res_dn; struct ldb_result *res; int ret; + ret = dsdb_get_expected_new_values(ac, + ac->msg, + "fSMORoleOwner", + &el, + ac->req->operation); + if (ret != LDB_SUCCESS) { + return ret; + } - el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner", - ac->req->operation); if (el == NULL) { /* we are not affected */ return LDB_SUCCESS; -- 2.25.1 From 21f7dc8359380f5b49347f047d2e74ced6a548a8 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 21 Oct 2021 12:52:07 +1300 Subject: [PATCH 569/645] CVE-2020-25722 s4/dsdb/samldb: samldb_fsmo_role_owner_check() wants one value BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/samldb.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index d75277b3853..810365ca030 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -4315,6 +4315,9 @@ static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac) /* we are not affected */ return LDB_SUCCESS; } + if (el->num_values != 1) { + goto choose_error_code; + } /* Create a temporary message for fetching the "fSMORoleOwner" */ tmp_msg = ldb_msg_new(ac->msg); @@ -4331,11 +4334,7 @@ static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac) if (res_dn == NULL) { ldb_set_errstring(ldb, "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!"); - if (ac->req->operation == LDB_ADD) { - return LDB_ERR_CONSTRAINT_VIOLATION; - } else { - return LDB_ERR_UNWILLING_TO_PERFORM; - } + goto choose_error_code; } /* Fetched DN has to reference a "nTDSDSA" entry */ @@ -4355,6 +4354,14 @@ static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac) talloc_free(res); return LDB_SUCCESS; + +choose_error_code: + /* this is just how it is */ + if (ac->req->operation == LDB_ADD) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; + } } /* -- 2.25.1 From b4a0ec23993cd03c66bc4a59d2647f391fee3e4f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:19:42 +1300 Subject: [PATCH 570/645] CVE-2020-25722 s4/dsdb/pwd_hash: password_hash_bypass gets all values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- .../dsdb/samdb/ldb_modules/password_hash.c | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index ab6151aa549..98de2da69ca 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -200,6 +200,7 @@ static int password_hash_bypass(struct ldb_module *module, struct ldb_request *r struct ldb_message_element *nthe; struct ldb_message_element *lmhe; struct ldb_message_element *sce; + int ret; switch (request->operation) { case LDB_ADD: @@ -213,17 +214,26 @@ static int password_hash_bypass(struct ldb_module *module, struct ldb_request *r } /* nobody must touch password histories and 'supplementalCredentials' */ - nte = dsdb_get_single_valued_attr(msg, "unicodePwd", - request->operation); - lme = dsdb_get_single_valued_attr(msg, "dBCSPwd", - request->operation); - nthe = dsdb_get_single_valued_attr(msg, "ntPwdHistory", - request->operation); - lmhe = dsdb_get_single_valued_attr(msg, "lmPwdHistory", - request->operation); - sce = dsdb_get_single_valued_attr(msg, "supplementalCredentials", - request->operation); +#define GET_VALUES(el, attr) do { \ + ret = dsdb_get_expected_new_values(request, \ + msg, \ + attr, \ + &el, \ + request->operation); \ + \ + if (ret != LDB_SUCCESS) { \ + return ret; \ + } \ +} while(0) + + GET_VALUES(nte, "unicodePwd"); + GET_VALUES(lme, "dBCSPwd"); + GET_VALUES(nthe, "ntPwdHistory"); + GET_VALUES(lmhe, "lmPwdHistory"); + GET_VALUES(sce, "supplementalCredentials"); + +#undef GET_VALUES #define CHECK_HASH_ELEMENT(e, min, max) do {\ if (e && e->num_values) { \ unsigned int _count; \ -- 2.25.1 From 18f8b486c44fa9f725acc9c79b2babb6b576b09f Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:20:54 +1300 Subject: [PATCH 571/645] CVE-2020-25722 s4/dsdb/pwd_hash: rework pwdLastSet bypass This tightens the logic a bit, in that a message with trailing DELETE elements is no longer accepted when the bypass flag is set. In any case this is an unlikely scenario as this is an internal flag set by a private control in pdb_samba_dsdb_replace_by_sam(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- .../dsdb/samdb/ldb_modules/password_hash.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 98de2da69ca..7e4a42ffd62 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -2223,23 +2223,31 @@ static int setup_last_set_field(struct setup_password_fields_io *io) } if (io->ac->pwd_last_set_bypass) { - struct ldb_message_element *el1 = NULL; - struct ldb_message_element *el2 = NULL; - + struct ldb_message_element *el = NULL; + size_t i; + size_t count = 0; + /* + * This is a message from pdb_samba_dsdb_replace_by_sam() + * + * We want to ensure there is only one pwdLastSet element, and + * it isn't deleting. + */ if (msg == NULL) { return LDB_ERR_CONSTRAINT_VIOLATION; } - el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet", - io->ac->req->operation); - if (el1 == NULL) { - return LDB_ERR_CONSTRAINT_VIOLATION; + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, + "pwdLastSet") == 0) { + count++; + el = &msg->elements[i]; + } } - el2 = ldb_msg_find_element(msg, "pwdLastSet"); - if (el2 == NULL) { + if (count != 1) { return LDB_ERR_CONSTRAINT_VIOLATION; } - if (el1 != el2) { + + if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) { return LDB_ERR_CONSTRAINT_VIOLATION; } -- 2.25.1 From 3549c1f5581646863b41135d878d8322dedf1bec Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Thu, 21 Oct 2021 13:49:28 +1300 Subject: [PATCH 572/645] CVE-2020-25722 s4/dsdb/util: remove unused dsdb_get_single_valued_attr() Nobody uses it now. It never really did what it said it did. Almost every use was wrong. It was a trap. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/util.c | 34 --------------------------- 1 file changed, 34 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c index da152e4d754..4c67873643a 100644 --- a/source4/dsdb/samdb/ldb_modules/util.c +++ b/source4/dsdb/samdb/ldb_modules/util.c @@ -1562,40 +1562,6 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, return LDB_SUCCESS; } -/* - * Gets back a single-valued attribute by the rules of the DSDB triggers when - * performing a modify operation. - * - * In order that the constraint checking by the "objectclass_attrs" LDB module - * does work properly, the change request should remain similar or only be - * enhanced (no other modifications as deletions, variations). - */ -struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg, - const char *attr_name, - enum ldb_request_type operation) -{ - struct ldb_message_element *el = NULL; - unsigned int i; - - /* We've to walk over all modification entries and consider the last - * non-delete one which belongs to "attr_name". - * - * If "el" is NULL afterwards then that means there was no interesting - * change entry. */ - 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) - == LDB_FLAG_MOD_DELETE)) { - continue; - } - el = &msg->elements[i]; - } - } - - return el; -} - /* * This function determines the (last) structural or 88 object class of a passed * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value. -- 2.25.1 From 5440a8994ab50aa4c5f4a83b429794196a46ca9e Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 12:20:49 +1300 Subject: [PATCH 573/645] CVE-2020-25722 selftest: Adapt ldap.py tests to new objectClass restrictions BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/ldap | 1 + source4/dsdb/tests/python/ldap.py | 36 +++++++++++++++++++------------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/selftest/knownfail.d/ldap b/selftest/knownfail.d/ldap index 0331d3687d4..545dc93db8e 100644 --- a/selftest/knownfail.d/ldap +++ b/selftest/knownfail.d/ldap @@ -1,3 +1,4 @@ # the attributes too long test returns the wrong error ^samba4.ldap.python.+test_attribute_ranges_too_long samba4.ldap.python\(ad_dc_default\).*__main__.BasicTests.test_ldapSearchNoAttributes +^samba4.ldap.python.+test_objectclasses diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py index bd30faeb1d9..9d79f90a306 100755 --- a/source4/dsdb/tests/python/ldap.py +++ b/source4/dsdb/tests/python/ldap.py @@ -436,33 +436,41 @@ class BasicTests(samba.tests.TestCase): (num, _) = e.args self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) - # Add a new top-most structural class "inetOrgPerson" and remove it - # afterwards + # Try to add a new top-most structural class "inetOrgPerson" m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) m["objectClass"] = MessageElement("inetOrgPerson", FLAG_MOD_ADD, "objectClass") - ldb.modify(m) + try: + ldb.modify(m) + self.fail() + except LdbError as e: + (num, _) = e.args + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) + # Try to remove the structural class "user" m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) - m["objectClass"] = MessageElement("inetOrgPerson", FLAG_MOD_DELETE, + m["objectClass"] = MessageElement("user", FLAG_MOD_DELETE, "objectClass") - ldb.modify(m) + try: + ldb.modify(m) + self.fail() + except LdbError as e: + (num, _) = e.args + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) - # Replace top-most structural class to "inetOrgPerson" and reset it - # back to "user" + # Try to replace top-most structural class to "inetOrgPerson" m = Message() m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) m["objectClass"] = MessageElement("inetOrgPerson", FLAG_MOD_REPLACE, "objectClass") - ldb.modify(m) - - m = Message() - m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn) - m["objectClass"] = MessageElement("user", FLAG_MOD_REPLACE, - "objectClass") - ldb.modify(m) + try: + ldb.modify(m) + self.fail() + except LdbError as e: + (num, _) = e.args + self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION) # Add a new auxiliary object class "posixAccount" to "ldaptestuser" m = Message() -- 2.25.1 From 60d2098ee78b951fb534dd9ffed3d1df31e7691c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:56:10 +1300 Subject: [PATCH 574/645] CVE-2020-25718 tests/krb5: Fix indentation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 5313dbc6045..480e3d8264d 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -667,7 +667,7 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds(replication_allowed=True, revealed_to_rodc=True) existing_rid = self._get_existing_rid(replication_allowed=True, - revealed_to_rodc=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) @@ -675,7 +675,7 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds(replication_allowed=True, revealed_to_rodc=True) existing_rid = self._get_existing_rid(replication_allowed=True, - revealed_to_rodc=True) + 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) @@ -693,7 +693,7 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds(replication_allowed=True, revealed_to_rodc=True) existing_rid = self._get_existing_rid(replication_allowed=True, - revealed_to_rodc=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) @@ -701,7 +701,7 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds(replication_allowed=True, revealed_to_rodc=True) existing_rid = self._get_existing_rid(replication_allowed=True, - revealed_to_rodc=True) + 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) -- 2.25.1 From fe0f24c6144b03834d3895be712ca880f620b4f7 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:33:38 +1300 Subject: [PATCH 575/645] CVE-2020-25719 krb5pac.idl: Add PAC_ATTRIBUTES_INFO PAC buffer type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- librpc/idl/krb5pac.idl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index ed488dee425..11e227026f6 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -111,6 +111,16 @@ interface krb5pac [switch_is(flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_EX ex; } PAC_UPN_DNS_INFO; + typedef [bitmap32bit] bitmap { + PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED = 0x00000001, + PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY = 0x00000002 + } PAC_ATTRIBUTE_INFO_FLAGS; + + typedef struct { + uint32 flags_length; /* length in bits */ + PAC_ATTRIBUTE_INFO_FLAGS flags; + } PAC_ATTRIBUTES_INFO; + typedef [public] struct { PAC_LOGON_INFO *info; } PAC_LOGON_INFO_CTR; @@ -130,7 +140,8 @@ interface krb5pac PAC_TYPE_CLIENT_CLAIMS_INFO = 13, PAC_TYPE_DEVICE_INFO = 14, PAC_TYPE_DEVICE_CLAIMS_INFO = 15, - PAC_TYPE_TICKET_CHECKSUM = 16 + PAC_TYPE_TICKET_CHECKSUM = 16, + PAC_TYPE_ATTRIBUTES_INFO = 17 } PAC_TYPE; typedef struct { @@ -147,6 +158,7 @@ interface krb5pac PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation; [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; + [case(PAC_TYPE_ATTRIBUTES_INFO)] PAC_ATTRIBUTES_INFO attributes_info; /* when new PAC info types are added they are supposed to be done in such a way that they are backwards compatible with existing servers. This makes it safe to just use a [default] for -- 2.25.1 From b81af956c0629362c602f827c58d321fc29e0454 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:33:49 +1300 Subject: [PATCH 576/645] CVE-2020-25719 krb5pac.idl: Add PAC_REQUESTER_SID PAC buffer type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- librpc/idl/krb5pac.idl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index 11e227026f6..bbe4a253e3a 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -121,6 +121,10 @@ interface krb5pac PAC_ATTRIBUTE_INFO_FLAGS flags; } PAC_ATTRIBUTES_INFO; + typedef struct { + dom_sid sid; + } PAC_REQUESTER_SID; + typedef [public] struct { PAC_LOGON_INFO *info; } PAC_LOGON_INFO_CTR; @@ -141,7 +145,8 @@ interface krb5pac PAC_TYPE_DEVICE_INFO = 14, PAC_TYPE_DEVICE_CLAIMS_INFO = 15, PAC_TYPE_TICKET_CHECKSUM = 16, - PAC_TYPE_ATTRIBUTES_INFO = 17 + PAC_TYPE_ATTRIBUTES_INFO = 17, + PAC_TYPE_REQUESTER_SID = 18 } PAC_TYPE; typedef struct { @@ -159,6 +164,7 @@ interface krb5pac [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; [case(PAC_TYPE_ATTRIBUTES_INFO)] PAC_ATTRIBUTES_INFO attributes_info; + [case(PAC_TYPE_REQUESTER_SID)] PAC_REQUESTER_SID requester_sid; /* when new PAC info types are added they are supposed to be done in such a way that they are backwards compatible with existing servers. This makes it safe to just use a [default] for -- 2.25.1 From 54b75f2518883307694b15123ee17e42a3749093 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:44:45 +1300 Subject: [PATCH 577/645] CVE-2020-25719 tests/krb5: Provide expected parameters for both AS-REQs in get_tgt() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 9be6cbab30b..6d6dcc21607 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1389,6 +1389,8 @@ class KDCBaseTest(RawKerberosTest): ticket_decryption_key = ( self.TicketDecryptionKey_from_creds(krbtgt_creds)) + expected_etypes = krbtgt_creds.tgs_supported_enctypes + if kdc_options is None: kdc_options = ('forwardable,' 'renewable,' @@ -1415,6 +1417,7 @@ class KDCBaseTest(RawKerberosTest): expected_salt=salt, expected_flags=expected_flags, unexpected_flags=unexpected_flags, + expected_supported_etypes=expected_etypes, etypes=etype, padata=None, kdc_options=kdc_options, @@ -1422,6 +1425,7 @@ class KDCBaseTest(RawKerberosTest): ticket_decryption_key=ticket_decryption_key, pac_request=pac_request, pac_options=pac_options, + expect_pac=expect_pac, to_rodc=to_rodc) self.check_pre_authentication(rep) @@ -1440,8 +1444,6 @@ class KDCBaseTest(RawKerberosTest): expected_sname = self.PrincipalName_create( name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) - expected_etypes = krbtgt_creds.tgs_supported_enctypes - rep, kdc_exchange_dict = self._test_as_exchange( cname=cname, realm=realm, @@ -1453,6 +1455,9 @@ class KDCBaseTest(RawKerberosTest): expected_cname=cname, expected_srealm=expected_realm, expected_sname=expected_sname, + expected_account_name=expected_account_name, + expected_upn_name=expected_upn_name, + expected_sid=expected_sid, expected_salt=salt, expected_flags=expected_flags, unexpected_flags=unexpected_flags, -- 2.25.1 From 28480ea16d08f9d85c4823cc73639a9495b191d8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:47:53 +1300 Subject: [PATCH 578/645] CVE-2020-25719 tests/krb5: Allow update_pac_checksums=True if the PAC is not present BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 18ee8738eaa..39ca4a69e1c 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -3293,7 +3293,7 @@ class RawKerberosTest(TestCaseInTempDir): self.assertFalse(checksum_keys) self.assertFalse(include_checksums) - expect_pac = update_pac_checksums or modify_pac_fn is not None + expect_pac = modify_pac_fn is not None key = ticket.decryption_key -- 2.25.1 From f2ed57ba3d8cdecd348dd2868f5462ef5e49b210 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:51:34 +1300 Subject: [PATCH 579/645] CVE-2020-25719 tests/krb5: Don't expect a kvno for user-to-user BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 39ca4a69e1c..f39e57c8189 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2225,9 +2225,19 @@ class RawKerberosTest(TestCaseInTempDir): self.assertIsNotNone(ticket_encpart) if ticket_encpart is not None: # Never None, but gives indentation self.assertElementPresent(ticket_encpart, 'etype') - # 'unspecified' means present, with any value != 0 - self.assertElementKVNO(ticket_encpart, 'kvno', - self.unspecified_kvno) + + kdc_options = kdc_exchange_dict['kdc_options'] + pos = len(tuple(krb5_asn1.KDCOptions('enc-tkt-in-skey'))) - 1 + expect_kvno = (pos >= len(kdc_options) + or kdc_options[pos] != '1') + if expect_kvno: + # 'unspecified' means present, with any value != 0 + self.assertElementKVNO(ticket_encpart, 'kvno', + self.unspecified_kvno) + else: + # For user-to-user, don't expect a kvno. + self.assertElementMissing(ticket_encpart, 'kvno') + self.assertElementPresent(ticket_encpart, 'cipher') ticket_cipher = self.getElementValue(ticket_encpart, 'cipher') self.assertElementPresent(rep, 'enc-part') -- 2.25.1 From 10a6e8884b909d74af9b0b8374184ea6159d2561 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:51:46 +1300 Subject: [PATCH 580/645] CVE-2020-25719 tests/krb5: Expect 'renew-till' element when renewing a TGT BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index f39e57c8189..79fe9ec4620 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2369,6 +2369,10 @@ class RawKerberosTest(TestCaseInTempDir): renewable_pos = len(tuple(krb5_asn1.KDCOptions('renewable'))) - 1 renewable = (renewable_pos < len(kdc_options) and kdc_options[renewable_pos] == '1') + renew_pos = len(tuple(krb5_asn1.KDCOptions('renew'))) - 1 + renew = (renew_pos < len(kdc_options) + and kdc_options[renew_pos] == '1') + expect_renew_till = renewable or renew expected_crealm = kdc_exchange_dict['expected_crealm'] expected_cname = kdc_exchange_dict['expected_cname'] @@ -2425,7 +2429,7 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertElementPresent(ticket_private, 'starttime') self.assertElementPresent(ticket_private, 'endtime') - if renewable: + if expect_renew_till: if self.strict_checking: self.assertElementPresent(ticket_private, 'renew-till') else: @@ -2461,7 +2465,7 @@ class RawKerberosTest(TestCaseInTempDir): if self.strict_checking: self.assertElementPresent(encpart_private, 'starttime') self.assertElementPresent(encpart_private, 'endtime') - if renewable: + if expect_renew_till: if self.strict_checking: self.assertElementPresent(encpart_private, 'renew-till') else: -- 2.25.1 From 0a1b523abdf34771353cee8db3ea4cf88fc5c3ef Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:05:08 +1300 Subject: [PATCH 581/645] CVE-2020-25719 tests/krb5: Return ticket from _tgs_req() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 480e3d8264d..11bf38766ae 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -1302,12 +1302,18 @@ class KdcTgsTests(KDCBaseTest): expect_edata=False, expect_claims=expect_claims) - self._generic_kdc_exchange(kdc_exchange_dict, - cname=None, - realm=srealm, - sname=sname, - etypes=etypes, - additional_tickets=additional_tickets) + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=srealm, + sname=sname, + etypes=etypes, + additional_tickets=additional_tickets) + if expected_error: + self.check_error_rep(rep, expected_error) + return None + else: + self.check_reply(rep, KRB_TGS_REP) + return kdc_exchange_dict['rep_ticket_creds'] if __name__ == "__main__": -- 2.25.1 From 78e9fefd9a759ebb0ada2842d275b5a3c5fc74c5 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:14:45 +1300 Subject: [PATCH 582/645] CVE-2020-25719 tests/krb5: Use correct credentials for user-to-user tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 9 ++++----- selftest/knownfail_heimdal_kdc | 1 - selftest/knownfail_mit_kdc | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 11bf38766ae..2787185f04a 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -949,7 +949,7 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds() tgt = self._get_tgt(creds) - user_name = self._get_mach_creds().get_username() + user_name = creds.get_username() sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=['host', user_name]) @@ -960,18 +960,17 @@ class KdcTgsTests(KDCBaseTest): creds = self._get_creds() tgt = self._get_tgt(creds) - user_name = self._get_mach_creds().get_username() + user_name = creds.get_username() sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[user_name]) - self._user2user(tgt, creds, sname=sname, - expected_error=KDC_ERR_BADMATCH) + self._user2user(tgt, creds, sname=sname, expected_error=0) def test_user2user_wrong_sname(self): creds = self._get_creds() tgt = self._get_tgt(creds) - other_creds = self.get_service_creds() + other_creds = self._get_mach_creds() user_name = other_creds.get_username() sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, names=[user_name]) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 46866823590..42f02473272 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -323,7 +323,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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_matching_sname_host -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_matching_sname_no_host ^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_non_existent_sname ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index d2acc5559ed..daf8012be43 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -441,7 +441,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_upn_dns_info_ex_upn_user ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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_matching_sname_no_host ^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_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied -- 2.25.1 From 14287bedc14bfb06dbb15356bd1c89f0a9975f5b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:15:53 +1300 Subject: [PATCH 583/645] CVE-2020-25719 tests/krb5: Adjust PAC tests to prepare for new PAC_ATTRIBUTES_INFO buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 10 +++++----- selftest/knownfail_heimdal_kdc | 1 - selftest/knownfail_mit_kdc | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 2787185f04a..10a146a5e59 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -324,10 +324,10 @@ class KdcTgsTests(KDCBaseTest): self.assertIsNotNone(pac) ticket = self._make_tgs_request(client_creds, service_creds, tgt, - pac_request=False) + pac_request=False, expect_pac=False) - pac = self.get_ticket_pac(ticket) - self.assertIsNotNone(pac) + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) def test_client_no_auth_data_required(self): client_creds = self.get_cached_creds( @@ -351,13 +351,13 @@ class KdcTgsTests(KDCBaseTest): opts={'no_auth_data_required': True}) service_creds = self.get_service_creds() - tgt = self.get_tgt(client_creds, pac_request=False) + tgt = self.get_tgt(client_creds) pac = self.get_ticket_pac(tgt) self.assertIsNotNone(pac) ticket = self._make_tgs_request(client_creds, service_creds, tgt, - pac_request=False) + pac_request=False, expect_pac=True) pac = self.get_ticket_pac(ticket) self.assertIsNotNone(pac) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 42f02473272..1ddf812da25 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -265,7 +265,6 @@ # # KDC TGS PAC tests # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_client_no_auth_data_required ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required ^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 diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index daf8012be43..720d243e05c 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -278,7 +278,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # # KDC TGS PAC tests # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_client_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required\(ad_dc\) -- 2.25.1 From a0463314d0423e71d218a1b43745669ed84664f9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:20:51 +1300 Subject: [PATCH 584/645] CVE-2020-25719 tests/krb5: Adjust expected error codes for user-to-user tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 10a146a5e59..3a60b9cafb9 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -40,6 +40,7 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_BADMATCH, KDC_ERR_BADOPTION, KDC_ERR_CLIENT_NAME_MISMATCH, + KDC_ERR_MODIFIED, KDC_ERR_POLICY, KDC_ERR_S_PRINCIPAL_UNKNOWN, KDC_ERR_TGT_REVOKED, @@ -996,7 +997,8 @@ class KdcTgsTests(KDCBaseTest): service_creds = self.get_service_creds() service_ticket = self.get_service_ticket(tgt, service_creds) - self._user2user(service_ticket, creds, expected_error=KDC_ERR_POLICY) + self._user2user(service_ticket, creds, + expected_error=(KDC_ERR_MODIFIED, KDC_ERR_POLICY)) def _get_tgt(self, client_creds, -- 2.25.1 From 5be597941e854e351106b4ac34e3ae75f25123b3 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:08:34 +1300 Subject: [PATCH 585/645] CVE-2020-25719 tests/krb5: tests/krb5: Adjust expected error code for S4U2Self no-PAC tests BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 32 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 3a60b9cafb9..3fd6fc1a7b1 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -23,7 +23,7 @@ import os import ldb -from samba import dsdb +from samba import dsdb, ntstatus from samba.dcerpc import krb5pac @@ -40,6 +40,7 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_BADMATCH, KDC_ERR_BADOPTION, KDC_ERR_CLIENT_NAME_MISMATCH, + KDC_ERR_GENERIC, KDC_ERR_MODIFIED, KDC_ERR_POLICY, KDC_ERR_S_PRINCIPAL_UNKNOWN, @@ -528,7 +529,10 @@ class KdcTgsTests(KDCBaseTest): 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_BADOPTION) + self._s4u2self(tgt, creds, + expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), + expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, + expect_edata=True) def test_user2user_no_pac(self): creds = self._get_creds() @@ -556,7 +560,10 @@ class KdcTgsTests(KDCBaseTest): 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_BADOPTION) + self._s4u2self(tgt, creds, + expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), + expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, + expect_edata=True) def test_user2user_authdata_no_pac(self): creds = self._get_creds() @@ -1210,7 +1217,8 @@ class KdcTgsTests(KDCBaseTest): self._tgs_req(tgt, expected_error, krbtgt_creds, kdc_options=kdc_options) - def _s4u2self(self, tgt, tgt_creds, expected_error): + def _s4u2self(self, tgt, tgt_creds, expected_error, + expect_edata=False, expected_status=None): user_creds = self._get_mach_creds() user_name = user_creds.get_username() @@ -1229,10 +1237,11 @@ class KdcTgsTests(KDCBaseTest): return [padata], req_body - self._tgs_req(tgt, expected_error, tgt_creds, - expected_cname=user_cname, - generate_padata_fn=generate_s4u2self_padata, - expect_claims=False) + return self._tgs_req(tgt, expected_error, tgt_creds, + expected_cname=user_cname, + generate_padata_fn=generate_s4u2self_padata, + expect_claims=False, expect_edata=expect_edata, + expected_status=expected_status) def _user2user(self, tgt, tgt_creds, expected_error, sname=None): user_creds = self._get_mach_creds() @@ -1250,7 +1259,9 @@ class KdcTgsTests(KDCBaseTest): additional_ticket=None, generate_padata_fn=None, sname=None, - expect_claims=True): + expect_claims=True, + expect_edata=False, + expected_status=None): srealm = target_creds.get_realm() if sname is None: @@ -1297,10 +1308,11 @@ class KdcTgsTests(KDCBaseTest): 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, authenticator_subkey=subkey, kdc_options=kdc_options, - expect_edata=False, + expect_edata=expect_edata, expect_claims=expect_claims) rep = self._generic_kdc_exchange(kdc_exchange_dict, -- 2.25.1 From 05adc4e5e785a5fe0ba03dcf784cb7e872f8cd83 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:12:12 +1300 Subject: [PATCH 586/645] CVE-2020-25719 tests/krb5: Extend _get_tgt() method to allow more modifications to tickets BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 55 ++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 3fd6fc1a7b1..4cb32c96250 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -25,7 +25,7 @@ import ldb from samba import dsdb, ntstatus -from samba.dcerpc import krb5pac +from samba.dcerpc import krb5pac, security sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" @@ -1014,7 +1014,11 @@ class KdcTgsTests(KDCBaseTest): from_rodc=False, new_rid=None, remove_pac=False, - allow_empty_authdata=False): + allow_empty_authdata=False, + can_modify_logon_info=True, + can_modify_requester_sid=True, + remove_pac_attrs=False, + remove_requester_sid=False): self.assertFalse(renewable and invalid) if remove_pac: @@ -1027,19 +1031,38 @@ class KdcTgsTests(KDCBaseTest): else: krbtgt_creds = self.get_krbtgt_creds() - if new_rid is not None: + if new_rid is not None or remove_requester_sid or remove_pac_attrs: def change_sid_fn(pac): - for pac_buffer in pac.buffers: + pac_buffers = pac.buffers + for pac_buffer in pac_buffers: if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_INFO: - logon_info = pac_buffer.info.info + if new_rid is not None and can_modify_logon_info: + logon_info = pac_buffer.info.info - logon_info.info3.base.rid = new_rid + logon_info.info3.base.rid = new_rid + elif pac_buffer.type == krb5pac.PAC_TYPE_REQUESTER_SID: + if remove_requester_sid: + pac.num_buffers -= 1 + pac_buffers.remove(pac_buffer) + elif new_rid is not None and can_modify_requester_sid: + requester_sid = pac_buffer.info - return pac + samdb = self.get_samdb() + domain_sid = samdb.get_domain_sid() + + new_sid = f'{domain_sid}-{new_rid}' + + requester_sid.sid = security.dom_sid(new_sid) + elif pac_buffer.type == krb5pac.PAC_TYPE_ATTRIBUTES_INFO: + if remove_pac_attrs: + pac.num_buffers -= 1 + pac_buffers.remove(pac_buffer) + + pac.buffers = pac_buffers - modify_pac_fn = change_sid_fn + return pac else: - modify_pac_fn = None + change_sid_fn = None krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) @@ -1051,7 +1074,7 @@ class KdcTgsTests(KDCBaseTest): } if renewable: - def set_renewable(enc_part): + def flags_modify_fn(enc_part): # Set the renewable flag. renewable_flag = krb5_asn1.TicketFlags('renewable') pos = len(tuple(renewable_flag)) - 1 @@ -1067,10 +1090,8 @@ class KdcTgsTests(KDCBaseTest): enc_part['renew-till'] = renew_till return enc_part - - modify_fn = set_renewable elif invalid: - def set_invalid(enc_part): + def flags_modify_fn(enc_part): # Set the invalid flag. invalid_flag = krb5_asn1.TicketFlags('invalid') pos = len(tuple(invalid_flag)) - 1 @@ -1086,16 +1107,14 @@ class KdcTgsTests(KDCBaseTest): enc_part['starttime'] = past_time return enc_part - - modify_fn = set_invalid else: - modify_fn = None + flags_modify_fn = None return self.modified_ticket( tgt, new_ticket_key=krbtgt_key, - modify_fn=modify_fn, - modify_pac_fn=modify_pac_fn, + modify_fn=flags_modify_fn, + modify_pac_fn=change_sid_fn, exclude_pac=remove_pac, allow_empty_authdata=allow_empty_authdata, update_pac_checksums=not remove_pac, -- 2.25.1 From 97716aa0228543ab62690609b9e4c443ac453c4f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 10:25:08 +1300 Subject: [PATCH 587/645] CVE-2020-25719 tests/krb5: Add _modify_tgt() method for modifying already obtained tickets https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 62 +++++++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 4cb32c96250..52a347b9ed4 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -1026,6 +1026,33 @@ class KdcTgsTests(KDCBaseTest): tgt = self.get_tgt(client_creds) + return self._modify_tgt( + tgt=tgt, + renewable=renewable, + invalid=invalid, + from_rodc=from_rodc, + new_rid=new_rid, + remove_pac=remove_pac, + allow_empty_authdata=allow_empty_authdata, + can_modify_logon_info=can_modify_logon_info, + can_modify_requester_sid=can_modify_requester_sid, + remove_pac_attrs=remove_pac_attrs, + remove_requester_sid=remove_requester_sid) + + def _modify_tgt(self, + tgt, + renewable=False, + invalid=False, + from_rodc=False, + new_rid=None, + remove_pac=False, + allow_empty_authdata=False, + cname=None, + crealm=None, + can_modify_logon_info=True, + can_modify_requester_sid=True, + remove_pac_attrs=False, + remove_requester_sid=False): if from_rodc: krbtgt_creds = self.get_mock_rodc_krbtgt_creds() else: @@ -1110,11 +1137,42 @@ class KdcTgsTests(KDCBaseTest): else: flags_modify_fn = None + if cname is not None or crealm is not None: + def modify_fn(enc_part): + if flags_modify_fn is not None: + enc_part = flags_modify_fn(enc_part) + + if cname is not None: + enc_part['cname'] = cname + + if crealm is not None: + enc_part['crealm'] = crealm + + return enc_part + else: + modify_fn = flags_modify_fn + + if cname is not None: + def modify_pac_fn(pac): + if change_sid_fn is not None: + pac = change_sid_fn(pac) + + for pac_buffer in pac.buffers: + if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME: + logon_info = pac_buffer.info + + logon_info.account_name = ( + cname['name-string'][0].decode('utf-8')) + + return pac + else: + modify_pac_fn = change_sid_fn + return self.modified_ticket( tgt, new_ticket_key=krbtgt_key, - modify_fn=flags_modify_fn, - modify_pac_fn=change_sid_fn, + modify_fn=modify_fn, + modify_pac_fn=modify_pac_fn, exclude_pac=remove_pac, allow_empty_authdata=allow_empty_authdata, update_pac_checksums=not remove_pac, -- 2.25.1 From 781c69772e78cf42da0e435258ff9d7e5028d79c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:50:09 +1300 Subject: [PATCH 588/645] CVE-2020-25719 tests/krb5: Add testing for PAC_TYPE_ATTRIBUTES_INFO PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 8 ++++- python/samba/tests/krb5/raw_testcase.py | 37 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 6d6dcc21607..dc1ba629b41 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1360,7 +1360,9 @@ class KDCBaseTest(RawKerberosTest): expected_flags=None, unexpected_flags=None, expected_account_name=None, expected_upn_name=None, expected_sid=None, - pac_request=True, expect_pac=True, fresh=False): + pac_request=True, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + fresh=False): user_name = creds.get_username() cache_key = (user_name, to_rodc, kdc_options, pac_request) @@ -1426,6 +1428,8 @@ class KDCBaseTest(RawKerberosTest): pac_request=pac_request, pac_options=pac_options, expect_pac=expect_pac, + expect_pac_attrs=expect_pac_attrs, + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, to_rodc=to_rodc) self.check_pre_authentication(rep) @@ -1470,6 +1474,8 @@ class KDCBaseTest(RawKerberosTest): pac_request=pac_request, pac_options=pac_options, expect_pac=expect_pac, + expect_pac_attrs=expect_pac_attrs, + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, to_rodc=to_rodc) self.check_as_reply(rep) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 79fe9ec4620..d63366318be 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2021,6 +2021,8 @@ class RawKerberosTest(TestCaseInTempDir): expect_pac=True, expect_claims=True, expect_upn_dns_info_ex=None, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2074,6 +2076,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_pac': expect_pac, 'expect_claims': expect_claims, 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, + 'expect_pac_attrs': expect_pac_attrs, + 'expect_pac_attrs_pac_request': expect_pac_attrs_pac_request, 'to_rodc': to_rodc } if callback_dict is None: @@ -2122,6 +2126,8 @@ class RawKerberosTest(TestCaseInTempDir): expect_pac=True, expect_claims=True, expect_upn_dns_info_ex=None, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, expected_proxy_target=None, expected_transited_services=None, to_rodc=False): @@ -2176,6 +2182,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_pac': expect_pac, 'expect_claims': expect_claims, 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, + 'expect_pac_attrs': expect_pac_attrs, + 'expect_pac_attrs_pac_request': expect_pac_attrs_pac_request, 'expected_proxy_target': expected_proxy_target, 'expected_transited_services': expected_transited_services, 'to_rodc': to_rodc @@ -2596,6 +2604,12 @@ class RawKerberosTest(TestCaseInTempDir): if not self.tkt_sig_support: require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs'] + 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) + buffer_types = [pac_buffer.type for pac_buffer in pac.buffers] self.assertSequenceElementsEqual( @@ -2671,6 +2685,25 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(expected_sid, str(upn_dns_info_ex.objectsid)) + elif (pac_buffer.type == krb5pac.PAC_TYPE_ATTRIBUTES_INFO + and expect_pac_attrs): + attr_info = pac_buffer.info + + self.assertEqual(2, attr_info.flags_length) + + flags = attr_info.flags + + 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, + given_pac) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -3663,6 +3696,8 @@ class RawKerberosTest(TestCaseInTempDir): pac_request=None, pac_options=None, expect_pac=True, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, to_rodc=False): def _generate_padata_copy(_kdc_exchange_dict, @@ -3706,6 +3741,8 @@ class RawKerberosTest(TestCaseInTempDir): pac_request=pac_request, pac_options=pac_options, expect_pac=expect_pac, + expect_pac_attrs=expect_pac_attrs, + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, -- 2.25.1 From 76ab4142ba4bbcea1ee8cd8807ff63a8513148ab Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:51:13 +1300 Subject: [PATCH 589/645] CVE-2020-25719 tests/krb5: Add testing for PAC_TYPE_REQUESTER_SID PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 3 +++ python/samba/tests/krb5/raw_testcase.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index dc1ba629b41..61eeb2333f9 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1362,6 +1362,7 @@ class KDCBaseTest(RawKerberosTest): expected_sid=None, pac_request=True, expect_pac=True, expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, fresh=False): user_name = creds.get_username() cache_key = (user_name, to_rodc, kdc_options, pac_request) @@ -1430,6 +1431,7 @@ class KDCBaseTest(RawKerberosTest): 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, to_rodc=to_rodc) self.check_pre_authentication(rep) @@ -1476,6 +1478,7 @@ class KDCBaseTest(RawKerberosTest): 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, to_rodc=to_rodc) self.check_as_reply(rep) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index d63366318be..8779d0f7869 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2023,6 +2023,7 @@ class RawKerberosTest(TestCaseInTempDir): expect_upn_dns_info_ex=None, expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, to_rodc=False): if expected_error_mode == 0: expected_error_mode = () @@ -2078,6 +2079,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, 'expect_pac_attrs': expect_pac_attrs, 'expect_pac_attrs_pac_request': expect_pac_attrs_pac_request, + 'expect_requester_sid': expect_requester_sid, 'to_rodc': to_rodc } if callback_dict is None: @@ -2128,6 +2130,7 @@ class RawKerberosTest(TestCaseInTempDir): expect_upn_dns_info_ex=None, expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, expected_proxy_target=None, expected_transited_services=None, to_rodc=False): @@ -2184,6 +2187,7 @@ class RawKerberosTest(TestCaseInTempDir): 'expect_upn_dns_info_ex': expect_upn_dns_info_ex, 'expect_pac_attrs': expect_pac_attrs, 'expect_pac_attrs_pac_request': expect_pac_attrs_pac_request, + 'expect_requester_sid': expect_requester_sid, 'expected_proxy_target': expected_proxy_target, 'expected_transited_services': expected_transited_services, 'to_rodc': to_rodc @@ -2610,6 +2614,12 @@ class RawKerberosTest(TestCaseInTempDir): 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: + 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] self.assertSequenceElementsEqual( @@ -2704,6 +2714,13 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(expect_pac_attrs_pac_request is None, given_pac) + elif (pac_buffer.type == krb5pac.PAC_TYPE_REQUESTER_SID + and expect_requester_sid): + requester_sid = pac_buffer.info.sid + + self.assertIsNotNone(expected_sid) + self.assertEqual(expected_sid, str(requester_sid)) + def generic_check_kdc_error(self, kdc_exchange_dict, callback_dict, @@ -3698,6 +3715,7 @@ class RawKerberosTest(TestCaseInTempDir): expect_pac=True, expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, to_rodc=False): def _generate_padata_copy(_kdc_exchange_dict, @@ -3743,6 +3761,7 @@ class RawKerberosTest(TestCaseInTempDir): 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, to_rodc=to_rodc) rep = self._generic_kdc_exchange(kdc_exchange_dict, -- 2.25.1 From ea27a7b59aaa38d82c2d697b05dfbfdc880459a9 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:47:24 +1300 Subject: [PATCH 590/645] CVE-2020-25719 tests/krb5: Add EXPECT_PAC environment variable to expect pac from all TGS tickets BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/raw_testcase.py | 25 ++++++++--- source4/selftest/tests.py | 55 +++++++++++++++++-------- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 8779d0f7869..42f2e94f5aa 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -596,6 +596,12 @@ class RawKerberosTest(TestCaseInTempDir): tkt_sig_support = '0' cls.tkt_sig_support = bool(int(tkt_sig_support)) + expect_pac = samba.tests.env_get_var_value('EXPECT_PAC', + allow_missing=True) + if expect_pac is None: + expect_pac = '1' + cls.expect_pac = bool(int(expect_pac)) + def setUp(self): super().setUp() self.do_asn1_print = False @@ -2417,7 +2423,10 @@ class RawKerberosTest(TestCaseInTempDir): etype=kcrypto.Enctype.RC4) krbtgt_keys.append(krbtgt_key_rc4) - expect_pac = kdc_exchange_dict['expect_pac'] + if self.expect_pac and self.is_tgs(expected_sname): + expect_pac = True + else: + expect_pac = kdc_exchange_dict['expect_pac'] ticket_session_key = None if ticket_private is not None: @@ -2448,8 +2457,9 @@ class RawKerberosTest(TestCaseInTempDir): self.assertElementMissing(ticket_private, 'renew-till') if self.strict_checking: self.assertElementEqual(ticket_private, 'caddr', []) - self.assertElementPresent(ticket_private, 'authorization-data', - expect_empty=not expect_pac) + if expect_pac is not None: + self.assertElementPresent(ticket_private, 'authorization-data', + expect_empty=not expect_pac) encpart_session_key = None if encpart_private is not None: @@ -2554,11 +2564,14 @@ class RawKerberosTest(TestCaseInTempDir): if ticket_private is not None: pac_data = self.get_ticket_pac(ticket_creds, expect_pac=expect_pac) - if expect_pac: - self.check_pac_buffers(pac_data, kdc_exchange_dict) - else: + if expect_pac is True: + self.assertIsNotNone(pac_data) + elif expect_pac is False: self.assertIsNone(pac_data) + if pac_data is not None: + self.check_pac_buffers(pac_data, kdc_exchange_dict) + expect_ticket_checksum = kdc_exchange_dict['expect_ticket_checksum'] if expect_ticket_checksum: self.assertIsNotNone(ticket_decryption_key) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 67764e43a9a..0c059d23f69 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -744,28 +744,33 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$U have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) +expect_pac = 0 planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", environ={'SERVICE_USERNAME':'$SERVER', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support}) + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac}) planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", environ={'ADMIN_USERNAME':'$USERNAME', 'ADMIN_PASSWORD':'$PASSWORD', 'FOR_USER':'$USERNAME', 'STRICT_CHECKING':'0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support}) + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac}) planoldpythontestsuite("rodc:local", "samba.tests.krb5.rodc_tests", environ={'ADMIN_USERNAME':'$USERNAME', 'ADMIN_PASSWORD':'$PASSWORD', 'STRICT_CHECKING':'0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support}) + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac}) planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests", environ={'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support}) + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac}) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", environ={ @@ -773,7 +778,8 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", environ={ @@ -781,7 +787,8 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) for env in ['ad_dc_default', 'ad_member']: planoldpythontestsuite(env, "samba.tests.krb5.test_rpc", @@ -790,7 +797,8 @@ for env in ['ad_dc_default', 'ad_member']: 'ADMIN_PASSWORD': '$DC_PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", environ={ @@ -798,7 +806,8 @@ planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planoldpythontestsuite("ad_member_no_nss_wb:local", "samba.tests.krb5.test_min_domain_uid", @@ -1350,7 +1359,8 @@ for env in ["fl2008r2dc", "fl2003dc"]: 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', @@ -1359,7 +1369,8 @@ planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: @@ -1381,7 +1392,8 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", environ={ @@ -1389,11 +1401,13 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests", environ={'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support}) + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac}) planpythontestsuite( "ad_dc", "samba.tests.krb5.kdc_tgs_tests", @@ -1402,7 +1416,8 @@ planpythontestsuite( 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite( "ad_dc", @@ -1412,7 +1427,8 @@ planpythontestsuite( 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite( "ad_dc", @@ -1422,7 +1438,8 @@ planpythontestsuite( 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite( "ad_dc", @@ -1432,7 +1449,8 @@ planpythontestsuite( 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) planpythontestsuite( "ad_dc", @@ -1442,7 +1460,8 @@ planpythontestsuite( 'ADMIN_PASSWORD': '$PASSWORD', 'STRICT_CHECKING': '0', 'FAST_SUPPORT': have_fast_support, - 'TKT_SIG_SUPPORT': tkt_sig_support + 'TKT_SIG_SUPPORT': tkt_sig_support, + 'EXPECT_PAC': expect_pac }) for env in [ -- 2.25.1 From 9591fb5780e5a774dec0b63a0038b829ec0a66cd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 11:18:36 +1300 Subject: [PATCH 591/645] CVE-2020-25719 tests/krb5: Add expected parameters to cache key for obtaining tickets If multiple calls to get_tgt() or get_service_ticket() specify different expected parameters, we want to perform the request again so that the checking can be performed, rather than reusing a previously obtained ticket and potentially skipping checks. It should be fine to cache tickets with the same expected parameters, as tickets that fail to be obtained will not be stored in the cache, so the checking will happen for every call. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 61eeb2333f9..4b4f1486f60 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1294,7 +1294,8 @@ class KDCBaseTest(RawKerberosTest): 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) + pac_request, str(expected_flags), str(unexpected_flags), + expect_pac) if not fresh: ticket = self.tkt_cache.get(cache_key) @@ -1365,7 +1366,11 @@ class KDCBaseTest(RawKerberosTest): expect_requester_sid=None, fresh=False): user_name = creds.get_username() - cache_key = (user_name, to_rodc, kdc_options, pac_request) + cache_key = (user_name, to_rodc, kdc_options, pac_request, + str(expected_flags), str(unexpected_flags), + expected_account_name, expected_upn_name, expected_sid, + expect_pac, expect_pac_attrs, + expect_pac_attrs_pac_request, expect_requester_sid) if not fresh: tgt = self.tkt_cache.get(cache_key) -- 2.25.1 From 83ed560eca3cea13d82b0739c49b0d2f20df6b49 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:02:08 +1300 Subject: [PATCH 592/645] CVE-2020-25719 tests/krb5: Add tests for PAC attributes buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 281 +++++++++++++++++++++-- selftest/knownfail_heimdal_kdc | 21 ++ selftest/knownfail_mit_kdc | 22 ++ 3 files changed, 308 insertions(+), 16 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 52a347b9ed4..40291677819 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -510,6 +510,20 @@ class KdcTgsTests(KDCBaseTest): tgt = self._get_tgt(creds) self._user2user(tgt, creds, expected_error=0) + def test_tgs_req_no_pac_attrs(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac_attrs=True) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, + expect_pac_attrs=False) + + def test_tgs_req_from_rodc_no_pac_attrs(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, remove_pac_attrs=True) + self._run_tgs(tgt, expected_error=0, expect_pac=True, + expect_pac_attrs=False) + # Test making a request without a PAC. def test_tgs_no_pac(self): creds = self._get_creds() @@ -1007,6 +1021,221 @@ class KdcTgsTests(KDCBaseTest): self._user2user(service_ticket, creds, expected_error=(KDC_ERR_MODIFIED, KDC_ERR_POLICY)) + def test_pac_attrs_none(self): + creds = self._get_creds() + self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + + def test_pac_attrs_false(self): + creds = self._get_creds() + self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + + def test_pac_attrs_true(self): + creds = self._get_creds() + self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + + def test_pac_attrs_renew_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + 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) + + def test_pac_attrs_renew_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + 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=False) + + def test_pac_attrs_renew_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + 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=True) + + def test_pac_attrs_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + + def test_pac_attrs_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + + def test_pac_attrs_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + + def test_pac_attrs_missing_renew_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + tgt = self._modify_tgt(tgt, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_pac_attrs_missing_renew_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + tgt = self._modify_tgt(tgt, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_pac_attrs_missing_renew_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + tgt = self._modify_tgt(tgt, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_pac_attrs_missing_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=None) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_pac_attrs_missing_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_pac_attrs_missing_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=True) + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True, + remove_pac_attrs=True) + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=False) + + def test_tgs_pac_attrs_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None, + expect_pac=True, + expect_pac_attrs=True, + 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) + + def test_tgs_pac_attrs_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, + expect_pac=True, + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + + self._run_tgs(tgt, expected_error=0, expect_pac=False) + + def test_tgs_pac_attrs_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True, + expect_pac=True, + expect_pac_attrs=True, + 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) + + def _get_tgt(self, client_creds, renewable=False, @@ -1278,23 +1507,34 @@ class KdcTgsTests(KDCBaseTest): def _get_non_existent_rid(self): return (1 << 30) - 1 - def _run_tgs(self, tgt, expected_error): + def _run_tgs(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None): target_creds = self.get_service_creds() - self._tgs_req(tgt, expected_error, target_creds) - - def _renew_tgt(self, tgt, expected_error): + return self._tgs_req( + tgt, expected_error, target_creds, + expect_pac=expect_pac, + expect_pac_attrs=expect_pac_attrs, + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request) + + def _renew_tgt(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None): krbtgt_creds = self.get_krbtgt_creds() kdc_options = str(krb5_asn1.KDCOptions('renew')) - self._tgs_req(tgt, expected_error, krbtgt_creds, - kdc_options=kdc_options) + 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) - def _validate_tgt(self, tgt, expected_error): + def _validate_tgt(self, tgt, expected_error, expect_pac=True): krbtgt_creds = self.get_krbtgt_creds() kdc_options = str(krb5_asn1.KDCOptions('validate')) - self._tgs_req(tgt, expected_error, krbtgt_creds, - kdc_options=kdc_options) + return self._tgs_req(tgt, expected_error, krbtgt_creds, + kdc_options=kdc_options, + expect_pac=expect_pac) - def _s4u2self(self, tgt, tgt_creds, expected_error, + def _s4u2self(self, tgt, tgt_creds, expected_error, expect_pac=True, expect_edata=False, expected_status=None): user_creds = self._get_mach_creds() @@ -1318,17 +1558,20 @@ class KdcTgsTests(KDCBaseTest): expected_cname=user_cname, generate_padata_fn=generate_s4u2self_padata, expect_claims=False, expect_edata=expect_edata, - expected_status=expected_status) + expected_status=expected_status, + expect_pac=expect_pac) - def _user2user(self, tgt, tgt_creds, expected_error, sname=None): + def _user2user(self, tgt, tgt_creds, expected_error, sname=None, + expect_pac=True): user_creds = self._get_mach_creds() user_tgt = self.get_tgt(user_creds) kdc_options = str(krb5_asn1.KDCOptions('enc-tkt-in-skey')) - self._tgs_req(user_tgt, expected_error, tgt_creds, - kdc_options=kdc_options, - additional_ticket=tgt, - sname=sname) + return self._tgs_req(user_tgt, expected_error, tgt_creds, + kdc_options=kdc_options, + additional_ticket=tgt, + sname=sname, + expect_pac=expect_pac) def _tgs_req(self, tgt, expected_error, target_creds, kdc_options='0', @@ -1337,6 +1580,9 @@ class KdcTgsTests(KDCBaseTest): generate_padata_fn=None, sname=None, expect_claims=True, + expect_pac=True, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, expect_edata=False, expected_status=None): srealm = target_creds.get_realm() @@ -1390,6 +1636,9 @@ class KdcTgsTests(KDCBaseTest): authenticator_subkey=subkey, kdc_options=kdc_options, expect_edata=expect_edata, + expect_pac=expect_pac, + expect_pac_attrs=expect_pac_attrs, + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, expect_claims=expect_claims) rep = self._generic_kdc_exchange(kdc_exchange_dict, diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 1ddf812da25..e9b510e0f09 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -349,3 +349,24 @@ ^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 +# +^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 diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 720d243e05c..cf0eb2495b2 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -467,3 +467,25 @@ 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_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 +# +^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 -- 2.25.1 From c581d18cc4caf1473cf7bc440588963e8c94a552 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:19:44 +1300 Subject: [PATCH 593/645] CVE-2020-25719 tests/krb5: Add tests for PAC-REQUEST padata BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 232 ++++++++++++++++++++++- selftest/knownfail_heimdal_kdc | 9 + selftest/knownfail_mit_kdc | 18 ++ 3 files changed, 256 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 40291677819..53d7dd4effb 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -1235,6 +1235,231 @@ class KdcTgsTests(KDCBaseTest): expect_pac_attrs=True, expect_pac_attrs_pac_request=True) + def test_tgs_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_tgs_pac_request_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_tgs_pac_request_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_renew_pac_request_none(self): + creds = self._get_creds() + 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) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_renew_pac_request_false(self): + creds = self._get_creds() + 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) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_renew_pac_request_true(self): + creds = self._get_creds() + 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) + + 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) + tgt = self._modify_tgt(tgt, invalid=True) + + tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) + + 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_false(self): + creds = self._get_creds() + 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) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_validate_pac_request_true(self): + creds = self._get_creds() + 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) + + 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) + + ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_s4u2self_pac_request_false(self): + 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) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_s4u2self_pac_request_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True) + + ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_user2user_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) + + ticket = self._user2user(tgt, creds, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_user2user_pac_request_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + + ticket = self._user2user(tgt, creds, expected_error=0, + expect_pac=True) + + pac = self.get_ticket_pac(ticket, expect_pac=True) + self.assertIsNotNone(pac) + + def test_user2user_pac_request_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=True) + + ticket = self._user2user(tgt, creds, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_user2user_user_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds) + + user_creds = self._get_mach_creds() + user_tgt = self.get_tgt(user_creds, pac_request=None) + + ticket = self._user2user(tgt, creds, expected_error=0, + user_tgt=user_tgt, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_user2user_user_pac_request_false(self): + creds = self._get_creds() + tgt = self.get_tgt(creds) + + user_creds = self._get_mach_creds() + user_tgt = self.get_tgt(user_creds, pac_request=False, expect_pac=None) + + ticket = self._user2user(tgt, creds, expected_error=0, + user_tgt=user_tgt, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_user2user_user_pac_request_true(self): + creds = self._get_creds() + tgt = self.get_tgt(creds) + + user_creds = self._get_mach_creds() + user_tgt = self.get_tgt(user_creds, pac_request=True) + + ticket = self._user2user(tgt, creds, expected_error=0, + user_tgt=user_tgt, 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) + tgt = self.get_tgt(creds, pac_request=None) + tgt = self._modify_tgt(tgt, from_rodc=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_tgs_rodc_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, from_rodc=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + + pac = self.get_ticket_pac(ticket, expect_pac=False) + self.assertIsNone(pac) + + def test_tgs_rodc_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, from_rodc=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) def _get_tgt(self, client_creds, @@ -1562,9 +1787,10 @@ class KdcTgsTests(KDCBaseTest): expect_pac=expect_pac) def _user2user(self, tgt, tgt_creds, expected_error, sname=None, - expect_pac=True): - user_creds = self._get_mach_creds() - user_tgt = self.get_tgt(user_creds) + user_tgt=None, expect_pac=True): + if user_tgt is None: + user_creds = self._get_mach_creds() + user_tgt = self.get_tgt(user_creds) kdc_options = str(krb5_asn1.KDCOptions('enc-tkt-in-skey')) return self._tgs_req(user_tgt, expected_error, tgt_creds, diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index e9b510e0f09..e6fad91b402 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -370,3 +370,12 @@ ^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 +# +# PAC request tests +# +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_none +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_true +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index cf0eb2495b2..17a9792c619 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -489,3 +489,21 @@ 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_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 +# +# PAC request tests +# +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_false +^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_tgs_pac_request_false +^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_pac_request_none +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_true +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_none +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_true +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_false -- 2.25.1 From 33da2c66642b13ca7ee2f1c67ecefb0dfc7c0f15 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:04:25 +1300 Subject: [PATCH 594/645] CVE-2020-25719 tests/krb5: Add tests for requester SID PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 222 ++++++++++++++++++++++- selftest/knownfail_heimdal_kdc | 18 ++ selftest/knownfail_mit_kdc | 20 ++ 3 files changed, 256 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 53d7dd4effb..2005d71fa81 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -510,6 +510,13 @@ class KdcTgsTests(KDCBaseTest): tgt = self._get_tgt(creds) self._user2user(tgt, creds, expected_error=0) + def test_tgs_req_no_requester_sid(self): + 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 + def test_tgs_req_no_pac_attrs(self): creds = self._get_creds() tgt = self._get_tgt(creds, remove_pac_attrs=True) @@ -517,6 +524,17 @@ class KdcTgsTests(KDCBaseTest): self._run_tgs(tgt, expected_error=0, expect_pac=True, expect_pac_attrs=False) + def test_tgs_req_from_rodc_no_requester_sid(self): + creds = self._get_creds(replication_allowed=True, + 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) + def test_tgs_req_from_rodc_no_pac_attrs(self): creds = self._get_creds(replication_allowed=True, revealed_to_rodc=True) @@ -617,6 +635,27 @@ class KdcTgsTests(KDCBaseTest): self._user2user(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + 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) + + def test_logon_info_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_requester_sid=False) + self._run_tgs(tgt, expected_error=0) + + def test_logon_info_only_sid_mismatch_existing(self): + creds = self._get_creds() + 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) + # Test changing the SID in the PAC to a non-existent one. def test_tgs_sid_mismatch_nonexisting(self): creds = self._get_creds() @@ -652,6 +691,27 @@ class KdcTgsTests(KDCBaseTest): self._user2user(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + 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) + + def test_logon_info_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_requester_sid=False) + self._run_tgs(tgt, expected_error=0) + + def test_logon_info_only_sid_mismatch_nonexisting(self): + creds = self._get_creds() + 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) + # Test with an RODC-issued ticket where the client is revealed to the RODC. def test_tgs_rodc_revealed(self): creds = self._get_creds(replication_allowed=True, @@ -728,6 +788,33 @@ class KdcTgsTests(KDCBaseTest): self._user2user(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + def test_tgs_rodc_requester_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, + can_modify_logon_info=False) + self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_tgs_rodc_logon_info_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, + can_modify_requester_sid=False) + self._run_tgs(tgt, expected_error=0) + + def test_tgs_rodc_logon_info_only_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, + remove_requester_sid=True) + self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + # Test with an RODC-issued ticket where the SID in the PAC is changed to a # non-existent one. def test_tgs_rodc_sid_mismatch_nonexisting(self): @@ -768,6 +855,30 @@ class KdcTgsTests(KDCBaseTest): self._user2user(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + def test_tgs_rodc_requester_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, + can_modify_logon_info=False) + self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + + def test_tgs_rodc_logon_info_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, + can_modify_requester_sid=False) + self._run_tgs(tgt, expected_error=0) + + def test_tgs_rodc_logon_info_only_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, + remove_requester_sid=True) + self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) + # Test with an RODC-issued ticket where the client is not revealed to the # RODC. def test_tgs_rodc_not_revealed(self): @@ -1235,6 +1346,99 @@ class KdcTgsTests(KDCBaseTest): expect_pac_attrs=True, expect_pac_attrs_pac_request=True) + def test_as_requester_sid(self): + creds = self._get_creds() + + samdb = self.get_samdb() + sid = self.get_objectSid(samdb, creds.get_dn()) + + self.get_tgt(creds, pac_request=None, + expect_pac=True, + expected_sid=sid, + expect_requester_sid=True) + + def test_tgs_requester_sid(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) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, + expected_sid=sid, + expect_requester_sid=True) + + def test_tgs_requester_sid_renew(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, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, + expected_sid=sid, + expect_requester_sid=True) + + def test_tgs_requester_sid_rodc_renew(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, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, + expected_sid=sid, + expect_requester_sid=True) + + def test_tgs_requester_sid_missing_renew(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, renewable=True, + remove_requester_sid=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, + expect_requester_sid=False) # Note: not expected + + def test_tgs_requester_sid_missing_rodc_renew(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, renewable=True, + remove_requester_sid=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, + expected_sid=sid, + expect_requester_sid=True) + def test_tgs_pac_request_none(self): creds = self._get_creds() tgt = self.get_tgt(creds, pac_request=None) @@ -1733,16 +1937,20 @@ class KdcTgsTests(KDCBaseTest): return (1 << 30) - 1 def _run_tgs(self, tgt, expected_error, expect_pac=True, - expect_pac_attrs=None, expect_pac_attrs_pac_request=None): + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, expected_sid=None): target_creds = self.get_service_creds() return self._tgs_req( tgt, expected_error, target_creds, expect_pac=expect_pac, expect_pac_attrs=expect_pac_attrs, - expect_pac_attrs_pac_request=expect_pac_attrs_pac_request) + expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) def _renew_tgt(self, tgt, expected_error, expect_pac=True, - expect_pac_attrs=None, expect_pac_attrs_pac_request=None): + 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('renew')) return self._tgs_req( @@ -1750,7 +1958,9 @@ class KdcTgsTests(KDCBaseTest): 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_pac_attrs_pac_request=expect_pac_attrs_pac_request, + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) def _validate_tgt(self, tgt, expected_error, expect_pac=True): krbtgt_creds = self.get_krbtgt_creds() @@ -1809,7 +2019,9 @@ class KdcTgsTests(KDCBaseTest): expect_pac=True, expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, expect_edata=False, + expected_sid=None, expected_status=None): srealm = target_creds.get_realm() @@ -1865,6 +2077,8 @@ class KdcTgsTests(KDCBaseTest): 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, expect_claims=expect_claims) rep = self._generic_kdc_exchange(kdc_exchange_dict, diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index e6fad91b402..41ad710d2f2 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -379,3 +379,21 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true +# +# 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_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_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_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_requester_sid_mismatch_existing +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 17a9792c619..cf3fc5abbaf 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -507,3 +507,23 @@ 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_user_pac_request_none ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_false +# +# 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_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_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_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_logon_info_sid_mismatch_existing +^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 -- 2.25.1 From 399ef3ab12835700ca6d99953dfd7d1f44b2f6fa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:06:58 +1300 Subject: [PATCH 595/645] CVE-2020-25719 tests/krb5: Add test for user-to-user with no sname BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 38 +++++++++++++++++------- selftest/knownfail_heimdal_kdc | 1 + selftest/knownfail_mit_kdc | 1 + 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index 2005d71fa81..b0f60c0a8ce 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -1122,6 +1122,14 @@ class KdcTgsTests(KDCBaseTest): self._user2user(tgt, creds, sname=sname, expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN) + def test_user2user_no_sname(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + self._user2user(tgt, creds, sname=False, + expected_error=(KDC_ERR_GENERIC, + KDC_ERR_S_PRINCIPAL_UNKNOWN)) + def test_user2user_service_ticket(self): creds = self._get_creds() tgt = self._get_tgt(creds) @@ -2025,16 +2033,24 @@ class KdcTgsTests(KDCBaseTest): expected_status=None): srealm = target_creds.get_realm() - if sname is None: - target_name = target_creds.get_username() - if target_name == 'krbtgt': - sname = self.PrincipalName_create(name_type=NT_SRV_INST, - names=[target_name, srealm]) - else: - if target_name[-1] == '$': - target_name = target_name[:-1] - sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=['host', target_name]) + if sname is False: + sname = None + expected_sname = self.get_krbtgt_sname() + else: + if sname is None: + target_name = target_creds.get_username() + if target_name == 'krbtgt': + sname = self.PrincipalName_create( + name_type=NT_SRV_INST, + names=[target_name, srealm]) + else: + if target_name[-1] == '$': + target_name = target_name[:-1] + sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, + names=['host', target_name]) + + expected_sname = sname if additional_ticket is not None: additional_tickets = [additional_ticket.ticket] @@ -2062,7 +2078,7 @@ class KdcTgsTests(KDCBaseTest): expected_crealm=tgt.crealm, expected_cname=expected_cname, expected_srealm=srealm, - expected_sname=sname, + expected_sname=expected_sname, ticket_decryption_key=decryption_key, generate_padata_fn=generate_padata_fn, check_error_fn=check_error_fn, diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 41ad710d2f2..fc2917761a1 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -323,6 +323,7 @@ ^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_matching_sname_host ^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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_non_existent_sname ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index cf3fc5abbaf..aa66f4cb0fc 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -441,6 +441,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_upn_dns_info_ex_user ^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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied -- 2.25.1 From 719dbd28d4c3667be1f9dee6cd5ad1295d55a2ba Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 21:09:32 +1300 Subject: [PATCH 596/645] CVE-2020-25719 tests/krb5: Add tests for mismatched names with user-to-user BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 105 ++++++++++++++++++- python/samba/tests/krb5/rfc4120_constants.py | 1 + selftest/knownfail_heimdal_kdc | 8 ++ selftest/knownfail_mit_kdc | 8 ++ 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index b0f60c0a8ce..cfe1ad42d61 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -43,8 +43,10 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_GENERIC, KDC_ERR_MODIFIED, KDC_ERR_POLICY, + KDC_ERR_C_PRINCIPAL_UNKNOWN, KDC_ERR_S_PRINCIPAL_UNKNOWN, KDC_ERR_TGT_REVOKED, + KDC_ERR_WRONG_REALM, NT_PRINCIPAL, NT_SRV_INST, ) @@ -1112,6 +1114,100 @@ class KdcTgsTests(KDCBaseTest): expected_error=(KDC_ERR_BADMATCH, KDC_ERR_BADOPTION)) + def test_user2user_other_sname(self): + other_name = self.get_new_username() + spn = f'host/{other_name}' + creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={'spn': spn}) + tgt = self._get_tgt(creds) + + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', other_name]) + + self._user2user(tgt, creds, sname=sname, expected_error=0) + + def test_user2user_wrong_sname_krbtgt(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + sname = self.get_krbtgt_sname() + + self._user2user(tgt, creds, sname=sname, + expected_error=(KDC_ERR_BADMATCH, + KDC_ERR_BADOPTION)) + + def test_user2user_wrong_srealm(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + self._user2user(tgt, creds, srealm='OTHER.REALM', + expected_error=(KDC_ERR_WRONG_REALM, + KDC_ERR_S_PRINCIPAL_UNKNOWN)) + + def test_user2user_tgt_correct_realm(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + realm = creds.get_realm().encode('utf-8') + tgt = self._modify_tgt(tgt, realm) + + self._user2user(tgt, creds, + expected_error=0) + + def test_user2user_tgt_wrong_realm(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + tgt = self._modify_tgt(tgt, b'OTHER.REALM') + + self._user2user(tgt, creds, + expected_error=0) + + def test_user2user_tgt_correct_cname(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + user_name = creds.get_username() + user_name = user_name.encode('utf-8') + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + + tgt = self._modify_tgt(tgt, cname=cname) + + self._user2user(tgt, creds, expected_error=0) + + def test_user2user_tgt_other_cname(self): + samdb = self.get_samdb() + + other_name = self.get_new_username() + upn = f'{other_name}@{samdb.domain_dns_name()}' + + creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={'upn': upn}) + tgt = self._get_tgt(creds) + + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[other_name.encode('utf-8')]) + + tgt = self._modify_tgt(tgt, cname=cname) + + self._user2user(tgt, creds, expected_error=0) + + def test_user2user_tgt_cname_host(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) + + user_name = creds.get_username() + user_name = user_name.encode('utf-8') + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[b'host', user_name]) + + tgt = self._modify_tgt(tgt, cname=cname) + + self._user2user(tgt, creds, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) + def test_user2user_non_existent_sname(self): creds = self._get_creds() tgt = self._get_tgt(creds) @@ -2005,7 +2101,7 @@ class KdcTgsTests(KDCBaseTest): expect_pac=expect_pac) def _user2user(self, tgt, tgt_creds, expected_error, sname=None, - user_tgt=None, expect_pac=True): + srealm=None, user_tgt=None, expect_pac=True): if user_tgt is None: user_creds = self._get_mach_creds() user_tgt = self.get_tgt(user_creds) @@ -2015,6 +2111,7 @@ class KdcTgsTests(KDCBaseTest): kdc_options=kdc_options, additional_ticket=tgt, sname=sname, + srealm=srealm, expect_pac=expect_pac) def _tgs_req(self, tgt, expected_error, target_creds, @@ -2023,6 +2120,7 @@ class KdcTgsTests(KDCBaseTest): additional_ticket=None, generate_padata_fn=None, sname=None, + srealm=None, expect_claims=True, expect_pac=True, expect_pac_attrs=None, @@ -2031,7 +2129,10 @@ class KdcTgsTests(KDCBaseTest): expect_edata=False, expected_sid=None, expected_status=None): - srealm = target_creds.get_realm() + if srealm is False: + srealm = None + elif srealm is None: + srealm = target_creds.get_realm() if sname is False: sname = None diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 490cd255ec3..5251e291fde 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -82,6 +82,7 @@ KDC_ERR_SKEW = 37 KDC_ERR_MODIFIED = 41 KDC_ERR_INAPP_CKSUM = 50 KDC_ERR_GENERIC = 60 +KDC_ERR_WRONG_REALM = 68 KDC_ERR_CLIENT_NAME_MISMATCH = 75 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index fc2917761a1..d1fb5f210af 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -325,6 +325,7 @@ ^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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_non_existent_sname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_other_sname ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied @@ -337,7 +338,14 @@ ^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_tgt_cname_host +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_cname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_realm +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_other_cname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_wrong_realm ^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_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_rodc_allowed_denied diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index aa66f4cb0fc..04efccf4a59 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -442,6 +442,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_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 +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_other_sname ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied @@ -454,7 +455,14 @@ 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_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_tgt_cname_host +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_cname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_realm +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_other_cname +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_wrong_realm ^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_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_rodc_allowed_denied -- 2.25.1 From 204d44531c7d25b1b347c1d5ab18afaebd178a28 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 11:00:38 +1300 Subject: [PATCH 597/645] CVE-2020-25719 s4/torture: Expect additional PAC buffers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 39 ++++++++++++++++++++++++++++++++ source4/torture/rpc/remote_pac.c | 24 ++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index d1fb5f210af..850346940ad 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -406,3 +406,42 @@ ^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_requester_sid_mismatch_existing ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting +# +# 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 a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index 14c23f674f1..c94decef5ce 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/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 = 5; + num_pac_buffers = 7; if (expect_pac_upn_dns_info) { num_pac_buffers += 1; } @@ -323,6 +323,18 @@ 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); @@ -1082,7 +1094,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 = 7; + num_pac_buffers = 9; 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"); @@ -1122,6 +1134,14 @@ 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 52e84eaea3672be1af6a2fb878b91db9d47b8897 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 19:18:20 +1300 Subject: [PATCH 598/645] CVE-2020-25722 pytest: Raise an error when adding a dynamic test that would overwrite an existing test BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index e04ddcb4ba8..ffb8e58f471 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -102,7 +102,10 @@ class TestCase(unittest.TestCase): def fn(self): getattr(self, "_%s_with_args" % fnname)(*args) fn.__doc__ = doc - setattr(cls, "%s_%s" % (fnname, suffix), fn) + attr = "%s_%s" % (fnname, suffix) + if hasattr(cls, attr): + raise RuntimeError(f"Dynamic test {attr} already exists!") + setattr(cls, attr, fn) @classmethod def setUpDynamicTestCases(cls): -- 2.25.1 From 71e409cd9eb257b6d58306e5722f10447a7daac7 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 12 Jul 2021 12:32:12 +0200 Subject: [PATCH 599/645] CVE-2020-25719 mit-samba: Make ks_get_principal() internally public BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/mit-kdb/kdb_samba.h | 5 +++++ source4/kdc/mit-kdb/kdb_samba_principals.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/source4/kdc/mit-kdb/kdb_samba.h b/source4/kdc/mit-kdb/kdb_samba.h index ad4f6e27573..132dcfed363 100644 --- a/source4/kdc/mit-kdb/kdb_samba.h +++ b/source4/kdc/mit-kdb/kdb_samba.h @@ -41,6 +41,11 @@ struct mit_samba_context *ks_get_context(krb5_context kcontext); +krb5_error_code ks_get_principal(krb5_context context, + krb5_const_principal principal, + unsigned int kflags, + krb5_db_entry **kentry); + bool ks_data_eq_string(krb5_data d, const char *s); krb5_data ks_make_data(void *data, unsigned int len); diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c index 8b67436dc47..79219e5a274 100644 --- a/source4/kdc/mit-kdb/kdb_samba_principals.c +++ b/source4/kdc/mit-kdb/kdb_samba_principals.c @@ -33,10 +33,10 @@ #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ -static krb5_error_code ks_get_principal(krb5_context context, - krb5_const_principal principal, - unsigned int kflags, - krb5_db_entry **kentry) +krb5_error_code ks_get_principal(krb5_context context, + krb5_const_principal principal, + unsigned int kflags, + krb5_db_entry **kentry) { struct mit_samba_context *mit_ctx; krb5_error_code code; -- 2.25.1 From 85ebfef42c8c341a44aaa9afcea4e50b64a5353c Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 14 Jul 2021 14:51:34 +0200 Subject: [PATCH 600/645] CVE-2020-25719 mit-samba: Add ks_free_principal() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 [abartlet@samba.org As submitted in patch to Samba bugzilla to address this issue as https://attachments.samba.org/attachment.cgi?id=16724 on overall bug https://bugzilla.samba.org/show_bug.cgi?id=14725] Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- source4/kdc/mit-kdb/kdb_samba.h | 2 + source4/kdc/mit-kdb/kdb_samba_principals.c | 52 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/source4/kdc/mit-kdb/kdb_samba.h b/source4/kdc/mit-kdb/kdb_samba.h index 132dcfed363..2ff8642cc50 100644 --- a/source4/kdc/mit-kdb/kdb_samba.h +++ b/source4/kdc/mit-kdb/kdb_samba.h @@ -46,6 +46,8 @@ krb5_error_code ks_get_principal(krb5_context context, unsigned int kflags, krb5_db_entry **kentry); +void ks_free_principal(krb5_context context, krb5_db_entry *entry); + bool ks_data_eq_string(krb5_data d, const char *s); krb5_data ks_make_data(void *data, unsigned int len); diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c index 79219e5a274..cc67c2392be 100644 --- a/source4/kdc/mit-kdb/kdb_samba_principals.c +++ b/source4/kdc/mit-kdb/kdb_samba_principals.c @@ -59,6 +59,58 @@ cleanup: return code; } +static void ks_free_principal_e_data(krb5_context context, krb5_octet *e_data) +{ + struct samba_kdc_entry *skdc_entry; + + skdc_entry = talloc_get_type_abort(e_data, + struct samba_kdc_entry); + talloc_set_destructor(skdc_entry, NULL); + TALLOC_FREE(skdc_entry); +} + +void ks_free_principal(krb5_context context, krb5_db_entry *entry) +{ + krb5_tl_data *tl_data_next = NULL; + krb5_tl_data *tl_data = NULL; + size_t i, j; + + if (entry != NULL) { + krb5_free_principal(context, entry->princ); + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) { + tl_data_next = tl_data->tl_data_next; + if (tl_data->tl_data_contents != NULL) { + free(tl_data->tl_data_contents); + } + free(tl_data); + } + + if (entry->key_data != NULL) { + for (i = 0; i < entry->n_key_data; i++) { + for (j = 0; j < entry->key_data[i].key_data_ver; j++) { + if (entry->key_data[i].key_data_length[j] != 0) { + if (entry->key_data[i].key_data_contents[j] != NULL) { + memset(entry->key_data[i].key_data_contents[j], 0, entry->key_data[i].key_data_length[j]); + free(entry->key_data[i].key_data_contents[j]); + } + } + entry->key_data[i].key_data_contents[j] = NULL; + entry->key_data[i].key_data_length[j] = 0; + entry->key_data[i].key_data_type[j] = 0; + } + } + free(entry->key_data); + } + + if (entry->e_data) { + ks_free_principal_e_data(context, entry->e_data); + } + + free(entry); + } +} + static krb5_boolean ks_is_master_key_principal(krb5_context context, krb5_const_principal princ) { -- 2.25.1 From 231bc4c5d47978c634464f57784765682a88bba5 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 12 Jul 2021 11:20:29 +0200 Subject: [PATCH 601/645] CVE-2020-25719 mit-samba: If we use client_princ, always lookup the db entry BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett [abartlet@samba.org backported due to support for MIT KDB < 10 in Samba 4.14] --- source4/kdc/mit-kdb/kdb_samba_policies.c | 81 ++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c index 9197551ed61..dce87c50049 100644 --- a/source4/kdc/mit-kdb/kdb_samba_policies.c +++ b/source4/kdc/mit-kdb/kdb_samba_policies.c @@ -323,6 +323,8 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, krb5_authdata ***signed_auth_data) { #endif + krb5_const_principal ks_client_princ = NULL; + krb5_db_entry *client_entry = NULL; krb5_authdata **authdata = NULL; krb5_boolean is_as_req; krb5_error_code code; @@ -341,8 +343,72 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0); + /* + * When using s4u2proxy client_princ actually refers to the proxied user + * while client->princ to the proxy service asking for the TGS on behalf + * of the proxied user. So always use client_princ in preference. + * + * Note that when client principal is not NULL, client entry might be + * NULL for cross-realm case, so we need to make sure to not + * dereference NULL pointer here. + */ + if (client_princ != NULL) { + ks_client_princ = client_princ; + if (!is_as_req) { + krb5_boolean is_equal = false; + + if (client != NULL && client->princ != NULL) { + is_equal = + krb5_principal_compare(context, + client_princ, + client->princ); + } + + /* + * When client principal is the same as supplied client + * entry, don't fetch it. + */ + if (!is_equal) { + code = ks_get_principal(context, + ks_client_princ, + 0, + &client_entry); + if (code != 0) { + char *client_name = NULL; + + (void)krb5_unparse_name(context, + ks_client_princ, + &client_name); + + DBG_DEBUG("We didn't find the client " + "principal [%s] in our " + "database.\n", + client_name); + SAFE_FREE(client_name); + + /* + * If we didn't find client_princ in our + * database it might be from another + * realm. + */ + client_entry = NULL; + } + } + } + } else { + if (client == NULL) { + *signed_auth_data = NULL; + return 0; + } + ks_client_princ = client->princ; + } + + if (client_entry == NULL) { + client_entry = client; + } + if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) { - code = ks_get_pac(context, client, client_key, &pac); + code = ks_get_pac(context, client_entry, client_key, &pac); if (code != 0) { goto done; } @@ -351,8 +417,8 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, if (!is_as_req) { code = ks_verify_pac(context, flags, - client_princ, - client, + ks_client_princ, + client_entry, server, krbtgt, server_key, @@ -365,9 +431,9 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, } } - if (pac == NULL && client != NULL) { + if (pac == NULL) { - code = ks_get_pac(context, client, client_key, &pac); + code = ks_get_pac(context, client_entry, client_key, &pac); if (code != 0) { goto done; } @@ -378,7 +444,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, goto done; } - code = krb5_pac_sign(context, pac, authtime, client_princ, + code = krb5_pac_sign(context, pac, authtime, ks_client_princ, server_key, krbtgt_key, &pac_data); if (code != 0) { DBG_ERR("krb5_pac_sign failed: %d\n", code); @@ -412,6 +478,9 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, code = 0; done: + if (client_entry != NULL && client_entry != client) { + ks_free_principal(context, client_entry); + } krb5_pac_free(context, pac); krb5_free_authdata(context, authdata); -- 2.25.1 From c62762461f44114e8a388a678a7836ef32613023 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 12 Jul 2021 13:12:00 +0200 Subject: [PATCH 602/645] CVE-2020-25719 mit-samba: Add mit_samba_princ_needs_pac() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/mit_samba.c | 8 ++++++++ source4/kdc/mit_samba.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 689e14e1c38..6aed3134544 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -1153,3 +1153,11 @@ void mit_samba_update_bad_password_count(krb5_db_entry *db_entry) p->msg, ldb_get_default_basedn(p->kdc_db_ctx->samdb)); } + +bool mit_samba_princ_needs_pac(krb5_db_entry *db_entry) +{ + struct samba_kdc_entry *skdc_entry = + talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry); + + return samba_princ_needs_pac(skdc_entry); +} diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h index ba824557bd5..636c77ec97c 100644 --- a/source4/kdc/mit_samba.h +++ b/source4/kdc/mit_samba.h @@ -85,4 +85,6 @@ void mit_samba_zero_bad_password_count(krb5_db_entry *db_entry); void mit_samba_update_bad_password_count(krb5_db_entry *db_entry); +bool mit_samba_princ_needs_pac(krb5_db_entry *db_entry); + #endif /* _MIT_SAMBA_H */ -- 2.25.1 From b9f94c047df8532085bc59ab7123b2a3b7ef734d Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 12 Jul 2021 13:58:57 +0200 Subject: [PATCH 603/645] CVE-2020-25719 mit-samba: Handle no DB entry in mit_samba_get_pac() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/mit_samba.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 6aed3134544..be6ea83c042 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -437,6 +437,10 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, &upn_dns_info_blob); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); + if (NT_STATUS_EQUAL(nt_status, + NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + return ENOENT; + } return EINVAL; } -- 2.25.1 From 14733e89e33eed0bfd40acf9fc66432fd3f4265a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 12 Jul 2021 14:00:19 +0200 Subject: [PATCH 604/645] CVE-2020-25719 mit-samba: Rework PAC handling in kdb_samba_db_sign_auth_data() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- selftest/knownfail_mit_kdc | 6 +- source4/kdc/mit-kdb/kdb_samba_policies.c | 116 ++++++++++++++++++----- 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 04efccf4a59..53aa05814c2 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -278,12 +278,13 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # # KDC TGS PAC tests # +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_client_no_auth_data_required\(ad_dc\) +^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_client_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required\(ad_dc\) ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac\(ad_dc\) -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_service_no_auth_data_required\(ad_dc\) # # MIT currently fails the following MS-KILE tests. # @@ -501,11 +502,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ # # PAC request tests # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_false ^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_tgs_pac_request_false ^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_pac_request_none ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_true @@ -515,7 +514,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_user_pac_request_false ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_false # # PAC requester SID tests # diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c index dce87c50049..7bc9a7b3347 100644 --- a/source4/kdc/mit-kdb/kdb_samba_policies.c +++ b/source4/kdc/mit-kdb/kdb_samba_policies.c @@ -4,7 +4,7 @@ Samba KDB plugin for MIT Kerberos Copyright (c) 2010 Simo Sorce . - Copyright (c) 2014 Andreas Schneider + Copyright (c) 2014-2021 Andreas Schneider 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 @@ -325,11 +325,16 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, #endif krb5_const_principal ks_client_princ = NULL; krb5_db_entry *client_entry = NULL; + krb5_authdata **pac_auth_data = NULL; krb5_authdata **authdata = NULL; krb5_boolean is_as_req; krb5_error_code code; krb5_pac pac = NULL; krb5_data pac_data; + bool with_pac = false; + bool generate_pac = false; + char *client_name = NULL; + #if KRB5_KDB_API_VERSION >= 10 krbtgt = krbtgt == NULL ? local_krbtgt : krbtgt; @@ -374,8 +379,6 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, 0, &client_entry); if (code != 0) { - char *client_name = NULL; - (void)krb5_unparse_name(context, ks_client_princ, &client_name); @@ -407,43 +410,105 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, client_entry = client; } - if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) { + if (is_as_req) { + with_pac = mit_samba_princ_needs_pac(client_entry); + } else { + with_pac = mit_samba_princ_needs_pac(server); + } + + code = krb5_unparse_name(context, + client_princ, + &client_name); + if (code != 0) { + goto done; + } + + if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC) != 0) { + generate_pac = true; + } + + DBG_DEBUG("*** Sign data for client principal: %s [%s %s%s]\n", + client_name, + is_as_req ? "AS-REQ" : "TGS_REQ", + with_pac ? is_as_req ? "WITH_PAC" : "FIND_PAC" : "NO_PAC", + generate_pac ? " GENERATE_PAC" : ""); + + /* + * Generate PAC for the AS-REQ or check or generate one for the TGS if + * needed. + */ + 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); if (code != 0) { goto done; } - } - - if (!is_as_req) { - code = ks_verify_pac(context, - flags, - ks_client_princ, - client_entry, - server, - krbtgt, - server_key, - krbtgt_key, - authtime, - tgt_auth_data, - &pac); + } else if (with_pac && !is_as_req) { + /* + * Find the PAC in the TGS, if one exists. + */ + code = krb5_find_authdata(context, + tgt_auth_data, + NULL, + KRB5_AUTHDATA_WIN2K_PAC, + &pac_auth_data); if (code != 0) { + DBG_ERR("krb5_find_authdata failed: %d\n", code); goto done; } - } + DBG_DEBUG("Found PAC data for TGS-REQ [%s]\n", client_name); - if (pac == NULL) { + if (pac_auth_data != NULL && pac_auth_data[0] != NULL) { + if (pac_auth_data[1] != NULL) { + DBG_ERR("Invalid PAC data!\n"); + code = KRB5KDC_ERR_BADOPTION; + goto done; + } - code = ks_get_pac(context, client_entry, client_key, &pac); - if (code != 0) { - goto done; + DBG_DEBUG("Verify PAC for TGS [%s]\n", + client_name); + + code = ks_verify_pac(context, + flags, + ks_client_princ, + client_entry, + server, + krbtgt, + server_key, + krbtgt_key, + authtime, + tgt_auth_data, + &pac); + if (code != 0) { + goto done; + } + } else { + if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) { + DBG_DEBUG("Generate PAC for constrained" + "delegation TGS [%s]\n", + client_name); + + code = ks_get_pac(context, + client_entry, + client_key, + &pac); + if (code != 0 && code != ENOENT) { + goto done; + } + } } } if (pac == NULL) { - code = KRB5_KDB_DBTYPE_NOSUP; + DBG_DEBUG("No PAC data - we're done [%s]\n", client_name); + *signed_auth_data = NULL; + code = 0; goto done; } + DBG_DEBUG("Signing PAC for %s [%s]\n", + is_as_req ? "AS-REQ" : "TGS-REQ", + client_name); code = krb5_pac_sign(context, pac, authtime, ks_client_princ, server_key, krbtgt_key, &pac_data); if (code != 0) { @@ -481,8 +546,9 @@ done: if (client_entry != NULL && client_entry != client) { ks_free_principal(context, client_entry); } - krb5_pac_free(context, pac); + SAFE_FREE(client_name); krb5_free_authdata(context, authdata); + krb5_pac_free(context, pac); return code; } -- 2.25.1 From 7d8c3ce840f53e6ac4400a6972aace08f72c60d9 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 9 Aug 2021 17:22:52 +0200 Subject: [PATCH 605/645] CVE-2020-25719 mit_samba: The samba_princ_needs_pac check should be on the server entry This does the same check as the hdb plugin now. The client check is already done earlier. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/mit_samba.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index be6ea83c042..d11e1640ee9 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -486,6 +486,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, DATA_BLOB *deleg_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; bool is_in_db = false; bool is_untrusted = false; size_t num_types = 0; @@ -499,6 +500,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, ssize_t srv_checksum_idx = -1; ssize_t kdc_checksum_idx = -1; krb5_pac new_pac = NULL; + bool ok; if (client != NULL) { client_skdc_entry = @@ -510,6 +512,16 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, return EINVAL; } + server_skdc_entry = + talloc_get_type_abort(server->e_data, + struct samba_kdc_entry); + + /* The account may be set not to want the PAC */ + ok = samba_princ_needs_pac(server_skdc_entry); + if (!ok) { + return EINVAL; + } + if (krbtgt == NULL) { return EINVAL; } -- 2.25.1 From b55f5fbb49f215eb207b39ed24a798915384c45f Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 9 Aug 2021 17:25:53 +0200 Subject: [PATCH 606/645] CVE-2020-25719 mit_samba: Create the talloc context earlier BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/mit_samba.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index d11e1640ee9..d0e68ec8ea4 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -502,6 +502,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, krb5_pac new_pac = NULL; bool ok; + /* Create a memory context early so code can use talloc_stackframe() */ + tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); + if (tmp_ctx == NULL) { + return ENOMEM; + } + if (client != NULL) { client_skdc_entry = talloc_get_type_abort(client->e_data, @@ -509,7 +515,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, } if (server == NULL) { - return EINVAL; + code = EINVAL; + goto done; } server_skdc_entry = @@ -519,21 +526,18 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, /* The account may be set not to want the PAC */ ok = samba_princ_needs_pac(server_skdc_entry); if (!ok) { - return EINVAL; + code = EINVAL; + goto done; } if (krbtgt == NULL) { - return EINVAL; + code = EINVAL; + goto done; } krbtgt_skdc_entry = talloc_get_type_abort(krbtgt->e_data, struct samba_kdc_entry); - tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); - if (tmp_ctx == NULL) { - return ENOMEM; - } - code = samba_krbtgt_is_in_db(krbtgt_skdc_entry, &is_in_db, &is_untrusted); -- 2.25.1 From 2677df10ff2f6094ec250a799488c679f20404ce Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 6 Aug 2021 12:03:49 +0200 Subject: [PATCH 607/645] CVE-2020-25719 s4:kdc: Remove trailing spaces in pac-glue.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/pac-glue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 688103d8477..4066389e717 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -575,12 +575,12 @@ int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, if (!mem_ctx) { return ENOMEM; } - + trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0); if (trust_direction != 0) { /* Domain trust - we cannot check the sig, but we trust it for a correct PAC - + This is exactly where we should flag for SID validation when we do inter-foreest trusts */ @@ -768,7 +768,7 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, return nt_status; } - nt_status = samba_get_logon_info_pac_blob(mem_ctx, + nt_status = samba_get_logon_info_pac_blob(mem_ctx, user_info_dc, pac_blob); return nt_status; -- 2.25.1 From ab0a15305d6e4bbb1d705a2c65e3ec84786cbea6 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 9 Aug 2021 17:19:45 +0200 Subject: [PATCH 608/645] CVE-2020-25719 s4:kdc: Add samba_kdc_validate_pac_blob() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- source4/kdc/pac-glue.c | 56 ++++++++++++++++++++++++++++++++++++++++++ source4/kdc/pac-glue.h | 5 ++++ 2 files changed, 61 insertions(+) diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 4066389e717..8a3ec22190c 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -918,3 +918,59 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, talloc_free(tmp_ctx); return nt_status; } + +/* Does a parse and SID check, but no crypto. */ +krb5_error_code samba_kdc_validate_pac_blob( + krb5_context context, + struct samba_kdc_entry *client_skdc_entry, + const krb5_pac pac) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct auth_user_info_dc *pac_user_info = NULL; + struct dom_sid *client_sid = NULL; + struct dom_sid pac_sid; + krb5_error_code code; + bool ok; + + code = kerberos_pac_to_user_info_dc(frame, + pac, + context, + &pac_user_info, + NULL, + NULL); + if (code != 0) { + goto out; + } + + if (pac_user_info->num_sids == 0) { + code = EINVAL; + goto out; + } + + pac_sid = pac_user_info->sids[0]; + client_sid = samdb_result_dom_sid(frame, + client_skdc_entry->msg, + "objectSid"); + + ok = dom_sid_equal(&pac_sid, client_sid); + if (!ok) { + struct dom_sid_buf buf1; + struct dom_sid_buf buf2; + + DBG_ERR("SID mismatch between PAC and looked up client: " + "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 + goto out; + } + + code = 0; +out: + TALLOC_FREE(frame); + return code; +} diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 7b51b0389f5..e83446647b3 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -69,3 +69,8 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, const char *client_name, const char *workstation, bool password_change); + +krb5_error_code samba_kdc_validate_pac_blob( + krb5_context context, + struct samba_kdc_entry *client_skdc_entry, + const krb5_pac pac); -- 2.25.1 From 6ce299b90029b3c039856be5724cf1415a0d0e7a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 9 Aug 2021 17:20:31 +0200 Subject: [PATCH 609/645] CVE-2020-25719 s4:kdc: Check if the pac is valid before updating it BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 31 ++++--------------------------- selftest/knownfail_mit_kdc | 10 ++-------- source4/kdc/mit_samba.c | 9 +++++++++ source4/kdc/wdc-samba4.c | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 850346940ad..75ca4bba8c4 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -271,13 +271,6 @@ ^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_request_no_pac # -# 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 TGT tests # ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac @@ -288,10 +281,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_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_rodc_allowed_denied @@ -300,10 +289,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed -^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_rodc_allowed_denied @@ -312,10 +297,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_allowed ^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_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_upn_dns_info_ex_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user @@ -354,10 +335,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_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 # @@ -392,8 +369,8 @@ # 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_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_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 @@ -402,8 +379,8 @@ ^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_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_logon_info_sid_mismatch_existing +^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 # diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 53aa05814c2..dfdd17c655a 100644 --- a/selftest/knownfail_mit_kdc +++ b/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_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 @@ -434,8 +432,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_upn_dns_info_ex_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user @@ -475,8 +471,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_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 # @@ -518,8 +512,8 @@ 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_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_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 diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index d0e68ec8ea4..592f6a3bac4 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -512,6 +512,15 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, client_skdc_entry = talloc_get_type_abort(client->e_data, struct samba_kdc_entry); + + /* + * Check the objectSID of the client and pac data are the same. + * Does a parse and SID check, but no crypto. + */ + code = samba_kdc_validate_pac_blob(context, client_skdc_entry, *pac); + if (code != 0) { + goto done; + } } if (server == NULL) { diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index ac9d7d51733..ed6e9fb9b63 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -137,6 +137,23 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, return ENOMEM; } + if (client != NULL) { + struct samba_kdc_entry *client_skdc_entry = NULL; + + client_skdc_entry = talloc_get_type_abort(client->ctx, + struct samba_kdc_entry); + + /* + * Check the objectSID of the client and pac data are the same. + * Does a parse and SID check, but no crypto. + */ + ret = samba_kdc_validate_pac_blob(context, client_skdc_entry, *pac); + if (ret != 0) { + talloc_free(mem_ctx); + return ret; + } + } + /* If the krbtgt was generated by an RODC, and we are not that * RODC, then we need to regenerate the PAC - we can't trust * it */ -- 2.25.1 From 35b9f894dd9e2fada9282a7d2a63184e07b8371f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:41:31 +1300 Subject: [PATCH 610/645] CVE-2020-25719 s4:kdc: Add KDC support for PAC_ATTRIBUTES_INFO PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 23 ----- source4/heimdal/kdc/kerberos5.c | 23 +++-- source4/heimdal/kdc/krb5tgs.c | 2 +- source4/heimdal/kdc/windc.c | 7 +- source4/heimdal/kdc/windc_plugin.h | 2 + source4/kdc/mit_samba.c | 7 +- source4/kdc/pac-glue.c | 147 ++++++++++++++++++++++++++++- source4/kdc/pac-glue.h | 10 +- source4/kdc/wdc-samba4.c | 45 ++++++++- 9 files changed, 223 insertions(+), 43 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 75ca4bba8c4..0f03e17c242 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -265,11 +265,9 @@ # # KDC TGS PAC tests # -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required ^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_request_no_pac # # KDC TGT tests # @@ -336,27 +334,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed # -# PAC attributes tests -# -^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 -# # PAC request tests # ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index a131f1af08e..c1d4cb1d4aa 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -913,27 +913,30 @@ _kdc_check_addresses(krb5_context context, */ static krb5_boolean -send_pac_p(krb5_context context, KDC_REQ *req) +send_pac_p(krb5_context context, KDC_REQ *req, krb5_boolean *pac_request) { krb5_error_code ret; PA_PAC_REQUEST pacreq; const PA_DATA *pa; int i = 0; + *pac_request = TRUE; + pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST); if (pa == NULL) - return TRUE; + return FALSE; ret = decode_PA_PAC_REQUEST(pa->padata_value.data, pa->padata_value.length, &pacreq, NULL); if (ret) - return TRUE; + return FALSE; i = pacreq.include_pac; free_PA_PAC_REQUEST(&pacreq); - if (i == 0) - return FALSE; + if (i == 0) { + *pac_request = FALSE; + } return TRUE; } @@ -1757,13 +1760,19 @@ _kdc_as_rep(krb5_context context, } /* Add the PAC */ - if (send_pac_p(context, req)) { + { krb5_pac p = NULL; krb5_data data; uint16_t rodc_id; krb5_principal client_pac; + krb5_boolean sent_pac_request; + krb5_boolean pac_request; + + sent_pac_request = send_pac_p(context, req, &pac_request); - ret = _kdc_pac_generate(context, client, pk_reply_key, &p); + ret = _kdc_pac_generate(context, client, pk_reply_key, + sent_pac_request ? &pac_request : NULL, + &p); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", client_name); diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 33120a28d34..7240b31f38f 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1745,7 +1745,7 @@ server_lookup: if (mspac) { krb5_pac_free(context, mspac); mspac = NULL; - ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &mspac); + ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", tpn); diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index 43dc89e2bc0..93b973f576b 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -74,6 +74,7 @@ krb5_error_code _kdc_pac_generate(krb5_context context, hdb_entry_ex *client, const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, krb5_pac *pac) { *pac = NULL; @@ -87,8 +88,10 @@ _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, pac); - return (windcft->pac_generate)(windcctx, context, client, pac); + client, pk_reply_key, + pac_request, pac); + return (windcft->pac_generate)(windcctx, context, client, + pac_request, pac); } krb5_error_code diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index dda258da3d1..c7f2bcb5ed9 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/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 */ + const krb5_boolean *, /* pac_request */ krb5_pac *); typedef krb5_error_code (*krb5plugin_windc_pac_pk_generate)(void *, krb5_context, struct hdb_entry_ex *, /* client */ const krb5_keyblock *, /* pk_replykey */ + const krb5_boolean *, /* pac_request */ krb5_pac *); typedef krb5_error_code diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 592f6a3bac4..69cdbfba929 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -434,7 +434,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, skdc_entry, &logon_info_blob, cred_ndr_ptr, - &upn_dns_info_blob); + &upn_dns_info_blob, + NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); if (NT_STATUS_EQUAL(nt_status, @@ -462,6 +463,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, pcred_blob, upn_dns_info_blob, NULL, + NULL, pac); talloc_free(tmp_ctx); @@ -564,7 +566,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, client_skdc_entry, &pac_blob, NULL, - &upn_blob); + &upn_blob, + NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { code = EINVAL; goto done; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 8a3ec22190c..06019e579eb 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -113,6 +113,43 @@ NTSTATUS samba_get_upn_info_pac_blob(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +static +NTSTATUS samba_get_pac_attrs_blob(TALLOC_CTX *mem_ctx, + const krb5_boolean *pac_request, + DATA_BLOB *pac_attrs_data) +{ + union PAC_INFO pac_attrs; + enum ndr_err_code ndr_err; + NTSTATUS nt_status; + + ZERO_STRUCT(pac_attrs); + + *pac_attrs_data = data_blob_null; + + /* Set the length of the flags in bits. */ + pac_attrs.attributes_info.flags_length = 2; + + if (pac_request == NULL) { + pac_attrs.attributes_info.flags + |= PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY; + } else if (*pac_request) { + pac_attrs.attributes_info.flags + |= PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED; + } + + ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs, + PAC_TYPE_ATTRIBUTES_INFO, + (ndr_push_flags_fn_t)ndr_push_PAC_INFO); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + nt_status = ndr_map_error2ntstatus(ndr_err); + DEBUG(1, ("PAC ATTRIBUTES_INFO (presig) push failed: %s\n", + nt_errstr(nt_status))); + return nt_status; + } + + return NT_STATUS_OK; +} + static NTSTATUS samba_get_cred_info_ndr_blob(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, @@ -413,12 +450,14 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, const DATA_BLOB *logon_blob, const DATA_BLOB *cred_blob, const DATA_BLOB *upn_blob, + const DATA_BLOB *pac_attrs_blob, const DATA_BLOB *deleg_blob, krb5_pac *pac) { krb5_data logon_data; krb5_data cred_data; krb5_data upn_data; + krb5_data pac_attrs_data; krb5_data deleg_data; krb5_error_code ret; #ifdef SAMBA4_USES_HEIMDAL @@ -463,6 +502,19 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, } } + ZERO_STRUCT(pac_attrs_data); + if (pac_attrs_blob != NULL) { + ret = smb_krb5_copy_data_contents(&pac_attrs_data, + pac_attrs_blob->data, + pac_attrs_blob->length); + if (ret != 0) { + smb_krb5_free_data_contents(context, &logon_data); + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + return ret; + } + } + ZERO_STRUCT(deleg_data); if (deleg_blob != NULL) { ret = smb_krb5_copy_data_contents(&deleg_data, @@ -472,6 +524,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &logon_data); smb_krb5_free_data_contents(context, &cred_data); smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); return ret; } } @@ -481,6 +534,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &logon_data); smb_krb5_free_data_contents(context, &cred_data); smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -488,8 +542,9 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &logon_data); smb_krb5_free_data_contents(context, &logon_data); if (ret != 0) { - smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -501,6 +556,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &cred_data); if (ret != 0) { smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -519,6 +575,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, &null_data); if (ret != 0) { smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -529,6 +586,18 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, PAC_TYPE_UPN_DNS_INFO, &upn_data); smb_krb5_free_data_contents(context, &upn_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } + } + + if (pac_attrs_blob != NULL) { + ret = krb5_pac_add_buffer(context, *pac, + PAC_TYPE_ATTRIBUTES_INFO, + &pac_attrs_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); if (ret != 0) { smb_krb5_free_data_contents(context, &deleg_data); return ret; @@ -562,6 +631,48 @@ bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry) return true; } +int samba_client_requested_pac(krb5_context context, + krb5_pac *pac, + TALLOC_CTX *mem_ctx, + bool *requested_pac) +{ + enum ndr_err_code ndr_err; + krb5_data k5pac_attrs_in; + DATA_BLOB pac_attrs_in; + union PAC_INFO pac_attrs; + int ret; + + *requested_pac = true; + + ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_ATTRIBUTES_INFO, + &k5pac_attrs_in); + if (ret != 0) { + return ret == ENOENT ? 0 : ret; + } + + pac_attrs_in = data_blob_const(k5pac_attrs_in.data, + k5pac_attrs_in.length); + + ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs, + PAC_TYPE_ATTRIBUTES_INFO, + (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); + smb_krb5_free_data_contents(context, &k5pac_attrs_in); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("can't parse the PAC ATTRIBUTES_INFO: %s\n", nt_errstr(nt_status))); + return EINVAL; + } + + if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY + | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) { + *requested_pac = true; + } else { + *requested_pac = false; + } + + return 0; +} + /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */ int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, bool *is_in_db, @@ -637,12 +748,15 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, struct samba_kdc_entry *p, DATA_BLOB **_logon_info_blob, DATA_BLOB **_cred_ndr_blob, - DATA_BLOB **_upn_info_blob) + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, + const krb5_boolean *pac_request) { struct auth_user_info_dc *user_info_dc; DATA_BLOB *logon_blob = NULL; DATA_BLOB *cred_blob = NULL; DATA_BLOB *upn_blob = NULL; + DATA_BLOB *pac_attrs_blob = NULL; NTSTATUS nt_status; *_logon_info_blob = NULL; @@ -650,6 +764,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, *_cred_ndr_blob = NULL; } *_upn_info_blob = NULL; + if (_pac_attrs_blob != NULL) { + *_pac_attrs_blob = NULL; + } logon_blob = talloc_zero(mem_ctx, DATA_BLOB); if (logon_blob == NULL) { @@ -668,6 +785,13 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + if (_pac_attrs_blob != NULL) { + pac_attrs_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (pac_attrs_blob == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), lpcfg_sam_name(p->kdc_db_ctx->lp_ctx), @@ -712,12 +836,27 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, return nt_status; } + if (pac_attrs_blob != NULL) { + nt_status = samba_get_pac_attrs_blob(pac_attrs_blob, + pac_request, + pac_attrs_blob); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Building PAC ATTRIBUTES failed: %s\n", + nt_errstr(nt_status))); + return nt_status; + } + } + TALLOC_FREE(user_info_dc); *_logon_info_blob = logon_blob; if (_cred_ndr_blob != NULL) { *_cred_ndr_blob = cred_blob; } *_upn_info_blob = upn_blob; + if (_pac_attrs_blob != NULL) { + *_pac_attrs_blob = pac_attrs_blob; + } return NT_STATUS_OK; } @@ -731,7 +870,9 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, nt_status = samba_kdc_get_pac_blobs(mem_ctx, p, _logon_info_blob, NULL, /* cred_blob */ - &upn_blob); + &upn_blob, + NULL, + NULL); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index e83446647b3..1b6264cb2c3 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -31,11 +31,17 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, const DATA_BLOB *logon_blob, const DATA_BLOB *cred_blob, const DATA_BLOB *upn_blob, + const DATA_BLOB *pac_attrs_blob, const DATA_BLOB *deleg_blob, krb5_pac *pac); bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry); +int samba_client_requested_pac(krb5_context context, + krb5_pac *pac, + TALLOC_CTX *mem_ctx, + bool *requested_pac); + int samba_krbtgt_is_in_db(struct samba_kdc_entry *skdc_entry, bool *is_in_db, bool *is_untrusted); @@ -44,7 +50,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, struct samba_kdc_entry *skdc_entry, DATA_BLOB **_logon_info_blob, DATA_BLOB **_cred_ndr_blob, - DATA_BLOB **_upn_info_blob); + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, + const krb5_boolean *pac_request); NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, struct samba_kdc_entry *skdc_entry, DATA_BLOB **_logon_info_blob); diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index ed6e9fb9b63..11d9ff84f04 100644 --- a/source4/kdc/wdc-samba4.c +++ b/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, const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, krb5_pac *pac) { TALLOC_CTX *mem_ctx; @@ -46,6 +47,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, DATA_BLOB _cred_blob = data_blob_null; DATA_BLOB *cred_blob = NULL; DATA_BLOB *upn_blob = NULL; + DATA_BLOB *pac_attrs_blob = NULL; krb5_error_code ret; NTSTATUS nt_status; struct samba_kdc_entry *skdc_entry = @@ -64,7 +66,9 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry, &logon_blob, cred_ndr_ptr, - &upn_blob); + &upn_blob, + &pac_attrs_blob, + pac_request); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return EINVAL; @@ -84,7 +88,8 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, } ret = samba_make_krb5_pac(context, logon_blob, cred_blob, - upn_blob, NULL, pac); + upn_blob, pac_attrs_blob, + NULL, pac); talloc_free(mem_ctx); return ret; @@ -92,9 +97,10 @@ 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, + const krb5_boolean *pac_request, krb5_pac *pac) { - return samba_wdc_get_pac(priv, context, client, NULL, pac); + return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac); } static krb5_error_code samba_wdc_reget_pac2(krb5_context context, @@ -132,6 +138,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, ssize_t srv_checksum_idx = -1; ssize_t kdc_checksum_idx = -1; ssize_t tkt_checksum_idx = -1; + ssize_t attrs_info_idx = -1; if (!mem_ctx) { return ENOMEM; @@ -239,7 +246,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, struct samba_kdc_entry); nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, - &pac_blob, NULL, &upn_blob); + &pac_blob, NULL, &upn_blob, + NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return EINVAL; @@ -356,6 +364,18 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, } tkt_checksum_idx = i; break; + case PAC_TYPE_ATTRIBUTES_INFO: + if (attrs_info_idx != -1) { + DEBUG(1, ("attributes info type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + attrs_info_idx, + i)); + SAFE_FREE(types); + talloc_free(mem_ctx); + return EINVAL; + } + attrs_info_idx = i; + break; default: continue; } @@ -403,6 +423,20 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, goto out; } + if (!server_skdc_entry->is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. + */ + bool requested_pac; + ret = samba_client_requested_pac(context, pac, mem_ctx, + &requested_pac); + if (ret != 0 || !requested_pac) { + new_pac = NULL; + goto out; + } + } + /* Otherwise build an updated PAC */ ret = krb5_pac_init(context, &new_pac); if (ret != 0) { @@ -488,6 +522,9 @@ 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; default: /* just copy... */ break; -- 2.25.1 From 6d6a154af1c274b4c011a0cd77a8f2e08264f486 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 18 Oct 2021 15:07:58 +1300 Subject: [PATCH 611/645] CVE-2020-25719 heimdal:kdc: Require authdata to be present BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 11 ----------- source4/heimdal/lib/krb5/pac.c | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 0f03e17c242..c315446386d 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -243,7 +243,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_pac ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed # # The lack of KRB5SignedPath means we no longer return @@ -263,16 +262,9 @@ ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer ^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer # -# KDC TGS PAC tests -# -^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 -# # KDC TGT tests # ^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 ^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 @@ -280,7 +272,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_revealed ^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_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_krbtgt_link @@ -288,7 +279,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed ^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_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 @@ -326,7 +316,6 @@ ^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_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_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 diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 05bcc523080..749d0fdb4eb 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -1369,7 +1369,7 @@ _krb5_kdc_pac_ticket_parse(krb5_context context, *ppac = NULL; if (ad == NULL || ad->len == 0) - return 0; + return KRB5KDC_ERR_BADOPTION; for (i = 0; i < ad->len; i++) { AuthorizationData child; -- 2.25.1 From ef3012201d1b97268d8193764ca6e0eb477c4f1f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 30 Sep 2021 14:55:06 +1300 Subject: [PATCH 612/645] CVE-2020-25718 kdc: Remove unused samba_kdc_get_pac_blob() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/kdc/pac-glue.c | 21 --------------------- source4/kdc/pac-glue.h | 3 --- 2 files changed, 24 deletions(-) diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 06019e579eb..7d45391dba4 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -860,27 +860,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, - struct samba_kdc_entry *p, - DATA_BLOB **_logon_info_blob) -{ - NTSTATUS nt_status; - DATA_BLOB *upn_blob = NULL; - - nt_status = samba_kdc_get_pac_blobs(mem_ctx, p, - _logon_info_blob, - NULL, /* cred_blob */ - &upn_blob, - NULL, - NULL); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - TALLOC_FREE(upn_blob); - return NT_STATUS_OK; -} - NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, struct ldb_context *samdb, diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 1b6264cb2c3..2a7cb68f274 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -53,9 +53,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, DATA_BLOB **_upn_info_blob, DATA_BLOB **_pac_attrs_blob, const krb5_boolean *pac_request); -NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, - struct samba_kdc_entry *skdc_entry, - DATA_BLOB **_logon_info_blob); NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, -- 2.25.1 From 7983b48c65b058ed6e57adf969f07896da398174 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 10:47:29 +1300 Subject: [PATCH 613/645] CVE-2020-25718 s4-rpc_server: Change sid list functions to operate on a array of struct dom_sid This is instead of an array of struct dom_sid *. The reason is that auth_user_info_dc has an array of struct dom_sid (the user token) and for checking if an RODC should be allowed to print a particular ticket, we want to reuse that a rather then reconstruct it via tokenGroups. This also avoids a lot of memory allocation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 44 +++++++++---------- source4/rpc_server/drsuapi/getncchanges.c | 33 +++++++++----- source4/rpc_server/netlogon/dcerpc_netlogon.c | 33 +++++++++----- 3 files changed, 67 insertions(+), 43 deletions(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index 698249391ef..65d7e7c7271 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -29,13 +29,16 @@ /* see if any SIDs in list1 are in list2 */ -bool sid_list_match(const struct dom_sid **list1, const struct dom_sid **list2) +bool sid_list_match(uint32_t num_sids1, + const struct dom_sid *list1, + uint32_t num_sids2, + const struct dom_sid *list2) { unsigned int i, j; /* do we ever have enough SIDs here to worry about O(n^2) ? */ - for (i=0; list1[i]; i++) { - for (j=0; list2[j]; j++) { - if (dom_sid_equal(list1[i], list2[j])) { + for (i=0; i < num_sids1; i++) { + for (j=0; j < num_sids2; j++) { + if (dom_sid_equal(&list1[i], &list2[j])) { return true; } } @@ -51,9 +54,10 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, struct ldb_message *msg, TALLOC_CTX *mem_ctx, const char *attr, - const struct dom_sid ***sids, - const struct dom_sid **additional_sids, - unsigned int num_additional) + uint32_t *num_sids, + struct dom_sid **sids, + const struct dom_sid *additional_sids, + unsigned int num_additional) { struct ldb_message_element *el; unsigned int i, j; @@ -65,30 +69,25 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, } /* Make array long enough for NULL and additional SID */ - (*sids) = talloc_array(mem_ctx, const struct dom_sid *, - el->num_values + num_additional + 1); + (*sids) = talloc_array(mem_ctx, struct dom_sid, + el->num_values + num_additional); W_ERROR_HAVE_NO_MEMORY(*sids); for (i=0; inum_values; i++) { enum ndr_err_code ndr_err; - struct dom_sid *sid; - sid = talloc(*sids, struct dom_sid); - W_ERROR_HAVE_NO_MEMORY(sid); - - ndr_err = ndr_pull_struct_blob(&el->values[i], sid, sid, + ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &(*sids)[i], (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_INTERNAL_DB_CORRUPTION; } - (*sids)[i] = sid; } for (j = 0; j < num_additional; j++) { (*sids)[i++] = additional_sids[j]; } - (*sids)[i] = NULL; + *num_sids = i; return WERR_OK; } @@ -101,7 +100,8 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, struct ldb_message *msg, TALLOC_CTX *mem_ctx, const char *attr, - const struct dom_sid ***sids) + uint32_t *num_sids, + struct dom_sid **sids) { struct ldb_message_element *el; unsigned int i; @@ -112,23 +112,21 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, return WERR_OK; } - (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1); + (*sids) = talloc_array(mem_ctx, struct dom_sid, el->num_values + 1); W_ERROR_HAVE_NO_MEMORY(*sids); for (i=0; inum_values; i++) { struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]); NTSTATUS status; - struct dom_sid *sid; + struct dom_sid sid = { 0, }; - sid = talloc(*sids, struct dom_sid); - W_ERROR_HAVE_NO_MEMORY(sid); - status = dsdb_get_extended_dn_sid(dn, sid, "SID"); + status = dsdb_get_extended_dn_sid(dn, &sid, "SID"); if (!NT_STATUS_IS_OK(status)) { return WERR_INTERNAL_DB_CORRUPTION; } (*sids)[i] = sid; } - (*sids)[i] = NULL; + *num_sids = i; return WERR_OK; } diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index e458b2a9931..c7d2addd104 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1171,10 +1171,10 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_result *rodc_res = NULL, *obj_res = NULL; - const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids; + uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids; + struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids; const struct dom_sid *object_sid = NULL; WERROR werr; - const struct dom_sid *additional_sids[] = { NULL, NULL }; DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n", drs_ObjectIdentifier_to_string(mem_ctx, ncRoot))); @@ -1259,12 +1259,13 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, /* if the object SID is equal to the user_sid, allow */ object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); + if (object_sid == NULL) { + goto failed; + } if (dom_sid_equal(user_sid, object_sid)) { goto allowed; } - additional_sids[0] = object_sid; - /* * Must be an RODC account at this point, verify machine DN matches the * SID account @@ -1294,13 +1295,17 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, } werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], - mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids); + mem_ctx, "msDS-NeverRevealGroup", + &num_never_reveal_sids, + &never_reveal_sids); if (!W_ERROR_IS_OK(werr)) { goto denied; } werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], - mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids); + mem_ctx, "msDS-RevealOnDemandGroup", + &num_reveal_sids, + &reveal_sids); if (!W_ERROR_IS_OK(werr)) { goto denied; } @@ -1311,19 +1316,27 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, * TODO determine if sIDHistory is required for this check */ werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], - mem_ctx, "tokenGroups", &token_sids, - additional_sids, 1); + mem_ctx, "tokenGroups", + &num_token_sids, + &token_sids, + object_sid, 1); if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { goto denied; } if (never_reveal_sids && - sid_list_match(token_sids, never_reveal_sids)) { + sid_list_match(num_token_sids, + token_sids, + num_never_reveal_sids, + never_reveal_sids)) { goto denied; } if (reveal_sids && - sid_list_match(token_sids, reveal_sids)) { + sid_list_match(num_token_sids, + token_sids, + num_reveal_sids, + reveal_sids)) { goto allowed; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 9972138dbde..c8dd0ceeb77 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2850,10 +2850,10 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, struct ldb_dn *rodc_dn; int ret; struct ldb_result *rodc_res = NULL, *obj_res = NULL; - const struct dom_sid *additional_sids[] = { NULL, NULL }; WERROR werr; struct dom_sid *object_sid; - const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids; + uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids; + struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids; rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "", dom_sid_string(mem_ctx, user_sid)); @@ -2868,17 +2868,22 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied; object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); - - additional_sids[0] = object_sid; + if (object_sid == NULL) { + goto denied; + } werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0], - mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids); + mem_ctx, "msDS-NeverRevealGroup", + &num_never_reveal_sids, + &never_reveal_sids); if (!W_ERROR_IS_OK(werr)) { goto denied; } werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0], - mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids); + mem_ctx, "msDS-RevealOnDemandGroup", + &num_reveal_sids, + &reveal_sids); if (!W_ERROR_IS_OK(werr)) { goto denied; } @@ -2889,19 +2894,27 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, * TODO determine if sIDHistory is required for this check */ werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0], - mem_ctx, "tokenGroups", &token_sids, - additional_sids, 1); + mem_ctx, "tokenGroups", + &num_token_sids, + &token_sids, + object_sid, 1); if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { goto denied; } if (never_reveal_sids && - sid_list_match(token_sids, never_reveal_sids)) { + sid_list_match(num_token_sids, + token_sids, + num_never_reveal_sids, + never_reveal_sids)) { goto denied; } if (reveal_sids && - sid_list_match(token_sids, reveal_sids)) { + sid_list_match(num_token_sids, + token_sids, + num_reveal_sids, + reveal_sids)) { goto allowed; } -- 2.25.1 From 93b6981e5c0b7ec600bc461efcd78c39fd2b8beb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 11:09:48 +1300 Subject: [PATCH 614/645] CVE-2020-25718 s4-rpc_server: Obtain the user tokenGroups earlier This will allow the creation of a common helper routine that takes the token SID list (from tokenGroups or struct auth_user_info_dc) and returns the allowed/denied result. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/drsuapi/getncchanges.c | 28 +++++++++---------- source4/rpc_server/netlogon/dcerpc_netlogon.c | 28 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index c7d2addd104..bc30e73e06b 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1282,6 +1282,20 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, goto allowed; } + /* + * The SID list needs to include itself as well as the tokenGroups. + * + * TODO determine if sIDHistory is required for this check + */ + werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], + mem_ctx, "tokenGroups", + &num_token_sids, + &token_sids, + object_sid, 1); + if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { + goto denied; + } + /* but it isn't allowed to get anyone elses krbtgt secrets */ if (samdb_result_dn(b_state->sam_ctx_system, mem_ctx, obj_res->msgs[0], "msDS-KrbTgtLinkBL", NULL)) { @@ -1310,20 +1324,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, goto denied; } - /* - * The SID list needs to include itself as well as the tokenGroups. - * - * TODO determine if sIDHistory is required for this check - */ - werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], - mem_ctx, "tokenGroups", - &num_token_sids, - &token_sids, - object_sid, 1); - if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { - goto denied; - } - if (never_reveal_sids && sid_list_match(num_token_sids, token_sids, diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index c8dd0ceeb77..51c6666a164 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2872,6 +2872,20 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, goto denied; } + /* + * The SID list needs to include itself as well as the tokenGroups. + * + * TODO determine if sIDHistory is required for this check + */ + werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0], + mem_ctx, "tokenGroups", + &num_token_sids, + &token_sids, + object_sid, 1); + if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { + goto denied; + } + werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0], mem_ctx, "msDS-NeverRevealGroup", &num_never_reveal_sids, @@ -2888,20 +2902,6 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, goto denied; } - /* - * The SID list needs to include itself as well as the tokenGroups. - * - * TODO determine if sIDHistory is required for this check - */ - werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0], - mem_ctx, "tokenGroups", - &num_token_sids, - &token_sids, - object_sid, 1); - if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { - goto denied; - } - if (never_reveal_sids && sid_list_match(num_token_sids, token_sids, -- 2.25.1 From 413f0f7e23905eda14a59c564a963636ec11c95d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 11:38:16 +1300 Subject: [PATCH 615/645] CVE-2020-25718 s4-rpc_server: Put RODC reveal/never reveal logic into a single helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 49 +++++++++++++++++++ source4/rpc_server/drsuapi/getncchanges.c | 37 +++----------- source4/rpc_server/netlogon/dcerpc_netlogon.c | 38 +++----------- 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index 65d7e7c7271..eaeab236fc0 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -130,3 +130,52 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, return WERR_OK; } + +WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ctx, + struct ldb_message *rodc_msg, + uint32_t num_token_sids, + struct dom_sid *token_sids) +{ + uint32_t num_never_reveal_sids, num_reveal_sids; + struct dom_sid *never_reveal_sids, *reveal_sids; + TALLOC_CTX *frame = talloc_stackframe(); + WERROR werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, + frame, "msDS-NeverRevealGroup", + &num_never_reveal_sids, + &never_reveal_sids); + if (!W_ERROR_IS_OK(werr)) { + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + } + + werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, + frame, "msDS-RevealOnDemandGroup", + &num_reveal_sids, + &reveal_sids); + if (!W_ERROR_IS_OK(werr)) { + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + } + + if (never_reveal_sids && + sid_list_match(num_token_sids, + token_sids, + num_never_reveal_sids, + never_reveal_sids)) { + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + } + + if (reveal_sids && + sid_list_match(num_token_sids, + token_sids, + num_reveal_sids, + reveal_sids)) { + TALLOC_FREE(frame); + return WERR_OK; + } + + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + +} diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index bc30e73e06b..3b1d674573f 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1171,8 +1171,8 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_result *rodc_res = NULL, *obj_res = NULL; - uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids; - struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids; + uint32_t num_token_sids; + struct dom_sid *token_sids; const struct dom_sid *object_sid = NULL; WERROR werr; @@ -1308,35 +1308,12 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, goto denied; } - werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], - mem_ctx, "msDS-NeverRevealGroup", - &num_never_reveal_sids, - &never_reveal_sids); - if (!W_ERROR_IS_OK(werr)) { - goto denied; - } - - werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0], - mem_ctx, "msDS-RevealOnDemandGroup", - &num_reveal_sids, - &reveal_sids); - if (!W_ERROR_IS_OK(werr)) { - goto denied; - } - - if (never_reveal_sids && - sid_list_match(num_token_sids, - token_sids, - num_never_reveal_sids, - never_reveal_sids)) { - goto denied; - } + werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(b_state->sam_ctx_system, + rodc_res->msgs[0], + num_token_sids, + token_sids); - if (reveal_sids && - sid_list_match(num_token_sids, - token_sids, - num_reveal_sids, - reveal_sids)) { + if (W_ERROR_IS_OK(werr)) { goto allowed; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 51c6666a164..1aecd65bb61 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2852,8 +2852,8 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, struct ldb_result *rodc_res = NULL, *obj_res = NULL; WERROR werr; struct dom_sid *object_sid; - uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids; - struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids; + uint32_t num_token_sids; + struct dom_sid *token_sids; rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "", dom_sid_string(mem_ctx, user_sid)); @@ -2886,38 +2886,14 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, goto denied; } - werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0], - mem_ctx, "msDS-NeverRevealGroup", - &num_never_reveal_sids, - &never_reveal_sids); - if (!W_ERROR_IS_OK(werr)) { - goto denied; - } - - werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0], - mem_ctx, "msDS-RevealOnDemandGroup", - &num_reveal_sids, - &reveal_sids); - if (!W_ERROR_IS_OK(werr)) { - goto denied; - } + werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, + rodc_res->msgs[0], + num_token_sids, + token_sids); - if (never_reveal_sids && - sid_list_match(num_token_sids, - token_sids, - num_never_reveal_sids, - never_reveal_sids)) { - goto denied; - } - - if (reveal_sids && - sid_list_match(num_token_sids, - token_sids, - num_reveal_sids, - reveal_sids)) { + if (W_ERROR_IS_OK(werr)) { goto allowed; } - denied: return false; allowed: -- 2.25.1 From 53ceac1af5cddef8318c5fbb24db061d32da1000 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 11:55:11 +1300 Subject: [PATCH 616/645] CVE-2020-25718 s4-rpc_server: Put msDS-KrbTgtLinkBL and UF_INTERDOMAIN_TRUST_ACCOUNT RODC checks in common While these checks were not in the NETLOGON case, there is no sense where an RODC should be resetting a bad password count on either a UF_INTERDOMAIN_TRUST_ACCOUNT nor a RODC krbtgt account. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 29 ++++++++++++++++--- source4/rpc_server/drsuapi/getncchanges.c | 13 +-------- source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 + 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index eaeab236fc0..ab2b4373b47 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -133,16 +133,37 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ctx, struct ldb_message *rodc_msg, + struct ldb_message *obj_msg, uint32_t num_token_sids, struct dom_sid *token_sids) { uint32_t num_never_reveal_sids, num_reveal_sids; struct dom_sid *never_reveal_sids, *reveal_sids; TALLOC_CTX *frame = talloc_stackframe(); - WERROR werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, - frame, "msDS-NeverRevealGroup", - &num_never_reveal_sids, - &never_reveal_sids); + WERROR werr; + + /* + * We are not allowed to get anyone elses krbtgt secrets (and + * in callers that don't shortcut before this, the RODC should + * not deal with any krbtgt) + */ + if (samdb_result_dn(sam_ctx, frame, + obj_msg, "msDS-KrbTgtLinkBL", NULL)) { + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + } + + if (ldb_msg_find_attr_as_uint(obj_msg, + "userAccountControl", 0) & + UF_INTERDOMAIN_TRUST_ACCOUNT) { + TALLOC_FREE(frame); + return WERR_DS_DRA_SECRETS_DENIED; + } + + werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, + frame, "msDS-NeverRevealGroup", + &num_never_reveal_sids, + &never_reveal_sids); if (!W_ERROR_IS_OK(werr)) { TALLOC_FREE(frame); return WERR_DS_DRA_SECRETS_DENIED; diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 3b1d674573f..a9d305fc9a0 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1296,20 +1296,9 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, goto denied; } - /* but it isn't allowed to get anyone elses krbtgt secrets */ - if (samdb_result_dn(b_state->sam_ctx_system, mem_ctx, - obj_res->msgs[0], "msDS-KrbTgtLinkBL", NULL)) { - goto denied; - } - - if (ldb_msg_find_attr_as_uint(obj_res->msgs[0], - "userAccountControl", 0) & - UF_INTERDOMAIN_TRUST_ACCOUNT) { - goto denied; - } - werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(b_state->sam_ctx_system, rodc_res->msgs[0], + obj_res->msgs[0], num_token_sids, token_sids); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 1aecd65bb61..92dd693ddcc 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2888,6 +2888,7 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, rodc_res->msgs[0], + obj_res->msgs[0], num_token_sids, token_sids); -- 2.25.1 From b9082da516ce79562898f5968dffc07d6c0fa972 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 12:01:12 +1300 Subject: [PATCH 617/645] CVE-2020-25718 s4-rpc_server: Confirm that the RODC has the UF_PARTIAL_SECRETS_ACCOUNT bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 13 +++++++++++++ source4/rpc_server/drsuapi/getncchanges.c | 7 ++++++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 7 ++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index ab2b4373b47..99c5fc20d9d 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -141,6 +141,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct struct dom_sid *never_reveal_sids, *reveal_sids; TALLOC_CTX *frame = talloc_stackframe(); WERROR werr; + uint32_t rodc_uac; /* * We are not allowed to get anyone elses krbtgt secrets (and @@ -160,6 +161,18 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct return WERR_DS_DRA_SECRETS_DENIED; } + /* Be very sure the RODC is really an RODC */ + rodc_uac = ldb_msg_find_attr_as_uint(rodc_msg, + "userAccountControl", + 0); + if ((rodc_uac & UF_PARTIAL_SECRETS_ACCOUNT) + != UF_PARTIAL_SECRETS_ACCOUNT) { + TALLOC_FREE(frame); + DBG_ERR("Attempt to use an RODC account that is not an RODC: %s\n", + ldb_dn_get_linearized(rodc_msg->dn)); + return WERR_DS_DRA_SECRETS_DENIED; + } + werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, frame, "msDS-NeverRevealGroup", &num_never_reveal_sids, diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index a9d305fc9a0..2fbd178cedc 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1168,7 +1168,12 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, struct ldb_dn *ntds_dn = NULL, *server_dn = NULL; struct ldb_dn *rodc_dn, *krbtgt_link_dn; int ret; - const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL }; + const char *rodc_attrs[] = { "msDS-KrbTgtLink", + "msDS-NeverRevealGroup", + "msDS-RevealOnDemandGroup", + "objectGUID", + "userAccountControl", + NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_result *rodc_res = NULL, *obj_res = NULL; uint32_t num_token_sids; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 92dd693ddcc..ff33389401c 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2845,7 +2845,12 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, struct dom_sid *user_sid, struct ldb_dn *obj_dn) { - const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL }; + const char *rodc_attrs[] = { "msDS-KrbTgtLink", + "msDS-NeverRevealGroup", + "msDS-RevealOnDemandGroup", + "objectGUID", + "userAccountControl", + NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_dn *rodc_dn; int ret; -- 2.25.1 From d40d2eba6dc72d756198851db0f6262c49743378 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 12:25:30 +1300 Subject: [PATCH 618/645] CVE-2020-25718 s4-rpc_server: Provide wrapper samdb_confirm_rodc_allowed_to_repl_to() This shares the lookup of the tokenGroups attribute. There will be a new caller that does not want to do this step, so this is a wrapper of samdb_confirm_rodc_allowed_to_repl_to_sid_list() rather than part of it BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 45 +++++++++++++++++++ source4/rpc_server/drsuapi/getncchanges.c | 24 ++-------- source4/rpc_server/netlogon/dcerpc_netlogon.c | 30 ++----------- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index 99c5fc20d9d..78cb35d3fc1 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -213,3 +213,48 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct return WERR_DS_DRA_SECRETS_DENIED; } + +/* + * This is a wrapper for the above that pulls in the tokenGroups + * rather than relying on the caller providing those + */ +WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, + struct ldb_message *rodc_msg, + struct ldb_message *obj_msg) +{ + TALLOC_CTX *frame = talloc_stackframe(); + WERROR werr; + uint32_t num_token_sids; + struct dom_sid *token_sids; + const struct dom_sid *object_sid = NULL; + + object_sid = samdb_result_dom_sid(frame, + obj_msg, + "objectSid"); + if (object_sid == NULL) { + return WERR_DS_DRA_BAD_DN; + } + + /* + * The SID list needs to include itself as well as the tokenGroups. + * + * TODO determine if sIDHistory is required for this check + */ + werr = samdb_result_sid_array_ndr(sam_ctx, + obj_msg, + frame, "tokenGroups", + &num_token_sids, + &token_sids, + object_sid, 1); + if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { + return WERR_DS_DRA_SECRETS_DENIED; + } + + werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, + rodc_msg, + obj_msg, + num_token_sids, + token_sids); + TALLOC_FREE(frame); + return werr; +} diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 2fbd178cedc..11a6c93d4cd 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1176,8 +1176,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_result *rodc_res = NULL, *obj_res = NULL; - uint32_t num_token_sids; - struct dom_sid *token_sids; const struct dom_sid *object_sid = NULL; WERROR werr; @@ -1287,25 +1285,9 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, goto allowed; } - /* - * The SID list needs to include itself as well as the tokenGroups. - * - * TODO determine if sIDHistory is required for this check - */ - werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], - mem_ctx, "tokenGroups", - &num_token_sids, - &token_sids, - object_sid, 1); - if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { - goto denied; - } - - werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(b_state->sam_ctx_system, - rodc_res->msgs[0], - obj_res->msgs[0], - num_token_sids, - token_sids); + werr = samdb_confirm_rodc_allowed_to_repl_to(b_state->sam_ctx_system, + rodc_res->msgs[0], + obj_res->msgs[0]); if (W_ERROR_IS_OK(werr)) { goto allowed; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ff33389401c..efdd95b8689 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2856,9 +2856,6 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, int ret; struct ldb_result *rodc_res = NULL, *obj_res = NULL; WERROR werr; - struct dom_sid *object_sid; - uint32_t num_token_sids; - struct dom_sid *token_sids; rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "", dom_sid_string(mem_ctx, user_sid)); @@ -2872,30 +2869,9 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0); if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied; - object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); - if (object_sid == NULL) { - goto denied; - } - - /* - * The SID list needs to include itself as well as the tokenGroups. - * - * TODO determine if sIDHistory is required for this check - */ - werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0], - mem_ctx, "tokenGroups", - &num_token_sids, - &token_sids, - object_sid, 1); - if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { - goto denied; - } - - werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, - rodc_res->msgs[0], - obj_res->msgs[0], - num_token_sids, - token_sids); + werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx, + rodc_res->msgs[0], + obj_res->msgs[0]); if (W_ERROR_IS_OK(werr)) { goto allowed; -- 2.25.1 From 3179154dca2937c6afdf00ce6a65cb91d28c3320 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 12:29:49 +1300 Subject: [PATCH 619/645] CVE-2020-25718 s4-rpc_server: Remove unused attributes in RODC check In particular the objectGUID is no longer used, and in the NETLOGON case the special case for msDS-KrbTgtLink does not apply. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/drsuapi/getncchanges.c | 1 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 11a6c93d4cd..3ec5acb5353 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1171,7 +1171,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", - "objectGUID", "userAccountControl", NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index efdd95b8689..edefdee39ca 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2845,10 +2845,8 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, struct dom_sid *user_sid, struct ldb_dn *obj_dn) { - const char *rodc_attrs[] = { "msDS-KrbTgtLink", - "msDS-NeverRevealGroup", + const char *rodc_attrs[] = { "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", - "objectGUID", "userAccountControl", NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; -- 2.25.1 From ccfb8541094d5c08b636c6f74a4fa21dafd0a1fc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 14:31:00 +1300 Subject: [PATCH 620/645] CVE-2020-25718 s4-rpc_server: Explain why we use DSDB_SEARCH_SHOW_EXTENDED_DN in RODC access check BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/drsuapi/getncchanges.c | 6 +++++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 3ec5acb5353..8a5243aba52 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1251,7 +1251,11 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, dom_sid_string(mem_ctx, user_sid)); if (!ldb_dn_validate(rodc_dn)) goto failed; - /* do the two searches we need */ + /* + * do the two searches we need + * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID lists + * out of the extended DNs + */ ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &rodc_res, rodc_dn, rodc_attrs, DSDB_SEARCH_SHOW_EXTENDED_DN); if (ret != LDB_SUCCESS || rodc_res->count != 1) goto failed; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index edefdee39ca..f4cce12207e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2859,7 +2859,11 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, dom_sid_string(mem_ctx, user_sid)); if (!ldb_dn_validate(rodc_dn)) goto denied; - /* do the two searches we need */ + /* + * do the two searches we need + * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list + * out of the extended DNs + */ ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs, DSDB_SEARCH_SHOW_EXTENDED_DN); if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied; -- 2.25.1 From 6d87ecd20f12fb714fd1f561e70c302c7bec07c4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 15:57:41 +1300 Subject: [PATCH 621/645] CVE-2020-25718 s4-rpc_server: Add in debug messages into RODC processing These are added for the uncommon cases. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/rpc_server/common/sid_helper.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c index 78cb35d3fc1..c6e7fbeb7ab 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/rpc_server/common/sid_helper.c @@ -151,12 +151,18 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct if (samdb_result_dn(sam_ctx, frame, obj_msg, "msDS-KrbTgtLinkBL", NULL)) { TALLOC_FREE(frame); + DBG_INFO("Denied attempt to replicate to/act as a RODC krbtgt trust account %s using RODC: %s\n", + ldb_dn_get_linearized(obj_msg->dn), + ldb_dn_get_linearized(rodc_msg->dn)); return WERR_DS_DRA_SECRETS_DENIED; } if (ldb_msg_find_attr_as_uint(obj_msg, "userAccountControl", 0) & UF_INTERDOMAIN_TRUST_ACCOUNT) { + DBG_INFO("Denied attempt to replicate to/act as a inter-domain trust account %s using RODC: %s\n", + ldb_dn_get_linearized(obj_msg->dn), + ldb_dn_get_linearized(rodc_msg->dn)); TALLOC_FREE(frame); return WERR_DS_DRA_SECRETS_DENIED; } @@ -167,9 +173,9 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct 0); if ((rodc_uac & UF_PARTIAL_SECRETS_ACCOUNT) != UF_PARTIAL_SECRETS_ACCOUNT) { - TALLOC_FREE(frame); DBG_ERR("Attempt to use an RODC account that is not an RODC: %s\n", ldb_dn_get_linearized(rodc_msg->dn)); + TALLOC_FREE(frame); return WERR_DS_DRA_SECRETS_DENIED; } @@ -178,6 +184,9 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct &num_never_reveal_sids, &never_reveal_sids); if (!W_ERROR_IS_OK(werr)) { + DBG_ERR("Failed to parse msDS-NeverRevealGroup on %s: %s\n", + ldb_dn_get_linearized(rodc_msg->dn), + win_errstr(werr)); TALLOC_FREE(frame); return WERR_DS_DRA_SECRETS_DENIED; } @@ -187,6 +196,9 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct &num_reveal_sids, &reveal_sids); if (!W_ERROR_IS_OK(werr)) { + DBG_ERR("Failed to parse msDS-RevealOnDemandGroup on %s: %s\n", + ldb_dn_get_linearized(rodc_msg->dn), + win_errstr(werr)); TALLOC_FREE(frame); return WERR_DS_DRA_SECRETS_DENIED; } @@ -247,6 +259,10 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, &token_sids, object_sid, 1); if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { + DBG_ERR("Failed to get tokenGroups on %s to confirm access via RODC %s: %s\n", + ldb_dn_get_linearized(obj_msg->dn), + ldb_dn_get_linearized(rodc_msg->dn), + win_errstr(werr)); return WERR_DS_DRA_SECRETS_DENIED; } -- 2.25.1 From ee2fd7bce6872853ebf518be562b0499df7375ba Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 15:59:28 +1300 Subject: [PATCH 622/645] CVE-2020-25718 dsdb: Bring sid_helper.c into common code as rodc_helper.c These common routines will assist the KDC to do the same access checking as the RPC servers need to do regarding which accounts a RODC can act with regard to. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- .../common/sid_helper.c => dsdb/common/rodc_helper.c} | 1 - source4/dsdb/wscript_build | 2 +- source4/rpc_server/drsuapi/getncchanges.c | 1 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 - source4/rpc_server/wscript_build | 9 +-------- 5 files changed, 2 insertions(+), 12 deletions(-) rename source4/{rpc_server/common/sid_helper.c => dsdb/common/rodc_helper.c} (99%) diff --git a/source4/rpc_server/common/sid_helper.c b/source4/dsdb/common/rodc_helper.c similarity index 99% rename from source4/rpc_server/common/sid_helper.c rename to source4/dsdb/common/rodc_helper.c index c6e7fbeb7ab..09aa3f5e710 100644 --- a/source4/rpc_server/common/sid_helper.c +++ b/source4/dsdb/common/rodc_helper.c @@ -23,7 +23,6 @@ #include "rpc_server/dcerpc_server.h" #include "librpc/gen_ndr/ndr_security.h" #include "source4/dsdb/samdb/samdb.h" -#include "rpc_server/common/sid_helper.h" #include "libcli/security/security.h" /* diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build index dbe58859a14..98364667b66 100644 --- a/source4/dsdb/wscript_build +++ b/source4/dsdb/wscript_build @@ -13,7 +13,7 @@ bld.SAMBA_LIBRARY('samdb', ) bld.SAMBA_LIBRARY('samdb-common', - source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c', + source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c common/rodc_helper.c', autoproto='common/proto.h', private_library=True, deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping UTIL_RUNCMD' diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 8a5243aba52..28223104c94 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -31,7 +31,6 @@ #include "libcli/security/security.h" #include "libcli/security/session.h" #include "rpc_server/drsuapi/dcesrv_drsuapi.h" -#include "rpc_server/common/sid_helper.h" #include "../libcli/drsuapi/drsuapi.h" #include "lib/util/binsearch.h" #include "lib/util/tsort.h" diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index f4cce12207e..a38e78a37e7 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -42,7 +42,6 @@ #include "librpc/gen_ndr/ndr_winbind.h" #include "librpc/gen_ndr/ndr_winbind_c.h" #include "lib/socket/netif.h" -#include "rpc_server/common/sid_helper.h" #include "lib/util/util_str_escape.h" #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \ diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build index 186e6a269e5..b5878133678 100644 --- a/source4/rpc_server/wscript_build +++ b/source4/rpc_server/wscript_build @@ -7,17 +7,10 @@ bld.SAMBA_SUBSYSTEM('DCERPC_SHARE', enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER'), ) -bld.SAMBA_SUBSYSTEM('DCERPC_SID_HELPER', - source='common/sid_helper.c', - autoproto='common/sid_helper.h', - deps='ldb', - enabled=bld.AD_DC_BUILD_IS_ENABLED(), - ) - bld.SAMBA_SUBSYSTEM('DCERPC_COMMON', source='common/server_info.c common/forward.c common/loadparm.c', autoproto='common/proto.h', - deps='ldb DCERPC_SHARE DCERPC_SID_HELPER', + deps='ldb DCERPC_SHARE', enabled=bld.AD_DC_BUILD_IS_ENABLED() ) -- 2.25.1 From 708b10d6a964fe13eb82205911376c6c50e239da Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2021 16:14:37 +1300 Subject: [PATCH 623/645] CVE-2020-25718 kdc: Confirm the RODC was allowed to issue a particular ticket BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- selftest/knownfail_heimdal_kdc | 12 -- source4/auth/sam.c | 5 +- source4/dsdb/common/rodc_helper.c | 47 ++++---- source4/kdc/mit_samba.c | 6 +- source4/kdc/pac-glue.c | 106 +++++++++++++++++- source4/kdc/pac-glue.h | 13 ++- source4/kdc/wdc-samba4.c | 40 ++++++- source4/rpc_server/drsuapi/getncchanges.c | 11 +- source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 + 9 files changed, 187 insertions(+), 54 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index c315446386d..7d0597fa279 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -265,25 +265,16 @@ # KDC TGT tests # ^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_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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_partial_secrets -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_revealed ^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_rodc_allowed_denied -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_krbtgt_link ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_partial_secrets -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed ^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_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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_partial_secrets -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_allowed ^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_upn_dns_info_ex_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac @@ -316,11 +307,8 @@ ^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_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_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 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_partial_secrets -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed # # PAC request tests diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 39e48c26b52..93b41be3b21 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -57,7 +57,10 @@ \ "pwdLastSet", \ "msDS-UserPasswordExpiryTimeComputed", \ - "accountExpires" + "accountExpires", \ + \ + /* Needed for RODC rule processing */ \ + "msDS-KrbTgtLinkBL" const char *krbtgt_attrs[] = { KRBTGT_ATTRS, NULL diff --git a/source4/dsdb/common/rodc_helper.c b/source4/dsdb/common/rodc_helper.c index 09aa3f5e710..1cd644c6def 100644 --- a/source4/dsdb/common/rodc_helper.c +++ b/source4/dsdb/common/rodc_helper.c @@ -47,19 +47,18 @@ bool sid_list_match(uint32_t num_sids1, /* * Return an array of SIDs from a ldb_message given an attribute name assumes - * the SIDs are in NDR form (with additional sids applied on the end). + * the SIDs are in NDR form (with primary_sid applied on the start). */ -WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, - struct ldb_message *msg, - TALLOC_CTX *mem_ctx, - const char *attr, - uint32_t *num_sids, - struct dom_sid **sids, - const struct dom_sid *additional_sids, - unsigned int num_additional) +static WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, + struct ldb_message *msg, + TALLOC_CTX *mem_ctx, + const char *attr, + uint32_t *num_sids, + struct dom_sid **sids, + const struct dom_sid *primary_sid) { struct ldb_message_element *el; - unsigned int i, j; + unsigned int i; el = ldb_msg_find_element(msg, attr); if (!el) { @@ -69,24 +68,25 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, /* Make array long enough for NULL and additional SID */ (*sids) = talloc_array(mem_ctx, struct dom_sid, - el->num_values + num_additional); + el->num_values + 1); W_ERROR_HAVE_NO_MEMORY(*sids); - for (i=0; inum_values; i++) { + (*sids)[0] = *primary_sid; + + for (i = 0; inum_values; i++) { enum ndr_err_code ndr_err; + struct dom_sid sid = { 0, }; - ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &(*sids)[i], + ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_INTERNAL_DB_CORRUPTION; } + /* Primary SID is already in position zero. */ + (*sids)[i+1] = sid; } - for (j = 0; j < num_additional; j++) { - (*sids)[i++] = additional_sids[j]; - } - - *num_sids = i; + *num_sids = i+1; return WERR_OK; } @@ -131,6 +131,7 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, } WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ctx, + const struct dom_sid *rodc_machine_account_sid, struct ldb_message *rodc_msg, struct ldb_message *obj_msg, uint32_t num_token_sids, @@ -202,6 +203,12 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct return WERR_DS_DRA_SECRETS_DENIED; } + /* The RODC can replicate and print tickets for itself. */ + if (dom_sid_equal(&token_sids[0], rodc_machine_account_sid)) { + TALLOC_FREE(frame); + return WERR_OK; + } + if (never_reveal_sids && sid_list_match(num_token_sids, token_sids, @@ -230,6 +237,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct * rather than relying on the caller providing those */ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, + struct dom_sid *rodc_machine_account_sid, struct ldb_message *rodc_msg, struct ldb_message *obj_msg) { @@ -256,7 +264,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, frame, "tokenGroups", &num_token_sids, &token_sids, - object_sid, 1); + object_sid); if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { DBG_ERR("Failed to get tokenGroups on %s to confirm access via RODC %s: %s\n", ldb_dn_get_linearized(obj_msg->dn), @@ -266,6 +274,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, } werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, + rodc_machine_account_sid, rodc_msg, obj_msg, num_token_sids, diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 69cdbfba929..99a5214a896 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -435,7 +435,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, &logon_info_blob, cred_ndr_ptr, &upn_dns_info_blob, - NULL, NULL); + NULL, NULL, + NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); if (NT_STATUS_EQUAL(nt_status, @@ -567,7 +568,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, &pac_blob, NULL, &upn_blob, - NULL, NULL); + NULL, NULL, + NULL); if (!NT_STATUS_IS_OK(nt_status)) { code = EINVAL; goto done; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 7d45391dba4..c94e4f08e76 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -35,6 +35,7 @@ #include "libcli/security/security.h" #include "dsdb/samdb/samdb.h" #include "auth/kerberos/pac_utils.h" +#include "source4/dsdb/common/util.h" static NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, @@ -744,13 +745,19 @@ int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, return 0; } +/* + * We return not just the blobs, but also the user_info_dc because we + * will need, in the RODC case, to confirm that the returned user is + * permitted to be replicated to the KDC + */ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, struct samba_kdc_entry *p, DATA_BLOB **_logon_info_blob, DATA_BLOB **_cred_ndr_blob, DATA_BLOB **_upn_info_blob, DATA_BLOB **_pac_attrs_blob, - const krb5_boolean *pac_request) + const krb5_boolean *pac_request, + struct auth_user_info_dc **_user_info_dc) { struct auth_user_info_dc *user_info_dc; DATA_BLOB *logon_blob = NULL; @@ -848,7 +855,15 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, } } - TALLOC_FREE(user_info_dc); + /* + * Return to the caller to allow a check on the allowed/denied + * RODC replication groups + */ + if (_user_info_dc == NULL) { + TALLOC_FREE(user_info_dc); + } else { + *_user_info_dc = user_info_dc; + } *_logon_info_blob = logon_blob; if (_cred_ndr_blob != NULL) { *_cred_ndr_blob = cred_blob; @@ -1094,3 +1109,90 @@ out: TALLOC_FREE(frame); return code; } + + +/* + * In the RODC case, to confirm that the returned user is permitted to + * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc + */ +WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids, + struct dom_sid *object_sids, + struct samba_kdc_entry *rodc, + struct samba_kdc_entry *object) +{ + int ret; + WERROR werr; + TALLOC_CTX *frame = talloc_stackframe(); + const char *rodc_attrs[] = { "msDS-KrbTgtLink", + "msDS-NeverRevealGroup", + "msDS-RevealOnDemandGroup", + "userAccountControl", + "objectSid", + NULL }; + struct ldb_result *rodc_machine_account = NULL; + struct ldb_dn *rodc_machine_account_dn = samdb_result_dn(rodc->kdc_db_ctx->samdb, + frame, + rodc->msg, + "msDS-KrbTgtLinkBL", + NULL); + const struct dom_sid *rodc_machine_account_sid = NULL; + + if (rodc_machine_account_dn == NULL) { + DBG_ERR("krbtgt account %s has no msDS-KrbTgtLinkBL to find RODC machine account for allow/deny list\n", + ldb_dn_get_linearized(rodc->msg->dn)); + TALLOC_FREE(frame); + return WERR_DS_DRA_BAD_DN; + } + + /* + * Follow the link and get the RODC account (the krbtgt + * account is the krbtgt_XXX account, but the + * msDS-NeverRevealGroup and msDS-RevealOnDemandGroup is on + * the RODC$ account) + * + * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID lists + * out of the extended DNs + */ + + ret = dsdb_search_dn(rodc->kdc_db_ctx->samdb, + frame, + &rodc_machine_account, + rodc_machine_account_dn, + rodc_attrs, + DSDB_SEARCH_SHOW_EXTENDED_DN); + if (ret != LDB_SUCCESS) { + DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: %s\n", + ldb_dn_get_linearized(rodc_machine_account_dn), + ldb_dn_get_linearized(rodc->msg->dn), + ldb_errstring(rodc->kdc_db_ctx->samdb)); + TALLOC_FREE(frame); + return WERR_DS_DRA_BAD_DN; + } + + if (rodc_machine_account->count != 1) { + DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: (%d)\n", + ldb_dn_get_linearized(rodc_machine_account_dn), + ldb_dn_get_linearized(rodc->msg->dn), + rodc_machine_account->count); + TALLOC_FREE(frame); + return WERR_DS_DRA_BAD_DN; + } + + /* if the object SID is equal to the user_sid, allow */ + rodc_machine_account_sid = samdb_result_dom_sid(frame, + rodc_machine_account->msgs[0], + "objectSid"); + if (rodc_machine_account_sid == NULL) { + return WERR_DS_DRA_BAD_DN; + } + + werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(rodc->kdc_db_ctx->samdb, + rodc_machine_account_sid, + rodc_machine_account->msgs[0], + object->msg, + num_object_sids, + object_sids); + + TALLOC_FREE(frame); + return werr; +} diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 2a7cb68f274..89aa8da63c3 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -52,8 +52,8 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, DATA_BLOB **_cred_ndr_blob, DATA_BLOB **_upn_info_blob, DATA_BLOB **_pac_attrs_blob, - const krb5_boolean *pac_request); - + const krb5_boolean *pac_request, + struct auth_user_info_dc **_user_info_dc); NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, struct ldb_context *samdb, @@ -79,3 +79,12 @@ krb5_error_code samba_kdc_validate_pac_blob( krb5_context context, struct samba_kdc_entry *client_skdc_entry, const krb5_pac pac); + +/* + * In the RODC case, to confirm that the returned user is permitted to + * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc + */ +WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_sids, + struct dom_sid *sids, + struct samba_kdc_entry *rodc, + struct samba_kdc_entry *object); diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index 11d9ff84f04..71507018120 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -27,6 +27,7 @@ #include "kdc/pac-glue.h" #include "sdb.h" #include "sdb_hdb.h" +#include "librpc/gen_ndr/auth.h" /* * Given the right private pointer from hdb_samba4, @@ -68,7 +69,8 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, cred_ndr_ptr, &upn_blob, &pac_attrs_blob, - pac_request); + pac_request, + NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return EINVAL; @@ -161,9 +163,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, } } - /* If the krbtgt was generated by an RODC, and we are not that + /* + * If the krbtgt was generated by an RODC, and we are not that * RODC, then we need to regenerate the PAC - we can't trust - * it */ + * it, and confirm that the RODC was permitted to print this ticket + * + * Becasue of the samba_kdc_validate_pac_blob() step we can be + * sure that the record in 'client' matches the SID in the + * original PAC. + */ ret = samba_krbtgt_is_in_db(krbtgt_skdc_entry, &is_in_db, &is_untrusted); if (ret != 0) { talloc_free(mem_ctx); @@ -237,6 +245,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, if (is_untrusted) { struct samba_kdc_entry *client_skdc_entry = NULL; + struct auth_user_info_dc *user_info_dc = NULL; + WERROR werr; if (client == NULL) { return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; @@ -247,12 +257,30 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, &pac_blob, NULL, &upn_blob, - NULL, NULL); + NULL, NULL, + &user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); - return EINVAL; + return KRB5KDC_ERR_TGT_REVOKED; + } + + /* + * Now check if the SID list in the user_info_dc + * intersects correctly with the RODC allow/deny + * lists + */ + + werr = samba_rodc_confirm_user_is_allowed(user_info_dc->num_sids, + user_info_dc->sids, + krbtgt_skdc_entry, + client_skdc_entry); + if (!W_ERROR_IS_OK(werr)) { + talloc_free(mem_ctx); + return KRB5KDC_ERR_TGT_REVOKED; } - } else { + } + + if (!is_untrusted) { pac_blob = talloc_zero(mem_ctx, DATA_BLOB); if (!pac_blob) { talloc_free(mem_ctx); diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 28223104c94..c3330a622af 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -1174,7 +1174,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, NULL }; const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; struct ldb_result *rodc_res = NULL, *obj_res = NULL; - const struct dom_sid *object_sid = NULL; WERROR werr; DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n", @@ -1262,15 +1261,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &obj_res, obj_dn, obj_attrs, 0); if (ret != LDB_SUCCESS || obj_res->count != 1) goto failed; - /* if the object SID is equal to the user_sid, allow */ - object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); - if (object_sid == NULL) { - goto failed; - } - if (dom_sid_equal(user_sid, object_sid)) { - goto allowed; - } - /* * Must be an RODC account at this point, verify machine DN matches the * SID account @@ -1288,6 +1278,7 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, } werr = samdb_confirm_rodc_allowed_to_repl_to(b_state->sam_ctx_system, + user_sid, rodc_res->msgs[0], obj_res->msgs[0]); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index a38e78a37e7..09d0252c0c2 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2871,6 +2871,7 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied; werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx, + user_sid, rodc_res->msgs[0], obj_res->msgs[0]); -- 2.25.1 From a441e7b7988538c2dacae19b82bd0dd8ddb00874 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 4 Oct 2021 12:43:13 +1300 Subject: [PATCH 624/645] CVE-2020-25718 kdc: Return ERR_POLICY if RODC krbtgt account is invalid BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 8 -------- source4/dsdb/common/rodc_helper.c | 2 +- source4/kdc/pac-glue.c | 4 ++-- source4/kdc/wdc-samba4.c | 6 +++++- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 7d0597fa279..5b6fb0ddf69 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -265,16 +265,10 @@ # KDC TGT tests # ^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_rodc_no_krbtgt_link -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_revealed ^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_rodc_no_krbtgt_link -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed ^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_rodc_no_krbtgt_link -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_partial_secrets ^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_upn_dns_info_ex_mac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac @@ -307,8 +301,6 @@ ^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_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_rodc_no_krbtgt_link -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed # # PAC request tests diff --git a/source4/dsdb/common/rodc_helper.c b/source4/dsdb/common/rodc_helper.c index 1cd644c6def..e81ecef79c0 100644 --- a/source4/dsdb/common/rodc_helper.c +++ b/source4/dsdb/common/rodc_helper.c @@ -176,7 +176,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct DBG_ERR("Attempt to use an RODC account that is not an RODC: %s\n", ldb_dn_get_linearized(rodc_msg->dn)); TALLOC_FREE(frame); - return WERR_DS_DRA_SECRETS_DENIED; + return WERR_DOMAIN_CONTROLLER_NOT_FOUND; } werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index c94e4f08e76..cb0a923fc2d 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -1141,7 +1141,7 @@ WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids, DBG_ERR("krbtgt account %s has no msDS-KrbTgtLinkBL to find RODC machine account for allow/deny list\n", ldb_dn_get_linearized(rodc->msg->dn)); TALLOC_FREE(frame); - return WERR_DS_DRA_BAD_DN; + return WERR_DOMAIN_CONTROLLER_NOT_FOUND; } /* @@ -1166,7 +1166,7 @@ WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids, ldb_dn_get_linearized(rodc->msg->dn), ldb_errstring(rodc->kdc_db_ctx->samdb)); TALLOC_FREE(frame); - return WERR_DS_DRA_BAD_DN; + return WERR_DOMAIN_CONTROLLER_NOT_FOUND; } if (rodc_machine_account->count != 1) { diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index 71507018120..c9bf5dd9cf5 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -276,7 +276,11 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, client_skdc_entry); if (!W_ERROR_IS_OK(werr)) { talloc_free(mem_ctx); - return KRB5KDC_ERR_TGT_REVOKED; + if (W_ERROR_EQUAL(werr, WERR_DOMAIN_CONTROLLER_NOT_FOUND)) { + return KRB5KDC_ERR_POLICY; + } else { + return KRB5KDC_ERR_TGT_REVOKED; + } } } -- 2.25.1 From 0bfd3b46237acd373baa184b7807b06adba98301 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 8 Oct 2021 08:29:51 +1300 Subject: [PATCH 625/645] CVE-2020-25719 kdc: Avoid races and multiple DB lookups in s4u2self check Looking up the DB twice is subject to a race and is a poor use of resources, so instead just pass in the record we already got when trying to confirm that the server in S4U2Self is the same as the requesting client. The client record has already been bound to the the original client by the SID check in the PAC. Likewise by looking up server only once we ensure that the keys looked up originally are in the record we confirm the SID for here. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/heimdal/kdc/krb5tgs.c | 26 +++++++++++------ source4/heimdal/lib/hdb/hdb.h | 2 +- source4/kdc/db-glue.c | 54 ++++++++++++----------------------- source4/kdc/db-glue.h | 5 ++-- source4/kdc/hdb-samba4.c | 43 ++++++++-------------------- 5 files changed, 52 insertions(+), 78 deletions(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 7240b31f38f..f8253fed422 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -313,7 +313,7 @@ check_constrained_delegation(krb5_context context, * Determine if s4u2self is allowed from this client to this server * * For example, regardless of the principal being impersonated, if the - * 'client' and 'server' are the same, then it's safe. + * 'client' and 'server' (target) are the same, then it's safe. */ static krb5_error_code @@ -321,18 +321,28 @@ check_s4u2self(krb5_context context, krb5_kdc_configuration *config, HDB *clientdb, hdb_entry_ex *client, - krb5_const_principal server) + hdb_entry_ex *target_server, + krb5_const_principal target_server_principal) { krb5_error_code ret; - /* if client does a s4u2self to itself, that ok */ - if (krb5_principal_compare(context, client->entry.principal, server) == TRUE) - return 0; - + /* + * Always allow the plugin to check, this might be faster, allow a + * policy or audit check and can look into the DB records + * directly + */ if (clientdb->hdb_check_s4u2self) { - ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server); + ret = clientdb->hdb_check_s4u2self(context, + clientdb, + client, + target_server); if (ret == 0) return 0; + } else if (krb5_principal_compare(context, + client->entry.principal, + target_server_principal) == TRUE) { + /* if client does a s4u2self to itself, and there is no plugin, that is ok */ + return 0; } else { ret = KRB5KDC_ERR_BADOPTION; } @@ -1757,7 +1767,7 @@ server_lookup: * Check that service doing the impersonating is * requesting a ticket to it-self. */ - ret = check_s4u2self(context, config, clientdb, client, sp); + ret = check_s4u2self(context, config, clientdb, client, server, sp); if (ret) { kdc_log(context, config, 0, "S4U2Self: %s is not allowed " "to impersonate to service " diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index 6a09ecb6fe1..5ef9d9565f3 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -266,7 +266,7 @@ typedef struct HDB{ /** * Check if s4u2self is allowed from this client to this server */ - krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal); + krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, hdb_entry_ex *); }HDB; #define HDB_INTERFACE_VERSION 7 diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index 5fd0f431cdf..d55bf1663d4 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -2508,53 +2508,37 @@ krb5_error_code samba_kdc_nextkey(krb5_context context, /* Check if a given entry may delegate or do s4u2self to this target principal * - * This is currently a very nasty hack - allowing only delegation to itself. + * The safest way to determine 'self' is to check the DB record made at + * the time the principal was presented to the KDC. */ krb5_error_code samba_kdc_check_s4u2self(krb5_context context, - struct samba_kdc_db_context *kdc_db_ctx, - struct samba_kdc_entry *skdc_entry, - krb5_const_principal target_principal) + struct samba_kdc_entry *skdc_entry_client, + struct samba_kdc_entry *skdc_entry_server_target) { - krb5_error_code ret; - struct ldb_dn *realm_dn; - struct ldb_message *msg; struct dom_sid *orig_sid; struct dom_sid *target_sid; - const char *delegation_check_attrs[] = { - "objectSid", NULL - }; - - TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_s4u2self"); - - if (!mem_ctx) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "samba_kdc_check_s4u2self: talloc_named() failed!"); - return ret; - } - - ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal, - SDB_F_GET_CLIENT|SDB_F_GET_SERVER, - delegation_check_attrs, &realm_dn, &msg); - - if (ret != 0) { - talloc_free(mem_ctx); - return ret; - } + TALLOC_CTX *frame = talloc_stackframe(); - orig_sid = samdb_result_dom_sid(mem_ctx, skdc_entry->msg, "objectSid"); - target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); + orig_sid = samdb_result_dom_sid(frame, + skdc_entry_client->msg, + "objectSid"); + target_sid = samdb_result_dom_sid(frame, + skdc_entry_server_target->msg, + "objectSid"); - /* Allow delegation to the same principal, even if by a different - * name. The easy and safe way to prove this is by SID - * comparison */ + /* + * Allow delegation to the same record (representing a + * principal), even if by a different name. The easy and safe + * way to prove this is by SID comparison + */ if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { - talloc_free(mem_ctx); + talloc_free(frame); return KRB5KDC_ERR_BADOPTION; } - talloc_free(mem_ctx); - return ret; + talloc_free(frame); + return 0; } /* Certificates printed by a the Certificate Authority might have a diff --git a/source4/kdc/db-glue.h b/source4/kdc/db-glue.h index aa630f5d349..cadfac1deb8 100644 --- a/source4/kdc/db-glue.h +++ b/source4/kdc/db-glue.h @@ -40,9 +40,8 @@ krb5_error_code samba_kdc_nextkey(krb5_context context, krb5_error_code samba_kdc_check_s4u2self(krb5_context context, - struct samba_kdc_db_context *kdc_db_ctx, - struct samba_kdc_entry *skdc_entry, - krb5_const_principal target_principal); + struct samba_kdc_entry *skdc_entry_client, + struct samba_kdc_entry *skdc_entry_server_target); krb5_error_code samba_kdc_check_pkinit_ms_upn_match(krb5_context context, diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 38ce9807c02..f0939193ad7 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -274,38 +274,19 @@ hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, static krb5_error_code hdb_samba4_check_s4u2self(krb5_context context, HDB *db, - hdb_entry_ex *entry, - krb5_const_principal target_principal) + hdb_entry_ex *client_entry, + hdb_entry_ex *server_target_entry) { - struct samba_kdc_db_context *kdc_db_ctx; - struct samba_kdc_entry *skdc_entry; - krb5_error_code ret; - - kdc_db_ctx = talloc_get_type_abort(db->hdb_db, - struct samba_kdc_db_context); - skdc_entry = talloc_get_type_abort(entry->ctx, - struct samba_kdc_entry); - - ret = samba_kdc_check_s4u2self(context, kdc_db_ctx, - skdc_entry, - target_principal); - switch (ret) { - case 0: - break; - case SDB_ERR_WRONG_REALM: - ret = HDB_ERR_WRONG_REALM; - break; - case SDB_ERR_NOENTRY: - ret = HDB_ERR_NOENTRY; - break; - case SDB_ERR_NOT_FOUND_HERE: - ret = HDB_ERR_NOT_FOUND_HERE; - break; - default: - break; - } - - return ret; + struct samba_kdc_entry *skdc_client_entry + = talloc_get_type_abort(client_entry->ctx, + struct samba_kdc_entry); + struct samba_kdc_entry *skdc_server_target_entry + = talloc_get_type_abort(server_target_entry->ctx, + struct samba_kdc_entry); + + return samba_kdc_check_s4u2self(context, + skdc_client_entry, + skdc_server_target_entry); } static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx, -- 2.25.1 From a5768291651f0be5f38be03e311987371e677db3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 27 Sep 2021 12:10:02 +1300 Subject: [PATCH 626/645] CVE-2020-25721 auth: Fill in the new HAS_SAM_NAME_AND_SID values BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- python/samba/tests/krb5/s4u_tests.py | 2 -- selftest/knownfail_heimdal_kdc | 10 ---------- selftest/knownfail_mit_kdc | 4 ---- source4/kdc/pac-glue.c | 8 ++++++++ 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 5005affd6b3..a80a7b3427e 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -309,7 +309,6 @@ class S4UKerberosTests(KDCBaseTest): tgt=service_tgt, authenticator_subkey=authenticator_subkey, kdc_options=str(kdc_options), - expect_upn_dns_info_ex=False, expect_claims=False) self._generic_kdc_exchange(kdc_exchange_dict, @@ -611,7 +610,6 @@ class S4UKerberosTests(KDCBaseTest): kdc_options=kdc_options, pac_options=pac_options, expect_edata=expect_edata, - expect_upn_dns_info_ex=False, expected_proxy_target=expected_proxy_target, expected_transited_services=expected_transited_services, expect_pac=expect_pac) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 5b6fb0ddf69..80044551c9c 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -245,12 +245,6 @@ ^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 # -# The lack of KRB5SignedPath means we no longer return -# KRB5KRB_ERR_RESPONSE_TOO_BIG in this specific case -# -^samba4.krb5.kdc with machine account.as-req-pac-request.fl2000dc:local -# -# ^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 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a @@ -270,10 +264,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed ^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_rodc_not_revealed -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_mac -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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_matching_sname_host ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index dfdd17c655a..b5b13110353 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -432,10 +432,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_upn_dns_info_ex_mac -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_mac -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_upn_user -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_upn_dns_info_ex_user ^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 diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index cb0a923fc2d..95f71c04b23 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -101,6 +101,14 @@ NTSTATUS samba_get_upn_info_pac_blob(TALLOC_CTX *mem_ctx, pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED; } + pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID; + + pac_upn.upn_dns_info.ex.sam_name_and_sid.samaccountname + = info->info->account_name; + + pac_upn.upn_dns_info.ex.sam_name_and_sid.objectsid + = &info->sids[0]; + ndr_err = ndr_push_union_blob(upn_data, mem_ctx, &pac_upn, PAC_TYPE_UPN_DNS_INFO, (ndr_push_flags_fn_t)ndr_push_PAC_INFO); -- 2.25.1 From 75f18ea20afb9932dce98cba308e14b0d7a7f628 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 20 Oct 2021 11:36:58 +1300 Subject: [PATCH 627/645] CVE-2020-25722 Ensure the structural objectclass cannot be changed If the structural objectclass is allowed to change, then the restrictions locking an object to remaining a user or computer will not be enforcable. Likewise other LDAP inheritance rules, which allow only certain child objects can be bypassed, which can in turn allow creation of (unprivileged) users where only DNS objects were expected. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14753 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14889 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- selftest/knownfail.d/ldap | 1 - selftest/knownfail.d/modify-order | 2 +- selftest/knownfail.d/uac_mod_lock | 28 --------------- selftest/knownfail.d/uac_objectclass_restrict | 4 --- source4/dsdb/samdb/ldb_modules/objectclass.c | 36 +++++++++++++++++++ 5 files changed, 37 insertions(+), 34 deletions(-) delete mode 100644 selftest/knownfail.d/uac_mod_lock diff --git a/selftest/knownfail.d/ldap b/selftest/knownfail.d/ldap index 545dc93db8e..0331d3687d4 100644 --- a/selftest/knownfail.d/ldap +++ b/selftest/knownfail.d/ldap @@ -1,4 +1,3 @@ # the attributes too long test returns the wrong error ^samba4.ldap.python.+test_attribute_ranges_too_long samba4.ldap.python\(ad_dc_default\).*__main__.BasicTests.test_ldapSearchNoAttributes -^samba4.ldap.python.+test_objectclasses diff --git a/selftest/knownfail.d/modify-order b/selftest/knownfail.d/modify-order index e14cd1eb356..76d538e1f9c 100644 --- a/selftest/knownfail.d/modify-order +++ b/selftest/knownfail.d/modify-order @@ -1,8 +1,8 @@ samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_account_locality_device samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_container_flags_multivalue -samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_objectclass samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_objectclass2 samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_singlevalue samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_account_locality_device samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_container_flags[^_] +samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_objectclass[^2] samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_objectclass2 diff --git a/selftest/knownfail.d/uac_mod_lock b/selftest/knownfail.d/uac_mod_lock deleted file mode 100644 index 068a47c6e61..00000000000 --- a/selftest/knownfail.d/uac_mod_lock +++ /dev/null @@ -1,28 +0,0 @@ -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar diff --git a/selftest/knownfail.d/uac_objectclass_restrict b/selftest/knownfail.d/uac_objectclass_restrict index c4d4507c833..a9ed5e888cc 100644 --- a/selftest/knownfail.d/uac_objectclass_restrict +++ b/selftest/knownfail.d/uac_objectclass_restrict @@ -15,7 +15,3 @@ ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-replace_CC_default_computer\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\) ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) -^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\) diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 36ab76e19fc..d8feff0262c 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -811,6 +811,7 @@ static int objectclass_do_mod(struct oc_context *ac) struct ldb_message_element *oc_el_entry, *oc_el_change; struct ldb_val *vals; struct ldb_message *msg; + const struct dsdb_class *current_structural_objectclass; const struct dsdb_class *objectclass; unsigned int i, j, k; bool found; @@ -830,6 +831,22 @@ static int objectclass_do_mod(struct oc_context *ac) return ldb_operr(ldb); } + /* + * Get the current new top-most structural object class + * + * We must not allow this to change + */ + + current_structural_objectclass + = dsdb_get_last_structural_class(ac->schema, + oc_el_entry); + if (current_structural_objectclass == NULL) { + ldb_asprintf_errstring(ldb, + "objectclass: cannot find current structural objectclass on %s!", + ldb_dn_get_linearized(ac->search_res->message->dn)); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* use a new message structure */ msg = ldb_msg_new(ac); if (msg == NULL) { @@ -939,6 +956,25 @@ static int objectclass_do_mod(struct oc_context *ac) return LDB_ERR_OBJECT_CLASS_VIOLATION; } + /* + * Has (so far, we re-check for each and every + * "objectclass" in the message) the structural + * objectclass changed? + */ + + if (objectclass != current_structural_objectclass) { + const char *dn + = ldb_dn_get_linearized(ac->search_res->message->dn); + ldb_asprintf_errstring(ldb, + "objectclass: not permitted " + "to change the structural " + "objectClass on %s [%s] => [%s]!", + dn, + current_structural_objectclass->lDAPDisplayName, + objectclass->lDAPDisplayName); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* Check for unrelated objectclasses */ ret = check_unrelated_objectclasses(ac->module, ac->schema, objectclass, -- 2.25.1 From 238e13e24484be4d267d96c3e07aeb78de272dda Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:42:41 +1300 Subject: [PATCH 628/645] CVE-2020-25719 s4:kdc: Add KDC support for PAC_REQUESTER_SID PAC buffer BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 57 ------------ source4/kdc/mit_samba.c | 4 +- source4/kdc/pac-glue.c | 163 ++++++++++++++++++++++++++++++--- source4/kdc/pac-glue.h | 2 + source4/kdc/wdc-samba4.c | 34 ++++++- 5 files changed, 185 insertions(+), 75 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 80044551c9c..9cad1ca4d05 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -301,60 +301,3 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true -# -# 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_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_sid_mismatch_existing -^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 -# -# 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 a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index 99a5214a896..e015c5a52db 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -435,7 +435,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, &logon_info_blob, cred_ndr_ptr, &upn_dns_info_blob, - NULL, NULL, + NULL, NULL, NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); @@ -465,6 +465,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, upn_dns_info_blob, NULL, NULL, + NULL, pac); talloc_free(tmp_ctx); @@ -569,6 +570,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, NULL, &upn_blob, NULL, NULL, + NULL, NULL); if (!NT_STATUS_IS_OK(nt_status)) { code = EINVAL; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 95f71c04b23..e0e483662c0 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -40,7 +40,8 @@ static NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, const struct auth_user_info_dc *info, - DATA_BLOB *pac_data) + DATA_BLOB *pac_data, + DATA_BLOB *requester_sid_blob) { struct netr_SamInfo3 *info3; union PAC_INFO pac_info; @@ -50,6 +51,9 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, ZERO_STRUCT(pac_info); *pac_data = data_blob_null; + if (requester_sid_blob != NULL) { + *requester_sid_blob = data_blob_null; + } nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx, info, &info3); if (!NT_STATUS_IS_OK(nt_status)) { @@ -75,6 +79,25 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, return nt_status; } + if (requester_sid_blob != NULL && info->num_sids > 0) { + union PAC_INFO pac_requester_sid; + + ZERO_STRUCT(pac_requester_sid); + + pac_requester_sid.requester_sid.sid = info->sids[0]; + + ndr_err = ndr_push_union_blob(requester_sid_blob, mem_ctx, + &pac_requester_sid, + PAC_TYPE_REQUESTER_SID, + (ndr_push_flags_fn_t)ndr_push_PAC_INFO); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + nt_status = ndr_map_error2ntstatus(ndr_err); + DEBUG(1, ("PAC_REQUESTER_SID (presig) push failed: %s\n", + nt_errstr(nt_status))); + return nt_status; + } + } + return NT_STATUS_OK; } @@ -460,6 +483,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, const DATA_BLOB *cred_blob, const DATA_BLOB *upn_blob, const DATA_BLOB *pac_attrs_blob, + const DATA_BLOB *requester_sid_blob, const DATA_BLOB *deleg_blob, krb5_pac *pac) { @@ -467,6 +491,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, krb5_data cred_data; krb5_data upn_data; krb5_data pac_attrs_data; + krb5_data requester_sid_data; krb5_data deleg_data; krb5_error_code ret; #ifdef SAMBA4_USES_HEIMDAL @@ -524,6 +549,20 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, } } + ZERO_STRUCT(requester_sid_data); + if (requester_sid_blob != NULL) { + ret = smb_krb5_copy_data_contents(&requester_sid_data, + requester_sid_blob->data, + requester_sid_blob->length); + if (ret != 0) { + smb_krb5_free_data_contents(context, &logon_data); + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); + return ret; + } + } + ZERO_STRUCT(deleg_data); if (deleg_blob != NULL) { ret = smb_krb5_copy_data_contents(&deleg_data, @@ -534,6 +573,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &cred_data); smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); return ret; } } @@ -544,6 +584,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &cred_data); smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -554,6 +595,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &cred_data); smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -566,6 +608,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, if (ret != 0) { smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -585,6 +628,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, if (ret != 0) { smb_krb5_free_data_contents(context, &upn_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -597,6 +641,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, smb_krb5_free_data_contents(context, &upn_data); if (ret != 0) { smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &requester_sid_data); smb_krb5_free_data_contents(context, &deleg_data); return ret; } @@ -607,6 +652,18 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, PAC_TYPE_ATTRIBUTES_INFO, &pac_attrs_data); smb_krb5_free_data_contents(context, &pac_attrs_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } + } + + if (requester_sid_blob != NULL) { + ret = krb5_pac_add_buffer(context, *pac, + PAC_TYPE_REQUESTER_SID, + &requester_sid_data); + smb_krb5_free_data_contents(context, &requester_sid_data); if (ret != 0) { smb_krb5_free_data_contents(context, &deleg_data); return ret; @@ -765,6 +822,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, DATA_BLOB **_upn_info_blob, DATA_BLOB **_pac_attrs_blob, const krb5_boolean *pac_request, + DATA_BLOB **_requester_sid_blob, struct auth_user_info_dc **_user_info_dc) { struct auth_user_info_dc *user_info_dc; @@ -772,6 +830,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, DATA_BLOB *cred_blob = NULL; DATA_BLOB *upn_blob = NULL; DATA_BLOB *pac_attrs_blob = NULL; + DATA_BLOB *requester_sid_blob = NULL; NTSTATUS nt_status; *_logon_info_blob = NULL; @@ -782,6 +841,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, if (_pac_attrs_blob != NULL) { *_pac_attrs_blob = NULL; } + if (_requester_sid_blob != NULL) { + *_requester_sid_blob = NULL; + } logon_blob = talloc_zero(mem_ctx, DATA_BLOB); if (logon_blob == NULL) { @@ -807,6 +869,13 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, } } + if (_requester_sid_blob != NULL) { + requester_sid_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (requester_sid_blob == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), lpcfg_sam_name(p->kdc_db_ctx->lp_ctx), @@ -824,7 +893,8 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, nt_status = samba_get_logon_info_pac_blob(logon_blob, user_info_dc, - logon_blob); + logon_blob, + requester_sid_blob); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Building PAC LOGON INFO failed: %s\n", nt_errstr(nt_status))); @@ -880,6 +950,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, if (_pac_attrs_blob != NULL) { *_pac_attrs_blob = pac_attrs_blob; } + if (_requester_sid_blob != NULL) { + *_requester_sid_blob = requester_sid_blob; + } return NT_STATUS_OK; } @@ -912,7 +985,7 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, } nt_status = samba_get_logon_info_pac_blob(mem_ctx, - user_info_dc, pac_blob); + user_info_dc, pac_blob, NULL); return nt_status; } @@ -1062,6 +1135,52 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, return nt_status; } +static krb5_error_code samba_get_requester_sid(TALLOC_CTX *mem_ctx, + krb5_pac pac, + krb5_context context, + struct dom_sid *sid) +{ + NTSTATUS nt_status; + enum ndr_err_code ndr_err; + krb5_error_code ret; + + DATA_BLOB pac_requester_sid_in; + krb5_data k5pac_requester_sid_in; + + union PAC_INFO info; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_REQUESTER_SID, + &k5pac_requester_sid_in); + if (ret != 0) { + talloc_free(tmp_ctx); + return ret; + } + + pac_requester_sid_in = data_blob_const(k5pac_requester_sid_in.data, + k5pac_requester_sid_in.length); + + ndr_err = ndr_pull_union_blob(&pac_requester_sid_in, tmp_ctx, &info, + PAC_TYPE_REQUESTER_SID, + (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); + smb_krb5_free_data_contents(context, &k5pac_requester_sid_in); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + nt_status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("can't parse the PAC REQUESTER_SID: %s\n", nt_errstr(nt_status))); + talloc_free(tmp_ctx); + return EINVAL; + } + + *sid = info.requester_sid.sid; + + talloc_free(tmp_ctx); + return 0; +} + /* Does a parse and SID check, but no crypto. */ krb5_error_code samba_kdc_validate_pac_blob( krb5_context context, @@ -1075,22 +1194,36 @@ krb5_error_code samba_kdc_validate_pac_blob( krb5_error_code code; bool ok; - code = kerberos_pac_to_user_info_dc(frame, - pac, - context, - &pac_user_info, - NULL, - NULL); - if (code != 0) { - goto out; - } + /* + * First, try to get the SID from the requester SID buffer in the PAC. + */ + code = samba_get_requester_sid(frame, pac, context, &pac_sid); + + if (code == ENOENT) { + /* + * If the requester SID buffer isn't present, fall back to the + * SID in the LOGON_INFO PAC buffer. + */ + code = kerberos_pac_to_user_info_dc(frame, + pac, + context, + &pac_user_info, + NULL, + NULL); + if (code != 0) { + goto out; + } + + if (pac_user_info->num_sids == 0) { + code = EINVAL; + goto out; + } - if (pac_user_info->num_sids == 0) { - code = EINVAL; + pac_sid = pac_user_info->sids[0]; + } else if (code != 0) { goto out; } - pac_sid = pac_user_info->sids[0]; client_sid = samdb_result_dom_sid(frame, client_skdc_entry->msg, "objectSid"); diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 89aa8da63c3..266e000f9cd 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -32,6 +32,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, const DATA_BLOB *cred_blob, const DATA_BLOB *upn_blob, const DATA_BLOB *pac_attrs_blob, + const DATA_BLOB *requester_sid_blob, const DATA_BLOB *deleg_blob, krb5_pac *pac); @@ -53,6 +54,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, DATA_BLOB **_upn_info_blob, DATA_BLOB **_pac_attrs_blob, const krb5_boolean *pac_request, + DATA_BLOB **_requester_sid_blob, struct auth_user_info_dc **_user_info_dc); NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, krb5_context context, diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index c9bf5dd9cf5..ecd182702c3 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -49,6 +49,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, DATA_BLOB *cred_blob = NULL; DATA_BLOB *upn_blob = NULL; DATA_BLOB *pac_attrs_blob = NULL; + DATA_BLOB *requester_sid_blob = NULL; krb5_error_code ret; NTSTATUS nt_status; struct samba_kdc_entry *skdc_entry = @@ -70,6 +71,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, &upn_blob, &pac_attrs_blob, pac_request, + &requester_sid_blob, NULL); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); @@ -91,7 +93,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, ret = samba_make_krb5_pac(context, logon_blob, cred_blob, upn_blob, pac_attrs_blob, - NULL, pac); + requester_sid_blob, NULL, pac); talloc_free(mem_ctx); return ret; @@ -125,6 +127,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, krb5_pac new_pac = NULL; DATA_BLOB *pac_blob = NULL; DATA_BLOB *upn_blob = NULL; + DATA_BLOB *requester_sid_blob = NULL; DATA_BLOB *deleg_blob = NULL; krb5_error_code ret; NTSTATUS nt_status; @@ -141,6 +144,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, ssize_t kdc_checksum_idx = -1; ssize_t tkt_checksum_idx = -1; ssize_t attrs_info_idx = -1; + ssize_t requester_sid_idx = -1; if (!mem_ctx) { return ENOMEM; @@ -257,7 +261,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, &pac_blob, NULL, &upn_blob, - NULL, NULL, + NULL, NULL, &requester_sid_blob, &user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); @@ -408,6 +412,18 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, } attrs_info_idx = i; break; + case PAC_TYPE_REQUESTER_SID: + if (requester_sid_idx != -1) { + DEBUG(1, ("requester sid type[%"PRIu32"] twice [%zd] and [%zu]: \n", + types[i], + requester_sid_idx, + i)); + SAFE_FREE(types); + talloc_free(mem_ctx); + return EINVAL; + } + requester_sid_idx = i; + break; default: continue; } @@ -546,6 +562,11 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, * we just add a place holder here. */ type_blob = data_blob_const(&zero_byte, 1); + + if (requester_sid_idx == -1 && requester_sid_blob != NULL) { + /* inject REQUESTER_SID behind */ + forced_next_type = PAC_TYPE_REQUESTER_SID; + } break; case PAC_TYPE_KDC_CHECKSUM: /* @@ -557,6 +578,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, case PAC_TYPE_ATTRIBUTES_INFO: /* just copy... */ break; + 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; + } + break; default: /* just copy... */ break; -- 2.25.1 From 481c21b8da270b81dc169dbf562bedc88121b08a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 13:53:25 +1300 Subject: [PATCH 629/645] CVE-2020-25719 heimdal:kdc: Check return code BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- source4/heimdal/kdc/krb5tgs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index f8253fed422..11bf4ea88d2 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1361,7 +1361,10 @@ tgs_build_reply(krb5_context context, ret = KRB5KDC_ERR_POLICY; goto out; } - _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); + ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); + if (ret) { + goto out; + } if(t->enc_part.kvno){ second_kvno = *t->enc_part.kvno; kvno_ptr = &second_kvno; -- 2.25.1 From 0354a7f48ab6aa6dee7fb0cd637666dd0c129837 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 26 Oct 2021 20:34:44 +1300 Subject: [PATCH 630/645] CVE-2020-25719 heimdal:kdc: Move fetching krbtgt entry to before enctype selection This allows us to use it when validating user-to-user. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- source4/heimdal/kdc/krb5tgs.c | 70 +++++++++++++++++------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 11bf4ea88d2..4bf6cd3144d 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1518,6 +1518,41 @@ server_lookup: goto out; } + /* Now refetch the primary krbtgt, and get the current kvno (the + * sign check may have been on an old kvno, and the server may + * have been an incoming trust) */ + ret = krb5_make_principal(context, &krbtgt_principal, + krb5_principal_get_comp_string(context, + krbtgt->entry.principal, + 1), + KRB5_TGS_NAME, + krb5_principal_get_comp_string(context, + krbtgt->entry.principal, + 1), NULL); + if(ret) { + kdc_log(context, config, 0, + "Failed to generate krbtgt principal"); + goto out; + } + + ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out); + krb5_free_principal(context, krbtgt_principal); + if (ret) { + krb5_error_code ret2; + char *ktpn, *ktpn2; + ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn); + ret2 = krb5_unparse_name(context, krbtgt_principal, &ktpn2); + kdc_log(context, config, 0, + "Request with wrong krbtgt: %s, %s not found in our database", + (ret == 0) ? ktpn : "", (ret2 == 0) ? ktpn2 : ""); + if(ret == 0) + free(ktpn); + if(ret2 == 0) + free(ktpn2); + ret = KRB5KRB_AP_ERR_NOT_US; + goto out; + } + /* * Select enctype, return key and kvno. */ @@ -1568,41 +1603,6 @@ server_lookup: * backward. */ - /* Now refetch the primary krbtgt, and get the current kvno (the - * sign check may have been on an old kvno, and the server may - * have been an incoming trust) */ - ret = krb5_make_principal(context, &krbtgt_principal, - krb5_principal_get_comp_string(context, - krbtgt->entry.principal, - 1), - KRB5_TGS_NAME, - krb5_principal_get_comp_string(context, - krbtgt->entry.principal, - 1), NULL); - if(ret) { - kdc_log(context, config, 0, - "Failed to generate krbtgt principal"); - goto out; - } - - ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out); - krb5_free_principal(context, krbtgt_principal); - if (ret) { - krb5_error_code ret2; - char *ktpn, *ktpn2; - ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn); - ret2 = krb5_unparse_name(context, krbtgt_principal, &ktpn2); - kdc_log(context, config, 0, - "Request with wrong krbtgt: %s, %s not found in our database", - (ret == 0) ? ktpn : "", (ret2 == 0) ? ktpn2 : ""); - if(ret == 0) - free(ktpn); - if(ret2 == 0) - free(ktpn2); - ret = KRB5KRB_AP_ERR_NOT_US; - goto out; - } - /* The first realm is the realm of the service, the second is * krbtgt//@REALM component of the krbtgt DN the request was * encrypted to. The redirection via the krbtgt_out entry allows -- 2.25.1 From 6a7db73a8269197c63856ec234592a920c448f18 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 13:50:03 +1300 Subject: [PATCH 631/645] CVE-2020-25719 heimdal:kdc: Use sname from request rather than user-to-user TGT client name BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 20 ------ source4/heimdal/kdc/krb5tgs.c | 113 ++++++++++++++++----------------- 2 files changed, 55 insertions(+), 78 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 9cad1ca4d05..852a02d6d18 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -265,39 +265,19 @@ ^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_rodc_not_revealed ^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_matching_sname_host ^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 -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_non_existent_sname -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_other_sname -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_partial_secrets ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_allowed ^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_user2user_rodc_revealed ^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_tgt_cname_host -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_cname -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_realm -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_other_cname -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_wrong_realm ^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_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_rodc_not_revealed -# -# PAC request tests -# -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_none -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_true -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 4bf6cd3144d..c0934b0af2f 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1339,64 +1339,7 @@ tgs_build_reply(krb5_context context, if (b->kdc_options.canonicalize) flags |= HDB_F_CANON; - if(b->kdc_options.enc_tkt_in_skey){ - Ticket *t; - hdb_entry_ex *uu; - krb5_principal p; - Key *uukey; - krb5uint32 second_kvno = 0; - krb5uint32 *kvno_ptr = NULL; - - if(b->additional_tickets == NULL || - b->additional_tickets->len == 0){ - ret = KRB5KDC_ERR_BADOPTION; /* ? */ - kdc_log(context, config, 0, - "No second ticket present in request"); - goto out; - } - t = &b->additional_tickets->val[0]; - if(!get_krbtgt_realm(&t->sname)){ - kdc_log(context, config, 0, - "Additional ticket is not a ticket-granting ticket"); - ret = KRB5KDC_ERR_POLICY; - goto out; - } - ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); - if (ret) { - goto out; - } - if(t->enc_part.kvno){ - second_kvno = *t->enc_part.kvno; - kvno_ptr = &second_kvno; - } - ret = _kdc_db_fetch(context, config, p, - HDB_F_GET_KRBTGT, kvno_ptr, - NULL, &uu); - krb5_free_principal(context, p); - if(ret){ - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto out; - } - ret = hdb_enctype2key(context, &uu->entry, - t->enc_part.etype, &uukey); - if(ret){ - _kdc_free_ent(context, uu); - ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ - goto out; - } - ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); - _kdc_free_ent(context, uu); - if(ret) - goto out; - - ret = verify_flags(context, config, &adtkt, spn); - if (ret) - goto out; - - s = &adtkt.cname; - r = adtkt.crealm; - } else if (s == NULL) { + if (s == NULL) { ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; krb5_set_error_message(context, ret, "No server in request"); goto out; @@ -1561,7 +1504,61 @@ server_lookup: krb5_enctype etype; if(b->kdc_options.enc_tkt_in_skey) { + Ticket *t; + hdb_entry_ex *uu; + krb5_principal p; + Key *uukey; + krb5uint32 second_kvno = 0; + krb5uint32 *kvno_ptr = NULL; size_t i; + + if(b->additional_tickets == NULL || + b->additional_tickets->len == 0){ + ret = KRB5KDC_ERR_BADOPTION; /* ? */ + kdc_log(context, config, 0, + "No second ticket present in request"); + goto out; + } + t = &b->additional_tickets->val[0]; + if(!get_krbtgt_realm(&t->sname)){ + kdc_log(context, config, 0, + "Additional ticket is not a ticket-granting ticket"); + ret = KRB5KDC_ERR_POLICY; + goto out; + } + ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); + if (ret) { + goto out; + } + if(t->enc_part.kvno){ + second_kvno = *t->enc_part.kvno; + kvno_ptr = &second_kvno; + } + ret = _kdc_db_fetch(context, config, p, + HDB_F_GET_KRBTGT, kvno_ptr, + NULL, &uu); + krb5_free_principal(context, p); + if(ret){ + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto out; + } + ret = hdb_enctype2key(context, &uu->entry, + t->enc_part.etype, &uukey); + if(ret){ + _kdc_free_ent(context, uu); + ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ + goto out; + } + ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); + _kdc_free_ent(context, uu); + if(ret) + goto out; + + ret = verify_flags(context, config, &adtkt, spn); + if (ret) + goto out; + ekey = &adtkt.key; for(i = 0; i < b->etype.len; i++) if (b->etype.val[i] == adtkt.key.keytype) -- 2.25.1 From f083a63e7bedc67e5cae75e66c7c63fa461bee1c Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 15:51:58 +1300 Subject: [PATCH 632/645] CVE-2020-25719 heimdal:kdc: Check name in request against name in user-to-user TGT BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 3 -- source4/heimdal/kdc/krb5tgs.c | 56 +++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 852a02d6d18..f1b3cfa6b56 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -276,8 +276,5 @@ ^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_tgt_cname_host -^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_rodc_not_revealed diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index c0934b0af2f..f402613096e 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1302,9 +1302,12 @@ tgs_build_reply(krb5_context context, krb5_error_code ret; krb5_principal cp = NULL, sp = NULL, tp = NULL, dp = NULL; krb5_principal krbtgt_principal = NULL; + krb5_principal user2user_princ = NULL; char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL; + char *user2user_name = NULL; hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL; HDB *clientdb, *s4u2self_impersonated_clientdb; + HDB *serverdb = NULL; krb5_realm ref_realm = NULL; EncTicketPart *tgt = &ticket->ticket; const char *tgt_realm = /* Realm of TGT issuer */ @@ -1370,7 +1373,7 @@ tgs_build_reply(krb5_context context, server_lookup: ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags, - NULL, NULL, &server); + NULL, &serverdb, &server); if(ret == HDB_ERR_NOT_FOUND_HERE) { kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp); @@ -1511,6 +1514,7 @@ server_lookup: krb5uint32 second_kvno = 0; krb5uint32 *kvno_ptr = NULL; size_t i; + hdb_entry_ex *user2user_client = NULL; if(b->additional_tickets == NULL || b->additional_tickets->len == 0){ @@ -1559,6 +1563,53 @@ server_lookup: if (ret) goto out; + /* Fetch the name from the TGT. */ + ret = _krb5_principalname2krb5_principal(context, &user2user_princ, + adtkt.cname, adtkt.crealm); + if (ret) { + goto out; + } + + ret = krb5_unparse_name(context, user2user_princ, &user2user_name); + if (ret) { + goto out; + } + + /* Look up the name given in the TGT in the database. */ + ret = db_fetch_client(context, config, flags, user2user_princ, user2user_name, + krb5_principal_get_realm(context, krbtgt_out->entry.principal), + NULL, &user2user_client); + if (ret) { + goto out; + } + + if (user2user_client != NULL) { + /* + * If the account is present in the database, check the account + * flags. + */ + ret = kdc_check_flags(context, config, + user2user_client, user2user_name, + NULL, NULL, + FALSE); + if (ret) { + _kdc_free_ent(context, user2user_client); + goto out; + } + + /* + * Also check that the account is the same one specified in the + * request. + */ + ret = check_s4u2self(context, config, serverdb, server, user2user_client, user2user_princ); + if (ret) { + _kdc_free_ent(context, user2user_client); + goto out; + } + } + + _kdc_free_ent(context, user2user_client); + ekey = &adtkt.key; for(i = 0; i < b->etype.len; i++) if (b->etype.val[i] == adtkt.key.keytype) @@ -2045,6 +2096,7 @@ server_lookup: reply); out: + free(user2user_name); if (tpn != cpn) free(tpn); free(spn); @@ -2062,6 +2114,8 @@ out: if(s4u2self_impersonated_client) _kdc_free_ent(context, s4u2self_impersonated_client); + if (user2user_princ) + krb5_free_principal(context, user2user_princ); if (tp && tp != cp) krb5_free_principal(context, tp); if (cp) -- 2.25.1 From 01fd313ccb77d1b91734a05d3d5b0dacab337c20 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 27 Oct 2021 15:52:06 +1300 Subject: [PATCH 633/645] CVE-2020-25719 heimdal:kdc: Verify PAC in TGT provided for user-to-user authentication BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 11 ----------- source4/heimdal/kdc/krb5tgs.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index f1b3cfa6b56..4bde0f33977 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -264,17 +264,6 @@ ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed ^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_rodc_not_revealed -^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_allowed_denied -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_partial_secrets -^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_allowed ^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_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_validate_authdata_no_pac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index f402613096e..2305be5af14 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1306,6 +1306,7 @@ tgs_build_reply(krb5_context context, char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL; char *user2user_name = NULL; hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL; + hdb_entry_ex *user2user_krbtgt = NULL; HDB *clientdb, *s4u2self_impersonated_clientdb; HDB *serverdb = NULL; krb5_realm ref_realm = NULL; @@ -1316,6 +1317,7 @@ tgs_build_reply(krb5_context context, krb5_keyblock sessionkey; krb5_kvno kvno; krb5_pac mspac = NULL; + krb5_pac user2user_pac = NULL; uint16_t rodc_id; krb5_boolean add_ticket_sig = FALSE; hdb_entry_ex *krbtgt_out = NULL; @@ -1508,13 +1510,13 @@ server_lookup: if(b->kdc_options.enc_tkt_in_skey) { Ticket *t; - hdb_entry_ex *uu; krb5_principal p; Key *uukey; krb5uint32 second_kvno = 0; krb5uint32 *kvno_ptr = NULL; size_t i; hdb_entry_ex *user2user_client = NULL; + krb5_boolean user2user_kdc_issued = FALSE; if(b->additional_tickets == NULL || b->additional_tickets->len == 0){ @@ -1540,22 +1542,20 @@ server_lookup: } ret = _kdc_db_fetch(context, config, p, HDB_F_GET_KRBTGT, kvno_ptr, - NULL, &uu); + NULL, &user2user_krbtgt); krb5_free_principal(context, p); if(ret){ if (ret == HDB_ERR_NOENTRY) ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } - ret = hdb_enctype2key(context, &uu->entry, + ret = hdb_enctype2key(context, &user2user_krbtgt->entry, t->enc_part.etype, &uukey); if(ret){ - _kdc_free_ent(context, uu); ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ goto out; } ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); - _kdc_free_ent(context, uu); if(ret) goto out; @@ -1608,7 +1608,27 @@ server_lookup: } } + /* Verify the PAC of the TGT. */ + ret = check_PAC(context, config, user2user_princ, NULL, + user2user_client, user2user_krbtgt, user2user_krbtgt, user2user_krbtgt, + &uukey->key, &tkey_check->key, &adtkt, &user2user_kdc_issued, &user2user_pac); _kdc_free_ent(context, user2user_client); + if (ret) { + const char *msg = krb5_get_error_message(context, ret); + kdc_log(context, config, 0, + "Verify PAC failed for %s (%s) from %s with %s", + spn, user2user_name, from, msg); + krb5_free_error_message(context, msg); + goto out; + } + + if (user2user_pac == NULL || !user2user_kdc_issued) { + ret = KRB5KDC_ERR_BADOPTION; + kdc_log(context, config, 0, + "Ticket not signed with PAC; user-to-user failed (%s).", + mspac ? "Ticket unsigned" : "No PAC"); + goto out; + } ekey = &adtkt.key; for(i = 0; i < b->etype.len; i++) @@ -2113,6 +2133,8 @@ out: _kdc_free_ent(context, client); if(s4u2self_impersonated_client) _kdc_free_ent(context, s4u2self_impersonated_client); + if (user2user_krbtgt) + _kdc_free_ent(context, user2user_krbtgt); if (user2user_princ) krb5_free_principal(context, user2user_princ); @@ -2131,6 +2153,7 @@ out: free_EncTicketPart(&adtkt); krb5_pac_free(context, mspac); + krb5_pac_free(context, user2user_pac); return ret; } -- 2.25.1 From e9f60b35d3b0462bed77efa93466163156dae825 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 4 Oct 2021 15:18:34 +1300 Subject: [PATCH 634/645] CVE-2020-25722 kdc: Do not honour a request for a 3-part SPN (ending in our domain/realm) unless a DC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14776 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- selftest/knownfail_heimdal_kdc | 6 ------ selftest/knownfail_mit_kdc | 6 ------ source4/kdc/db-glue.c | 23 +++++++++++++++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 4bde0f33977..8bf36faf8ed 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -250,12 +250,6 @@ ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_b # -# SPN tests -# -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer -# # KDC TGT tests # ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index b5b13110353..b4e819c83df 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -381,12 +381,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^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 # -# SPN tests -# -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_instance_spn_computer -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_domain_spn_computer -^samba.tests.krb5.spn_tests.samba.tests.krb5.spn_tests.SpnTests.test_spn_3_part_our_realm_spn_computer -# # Alias tests # ^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index d55bf1663d4..0f19e8d1c93 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -968,6 +968,29 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, entry_ex->entry.flags.server = 0; } } + + /* + * We restrict a 3-part SPN ending in my domain/realm to full + * domain controllers. + * + * This avoids any cases where (eg) a demoted DC still has + * these more restricted SPNs. + */ + if (krb5_princ_size(context, principal) > 2) { + char *third_part + = smb_krb5_principal_get_comp_string(mem_ctx, + context, + principal, + 2); + bool is_our_realm = + lpcfg_is_my_domain_or_realm(lp_ctx, + third_part); + bool is_dc = userAccountControl & + (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT); + if (is_our_realm && !is_dc) { + entry_ex->entry.flags.server = 0; + } + } /* * To give the correct type of error to the client, we must * not just return the entry without .server set, we must -- 2.25.1 From 1dbadfec60cae64acf5b330ff0f199af72329003 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 14:35:52 +1300 Subject: [PATCH 635/645] CVE-2020-25719 heimdal:kdc: Require PAC to be present BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 4 ---- source4/heimdal/kdc/krb5tgs.c | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 8bf36faf8ed..933b6c2af04 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -252,12 +252,8 @@ # # KDC TGT tests # -^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_rodc_not_revealed -^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_rodc_not_revealed -^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_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_authdata_no_pac ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 2305be5af14..42933cc16de 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -74,9 +74,12 @@ check_PAC(krb5_context context, *ppac = NULL; ret = _krb5_kdc_pac_ticket_parse(context, tkt, &signedticket, &pac); - if (ret || pac == NULL) + if (ret) return ret; + if (pac == NULL) + return KRB5KDC_ERR_BADOPTION; + /* Verify the server signature. */ ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal, server_check_key, NULL); -- 2.25.1 From 3e76955263720c3d521e5b6de82cc087ceb3f00b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 15:43:28 +1300 Subject: [PATCH 636/645] CVE-2020-25718 tests/krb5: Only fetch RODC account credentials when necessary BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_base_test.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 4b4f1486f60..f64bd0b206e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -710,9 +710,6 @@ class KDCBaseTest(RawKerberosTest): self.assertFalse(not_delegated) samdb = self.get_samdb() - rodc_samdb = self.get_rodc_samdb() - - rodc_dn = self.get_server_dn(rodc_samdb) user_name = self.get_new_username() if name_prefix is not None: @@ -764,6 +761,9 @@ class KDCBaseTest(RawKerberosTest): # Handle secret replication to the RODC. if allowed_replication or revealed_to_rodc: + rodc_samdb = self.get_rodc_samdb() + rodc_dn = self.get_server_dn(rodc_samdb) + # Allow replicating this account's secrets if requested, or allow # it only temporarily if we're about to replicate them. allowed_cleanup = self.add_to_group( @@ -784,6 +784,9 @@ class KDCBaseTest(RawKerberosTest): revealed=revealed_to_rodc) if denied_replication: + rodc_samdb = self.get_rodc_samdb() + rodc_dn = self.get_server_dn(rodc_samdb) + # Deny replicating this account's secrets to the RODC. self.add_to_group(dn, rodc_dn, 'msDS-NeverRevealGroup') -- 2.25.1 From 608d82404e34282011dd96c3dd7f5daa222fbb61 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 15:07:07 +1300 Subject: [PATCH 637/645] CVE-2020-25719 tests/krb5: Add tests for using a ticket with a renamed account BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/kdc_tgs_tests.py | 17 ++++++++++ python/samba/tests/krb5/test_ccache.py | 41 ++++++++++++++++------ python/samba/tests/krb5/test_ldap.py | 33 ++++++++++++++---- python/samba/tests/krb5/test_rpc.py | 27 ++++++++++++--- python/samba/tests/krb5/test_smb.py | 43 ++++++++++++++++++------ selftest/knownfail_mit_kdc | 1 + 6 files changed, 129 insertions(+), 33 deletions(-) diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py index cfe1ad42d61..abac5a47a56 100755 --- a/python/samba/tests/krb5/kdc_tgs_tests.py +++ b/python/samba/tests/krb5/kdc_tgs_tests.py @@ -1769,6 +1769,23 @@ class KdcTgsTests(KDCBaseTest): pac = self.get_ticket_pac(ticket) self.assertIsNotNone(pac) + def test_tgs_rename(self): + creds = self.get_cached_creds(account_type=self.AccountType.USER, + use_cache=False) + tgt = self.get_tgt(creds) + + # Rename the account. + new_name = self.get_new_username() + + samdb = self.get_samdb() + msg = ldb.Message(creds.get_dn()) + msg['sAMAccountName'] = ldb.MessageElement(new_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + + self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) + def _get_tgt(self, client_creds, renewable=False, diff --git a/python/samba/tests/krb5/test_ccache.py b/python/samba/tests/krb5/test_ccache.py index d21ec84796e..75038ea5cc1 100755 --- a/python/samba/tests/krb5/test_ccache.py +++ b/python/samba/tests/krb5/test_ccache.py @@ -20,6 +20,8 @@ import sys import os +import ldb + from ldb import SCOPE_SUBTREE from samba import NTSTATUSError, gensec from samba.auth import AuthContext @@ -42,13 +44,16 @@ class CcacheTests(KDCBaseTest): """ def test_ccache(self): - self._run_ccache_test("ccacheusr") + self._run_ccache_test() + + def test_ccache_rename(self): + self._run_ccache_test(rename=True) def test_ccache_no_pac(self): - self._run_ccache_test("ccacheusr_nopac", include_pac=False, + self._run_ccache_test(include_pac=False, expect_anon=True, allow_error=True) - def _run_ccache_test(self, user_name, include_pac=True, + def _run_ccache_test(self, rename=False, include_pac=True, expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the @@ -60,7 +65,10 @@ class CcacheTests(KDCBaseTest): samdb = self.get_samdb() # Create the user account. - (user_credentials, _) = self.create_account(samdb, user_name) + user_credentials = self.get_cached_creds( + account_type=self.AccountType.USER, + use_cache=False) + user_name = user_credentials.get_username() # Create the machine account. (mach_credentials, _) = self.create_account( @@ -80,6 +88,24 @@ class CcacheTests(KDCBaseTest): # Remove the cached credentials file. self.addCleanup(os.remove, cachefile.name) + # Retrieve the user account's SID. + ldb_res = samdb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) + self.assertEqual(1, len(ldb_res)) + sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + + if rename: + # Rename the account. + + new_name = self.get_new_username() + + msg = ldb.Message(user_credentials.get_dn()) + msg['sAMAccountName'] = ldb.MessageElement(new_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + # Authenticate in-process to the machine account using the user's # cached credentials. @@ -121,13 +147,6 @@ class CcacheTests(KDCBaseTest): # Ensure that the first SID contained within the obtained security # token is the SID of the user we created. - # Retrieve the user account's SID. - ldb_res = samdb.search(scope=SCOPE_SUBTREE, - expression="(sAMAccountName=%s)" % user_name, - attrs=["objectSid"]) - self.assertEqual(1, len(ldb_res)) - sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) - # Retrieve the SIDs from the security token. try: session = gensec_server.session_info() diff --git a/python/samba/tests/krb5/test_ldap.py b/python/samba/tests/krb5/test_ldap.py index 0205bdf6fb7..c1375730e6f 100755 --- a/python/samba/tests/krb5/test_ldap.py +++ b/python/samba/tests/krb5/test_ldap.py @@ -20,6 +20,8 @@ import sys import os +import ldb + from ldb import LdbError, ERR_OPERATIONS_ERROR, SCOPE_BASE, SCOPE_SUBTREE from samba.dcerpc import security from samba.ndr import ndr_unpack @@ -41,13 +43,16 @@ class LdapTests(KDCBaseTest): """ def test_ldap(self): - self._run_ldap_test("ldapusr") + self._run_ldap_test() + + def test_ldap_rename(self): + self._run_ldap_test(rename=True) def test_ldap_no_pac(self): - self._run_ldap_test("ldapusr_nopac", include_pac=False, + self._run_ldap_test(include_pac=False, expect_anon=True, allow_error=True) - def _run_ldap_test(self, user_name, include_pac=True, + def _run_ldap_test(self, rename=False, include_pac=True, expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the @@ -59,7 +64,10 @@ class LdapTests(KDCBaseTest): service = "ldap" # Create the user account. - (user_credentials, _) = self.create_account(samdb, user_name) + user_credentials = self.get_cached_creds( + account_type=self.AccountType.USER, + use_cache=False) + user_name = user_credentials.get_username() mach_credentials = self.get_dc_creds() @@ -75,9 +83,6 @@ class LdapTests(KDCBaseTest): # Remove the cached credentials file. self.addCleanup(os.remove, cachefile.name) - # Authenticate in-process to the machine account using the user's - # cached credentials. - # Retrieve the user account's SID. ldb_res = samdb.search(scope=SCOPE_SUBTREE, expression="(sAMAccountName=%s)" % user_name, @@ -85,6 +90,20 @@ class LdapTests(KDCBaseTest): self.assertEqual(1, len(ldb_res)) sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + if rename: + # Rename the account. + + new_name = self.get_new_username() + + msg = ldb.Message(user_credentials.get_dn()) + msg['sAMAccountName'] = ldb.MessageElement(new_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + + # Authenticate in-process to the machine account using the user's + # cached credentials. + # Connect to the machine account and retrieve the user SID. try: ldb_as_user = SamDB(url="ldap://%s" % mach_name, diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py index 0f2170a8ded..03c125f518a 100755 --- a/python/samba/tests/krb5/test_rpc.py +++ b/python/samba/tests/krb5/test_rpc.py @@ -20,6 +20,8 @@ import sys import os +import ldb + from samba import NTSTATUSError, credentials from samba.dcerpc import lsa from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN @@ -39,13 +41,16 @@ class RpcTests(KDCBaseTest): """ def test_rpc(self): - self._run_rpc_test("rpcusr") + self._run_rpc_test() + + def test_rpc_rename(self): + self._run_rpc_test(rename=True) def test_rpc_no_pac(self): - self._run_rpc_test("rpcusr_nopac", include_pac=False, + self._run_rpc_test(include_pac=False, expect_anon=True, allow_error=True) - def _run_rpc_test(self, user_name, include_pac=True, + def _run_rpc_test(self, rename=False, include_pac=True, expect_anon=False, allow_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the @@ -57,7 +62,10 @@ class RpcTests(KDCBaseTest): service = "cifs" # Create the user account. - (user_credentials, _) = self.create_account(samdb, user_name) + user_credentials = self.get_cached_creds( + account_type=self.AccountType.USER, + use_cache=False) + user_name = user_credentials.get_username() mach_credentials = self.get_dc_creds() @@ -73,6 +81,17 @@ class RpcTests(KDCBaseTest): # Remove the cached credentials file. self.addCleanup(os.remove, cachefile.name) + if rename: + # Rename the account. + + new_name = self.get_new_username() + + msg = ldb.Message(user_credentials.get_dn()) + msg['sAMAccountName'] = ldb.MessageElement(new_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + # Authenticate in-process to the machine account using the user's # cached credentials. diff --git a/python/samba/tests/krb5/test_smb.py b/python/samba/tests/krb5/test_smb.py index 7408e5dbece..47e9e48c971 100755 --- a/python/samba/tests/krb5/test_smb.py +++ b/python/samba/tests/krb5/test_smb.py @@ -20,6 +20,8 @@ import sys import os +import ldb + from ldb import SCOPE_SUBTREE from samba import NTSTATUSError from samba.dcerpc import security @@ -43,13 +45,16 @@ class SmbTests(KDCBaseTest): """ def test_smb(self): - self._run_smb_test("smbusr") + self._run_smb_test() + + def test_smb_rename(self): + self._run_smb_test(rename=True) def test_smb_no_pac(self): - self._run_smb_test("smbusr_nopac", include_pac=False, + self._run_smb_test(include_pac=False, expect_error=True) - def _run_smb_test(self, user_name, include_pac=True, + def _run_smb_test(self, rename=False, include_pac=True, expect_error=False): # Create a user account and a machine account, along with a Kerberos # credentials cache file where the service ticket authenticating the @@ -62,7 +67,12 @@ class SmbTests(KDCBaseTest): share = "tmp" # Create the user account. - (user_credentials, _) = self.create_account(samdb, user_name) + user_credentials = self.get_cached_creds( + account_type=self.AccountType.USER, + use_cache=False) + user_name = user_credentials.get_username() + + mach_credentials = self.get_dc_creds() mach_credentials = self.get_dc_creds() @@ -78,6 +88,24 @@ class SmbTests(KDCBaseTest): # Remove the cached credentials file. self.addCleanup(os.remove, cachefile.name) + # Retrieve the user account's SID. + ldb_res = samdb.search(scope=SCOPE_SUBTREE, + expression="(sAMAccountName=%s)" % user_name, + attrs=["objectSid"]) + self.assertEqual(1, len(ldb_res)) + sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) + + if rename: + # Rename the account. + + new_name = self.get_new_username() + + msg = ldb.Message(user_credentials.get_dn()) + msg['sAMAccountName'] = ldb.MessageElement(new_name, + ldb.FLAG_MOD_REPLACE, + 'sAMAccountName') + samdb.modify(msg) + # Set the Kerberos 5 credentials cache environment variable. This is # required because the codepath that gets run (gse_krb5) looks for it # in here and not in the credentials object. @@ -88,13 +116,6 @@ class SmbTests(KDCBaseTest): # Authenticate in-process to the machine account using the user's # cached credentials. - # Retrieve the user account's SID. - ldb_res = samdb.search(scope=SCOPE_SUBTREE, - expression="(sAMAccountName=%s)" % user_name, - attrs=["objectSid"]) - self.assertEqual(1, len(ldb_res)) - sid = ndr_unpack(security.dom_sid, ldb_res[0]["objectSid"][0]) - # Connect to a share and retrieve the user SID. s3_lp = s3param.get_context() s3_lp.load(self.get_lp().configfile) diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index b4e819c83df..8cd36fe2d96 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -417,6 +417,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_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_rename ^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 -- 2.25.1 From 00b8d39c50e71796d7137cac9a87dc09d5e3fd5f Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 29 Oct 2021 15:53:33 +1300 Subject: [PATCH 638/645] CVE-2020-25718 heimdal:kdc: Add comment about tests for tickets of users not revealed to an RODC BUG: https://bugzilla.samba.org/show_bug.cgi?id=14886 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail_heimdal_kdc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 933b6c2af04..7eba899966e 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -250,7 +250,9 @@ ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_b # -# KDC TGT tests +# https://bugzilla.samba.org/show_bug.cgi?id=14886: Tests for accounts not revealed to the RODC +# +# The KDC should not accept tickets from an RODC for accounts not in the msDS-RevealedUsers list. # ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_not_revealed ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_not_revealed -- 2.25.1 From bea9c1ae5cb0f7c97d2e3d85adf27798d5663c26 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Nov 2021 14:52:22 +1300 Subject: [PATCH 639/645] Revert "CVE-2020-25719 heimdal:kdc: Require authdata to be present" This reverts an earlier commit that was incorrect. It is not Samba practice to include a revert, but at this point in the patch preperation the ripple though the knownfail files is more trouble than can be justified. It is not correct to refuse to parse all tickets with no authorization data, only for the KDC to require that a PAC is found, which is done in "heimdal:kdc: Require PAC to be present" Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/heimdal/lib/krb5/pac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 749d0fdb4eb..05bcc523080 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -1369,7 +1369,7 @@ _krb5_kdc_pac_ticket_parse(krb5_context context, *ppac = NULL; if (ad == NULL || ad->len == 0) - return KRB5KDC_ERR_BADOPTION; + return 0; for (i = 0; i < ad->len; i++) { AuthorizationData child; -- 2.25.1 From 526541fecdbc48be8ae73f979d5cd748160e58d2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Nov 2021 14:02:14 +1300 Subject: [PATCH 640/645] CVE-2020-25719 selftest: Always expect a PAC in TGS replies with Heimdal This is tested in other places already, but this ensures a global check that a TGS-REP has a PAC, regardless. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- source4/selftest/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 0c059d23f69..e44ea924a54 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -744,7 +744,7 @@ planoldpythontestsuite("ad_dc:local", "samba.tests.dckeytab", extra_args=['-U"$U have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) -expect_pac = 0 +expect_pac = int('SAMBA4_USES_HEIMDAL' in config_hash) planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", environ={'SERVICE_USERNAME':'$SERVER', -- 2.25.1 From 77b82da08bfc8cc683ee6d676f626803eae1d33d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 2 Nov 2021 14:11:27 +0100 Subject: [PATCH 641/645] CVE-2020-25722 pytests: Give computer accounts unique (and valid) sAMAccountNames and SPNs BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Stefan Metzmacher --- python/samba/tests/samba_tool/computer.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/python/samba/tests/samba_tool/computer.py b/python/samba/tests/samba_tool/computer.py index 3110a3b04e8..df109e1b1c9 100644 --- a/python/samba/tests/samba_tool/computer.py +++ b/python/samba/tests/samba_tool/computer.py @@ -39,23 +39,29 @@ class ComputerCmdTestCase(SambaToolCmdTest): # ips used to test --ip-address option self.ipv4 = '10.10.10.10' self.ipv6 = '2001:0db8:0a0b:12f0:0000:0000:0000:0001' + computer_basename = self.randomName().lower() data = [ { - 'name': 'testcomputer1', + 'name': computer_basename + 'cmp1', 'ip_address_list': [self.ipv4] }, { - 'name': 'testcomputer2', + 'name': computer_basename + 'cmp2', 'ip_address_list': [self.ipv6], - 'service_principal_name_list': ['SPN0'] + 'service_principal_name_list': [ + 'host/' + computer_basename + 'SPN20', + ], }, { - 'name': 'testcomputer3$', + 'name': computer_basename + 'cmp3$', 'ip_address_list': [self.ipv4, self.ipv6], - 'service_principal_name_list': ['SPN0', 'SPN1'] + 'service_principal_name_list': [ + 'host/' + computer_basename + 'SPN30', + 'host/' + computer_basename + 'SPN31', + ], }, { - 'name': 'testcomputer4$', + 'name': computer_basename + 'cmp4$', }, ] self.computers = [self._randomComputer(base=item) for item in data] -- 2.25.1 From b272ed57659e62f11188ea57facc59d81023c179 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 2 Nov 2021 21:21:17 +1300 Subject: [PATCH 642/645] CVE-2020-25722 selftest: Add test for duplicate servicePrincipalNames on an add operation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 Signed-off-by: Joseph Sutton --- selftest/knownfail.d/spn_uniqueness | 2 ++ source4/dsdb/tests/python/sam.py | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 selftest/knownfail.d/spn_uniqueness diff --git a/selftest/knownfail.d/spn_uniqueness b/selftest/knownfail.d/spn_uniqueness new file mode 100644 index 00000000000..3f6c2f03191 --- /dev/null +++ b/selftest/knownfail.d/spn_uniqueness @@ -0,0 +1,2 @@ +^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_service_principal_name_uniqueness\(ad_dc_default\) +^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_service_principal_name_uniqueness\(fl2008r2dc\) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index faa882e1287..44be10fce2c 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -90,6 +90,7 @@ class SamTests(samba.tests.TestCase): delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + delete_force(self.ldb, "cn=ldaptestcomputer2,cn=computers," + self.base_dn) delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn) @@ -3501,6 +3502,26 @@ class SamTests(samba.tests.TestCase): delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn) + def test_service_principal_name_uniqueness(self): + """Test the servicePrincipalName uniqueness behaviour""" + print("Testing servicePrincipalName uniqueness behaviour") + + ldb.add({ + "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn, + "objectclass": "computer", + "servicePrincipalName": "HOST/testname.testdom"}) + + try: + ldb.add({ + "dn": "cn=ldaptestcomputer2,cn=computers," + self.base_dn, + "objectclass": "computer", + "servicePrincipalName": "HOST/testname.testdom"}) + except LdbError as e: + num, _ = e.args + self.assertEqual(num, ERR_CONSTRAINT_VIOLATION) + else: + self.fail() + def test_sam_description_attribute(self): """Test SAM description attribute""" print("Test SAM description attribute") -- 2.25.1 From b2b235c16be2a0ed7a5038f3ee9da23d483d5df2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 2 Nov 2021 21:00:00 +1300 Subject: [PATCH 643/645] CVE-2020-25722 selftest: Ensure check for duplicate servicePrincipalNames is not bypassed for an add operation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14564 If one of the objectClass checks passed, samldb_add() could return through one of the samldb_fill_*() functions and skip the servicePrincipalName uniqueness checking. Signed-off-by: Joseph Sutton --- selftest/knownfail.d/spn_uniqueness | 2 -- source4/dsdb/samdb/ldb_modules/samldb.c | 25 ++++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) delete mode 100644 selftest/knownfail.d/spn_uniqueness diff --git a/selftest/knownfail.d/spn_uniqueness b/selftest/knownfail.d/spn_uniqueness deleted file mode 100644 index 3f6c2f03191..00000000000 --- a/selftest/knownfail.d/spn_uniqueness +++ /dev/null @@ -1,2 +0,0 @@ -^samba4.sam.python\(ad_dc_default\).__main__.SamTests.test_service_principal_name_uniqueness\(ad_dc_default\) -^samba4.sam.python\(fl2008r2dc\).__main__.SamTests.test_service_principal_name_uniqueness\(fl2008r2dc\) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 810365ca030..f0227411ccd 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -4838,6 +4838,18 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) } } + el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); + if ((el != NULL)) { + /* + * We need to check whether the SPN collides with an existing + * one (anywhere) including via aliases. + */ + ret = samldb_spn_uniqueness_check(ac, el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + if (samdb_find_attribute(ldb, ac->msg, "objectclass", "user") != NULL) { ac->type = SAMLDB_TYPE_USER; @@ -4936,19 +4948,6 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return samldb_fill_object(ac); } - - el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); - if ((el != NULL)) { - /* - * We need to check whether the SPN collides with an existing - * one (anywhere) including via aliases. - */ - ret = samldb_spn_uniqueness_check(ac, el); - if (ret != LDB_SUCCESS) { - return ret; - } - } - if (samdb_find_attribute(ldb, ac->msg, "objectclass", "subnet") != NULL) { ret = samldb_verify_subnet(ac, ac->msg->dn); -- 2.25.1 From 7549d6db2ac944fa7c7cd4d93aec3cbcf671c296 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Nov 2021 21:10:32 +1300 Subject: [PATCH 644/645] skip ad_member_no_nss_wb as we do not test the fileserver Signed-off-by: Andrew Bartlett --- .gitlab-ci.yml | 6 ------ selftest/skip | 7 +++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7c7597e31b6..d387608cf99 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -196,9 +196,6 @@ samba-simpleserver: samba-fileserver: extends: .private_template -samba-ktest-heimdal: - extends: .private_template - samba-ad-dc-1: extends: .private_template @@ -223,8 +220,6 @@ pages: - samba - samba-mitkrb5 - samba-none-env - - samba-nopython - - samba-nopython-py2 - samba-xc - samba-admem - samba-ad-dc-2 @@ -243,7 +238,6 @@ pages: - samba-ad-dc-backup - samba-simpleserver - samba-fileserver - - samba-ktest-heimdal - samba-ad-dc-1 - samba-nt4 - samba-schemaupgrade diff --git a/selftest/skip b/selftest/skip index 549ba202021..146e21aa040 100644 --- a/selftest/skip +++ b/selftest/skip @@ -157,3 +157,10 @@ bench # don't run benchmarks in our selftest ^samba4.blackbox.ktpass # this test isn't portable ... ^samba4.rpc.unixinfo # This contains a server-side getpwuid call which hangs the server when nss_winbindd is in use ^samba.tests.dcerpc.unix # This contains a server-side getpwuid call which hangs the server when nss_winbindd is in use +# +# skip ktest for Samba 4.12 as fails and not needed to prove Samba AD DC behaviour +# +# REMOVE THIS if using the Samba fileserver and fix +# +ktest +ad_member_no_nss_wb \ No newline at end of file -- 2.25.1 From c5689fcf3b819e187e322009a2e8780c1dc0ee20 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Nov 2021 23:57:14 +1300 Subject: [PATCH 645/645] do not use ad_dc_smb1, this is not supported but smb1 is supported everywhere Signed-off-by: Andrew Bartlett --- source4/selftest/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index e44ea924a54..09c1ca71e23 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -800,7 +800,7 @@ for env in ['ad_dc_default', 'ad_member']: 'TKT_SIG_SUPPORT': tkt_sig_support, 'EXPECT_PAC': expect_pac }) -planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", +planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_smb", environ={ 'ADMIN_USERNAME': '$USERNAME', 'ADMIN_PASSWORD': '$PASSWORD', -- 2.25.1