From 70c0a862a50918cedf7a81fa8a74ffe25825e7e0 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 f27bc8cd2c242ce5dd44ffe2d442d76d89bdbd52 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 f88848cfdb89950104d65b3fe0be57dbeb13bd45 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 c65cae063769f34632bd2e59442ab5db235b563e 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 a01c0cb17774cf8bccb8e6654320c9be9e943517 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 bb3ca8649b325cb2236ccb7a39c3127e79fc4e89 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 ede75201bf9edb264ca199cb07398c1b8b731b3b 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 6fd0538f72cef8f3f196359184cef80f4f1a368b 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 f393c55c4ea5e5bf773693b3d14b99c6f9921c28 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 fbd5f9cf5a35821aa1378416a2dc48322032d75c 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 6bb67e49b3d6190a0795d2a1c56f76205aee06c5 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 53566be8e3b69486e200695c03a50ba41ff5c962 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 c08c1a25cae7d2c84bb3c506f26b8fe3fd1f196b 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 25473c5efd6e52e48b4e8658194db4b55805a7cb 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 a42d96c7183b360c296eb87251dc39318d87da16 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 4f66a58e9136be3a8d7440b67a648c4e296d23d0 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 982df08ebe457ad736829098e2bf133e1d075b48 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 266f0145df9d3368212117ae2ca570cb3d41e334 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 3177a6d07bd528b91542a0fc3320043450a161a8 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 357f10f848c4477f39e7d7a167986c84199a5dbb 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 e7485c4cb86bf9c80ecf619a4002110927afb3e1 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 5d8d51828e01e09d4c761b23e77561da54193ac9 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 cc4163316f4cf99ac1244bb0a3a558684d4d7e33 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 023e70000609f2435efb1e211121cb377f069732 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 7b3c0a2d93a0039661f255a34d1fb18f381ee29b 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 92e98ff4fedd830e84fc5b30f868c2366cf09298 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 62776b51d8fb3eb48de4b3f91ff090f48b91ef3d 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 851e867c8e6c1558e7c6d5e98887ed549a17d300 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 6c4f0ce7457fcd23e4cd88fc9e50acf2bf2231a1 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 1fe95c192921022e50f4d3de418ae13fc0be458b 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 bcd99520ade162bdf715d1131fcc0dab610ccea5 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 e938f1d1e7e23ef1fafbb822d8dabfffeb4b5081 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 dec3290a72ed6a2a6c343626317cae56ee8936b2 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 17ed1e23ad5cc5a96c00a17f062f72c22deb33c7 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 ae8095ce1f0cf474c65c594715d3528557a8fc5d 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 0d7d996371cae152e006d7e30d2d20b69284f685 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 325df9238657651367f4da6e2f13bed84c6db951 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 a01a44304b99b88d441ea8d1c093348f5bee992d 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 9a781e3b87347d2e4aa2e701c68b049d32d74b83 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 32e846c99b46adce1c145ba55054ae050ab55d83 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 ad315489237b7a6ff1d6497505331cfb493d92b4 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 d2c9b12dab67d19be9a26c328396044aeaa2ce94 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 0c846c863960cb2a5894e9f723214c4264c92c6e 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 f0273a3ca28b2a4eca116c404bf4576d981db41a 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 cb1eed75b7bd8363b269f50a0650d7d7111661e1 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 f4d0ee9f0194aee5ce47b4dcf0c52cd6befaa074 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 4879598ce785630d039b7aec52e8b4d1466e6720 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 1c3a2e648e2a834684502b3087a86d57457e1fda 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 29957d32a96b5f2ff179a677a5532de767929c6d 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 83371fc2257a0ae11e805decb0cf78b549b144c0 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 258e219a2115a67ddb3828b53402ac0996055b68 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 bfe38ee8c7174693927fdffd43ccc8e320ff4562 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 a955c42f352c6a05696890ed4ff828c6ac503a3a 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 fb333794d83aa0c330e17cf8cb067b175fec79ec 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 8eee93743d3a1d55d21c5862926ccf031a9dc80e 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 f58c6fafddfefc47c7cc5e852b42f9648ea2d5dc 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 12c7349333a229b399eb29a79cd874164670db63 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 af91c266a6e0024a111a5fcf64c942241d273ce0 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 82c6f53ed53d3869758c84733ac92558e785d2a7 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 2f5c5ca21ee216520cb18a0d019fdaf4b5317c12 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 2d12c23f313859427228886502b0fc1c61ebecef 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 256cfa67d9d57da2a89990894344092d1200abba 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 f8db82189635490540f19c1969b80fc607ec9e19 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 cd82bdbdd16cfc2265ed969719dbe8508bcd12db 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 49fa4407eb5dc96304f341cdf99d755f3a246272 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 af8bc90de3eb58292900035ecddd737a8f498aa1 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 9f723a4b74eff1f80da1d547ba524553630c3833 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 1e5211c45b77108ce2c571a90c4b7d357011f30d 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 851c58ac5b9749a8147cf505742a1b7759a6a5f3 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 0c2ca638dbdf40ca381d577df190275a9eaffc82 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 5165b3238d7786fdca0ee577cb477fb5acd9dbde 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 b362c466446be56c4ef0dcd665e5f5eebfc7c72e 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 830abaa330171717e384dde50b649de0a8bfdb3e 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 d596103d9f4da94f975a7c3e70997c237d6eb0f2 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 ce92cc134725c7b07e8af5abea2fad6614f3399a 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 cf40e9af2d8dd4b6883b8e68098109a9f1261e7b 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 46b83bc8cfeb7ba431789c5deadf54b451b2485d 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 0898cbd2a78bf1d42ef965820ce8f26440963e77 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 035659f19b18428582ce220fd285f219684a4951 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 2c38fab1016d0c8746ac6c55bba0d656f8de861b 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 0e813a3f72a4c5886a90b41367c5cae0ab443a7c 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 911f64521c9d9fbd9d33941a54add7608c6b3927 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 e40839de38454c80084edeb9e2ef147226ac242a 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 2d64489462076530076997833d631f4219b034ec 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 03fefce3f8642021b2d2d70e20b8ac4cb70d3b34 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) --- python/samba/tests/krb5/pyasn1_regen.sh | 41 +++++++++++++++++++ .../samba/tests/krb5/rfc4120_pyasn1_regen.sh | 41 ------------------- 2 files changed, 41 insertions(+), 41 deletions(-) create mode 100755 python/samba/tests/krb5/pyasn1_regen.sh delete mode 100755 python/samba/tests/krb5/rfc4120_pyasn1_regen.sh diff --git a/python/samba/tests/krb5/pyasn1_regen.sh b/python/samba/tests/krb5/pyasn1_regen.sh new file mode 100755 index 00000000000..2e3995688f2 --- /dev/null +++ b/python/samba/tests/krb5/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/krb5/rfc4120_pyasn1_regen.sh b/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh deleted file mode 100755 index 2e3995688f2..00000000000 --- a/python/samba/tests/krb5/rfc4120_pyasn1_regen.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/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}" -- 2.25.1 From 137a080d1728f08200aec0ccb8fda0e424099539 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 3df3c83c86df1ca2b9fcfe9496fafbe517524413 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 1c43aedecfcdc6f5f30e98c3c4bad71a302dd49f 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 907191b08b903fe11f94efdb17388cac15d09b0a 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 8a9e6d9ba3e9200c70e0a7e15ad0b01a0f57a878 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 59ce86e1aeba60184f32d52ecb9adf46afbfa2ab 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 0e858cffdc8acd6c0ee9a7cc5f5c23b82a9d3ebc 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 727b6a5288a29830ac44a648513c852387eb04e0 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 c10b855a605e1cfb3201e40efc654bd0f952d78f 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 144a8a979b428360b346197bf3738aa7a6b415f7 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 dad5350058ba3182e6ca1d43070821f62b534cad 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 8e9a054f671b939fbfb1f4d129188e61236e4890 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 79e502532b00e0fc32fd10d3e808d6a20e0e317c 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 773bf6359b39ec21b6d1e144227218577a59b564 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 05dc682dde39407079e1db27ac10ff99f2c94c9f 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 058aeede89a4aed1c673bee23305beda7ee878b0 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 3f4d38d759afd99ddb68c1b183b132421a493870 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 ca225c748d3264fdcdaa4bd2755db0313b916114 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 f605c38879a2a87eca7fc2b2146e7c2cb2b61f31 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 c6aa9eea72eb0faab233421aafb03f3a56d19068 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 3538f3e330b8e580085cbdad44f6f1d7b9696fa2 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 154a722853c21be94c3efe2619d131f4d586ab5e 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 85b01fddfcb3de36f1166ef2d537b07ede8acd90 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 ae17cdd7ba38c3ea31b1cddcebfad5f5f72bf0f8 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 ec1b51460c44b5c16fcd0c9d25035b91f584b363 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 1e6da055d276ca680efe3a41b0c0499dc4b39c63 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 46d1125a75bb8a9179d61d727495f303282e170e 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 fd25d8f45e099956da50607a286401960a6c7440 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 cf066c8f165d4675760bb577740ce3197a9f6365 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 6011799d416e4183bed15b94322ca315706356c0 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 a4c5e05821a8f25cb9bd37bc5cead2712b484a54 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 5be5913d5a1e8ae52623a639ebc3b4a550b0b64a 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 feb47459b35a7e906d105fcfb625da63b672583d 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 cf2073e74f5ace75124c876adf138cdcbb666ce7 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 899485edbb6bbdea3c2f2ade6ccb7b07335c662c 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 079575f32ee54e5b870e6f683a9a59d5e15b56f2 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 760553a8cb2d96c3b4bedf37cfc058019173f812 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 4a62afa830cdb44cfad785f5ebdbaeffb5e8d2fb 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 8bf785c8a504e678799fff03f50fa1187dd9b174 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 be9eed29787e0e8da210a18e113535596bb1b874 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 254c929f1c888a638440f6ef63bf767e7cf43b4c 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 be0bbbdbd6f882a018354e0c73d300e7d6b7e515 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 ad1eb7c18d9165b2594025ca198f48dda3535fc0 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 6ee8f2ca355b2949441052673ea2707e5cae235e 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 9ac720ec2046d47008a23a63af5572762b82f9e9 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 2f4e6ddc0684a235fcac6114defbe8036e35ce1e 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 c65b15b3d0cdb9243cb4c755b94f70c6598939f6 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 325e5eefb0438b834cc5a99235488e015d88aa88 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 20de8beaf663a0d06b4c704cdae65af84aa464db 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 93d2c81dc297b379cb8cde6c1672e1aa5e8f49dc 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 5329e050b861b39983f0ae6454316c4766d1e047 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 48ca4aab1f97a512967f6e996b2a1dbbef460b80 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 591fa7771973b05cf5a70155edf3eb412940fda3 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 6e66af659d967d513f77e963223c3bc561e4c853 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 e6e7aef2b2ee6df61d924793e06062ce7a9c1c67 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 b4aacee0b0b79e8517cd84bfa1bad93f9fce8eb9 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 8c337dab27bc4475cf60edc03320b3ceec154153 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 2866f679990f79a4f0da39bae9f3c7f258c031a8 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 ca7c7dece23b582ab765b8c0537bbf5d042f7bbe 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 42bc9bad4c3d02df0eaf796a044fa03af235dd18 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 c29de38440a0cbea85326eeb9fcbdae7e630d7b6 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 5b2627d98d2ee5fb40e002b15c2eca251e8d911b 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 183f7ff96ec1395b4280cef109b209a80034e41d 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 8afb5494c6b37adbc8209f0a32b0d3c16764697e 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 09357c65c83aebb1c2f208f0c8c8ee8d0a5582ab 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 5ec9128060a67c924903c4065ae0eb43266800b3 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 18b1f20d5b7fb1f19bd9a3206a5647b65aed5868 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 c6ccb11766f6d310702f7dd0642ff5ba829a93dc 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 1c8fd78fd238e0b5183c09b2195a90102419e7d8 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 875d24806f352847c9b6f160fa6c2de2b92bf028 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 705d3f0d589d0bea94ac8a96a04ed5b8769d06a8 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 cc7fea7ebe5f7214f8b4a7a1e957390e134d06be 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 d1c165834eaaa231b905f9f9bfedd8acb075a007 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 8780d369779832358c4879912c24cc607dedcc59 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 da2386c6df54d3a075eef2ae20955f00fdff3fe5 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 a83b85a7f899921284144ec7b60e2ba99238e979 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 8c4ea1c7c9b7e98021e368f040deac1382646d78 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 ffaea177ef94823b8154fb94059ffb8f27c0f4d3 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 2bb2010b3ddbaae2721acac664afce1da01f4eb1 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 c5ae9388c41f7b22dac796dd0fa819ea622a288e 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 18b806829d4de167cf726907cb85f9034398f487 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 46188228f3b4848668e6c96f651d3df6a4f12b05 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 b49a8f0003eaf9f76af1cde3097d5497a3ecc3ff 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 4bfbf3ff5073aa8666adc458c460a48255a50177 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 db740f21937e963a135a4abfa38a732fe4ac69e3 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 350198085d968baf226a422360c4d89a55189497 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 2f0f723aff2426cfec83996eef07dff74a784ca1 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 0a8869a2e57ab95a027a72c68f1482159bc8172b 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 015b1f6c34ba9ecc1809130033c1f5376fe924d8 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 734a09894268adfc18cb93c3821d65951b268ed4 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 ae04a40f9a337b04b026df2711f0d82531abfe01 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 af93d9d6f516f1039b7cd5583a06d8d8a003ec62 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 2c2b57fada622d6e364937f996b3548095105cf3 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 fbed232e62684d8d80f31ece92e3f9d6e99e8b9b 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 d93d28214a2e7e6bf92c1ac9e3ac5404783b6e32 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 5e5ceb40e88b5df81720de2df7753ab74dee73f5 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 5dd1f2185a3b643a0ffbc21d28e4a99717994f98 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 097edc74a34b71001f855aaed6bd390d8cb60aa8 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 8384afd1341dd036d42fdb897bab290b1ca54f0d 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 c42de581f00f406fd3422133d2cb565a8a3938ec 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 f8f6425f05f90668bfeb1369cb7e090dde4eea24 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 362eb0013c4d1d6d35ea9c5a6148a420fa3b1fcb 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 12ddec721b25d816ada0f0670fa34e67e6d51b5a 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 3e471634e8f5326ea2e9fb80a93d4a1319e116bb 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 1a73afc0f359e1d1cb878c4e6985c388c504f409 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 3522d22c2a2249a543142f4e3ae7fbdd574f1be4 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 a64e2f786c809bb4745cfc1c9e57a19f6ed7d334 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 27ec03ae94ae89c2231532f6caab35c3228077ef 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 c29f99c539904ef5e788a0c35f1a845df86f3d07 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 979189ba298e71ba67454a3f026c4a4576790ce7 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 c50783eacf7ef69a46e5bafff292ab7c9b7c44e8 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 2f96a3302c2b731b7e96c5adaa1da251846a8b73 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 fc754c039efe93195e680acf57bbd378e495d4df 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 be1035496e6bee79c3b6bcfad8241ed0829d790f 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 40bdf9d8efe5873588d47dc522d3179c82431d80 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 bd2b8b382060e00065d5bfe116a44a4a8f15866d 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 89ba05e882ad30ab903ecce6259c388cdfa70c44 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 d3497152e66b8fa953f9ed9a570a0bebf1d0e00c 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 bb4cb1d7c91c0bbccf886d61d003e74ea6a1dbdb 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 c3c28ec029b036f1c7a182c9366b609b493da966 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 4bb5ff26be30023cc94260958784d5f6239db11b 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 7895a67c1e966b1dd897132e2e8a854eacf12e31 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 56487f3aec0c9b0c6a910a850b3afdd42fc7b5e3 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 2e76cb7f783f88be1bb1b1780704ae40a93d9da2 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 39aca3efd5eb6607a080582573a1ce7af7e074e7 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 883b5c134f763bb12f821acfd1fb9cd4da296ab4 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 1c601c92f06a7c7d0d397aa383d5319f4144ce3a 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 51f3317f94809bcf7b707114f4c12202b0db5649 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 a1a6c66573c8679aedad8c1851e972cbf971cd1b 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 99b906ad87e2c43a66586f11d59518be4c9ccf7c 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 ef600d555671e5e9f6855174a3133098d10cfd07 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 16027ea86ead7c38c65a29a6802553c87b21ef79 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 0f2180cbf38b5c8f90d22246c00dc7e7bc6c4030 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 046876d8342bd45d2055adef729989422488aab5 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 100613a7eaab59cb19d3df1e696827060a9ededb 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 e8e9b1c4b35e5cc9958dcef8008d475aa79ff1c0 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 104c196a06a8feb97161984ac2fb16f6d6bad0ec 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 22cf8eae9691be7b928988dbeef4618b563895ab 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 329f431a35c21a252282b451534328ee6e6b3dd5 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 acca3167a74d750c1eeb2191bba3989a0067d8ac 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 db26beb896e168d9d13f43d76757852bb7ff216b 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 60c97804b044a7147fb0f096b9d46c0d9b180d18 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 94a1fcde1c76b4291c4a68e6a6ff1fc1e5c53619 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 bbdab5554295416548d6d03c64a85bd1d89b215e 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 c2e05f0bf81bc10564d8ee81828c4a949e3f3da9 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 1412bbdacfc7e853f4da59f3e3764ba822b3a009 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 1bd0f9d6622cc43bd796415363437e97e3ce9e79 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 815eaad071014f3ed830301967d94e83825ad436 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 2bd7d7225c1e16041a7e4f39dee227c85b81a53e 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 49bd802deed17bfe101862f802024e6fb9ba9ce7 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 266c292dd22d3226f7bc2fe94d17b8843c867ba8 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 992d5265027e5204b7b5ef803c0ded2e8418b63a 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 79a326b21709b0b2fea691417e41c1b8b296b78c 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 fe654ff41910f1cd354b577f9e6e2bd62ba2bb9c 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 20c38cb82409a9a751b259e65958076b78aa678d 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 53c92ef37f8c850293f13a270b81b42167f0f1b7 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 c2c1f9a0aa9a3c8f067a9079fd96e497ccd13e83 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 e1e6b0ffe20d19db7bca04cc3bdbacaa6064b05e 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 5d78675fa13f1a7a5dacc2646d723bce929aef7c 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 87c8fe9b13f12ddd9c1fcfd1c223fd021a756a70 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 ecefb9cb8c7179e50261b3058bc1ac8ea93a9959 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 c087deb50c64e4315c1b2f70f2014d0da7f4a234 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 8af89f8d39b97d6acbfe2e7048bca4f5527975a2 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 55831bdde81020b33ae683745dc2238f3d268a52 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 11fefb4eff0bbf515d0b27d9790ee3ee8f055b23 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 accf896225e9b4afcaa554b6c3639329665eca5e 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 d3bd34878f577322fa45ca766011cb3726f53a6f 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 24b3234669217c17f93aae9b1b8a72fb29d277cb 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 78aded802897124a16b47e204d0455df7cdcae26 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 b2adcae8367fc73873cc897950c677a562e46fe8 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 57478d8d356971b3bf757acd3cd12dd0f76b9ae8 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 f7529a1860888e277f8270fc5724bc5073bc1a49 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 5d211e7661efe8b94ba9958ef1efd5a6096f119f 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 fa5abb1f0d56fa12cee04f3aa0c6ff311e4201bc 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 b8922ae5c789c7312e081a1e08ec5ee1436f70ee 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 9ff896c68136dd93e229c45b874e8a482aea693e 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 f23165b040e87ba1b7c800397e2a54c528c99595 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 189a8e4756fa7f875024d98352c08a317f00ea95 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 c1e40643d55fd74fd9c3fd288528dc93272b9470 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 78149f6f0db1dca6db0bc71b627eb369b6e46e44 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 cdfbf449e6d25a6d72c1bbb1519915e871cbe56a 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 55f2a7abd3848fb7e15774c24b82ed4f1937c05f 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 59f7946bd5fb7ffeef9040690f0603969881bfb8 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 212979fcd53de64be9c85173ee128bf9c7ebc21f 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 54ae40d4c4376b670e38c5115de45d5cdd14882f 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 ab78f3566d4adb17d7c68fa7ce234e1269960985 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 bca2019846986b8a93e74a5a47bd77001649c93c 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 74f793b9002aecda8ce10ab8941c6c41aace30c0 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 ebee7d5e41d1878f4843709d67c3f5949e069e26 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 5fb14f691ae364bd3f1b92177d628ceefc4c6cfd 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 000408a251e5c07392470671ac57999eca8a731e 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 8ed3ce88a8aa92339b8628d53569cb14c94e653f 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 f5067ed4c7a23afb414b154981858c2801682e09 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 04ea3cd241154d0e4643e46e632b6315f64a07d8 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 2be448282019bcb6966aa338e6936e5e90770024 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 0f47258599dc9a4d1bb01357455ee8bdc282497b 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 66ef6d5f2c1f3bd935d6142f9790fde09d5d98cd 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 3613814fcf8444cd966fbf0710e51be8e3a5adf8 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 0e4e983c2008c530115d38eb89977f673a3b7951 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 07276b93715ff90c9fea521edbcaa0799f943544 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 763a79513c6a19479c7eaf621ed4e676ac8c2faf 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 85618e52dcc79bff7b0fbaddc39734dbb857f976 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 261557e742ed6871b65dd72e185e80047e477abd 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 73d94bd3e0801aa4ce7492144aa6588a9c9d5362 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 ed84882f007d1ee0cf7efda377e26c68d4d3fe2d 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 871a8977f5a77405bf76f2f063be0326fdf8d263 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 046ac7d19a0c3cb13669b2e15a27a7b7170bdb3f 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 322872fddba6e1d3c02b43adaa719f3a1831755d 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 e3f6707e58dcc06bd197c05b35ede0ad6434a8d6 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 3dd4fbe01ba46f72b8d920536581fe9cce203f1c 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 9422abbf549a04e3edd71dd3efb0c1143f3686ed 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 dd97b2fe25dab928cca17bd2699945f1ab1d432c 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 46b4915ce51e8f7a50e96a819f7b5918c92b5a90 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 414cadc96aabc28cc71678af48a3b912c0d5e8aa 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 fcb304a5c9a7bf45645a171a571e963de2648344 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 ccdb04f6957e3c5243c23ba9dece6e382dde0bb7 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 fc24284c6e806af9b66cb79de35503b8ec98a425 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 986a6a7124aeaa9380d1a2f2dfcc4e639b629046 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 fb96a75dd6ba978e06f4e23f100e207ce5f3ab69 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 21c0bfce9593fc17c47b2b4dda44bbc0c8e52c87 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 42c6fc8231face922601c33941e94e3bedc2e878 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 2aa3ecbf8379598e25c390fbc956589e92e03950 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 78fdc91b7fbeeb5124c930e7c7eb2b907feb615e 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 1f9a74b84d372a5a6db5086b54ff4fa175e498c6 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 0034061f702cffc337c6946a30ad9e5447d3bfe8 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 b6e6b92f733e1792bc7c430b59af248fb6ba32ac 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 6ab9dfda25da011cf073a64dbe253f364bcfbe13 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 2d2b9ac7e2aa71f079bb3763a1bf85eeef7b4d3c 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 a30f0576fc9822feea233ca612c7a2379726cdc1 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 8978a486a0174056929ac47e37ec3774d51a8e40 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 e99172eaa8513a4738d4877ce187503e11e441ea 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 4327c71a48f44fb699dede4657d568b071bfcc90 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 e5b2594098bc58b28885740b2bfb7d84b8224b24 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 42f7b38ff6eaa317c985ff3d345e7d9e531247ad 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 07ecfb0ff5dd71a6877e8d995134fe233035e39d 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 69e602c621a390f35d3ec2699672c41607aa68e6 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 fae4615ad85c8f35bd334e9b173db43396dcdcb6 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 26d4c5f0b3d81a53d4e8420df4e21986e04916a2 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 fa09b201012c8ec2038b090e8e1817717688a748 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 20af5de330ffa7edfeba0fe9fbbb0beb8a6c4e64 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 3c9b6f24c6f210efb91e60f42a648e695759d35b 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 40d2d2f44d26df3c5f618cf03a90908c9b7bfd1c 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 eb6842269b972c6ff6062ebaa45b9ef2f2de9f90 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 0dde39c2e62d4ac1767a48384208559c607c92d5 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 84ea90cbb0c1c0c6a821bb1cbcb910164300e7e3 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 a35354fc25d433d00170616d236476d23f8ae557 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 72f2bb7728a7644325611b15159b8a3a18619727 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 a95eb4eb5d6432bfe7093c11755159be32bdcd03 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 887a8dfaeaec3382515566a6c09a7c6cad6046b8 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 5f041e6adea561fcb5b3d1ba28b70dfa8168a825 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 094d7732e5f50def6063da1dfc161fe3bf153151 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 4e74f8a462e0e44e13f8cefad5c657b0e340b5fb 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 991bcab222927c4ea6160bd0f4f865c0454a3c2c 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 6c404e304256f05db3969ae92fe3bfe5fd882624 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 83ce808f9e8cb716b0c142a6e5e52f30d6162017 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 7c45a7da6fc2180ef13dde09d7cc8fa2d54652d5 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 681edf7b828ca48774f5c1ccea1a7b92e692d9ad 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 f0d8743ed6e41a064f36b7eea63b9f7e42cb9f31 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 04f69ed6c867a1ed20fa2d86987cba21c82fce4d 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 1241bd1d4b6669afaca24c22d5630b645fa79a2f 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 b1f7e998dece58ebd1dfc69c028131d13c3919ed 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 3e6c5031d4ba4672fcd4d7d4645de57665df46fb 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 7d6b7aebb06f2ea1a2710ef21fe80b041b7dd75d 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 c3d8e8aa16964e68814805868285613e37897b74 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 4defb5ffd7db38cb6393db416901b39739388f9f 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 37d78f8c4d5d12b9e355b86d8f61995d7f921884 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 87e0e05802a9f7710c8dac3c5920a8110359146b 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 3028c68fd79a1d5700939961cf870244bdab92d7 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 a5c25d5154bf8b50083fbbd531b00cf43dfad73d 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 a9f2bd99c29821422ced231e2d00aee6c3747964 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 7699736ce293a788da954b49c0cdbc7139157a71 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 1fbff53581fbf899aec655d220f66e6129b4dfae 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 8be276dae1e10f127434d3bdea46fadb2d885789 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 587007b906210bb3d9c125c2867b6f106768e2ef 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 ac0e302ac76592f6a79db56b6fbcba4ae4d76d18 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 2fe290257c05859598fd4f6897933ca15b1aa4db 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 7639c42f3cf1356e811620b228e4823c351a3b12 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 c2d5b59be85b27f118daf003533418f16315c280 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 0c981f6962b25bef88e5211a3879bb09b13fa175 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 845ea89bde9d68d0e98ccc6dc9c43a28791a063f 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 d2ad673d1f4c0cb65645f4aa5ef17e4b2cd0a448 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 592283b784537cfb30ba86ee2a95a46840d3940b 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 ff4515309164bfa148afcb819ba588cdfc2315a5 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 4396500893cf81a0848af00f1a4d2f51de9ebbb2 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 a38adde581014d365f052a9f824388125d255b0e 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 24cd674504b44683d3740d67bb6891552437ea96 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 9cb22defd0098a7755ab09b3b5d1d4e71bafddc0 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 144417d9e2c84feecc612fb5cd9c443500636eb5 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 2ffa0eab3ac9a4e7e4ea0ec8f0c87eae24531737 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 25b9201eeb202cd8b04089d09b11a034b00991c2 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 54e08f269ea7cdb41aa9c1fcb89e12c87e065212 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 34a87e51b9767def7b079e47fff6bd8691392304 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 8a59ac26ec402d247b3753418e3b858728184d7e 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 b222041e364fff3d4c015db3f0e6dd34c9456b2c 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 856ba083d45e9c599585d866aee48f6a68ecaced 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 33ab825e42ea97cda473e2e28ae474a3e3e59576 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 24655447bb6533fed2d596bc27f7c892a60d7658 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 d3c246317435e7ccaae05c088ccda83b95ee99d2 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 02e42485981309a254870da9b3caed24a7ba2387 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 bc2ed23c50c55f812ea72231cf943334eec3d924 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 8ddaf9265dfc641c65ee215c08718fd31977b360 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 0367f2a2532bbe40d1ce22a1e502bd3850ac4fe1 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 5910fd84f5102b39eb74b9ecb7bd6a9719dec6f8 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 75959d108009e05cceb5d473dcc6d64b06e82cbb 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 5bfb476e7f1818074c3f9a4c83cc547513ecf59b 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 d333a14f58459c753a2b9c0627d68e337bf92889 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 aecd0f21dd413c01e3f50cf711eb4ca486526961 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 85054779548ad351c39efcc93e593ef06e487ba9 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 4e03fb1752b2d308b8defe669d5e459d4041cfea 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 1e0c4a0329351a548afd71ad32dd39eff65abfdd 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 6006dc431f392cbb8be221d39e5469158ac46bad 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 3144655c87535e298f9d21674f8749bab25fb767 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 bdd29e17b38fb36d14300ec6e91bc00019b49f60 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 de1f0da12b44cee4fc7cf45b2767b16ee6c32b62 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 e3ec60a8498bd336671177b1714c607fc47596a1 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 827f9bb4687ba183f9c5b4ebc9ddfe5c04ffb55e 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 8a4a41ceb333d7ab1617594a3274879a636c1a8a 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 3b7cb34dd8cb64bea8f416f3e3de0683faa4d879 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 e85d7d321e132ad75609f95b2307b822cdc63b1c 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 d166e7bcbb8b07e7298e5a26e2517dfb23fb5b54 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 c909b4a20a77bb1bab1b995dbce1c025eaa14727 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 b66176c7e3094a5400fdad0634a0401ff1d36712 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 2e3b0b170b0f2dcf20b4f5f16e62dfec84b7c27e 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 86338b74365b2b303e6b0994d8cda3c0d564fd45 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 15b4c7b51aa3ba3273bca8c8c84553793b1cd41c 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 62b7a5a7b74e8a0d1b137fdc189c19052a33b6f1 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 b1a36e6c8b663acebbe891ca3057b4a31a6af607 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 825af2d2076e3b9f2d9427249cb5d65881bd4930 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 795036b35a95ae4e387888cae86b5bb92c953628 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 c3ca6224fddfeabf0cf3267ae00f29cef8de258a 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 03df2e637c08e0236b8bec8c5dbed413d0dd2d55 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 e1150e98b4ef2ac6bebc8c45fee1a3bba0c267a9 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 7529619ee0211310f2faee8a679ee998af8f4fc1 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 7473cf41b7df333dca4339ef068bf26376e7a036 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 9ddea22067f59c577b6241ccc6c946bbee9008ca 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 5da0ca07d9cddb0583c097af37741a87a8397e85 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 9429dcb033803b575f0897ff7a6993c3db0bb827 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 2c714c2ebc056d4f560f3b8535d76401843f9c5c 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 755b88820b59c47b8840afc3fe5bc8613a69afc7 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 17f0a43e131d9d3ce00a76420e56c2c345c13420 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 33e814a2422525379fc4df1eb0afd02c360f1792 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 da88a62b7a5404d02b607b28f6a8df3c868732f6 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 896dbf0ed47435ece5afc521c528dc2bc50a8cac 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 3675b508577f9d40840b941bca6eae9b40822c90 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 9dbc975489993c7943ea4412751bad02b84ddcac 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 7c521a300a2432a085b787d28770de3933b67c9c 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 6869d5e317ffdb7ea5e34a05c6465f347632801f 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 6859affab87dd3fa93a9b9e1eb5e0cbaceda34d6 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 9bb49b60ebb1bf50ae6493ebdce8e021f639f7e3 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 0f57603765a241ebc9f972e885077d9663063a32 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 4b42393d30953e68453e408fca47c448d2c35baa 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 b64343bb6d37dc414394bcc006f7a62d127c6174 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 9b4324564be3adba93af8f54320cb1480d8c8fc9 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 6c1d434fcbf4e214fa9d96c4c7c6c5329947567a 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 34f19c3ec5040e377dca9efc5c6da507f4256bfb 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 82e5d2ef7836642da8eca5f633990085463eda9d 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 df372ba83e89c27c1c1dec4304ad0318325fdebf 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 ac6abd652d3a3f943c2d97139f2a0a3f02ccea91 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 f8bcd4c84631090e3de9d054a7f805801cea34ae 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 51c3006568ae3544b912787656099d09cca6bf7b 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 f0032f756e6e068310c01e11db7a7997560c38cb 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 8c4d97b20eace15ee50a400465e7f001c4a96b30 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 9084270db0f1273109a2c7b69b7a1e63a3c136ff 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 dfd24fa881142f153eea500c0e407a880b2fe39f 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 9a51ea95127900fc46aa8885bfb77a738385eba3 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 020f10a88a941ee5b58c1be69a79b19f2312dd35 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 7bda573f71b8bca2ee71e6e766c22b6f6ec9d770 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 e502ed27ec0a2e37e38065013992f050a34972e7 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 bcc61f5276bd98f1d07d0fdc2758b560688ad255 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 03e22ebe68717304049621a5a3cabd8c78692346 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 7cb815409c8920186281dd753affd4180bf4fc45 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 a69a6e97686b0e40e05601b9340178bde94f85a7 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 7c31a9d51f960e3376aba912da76075a449cbb11 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 36daf72f40ef43eb54d30813daf068d8bd9325dd 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 49ad4d2ec82a8ce24d351d088c833186383a15ec 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 9b28fe9b352b219b48ba13f72b04f4c992751759 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 097268c2e5e9dd34c86f67d253388cbdc5dee2d7 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 4ad46de00d185083e51902a96932d059f0a53078 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 f24efab6c6839c004ae2cd1dea90efc8ddbdc435 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 c015ec7523c0c8e95f58bce4913cf14e5b351281 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 068dc0cf775bd28a91801f573a3e5dbe29de7d14 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 5b191d0aa69141c2bccac19b311e3370d945eb5e 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 784081b92fe4ed7d43c12d3cffa34e0c815a4e31 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 fea9fc3253b8c65601d243aaa829b897f08e9586 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 4a639652b3752864fca53285e72092fe61f72370 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 8af061aee3d3c1477b42f209e368e50b6e7ca59b 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 ca6fac370f8ef041c5d37186a299014bd47d6cd2 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 285e044b71cdc2444fc9660fdb8e59e991c4c209 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 154061fb24ea78db9a694ca5af5ed1853639fcef 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 58b9ca172d1f1783021f79c4cbb5a43f4750d6d7 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 0b554d9b26d2b6840a577ce4ffcaa3b461520244 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 a98b17c09096c8f6784d218ca2c097c32e5c88a8 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 f3b38a72a63fd709e308667e2cda45bc2716ddc3 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 e8445cde3d8598b664680a8e2a8f6751bc2cf83d 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 300341a1f2d72c0b21e9d1748c2e758a5b957dd2 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 b4a26fef5733647b3204d7cb2119ef39652969d8 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 711641e060356047ce0a7ed3b6116142e394597b 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 af44422426d755a23b7a1762700e4ad93236d3e5 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 201b084012c3322624fe1420ef2471778a68228f 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 ad190927da2e1536178754ddc2280503eed2e0f5 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 4a5069212d33392e0f453d19d5cffe816b97a40e 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 855c406ffece3b815f4d67f9c83afcc959021f37 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 4521b34d9fd5310ffe2bbf17007ae6d7561c3940 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 531e7b336db9625f34f14821f6d0416d9ad1c493 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 c1dad4b4c5437243bfd284db327a9d3d0558c0a0 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 26efb4a2334e9e46e6107a41c358d35455a6963c 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 f21d68969a35711f1916335493b3a07e48e64254 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 2872d211e17ab40e2223ba66dd8797566f594102 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 8d825a397132b87405bdd8168bc9769b29dc8935 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 6936c1ed34081a89141440d6bc51a2dc32681cfe 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 c86d6023b2b525645e2ac49508131dc14cde582e 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 06c81566a2d9ef754f559bfa517207548b59c61c 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 8492883ec08ba601e913613b9e2fdc9f23f4b0ed 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 2d597e0389b6af7bf7413f3bef94bfbccc9631e1 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 03e19d74622d9eea3bbc518f62e8b24cd445dffa 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 ea670d10cccf1f4687e1dbc2121f4689eb38a481 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 1dff3f219882331d0baa24e052d4b18bdb72a7a2 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 8dd59593eea5099c192be795dff878880e09d6a4 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 4c3e595f4dc79d98a982595f75c2cb9e27b0db27 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 e5598d9230c4d775885678f74e2a9e0851025beb 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 6c22d6684dd9309a8d75411935ebcdf53f226597 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 37acb5abadcbeccdc8db31e3a54808a4091740af 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 623d2c8ee080fe562b3afad8939154fdb4af26f0 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 aaba3abc48a4076a0feb9bc1e836dd1132d62a3e 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 428b566f3698dd6d2403a8e6bcae65e0d3b5e242 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 bc3942c6dd8f9f2942bae952e9433c4cc14b6aff 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 305fe9b7ccd60eadde030021f73e75527fa5bec4 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 5218e72bdb4e7b10742de9f50a9c4e746bd3bc31 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 dffe483d29e9c8df91cd02b577d633c56efb9bce 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 ec0c4113a7c815f7d52a14e7bea13ce9d16e071d 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 20b3c26d671324ed8e02adb09f26c826799c9c95 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 bd22c560a54a67700539a387980669dca58c0517 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 f634404c4cc0f4020d71362d6f1944122e669886 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 0e71b55e38e63f4cd97e490f122a92153bb91f8a 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 ef015e8450cd8ec322e5ceb9d044a6f9546cd902 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 6bf9d292fe6894e06fb45c8b8c9f1a94573d9b5a 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 ce7b166f21fd0f9cbe2739f3a5079319a37c192c 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 ed131f0be8438e078b741ec3d9fe7f4bb9c4e5f5 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 179526be837c6132b3a9b4abe10d2dbf90e2ef5f 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 88f3c24e1725ca1a8e75d8ebecc28a7923bc3655 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 b43da16f08d9371bedf64f2d0a28d5aee03b8b02 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 623ff8374a38aac7aeeab14dde70a19dae4f796e 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 6108798e59ea888aecd64c2a6c95e42e67bb01ef 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 8bbfea6bc1110b3ee2db13e75e4d1a74be039032 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 15e4076df2fccc39ede95ba318f4d61bd1a105f2 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 f2c7e1620efa1b4c5315534a174ac04317ce6670 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 526ad8c92bb326cd1aa7427fa4ea4f3a669e6a21 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 e6c4f56416634a4290a66b49fe053f9c4ac04549 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 49ee116a65aabe30e26917c66e98e9cccdfe5fc3 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 e8bca38dc0401174b3ec3da997340ff0329bfeff 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 f1ac794b75b7d0983526813dc9acac08ba9c908e 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 3246bd5c2cfb04a8d41de260d1c4e58b9601797d 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 658b40783acc27a06beeb87a4a9a548449ae4e4b 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 b4f75d7c4d17e375061295c3c450c334334c1c2b 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 6c09c131d7911d1f54665caad598cdc779087666 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 0ceeb185ab016680d270635da63d271c0208d927 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 c0d70ffeecb7bbd3b173b5f419c3cf3751d95fcd 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 d784eca3f89b6263e7a88a06ecf5c597253053b2 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 207cbf03511fea853607e89a6a0ef8adbf9d1d25 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 e6508f74db79ffcd194c6abffed9e09e94541ed1 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 5345d1c7f6a72e1572f00493aa928b41e1499912 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 296b98cad3d4e0be2b4074a424d7733a137e8226 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 b552a44453c1e9aabe41e5419c31ff0481dcdcb3 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 f4d15e426e37c5c963a9fba79f6e2da653dd7c2f 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 9921a9fb412f45c5cb1cfb85fcae37d053229e62 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 f593d7ca7da78ecf2a51475cd1c6024f42d3d8da 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 233195102f90188222da4b30232616d9d1d5a577 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 3be7c0456c61d73ab6267e604d9f4f00cc99f50c 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 fdf2a85e74d48da8404727e407195eac3426f74b 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 f54ffa0061898e638f4e22ebbc33b6db67172fce 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 f5b79e27af362af98e836d7eadd3d06e2bbaa847 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 52b18199d316084adbd7b10b5b3907780c07a181 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 175278c44c3cba7fc16b474054e8748fad30a313 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 e4fe1bb7e3a9638acc610acb72f3eeebdb76d0c4 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 2e07208527f432cc1efcdd358530dae41d8708a9 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 be894607752aa11b4fe138f10226f74c93b2887b 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 e8648ae42d8ea202ac5c497a19cabb3884539b42 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 0a26015f6252748c63134a86d0350d71a850856c 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 501701b290b898018fff2b554e5ba3720f7aa909 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 0d07491c2e5700084be8b0fd09d5326e564d8281 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 3339fe2576d9627b4b2ed2b65c6065f7335f0e5d 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 b0191d6b1d2690eff4fc26f30be176dff5b26f40 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 896f4a837c9a8c45a73d61c529f19b94ba9bb6cd 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 2a5b27675d0d589018cb4a58a3446c7b060f1106 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 aee7531002f3f2ffab027fe621652d8fc1c5a90a 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 da7b9b9d6e055722aa16120e918a36bce753c477 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 af4f75f8f462f975e30d5e6a6026076cee7c434f 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 3e731f3960647d9bd375d99a60ec953befa689a9 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 33218205e4e25089e5d5a81e7c49b8b566969d0d 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 aed848fc930c13503974cf4043b6bef7a5e76d0f 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 89ba2b5f325265e4e8b35a1cea864fe719cb785e 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 3263cdb39564c6661a313b690a8d825086409cc7 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 fe70bca2a21fe3f1c5fd37417c4b385f4224278f 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 17490163544335d65ebafdc40fdcdb8ef63b8db3 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 af404e94e23a64eba43c80cad92c2bd52bf13c78 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 38a06c5380c25d7cc94d01b2eb53bbb9b015c1e2 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 6727329429f05d16aab6da01b3115a8c8d47131a 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 8b765cb323a62d60d07fe62ad27b27571274002c 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 99c17e5826ef82fc0e1177f542d1c98f1fc5db3e 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 c192c62433500b44a92de65b509c850c10df5afd 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 5f5e276cdfdc0b87838d1a003b88e05afb553f9c 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 ea361b96ddaa7fd2ab1cfeab853f3a5a795109e3 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 f3306d83eed53e53e56542d6ddc3cb509a9b08a7 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 5783fbd2916a6ccecbaaea7bec3d81f7d3cb2122 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 b0ac5c69a8a3a17fcceb7c5fa50c10b432c65feb 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 2609a1395333e508e9ea2fc3cb07fb79efbc09a8 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 0f4993729da34490750176b6c3bf992fc990bffb 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 2423fad67e9f2d885ebeab3a4e5d78be96126c9d 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 e0ca5568bf760ea30412bd2a6f8c98da39813e9d 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 1838fc6a884a91c4247ada13a2a717611bd6648f 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 be1a3c12189f478687f35e53da263831107a6d92 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 0c03c3039d0dfa065aa47c23c23d28a5fc58639e 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 a8e7016d6073642b0cd70c19d0b5c76f9604f3ea 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 f98103df973bb2331215a2da0e6a3677935a01a1 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 d9a8404b7ba872c0fa8b877140bd82e86e9d4a9d 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 45bee74f66daf7d1e90cb8924657bb88bbd25508 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 199fb348604b8345ede47bcafcfa55fb6fabba5c 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 ea753ddc65e948eb8cb7b14e5b4a6c18f0b05796 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 7a6c28412718b7899397f1ed05e691c56c6164c5 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 aa2fbf8b99805d75b4627d32eff2dbe84ac82034 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 1188aa460b3d915d83631818bc57bc47c8293568 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 a881836b95866411abe3a34df1d877293ca538d6 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 e00e9f947414737bd866a9999b926317e578beb4 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 31bf6c7935177d1ad5db8f7a571cefdee1d2815d 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 51fe7192630b031cf3b599cced0356068a0ffbaa 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 b834a2697ae737da4849fc30f71427d206a5b7ae 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 dc063f4bb1250b9167039e95c0be595601316ad3 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 4c9b7d416d497fd6c1bd1f20576fff7d5c767321 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 a795d292d85641a9531fb80fe64438f6b15aa8b4 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 a1bc193a090ea1572d42d6f98b045971501dbcc6 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 8266534ca88c8b07daaf172b90872d3a8d06c649 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 5145f3c148ca8edf052203d7c00f446770f17d2a 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 --- source4/dsdb/common/rodc_helper.c | 275 +++++++++++++++++ source4/dsdb/wscript_build | 2 +- source4/rpc_server/common/sid_helper.c | 276 ------------------ source4/rpc_server/drsuapi/getncchanges.c | 1 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 - source4/rpc_server/wscript_build | 9 +- 6 files changed, 277 insertions(+), 287 deletions(-) create mode 100644 source4/dsdb/common/rodc_helper.c delete mode 100644 source4/rpc_server/common/sid_helper.c diff --git a/source4/dsdb/common/rodc_helper.c b/source4/dsdb/common/rodc_helper.c new file mode 100644 index 00000000000..09aa3f5e710 --- /dev/null +++ b/source4/dsdb/common/rodc_helper.c @@ -0,0 +1,275 @@ +/* + Unix SMB/CIFS implementation. + + common sid helper functions + + Copyright (C) Catalyst.NET Ltd 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "rpc_server/dcerpc_server.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "source4/dsdb/samdb/samdb.h" +#include "libcli/security/security.h" + +/* + see if any SIDs in list1 are in 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; i < num_sids1; i++) { + for (j=0; j < num_sids2; j++) { + if (dom_sid_equal(&list1[i], &list2[j])) { + return true; + } + } + } + return false; +} + +/* + * 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). + */ +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) +{ + struct ldb_message_element *el; + unsigned int i, j; + + el = ldb_msg_find_element(msg, attr); + if (!el) { + *sids = NULL; + return WERR_OK; + } + + /* Make array long enough for NULL and additional SID */ + (*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; + + 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; + } + } + + for (j = 0; j < num_additional; j++) { + (*sids)[i++] = additional_sids[j]; + } + + *num_sids = i; + + return WERR_OK; +} + +/* + return an array of SIDs from a ldb_message given an attribute name + assumes the SIDs are in extended DN format + */ +WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, + struct ldb_message *msg, + TALLOC_CTX *mem_ctx, + const char *attr, + uint32_t *num_sids, + struct dom_sid **sids) +{ + struct ldb_message_element *el; + unsigned int i; + + el = ldb_msg_find_element(msg, attr); + if (!el) { + *sids = NULL; + return WERR_OK; + } + + (*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 = { 0, }; + + status = dsdb_get_extended_dn_sid(dn, &sid, "SID"); + if (!NT_STATUS_IS_OK(status)) { + return WERR_INTERNAL_DB_CORRUPTION; + } + (*sids)[i] = sid; + } + *num_sids = i; + + return WERR_OK; +} + +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; + uint32_t rodc_uac; + + /* + * 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); + 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; + } + + /* 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) { + 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; + } + + 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)) { + 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; + } + + werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, + frame, "msDS-RevealOnDemandGroup", + &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; + } + + 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; + +} + +/* + * 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) { + 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; + } + + 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/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/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c deleted file mode 100644 index c6e7fbeb7ab..00000000000 --- a/source4/rpc_server/common/sid_helper.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - common sid helper functions - - Copyright (C) Catalyst.NET Ltd 2017 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "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" - -/* - see if any SIDs in list1 are in 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; i < num_sids1; i++) { - for (j=0; j < num_sids2; j++) { - if (dom_sid_equal(&list1[i], &list2[j])) { - return true; - } - } - } - return false; -} - -/* - * 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). - */ -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) -{ - struct ldb_message_element *el; - unsigned int i, j; - - el = ldb_msg_find_element(msg, attr); - if (!el) { - *sids = NULL; - return WERR_OK; - } - - /* Make array long enough for NULL and additional SID */ - (*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; - - 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; - } - } - - for (j = 0; j < num_additional; j++) { - (*sids)[i++] = additional_sids[j]; - } - - *num_sids = i; - - return WERR_OK; -} - -/* - return an array of SIDs from a ldb_message given an attribute name - assumes the SIDs are in extended DN format - */ -WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, - struct ldb_message *msg, - TALLOC_CTX *mem_ctx, - const char *attr, - uint32_t *num_sids, - struct dom_sid **sids) -{ - struct ldb_message_element *el; - unsigned int i; - - el = ldb_msg_find_element(msg, attr); - if (!el) { - *sids = NULL; - return WERR_OK; - } - - (*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 = { 0, }; - - status = dsdb_get_extended_dn_sid(dn, &sid, "SID"); - if (!NT_STATUS_IS_OK(status)) { - return WERR_INTERNAL_DB_CORRUPTION; - } - (*sids)[i] = sid; - } - *num_sids = i; - - return WERR_OK; -} - -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; - uint32_t rodc_uac; - - /* - * 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); - 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; - } - - /* 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) { - 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; - } - - 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)) { - 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; - } - - werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg, - frame, "msDS-RevealOnDemandGroup", - &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; - } - - 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; - -} - -/* - * 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) { - 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; - } - - 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 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 aa6147a1b7526ffa3bfbad74e1d25efaf2b21def 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 5d13dbc2f3c3bc1b8a887bda73aabb8638d372ee 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 e85ec4fde1f6f26b6316c3cc802db11d6ee1c0f2 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 2fe3b1dfb50ed1d767c6b7ed9227ecebbe8f4c29 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 a6aa0c29744118986796510d425bcdfff8c48d72 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 f7b5e9df14a851f397e1b23daa12e4b74553854a 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 71b3649fa15e9765eed915756092cafd30f39a26 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 92626b8bf8411cbbb1cf8e64d156673d38859310 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 53fd0b7248dd6d05d6b722cd39c43c3cdc2862b5 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 07d9cbd152319d77bc4da3bedc5c8a144ec4316c 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 ebf576b02b0c852cdc6b5f234780b0f65f10fe9c 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 b04e7e371df361b2b55b208ac86cc78bea89c4ac 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 c19c00b7ceeecfbbd67d38866bb8d7123d0aff5e 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 9acd28e4f1c1d60d51872351fbf79c4ea1d6d0f1 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 e4495d0848f18780b9d9a66ce1e8870e6da5136e 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 cdab1e434776766be78c8903129e39046f0995ea 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 bde9bb3f001b6616aaaeb5d907181808edaa76f3 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 ea931c3975cd30ef1ab5ad64e0ce515c7e015048 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 e0a4f61e74df2bc0a2437c89f5562a0ac98d353a 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 b492e9fc390529da0fa9ddd1ace7056979f48a40 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 4fba9ced7292523d70dcc9afbddef21eaf346be8 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 6f762e6124099b5b9a5fa690018d3241b7db4100 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 838a82173c8dcbaee9ca5b35bcbb287efefb41cb 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